svn merge -r 13415:13452 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorDaniel Genrich <daniel.genrich@gmx.net>
Tue, 29 Jan 2008 16:42:57 +0000 (16:42 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Tue, 29 Jan 2008 16:42:57 +0000 (16:42 +0000)
68 files changed:
release/scripts/add_mesh_torus.py
release/scripts/render_save_layers.py [new file with mode: 0644]
source/blender/blenkernel/BKE_armature.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenloader/intern/readfile.c
source/blender/imbuf/intern/openexr/openexr_api.cpp
source/blender/include/BDR_drawaction.h
source/blender/include/BIF_editarmature.h
source/blender/include/BIF_editdeform.h
source/blender/include/BIF_editsima.h
source/blender/include/BIF_poseobject.h
source/blender/include/BSE_editipo.h
source/blender/include/transform.h
source/blender/makesdna/DNA_action_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_sequence_types.h
source/blender/nodes/intern/CMP_nodes/CMP_defocus.c
source/blender/nodes/intern/CMP_nodes/CMP_idMask.c
source/blender/nodes/intern/CMP_nodes/CMP_zcombine.c
source/blender/python/api2_2x/Mathutils.c
source/blender/python/api2_2x/quat.c
source/blender/python/api2_2x/sceneRender.c
source/blender/python/api2_2x/sceneRender.h
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/extern/include/RE_shader_ext.h
source/blender/render/intern/include/render_types.h
source/blender/render/intern/include/rendercore.h
source/blender/render/intern/include/renderdatabase.h
source/blender/render/intern/include/shading.h
source/blender/render/intern/include/strand.h
source/blender/render/intern/include/zbuf.h
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/envmap.c
source/blender/render/intern/source/occlusion.c
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/pixelblending.c
source/blender/render/intern/source/rendercore.c
source/blender/render/intern/source/renderdatabase.c
source/blender/render/intern/source/shadeinput.c
source/blender/render/intern/source/strand.c
source/blender/render/intern/source/zbuf.c
source/blender/src/buttons_editing.c
source/blender/src/buttons_object.c
source/blender/src/buttons_scene.c
source/blender/src/buttons_shading.c
source/blender/src/drawaction.c
source/blender/src/drawarmature.c
source/blender/src/drawobject.c
source/blender/src/drawview.c
source/blender/src/edit.c
source/blender/src/editaction.c
source/blender/src/editarmature.c
source/blender/src/editdeform.c
source/blender/src/editipo.c
source/blender/src/editobject.c
source/blender/src/editseq.c
source/blender/src/editsima.c
source/blender/src/header_action.c
source/blender/src/header_image.c
source/blender/src/header_view3d.c
source/blender/src/poselib.c
source/blender/src/poseobject.c
source/blender/src/sequence.c
source/blender/src/space.c
source/blender/src/transform.c
source/blender/src/transform_conversions.c

index de2db42d482c19053405d9b1de971eb87b218126..4f759256497b66dfe9f26c5a545667f9df9bf75f 100644 (file)
@@ -51,9 +51,9 @@ def main():
 
        if not Draw.PupBlock('Add Torus', [\
        ('Major Radius:', PREF_MAJOR_RAD,  0.01, 100, 'Radius for the main ring of the torus'),\
-       ('Minor Radius:', PREF_MINOR_RAD,  0.01, 100, 'Radius for the minor ring of the torus setting the thickness of the ring.'),\
-       ('Major Segments:', PREF_MAJOR_SEG,  3, 256, 'Radius for the main ring of the torus'),\
-       ('Minor Segments:', PREF_MINOR_SEG,  3, 256, 'Radius for the minor ring of the torus setting the thickness of the ring.'),\
+       ('Minor Radius:', PREF_MINOR_RAD,  0.01, 100, 'Radius for the minor ring of the torus setting the thickness of the ring'),\
+       ('Major Segments:', PREF_MAJOR_SEG,  3, 256, 'Number of segments for the main ring of the torus'),\
+       ('Minor Segments:', PREF_MINOR_SEG,  3, 256, 'Number of segments for the minor ring of the torus'),\
        ]):
                return
        
@@ -61,4 +61,5 @@ def main():
        
        BPyAddMesh.add_mesh_simple('Torus', verts, [], faces)
 
-main()
\ No newline at end of file
+main()
+
diff --git a/release/scripts/render_save_layers.py b/release/scripts/render_save_layers.py
new file mode 100644 (file)
index 0000000..04bedde
--- /dev/null
@@ -0,0 +1,116 @@
+#!BPY
+
+"""
+Name: 'Save Render Layers...'
+Blender: 245
+Group: 'Render'
+Tooltip: 'Save current renderlayers as a BPython script'
+"""
+
+__author__ = "Campbell Barton"
+__url__ = ("blender", "elysiun")
+__version__ = "1.0"
+
+__bpydoc__ = """\
+"""
+
+# --------------------------------------------------------------------------
+# The scripts generated by this script are put under Public Domain by
+# default, but you are free to edit the ones you generate with this script
+# and change their license to another one of your choice.
+# --------------------------------------------------------------------------
+# ***** 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+# --------------------------------------------------------------------------
+
+import Blender
+from Blender.Window import Theme, FileSelector
+from Blender import Scene
+
+sce = Scene.GetCurrent()
+rend = sce.render
+
+# default filename: theme's name + '_theme.py' in user's scripts dir:
+default_fname = Blender.Get("scriptsdir")
+default_fname = Blender.sys.join(default_fname, sce.name + '_renderlayer.py')
+default_fname = default_fname.replace(' ','_')
+
+def write_renderlayers(filename):
+       "Write the current renderlayer as a bpython script"
+       
+       if not filename.endswith('.py'): filename += '.py'
+
+       fout = file(filename, "w")
+
+       fout.write("""#!BPY
+
+# \"\"\"
+# Name: '%s'
+# Blender: 245
+# Group: 'Render'
+# Tooltip: ''
+# \"\"\"
+
+__%s__ = "????"
+__%s__ = "2.43"
+__%s__ = ["blender"]
+__%s__ = \"\"\"\\
+You can edit this section to write something about your script that can
+be read then with the Scripts Help Browser script in Blender.
+
+Remember to also set author, version and possibly url(s) above.  You can also
+define an __email__ tag, check some bundled script's source for examples.
+\"\"\"
+
+# This script was automatically generated by the save_theme.py bpython script.
+# By default, these generated scripts are released as Public Domain, but you
+# are free to change the license of the scripts you generate with
+# save_theme.py before releasing them.
+
+import Blender
+from Blender import Scene
+
+sce = Scene.GetCurrent()
+rend = sce.render
+""" % (sce.name, "author", "version", "url", "bpydoc"))
+
+       for lay in rend.renderLayers: # 
+               fout.write("\nlay = rend.addRenderLayer()\n")
+               fout.write("lay.name = \"%s\"\n" % lay.name)
+               
+               exec("vars = dir(lay)")
+
+               for var in vars:
+                       if var.startswith('_'):
+                               continue
+                               
+                       v = "lay.%s" % var
+                       exec("value = %s" % v)
+                       if type(value) == str:
+                               fout.write("%s = '%s'\n" % (v, value))
+                       else:
+                               fout.write("%s = %s\n" % (v, value))
+
+       fout.write('\nBlender.Redraw(-1)')
+       fout.close()
+       try:
+               Blender.UpdateMenus()
+       except:
+               Blender.Draw.PupMenu("Warning - check console!%t|Menus could not be automatically updated")
+
+FileSelector(write_renderlayers, "Save RenderLayers", default_fname)
\ No newline at end of file
index fb527051a0d76771c64a39d3ade6bdda61a459da..2c573faeb873a8f220fed847e123de4d560c95bb 100644 (file)
@@ -78,7 +78,9 @@ void unlink_armature(struct bArmature *arm);
 void free_armature(struct bArmature *arm);
 void make_local_armature(struct bArmature *arm);
 struct bArmature *copy_armature(struct bArmature *arm);
+
 void bone_flip_name (char *name, int strip_number);
+void bone_autoside_name (char *name, int strip_number, short axis, float head, float tail);
 
 struct bArmature *get_armature (struct Object *ob);
 struct Bone *get_named_bone (struct bArmature *arm, const char *name);
index 9ee4e62b9cb1d3d61d90e86f0cd297c6b687cc0e..94a968970fabafd5f6395e727d1f06bca19906a8 100644 (file)
@@ -2479,7 +2479,7 @@ static void mesh_build_data(Object *ob, CustomDataMask dataMask)
                        CustomData_free_layer_active(&me->fdata, CD_MCOL, me->totface);
                } else {
                        mesh_calc_modifiers(ob, NULL, &ob->derivedDeform,
-                                           &ob->derivedFinal, 0, 1,
+                                           &ob->derivedFinal, G.rendering, 1,
                                            needMapping, dataMask);
                }
 
index f4da821e3eae046d96f5516db763d5faf90f8252..28a5430a5b3980daa1a9b8fac3b7e0b8eb3b271d 100644 (file)
@@ -30,6 +30,8 @@
 #include <math.h>
 #include <string.h>
 #include <stdio.h>
+#include <float.h>
+
 #include "MEM_guardedalloc.h"
 
 #include "nla.h"
@@ -354,6 +356,88 @@ void bone_flip_name (char *name, int strip_number)
        sprintf (name, "%s%s%s%s", prefix, replace, suffix, number);
 }
 
+/* Finds the best possible extension to the name on a particular axis. (For renaming, check for unique names afterwards)
+ * This assumes that bone names are at most 32 chars long!
+ *     strip_number: removes number extensions  (TODO: not used)
+ *     axis: the axis to name on
+ *     head/tail: the head/tail co-ordinate of the bone on the specified axis
+ */
+void bone_autoside_name (char *name, int strip_number, short axis, float head, float tail)
+{
+       int             len;
+       char    basename[32]={""};
+       char    extension[3]={""};
+
+       len= strlen(name);
+       if (len == 0) return;
+       strcpy(basename, name);
+       
+       /* Figure out extension to append: 
+        *      - The extension to append is based upon the axis that we are working on.
+        *      - If head happens to be on 0, then we must consider the tail position as well to decide
+        *        which side the bone is on
+        *              -> If tail is 0, then it's bone is considered to be on axis, so no extension should be added
+        *              -> Otherwise, extension is added from perspective of object based on which side tail goes to
+        *      - If head is non-zero, extension is added from perspective of object based on side head is on
+        */
+       if (axis == 2) {
+               /* z-axis - vertical (top/bottom) */
+               if (IS_EQ(head, 0)) {
+                       if (tail < 0)
+                               strcpy(extension, ".Bot");
+                       else if (tail > 0)
+                               strcpy(extension, ".Top");
+               }
+               else {
+                       if (head < 0)
+                               strcpy(extension, ".Bot");
+                       else
+                               strcpy(extension, ".Top");
+               }
+       }
+       else if (axis == 1) {
+               /* y-axis - depth (front/back) */
+               if (IS_EQ(head, 0)) {
+                       if (tail < 0)
+                               strcpy(extension, ".Fr");
+                       else if (tail > 0)
+                               strcpy(extension, ".Bk");
+               }
+               else {
+                       if (head < 0)
+                               strcpy(extension, ".Fr");
+                       else
+                               strcpy(extension, ".Bk");
+               }
+       }
+       else {
+               /* x-axis - horizontal (left/right) */
+               if (IS_EQ(head, 0)) {
+                       if (tail < 0)
+                               strcpy(extension, ".R");
+                       else if (tail > 0)
+                               strcpy(extension, ".L");
+               }
+               else {
+                       if (head < 0)
+                               strcpy(extension, ".R");
+                       else if (head > 0)
+                               strcpy(extension, ".L");
+               }
+       }
+
+       /* Simple name truncation 
+        *      - truncate if there is an extension and it wouldn't be able to fit
+        *      - otherwise, just append to end (TODO: this should really check if there was already a tag there, and remove it)
+        */
+       if (extension[0]) {
+               if ((32 - len) < strlen(extension)) {
+                       strncpy(name, basename, len-strlen(extension));
+               }
+       }
+
+       sprintf(name, "%s%s", basename, extension);
+}
 
 /* ************* B-Bone support ******************* */
 
index 3db42f091d4267c16c53ee6c66bf8b165d77419d..c0ffb7c62f857ed2e2b154777f1f6f7bd257efcb 100644 (file)
@@ -780,6 +780,21 @@ void *exec_distribution(void *data)
        return 0;
 }
 
+/* not thread safe, but qsort doesn't take userdata argument */
+static int *COMPARE_ORIG_INDEX = NULL;
+static int 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];
+
+       if(index1 < index2)
+               return -1;
+       else if(index1 == index2)
+               return 0;
+       else
+               return 1;
+}
+
 /* creates a distribution of coordinates on a DerivedMesh      */
 /*                                                                                                                     */
 /* 1. lets check from what we are emitting                                     */
@@ -1157,6 +1172,13 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm
 
        MEM_freeN(sum);
 
+       /* for hair, sort by origindex, allows optimizations in rendering */
+       if(part->type == PART_HAIR) {
+               COMPARE_ORIG_INDEX= dm->getFaceDataArray(dm, CD_ORIGINDEX);
+               if(COMPARE_ORIG_INDEX)
+                       qsort(index, totpart, sizeof(int), compare_orig_index);
+       }
+
        /* weights are no longer used except for FROM_PARTICLE, which needs them zeroed for indexing */
        if(from==PART_FROM_PARTICLE){
                for(i=0; i<tot; i++)
index 4feb8c00659d5f76f398f757b9911c1817335b08..f6c5264efc41106e39160daeccb63c3e3a745b1a 100644 (file)
@@ -3436,6 +3436,8 @@ static void direct_link_scene(FileData *fd, Scene *sce)
                        if(seq->strip && seq->strip->done==0) {
                                seq->strip->done= 1;
                                seq->strip->tstripdata = 0;
+                               seq->strip->tstripdata_startstill = 0;
+                               seq->strip->tstripdata_endstill = 0;
 
                                if(seq->type == SEQ_IMAGE ||
                                   seq->type == SEQ_MOVIE ||
index 3cbada812b9da8868c155f55b1f748bd24465544..b124cb2f80cdef9fcc02205e530b63755b86a305 100644 (file)
@@ -547,9 +547,14 @@ void IMB_exrtile_write_channels(void *handle, int partx, int party)
        }
        
        data->tofile->setFrameBuffer (frameBuffer);
-       // printf("write tile %d %d\n", partx/data->tilex, party/data->tiley);
-       data->tofile->writeTile (partx/data->tilex, party/data->tiley); 
-       
+
+       try {
+               // printf("write tile %d %d\n", partx/data->tilex, party/data->tiley);
+               data->tofile->writeTile (partx/data->tilex, party/data->tiley); 
+       }
+       catch (const std::exception &exc) {
+               std::cerr << "OpenEXR-writeTile: ERROR: " << exc.what() << std::endl;
+       }
 }
 
 void IMB_exr_write_channels(void *handle)
index 1753f4ecf4274538f291a4f00b5d4781e46915a2..72b3de1e54d61bb25e059fe307290afabe66164c 100644 (file)
@@ -68,6 +68,12 @@ typedef struct ActKeyBlock {
 } ActKeyBlock;
 
 
+/* Inclusion-Range Limiting Struct (optional) */
+typedef struct ActKeysInc {
+       struct Object *ob;                              /* if present, used to find action-scaled time */
+       float start, end;                               /* frames (global-time) to only consider keys between */
+} ActKeysInc;
+
 /* ******************************* Methods ****************************** */
 
 /* Action Generics */
@@ -81,11 +87,11 @@ void draw_action_channel(struct gla2DDrawInfo *di, struct bAction *act, float yp
 void draw_object_channel(struct gla2DDrawInfo *di, struct Object *ob, float ypos);
 
 /* Keydata Generation */
-void icu_to_keylist(struct IpoCurve *icu, ListBase *keys, ListBase *blocks);
-void ipo_to_keylist(struct Ipo *ipo, ListBase *keys, ListBase *blocks);
-void agroup_to_keylist(struct bActionGroup *agrp, ListBase *keys, ListBase *blocks);
-void action_to_keylist(struct bAction *act, ListBase *keys, ListBase *blocks);
-void ob_to_keylist(struct Object *ob, ListBase *keys, ListBase *blocks);
+void icu_to_keylist(struct IpoCurve *icu, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+void ipo_to_keylist(struct Ipo *ipo, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+void agroup_to_keylist(struct bActionGroup *agrp, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+void action_to_keylist(struct bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
+void ob_to_keylist(struct Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki);
 
 #endif  /*  BDR_DRAWACTION_H */
 
index 8cf63a005cb92a47ab35b90009e16738baaa3eb3..cc34cb58ae394c963a99428419ab2e6fd79db155 100644 (file)
@@ -128,6 +128,7 @@ int         bone_looper(struct Object *ob, struct Bone *bone, void *data,
 void   undo_push_armature(char *name);
 void   armature_bone_rename(struct bArmature *arm, char *oldname, char *newname);
 void   armature_flip_names(void);
+void   armature_autoside_names(short axis);
 EditBone *armature_bone_get_mirrored(EditBone *ebo);
 void   transform_armature_mirror_update(void);
 
index 62b850f9094d38ce5e667c294bf461ceb9855624..84deb134be9cf56d9537a6509f3abe5170d40856 100644 (file)
@@ -50,6 +50,7 @@ void del_defgroup (struct Object *ob);
 void duplicate_defgroup ( struct Object *ob );
 void assign_verts_defgroup (void);
 void remove_verts_defgroup (int allverts);
+void remove_verts_defgroups (int allverts);
 void sel_verts_defgroup (int select);
 
 struct MDeformWeight *get_defweight (struct MDeformVert *dv, int defgroup);
index c0e28d7b1f11de62e909cba210b73ff7cbd4afd7..aba2430fe1fa36b85d6a16e0d7c5ffba6f47637c 100644 (file)
@@ -65,7 +65,6 @@ void aspect_sima(struct SpaceImage *sima, float *x, float *y);
 void select_invert_tface_uv(void);
 void select_swap_tface_uv(void);
 void mirrormenu_tface_uv(void);
-void mirror_tface_uv(char mirroraxis);
 void hide_tface_uv(int swap);
 void reveal_tface_uv(void);
 void stitch_limit_uv_tface(void);
index f356c9d664cb9a06d385ca6b98807f19ca5f1024..3aa4413e9f94ca39564dc58bc00c3a7d5a3c45a1 100644 (file)
@@ -73,6 +73,7 @@ void pose_recalculate_paths(struct Object *ob);
 void pose_clear_paths(struct Object *ob);
 
 void pose_flip_names(void);
+void pose_autoside_names(short axis);
 void pose_activate_flipped_bone(void);
 void pose_movetolayer(void);
 void pose_relax(void);
index 11691cfbd23a952065c3200669dc2cdeb2eeb8f7..99a7930ddb18bacc6a26251d877033ed473fbdc5 100644 (file)
@@ -157,7 +157,7 @@ void mirror_ipo_keys(struct Ipo *ipo, short mirror_mode);
 void setipotype_ipo(struct Ipo *ipo, int code);
 void set_ipo_key_selection(struct Ipo *ipo, int sel);
 int is_ipo_key_selected(struct Ipo *ipo);
-void delete_icu_key(struct IpoCurve *icu, int index);
+void delete_icu_key(struct IpoCurve *icu, int index, short do_recalc);
 void delete_ipo_keys(struct Ipo *ipo);
 int fullselect_ipo_keys(struct Ipo *ipo);
 int add_trans_ipo_keys(struct Ipo *ipo, struct TransVert *tv, int tvtot);
index 48e840a7128dde94e315ebe29852a21f6d8c7282..8f6d9bd75c75bc56eb47599fbe151927e7c99eb3 100644 (file)
@@ -473,6 +473,10 @@ char handleNumInput(NumInput *n, unsigned short event);
 int manageObjectSpace(int confirm, int set);
 int manageMeshSpace(int confirm, int set);
 
+/* Those two fill in mat and return non-zero on success */
+int createSpaceNormal(float mat[3][3], float normal[3]);
+int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]);
+
 int addMatrixSpace(float mat[3][3], char name[]);
 int addObjectSpace(struct Object *ob);
 void applyTransformOrientation(void);
index 977abaffeb49bac2b6cdc3e8aac857d3117b79a3..15e88ea0b8644253edc3867cbbd64a8a83ad84ad 100644 (file)
@@ -219,7 +219,9 @@ typedef enum SACTION_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)
+       SACTION_NOHIDE = (1<<3),
+               /* don't kill overlapping keyframes after transform */
+       SACTION_NOTRANSKEYCULL = (1<<4)
 } SACTION_FLAG;        
 
 /* SpaceAction AutoSnap Settings (also used by SpaceNLA) */
index 8bdea93b1f416505ff9e1338fbfa963bb0dfe042..7f2ea6cbeaa8bc863cc42e2d2428ac0b6f5dceda 100644 (file)
@@ -589,8 +589,9 @@ typedef struct Scene {
 #define R_EXR_TILE_FILE                0x0400
 #define R_COMP_FREE                    0x0800
 #define R_NO_IMAGE_LOAD                0x1000
-#define R_NO_TEX               0x2000
+#define R_NO_TEX                       0x2000
 #define R_STAMP_INFO           0x4000
+#define R_FULL_SAMPLE          0x8000
 
 /* r->stamp */
 #define R_STAMP_TIME   0x0001
index 066e23ca984c66d10716744a774790dfa29393b8..6798e726ce802ac206a5c92ffed21daf1ae9f15b 100644 (file)
@@ -79,6 +79,7 @@ typedef struct StripProxy {
 typedef struct Strip {
        struct Strip *next, *prev;
        int rt, len, us, done;
+       int startstill, endstill;
        StripElem *stripdata;
        char dir[160];
        int orx, ory;
@@ -86,6 +87,8 @@ typedef struct Strip {
        StripTransform *transform;
        StripProxy *proxy;
        TStripElem *tstripdata;
+       TStripElem *tstripdata_startstill;
+       TStripElem *tstripdata_endstill;
 } Strip;
 
 
@@ -157,6 +160,9 @@ typedef struct Sequence {
 
        int blend_mode;
        float blend_opacity;
+
+       int scenenr;          /* for scene selection */
+       int pad;
 } Sequence;
 
 typedef struct MetaStack {
index 53d01ab1d12152e1d14a3abbc3e43b798aa79f47..a7db8c2d53dd33d3475a99679f24c62001eb8ec3 100644 (file)
@@ -376,8 +376,10 @@ static void defocus_blur(bNode *node, CompBuf *new, CompBuf *img, CompBuf *zbuf,
                // some sort of visual feedback would be nice, or at least this text in the renderwin header
                // but for now just print some info in the console every 8 scanlines.
                if (((y & 7)==0) || (y==(img->y-1))) {
-                       printf("\rdefocus: Processing Line %d of %d ... ", y+1, img->y);
-                       fflush(stdout);
+                       if(G.background==0) {
+                               printf("\rdefocus: Processing Line %d of %d ... ", y+1, img->y);
+                               fflush(stdout);
+                       }
                }
                // esc set by main calling process
                if(node->exec & NODE_BREAK)
index abb9fa98d9769c067de1617c153f50080b547bd9..a40579ac3b2fceebc7763a99d063fa5e2b751d5f 100644 (file)
@@ -63,8 +63,25 @@ static void do_idmask(CompBuf *stackbuf, CompBuf *cbuf, float idnr)
        MEM_freeN(abuf);
 }
 
+/* full sample version */
+static void do_idmask_fsa(CompBuf *stackbuf, CompBuf *cbuf, float idnr)
+{
+       float *rect, *rs;
+       int x;
+       
+       rect= cbuf->rect;
+       rs= stackbuf->rect;
+       for(x= cbuf->x*cbuf->y - 1; x>=0; x--)
+               if(rect[x]==idnr)
+                       rs[x]= 1.0f;
+       
+}
+
+
 static void node_composit_exec_idmask(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
 {
+       RenderData *rd= data;
+       
        if(out[0]->hasoutput==0)
                return;
        
@@ -77,7 +94,10 @@ static void node_composit_exec_idmask(void *data, bNode *node, bNodeStack **in,
                
                stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */;
                
-               do_idmask(stackbuf, cbuf, (float)node->custom1);
+               if(rd->scemode & R_FULL_SAMPLE)
+                       do_idmask_fsa(stackbuf, cbuf, (float)node->custom1);
+               else
+                       do_idmask(stackbuf, cbuf, (float)node->custom1);
                
                out[0]->data= stackbuf;
        }
index 29cf8f34d548a7138442bd02914e70eec88de1d2..eb9391006446679bc6c4ea31aededd60ffd567ae 100644 (file)
@@ -45,6 +45,16 @@ static bNodeSocketType cmp_node_zcombine_out[]= {
        {       -1, 0, ""       }
 };
 
+static void do_zcombine(bNode *node, float *out, float *src1, float *z1, float *src2, float *z2)
+{
+       if(*z1 <= *z2) {
+               QUATCOPY(out, src1);
+       }
+       else {
+               QUATCOPY(out, src2);
+       }
+}
+
 static void do_zcombine_mask(bNode *node, float *out, float *z1, float *z2)
 {
        if(*z1 > *z2) {
@@ -67,6 +77,8 @@ static void do_zcombine_add(bNode *node, float *out, float *col1, float *col2, f
 
 static void node_composit_exec_zcombine(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
 {
+       RenderData *rd= data;
+       
        /* stack order in: col z col z */
        /* stack order out: col z */
        if(out[0]->hasoutput==0) 
@@ -76,6 +88,16 @@ static void node_composit_exec_zcombine(void *data, bNode *node, bNodeStack **in
        if(in[0]->data==NULL) {
                return;
        }
+       else if(rd->scemode & R_FULL_SAMPLE) {
+               /* make output size of first input image */
+               CompBuf *cbuf= in[0]->data;
+               CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs
+               
+               composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, 
+                                                                 in[3]->data, in[3]->vec, do_zcombine, CB_RGBA, CB_VAL, CB_RGBA, CB_VAL);
+               
+               out[0]->data= stackbuf;
+       }
        else {
                /* make output size of first input image */
                CompBuf *cbuf= in[0]->data;
index 3605c956a585144714a42f9c58e9f6fe6149ca72..65ae46ffccd8f641b9160094c7aeb9b8b5925bb0 100644 (file)
@@ -500,10 +500,7 @@ PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args)
        }
        dot /= (sqrt(test_v1) * sqrt(test_v2));
 
-       if (dot < -1.0f || dot > 1.0f) {
-               CLAMP(dot,-1.0f,1.0f);
-       }
-       angleRads = (double)acos(dot);
+       angleRads = (double)saacos(dot);
 
        return PyFloat_FromDouble(angleRads * (180/ Py_PI));
 
index 3793db47686cd5c125b7c07e54134635bb7f3ca4..a4a99c28d72c7e4cc18d9b39d7ff7b221e699c4f 100644 (file)
@@ -184,13 +184,13 @@ static PyObject *Quaternion_getattr(QuaternionObject * self, char *name)
        }
        if(STREQ(name, "angle")) {
                mag = self->quat[0];
-               mag = 2 * (acos(mag));
+               mag = 2 * (saacos(mag));
                mag *= (180 / Py_PI);
                return PyFloat_FromDouble(mag);
        }
        if(STREQ(name, "axis")) {
                mag = self->quat[0] * (Py_PI / 180);
-               mag = 2 * (acos(mag));
+               mag = 2 * (saacos(mag));
                mag = sin(mag / 2);
                for(x = 0; x < 3; x++) {
                        vec[x] = (float)(self->quat[x + 1] / mag);
index f5861995073fe500b4d6cb18a56033256b2a99b8..1e0997630a197ace017efa8f5a773235b5c0e7d3 100644 (file)
@@ -33,12 +33,16 @@ struct View3D; /* keep me up here */
 
 #include "sceneRender.h" /*This must come first*/
 
+#include "MEM_guardedalloc.h"
+                                
 #include "DNA_image_types.h"
+#include "DNA_node_types.h"
 
 #include "BKE_image.h"
 #include "BKE_global.h"
 #include "BKE_screen.h"
 #include "BKE_scene.h"
+#include "BKE_node.h"
 
 #include "BIF_drawscene.h"
 #include "BIF_renderwin.h"
@@ -52,8 +56,10 @@ struct View3D; /* keep me up here */
 #include "butspace.h"
 #include "blendef.h"
 #include "gen_utils.h"
+#include "gen_library.h"
 
 #include "Scene.h"
+#include "Group.h"
 
 /* local defines */
 #define PY_NONE                     0
@@ -1758,6 +1764,67 @@ static PyObject *RenderData_getTimeCode( BPy_RenderData * self) {
        return PyString_FromString(tc);
 }            
 
+
+/***************************************************************************/
+/* Render layer functions                                                  */
+/***************************************************************************/
+PyObject *RenderData_getRenderLayers(BPy_RenderData * self)
+{
+       PyObject *list, *layer;
+       SceneRenderLayer *srl;
+       
+       list = PyList_New(0);
+       
+       for(srl= self->renderContext->layers.first; srl; srl= srl->next) {      
+               layer = RenderLayer_CreatePyObject( self->scene, srl );
+               PyList_Append(list, layer);
+               Py_DECREF(layer);
+       }
+       return list;
+}
+
+PyObject *RenderData_removeRenderLayer(BPy_RenderData * self, BPy_RenderLayer *value)
+{
+       int index;
+       if (!BPy_RenderLayer_Check(value))
+               return EXPP_ReturnPyObjError( PyExc_TypeError,
+                       "can only remove a render layer" );
+       
+       index = BLI_findindex(&self->renderContext->layers, value->renderLayer);
+       
+       if (index == -1)
+               return EXPP_ReturnPyObjError( PyExc_ValueError,
+                       "render layer is not in this scene" );
+       
+       if (BLI_countlist(&self->renderContext->layers)<=1)
+               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                       "cannot remove the last render layer" );
+       
+       BLI_remlink(&self->scene->r.layers, value->renderLayer);
+       MEM_freeN(value->renderLayer);
+       self->scene->r.actlay= 0;
+       
+       if(self->scene->nodetree) {
+               bNode *node;
+               for(node= self->scene->nodetree->nodes.first; node; node= node->next) {
+                       if(node->type==CMP_NODE_R_LAYERS && node->id==NULL) {
+                               if(node->custom1==index)
+                                       node->custom1= 0;
+                               else if(node->custom1 > index)
+                                       node->custom1--;
+                       }
+               }
+       }
+       
+       value->renderLayer = NULL;
+}
+
+PyObject *RenderData_addRenderLayer(BPy_RenderData * self ) {
+       scene_add_render_layer(self->scene);
+       return RenderLayer_CreatePyObject( self->scene, self->renderContext->layers.last );
+       
+}
+
 /***************************************************************************/
 /* generic handlers for getting/setting attributes                         */
 /***************************************************************************/
@@ -2631,11 +2698,16 @@ static PyGetSetDef BPy_RenderData_getseters[] = {
         "Scene link 'set' value",
         NULL},
 
+       /* renderlayers */
        {"activeLayer",
         (getter)RenderData_getActiveLayer, (setter)RenderData_setActiveLayer,
         "Active rendering layer",
         NULL},
-
+       {"renderLayers",
+        (getter)RenderData_getRenderLayers, (setter)NULL,
+        "Active rendering layer",
+        NULL},
+  
        {"halfFloat",
      (getter)RenderData_getSubImTypeBits, (setter)RenderData_setSubImTypeBits,
      "'Half' openexr option enabled",
@@ -2960,6 +3032,11 @@ static PyMethodDef BPy_RenderData_methods[] = {
         "(int) - get/set specify old map value in frames"},
        {"newMapValue", ( PyCFunction ) RenderData_NewMapValue, METH_VARARGS,
         "(int) - get/set specify new map value in frames"},
+  /* renderlayers */
+       {"addRenderLayer", ( PyCFunction ) RenderData_addRenderLayer, METH_VARARGS,
+        "(string) - add a new render layer"},
+       {"removeRenderLayer", ( PyCFunction ) RenderData_removeRenderLayer, METH_O,
+        "(renderLayer) - remove a render layer from this scene"},
        {NULL, NULL, 0, NULL}
 };
  
@@ -3046,6 +3123,470 @@ PyTypeObject RenderData_Type = {
        NULL
 };
 
+
+
+
+/* render layers */
+
+static PyObject *RenderLayer_repr( BPy_RenderLayer * self )
+{
+       if( self->renderLayer )
+               return PyString_FromFormat( "[RenderLayer \"%s\"]",
+                                           self->renderLayer->name  );
+       else
+               return PyString_FromString( "NULL" );
+}
+
+static PyObject *RenderLayer_getName( BPy_RenderLayer * self )
+{
+       if( !self->renderLayer )
+               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                               "This render layer has been removed!" );
+       
+       return PyString_FromString( self->renderLayer->name );
+}
+
+static int RenderLayer_setName( BPy_RenderLayer * self, PyObject *value )
+{
+       char *name = NULL;
+       int index = BLI_findindex(&self->scene->r.layers, self->renderLayer);
+       
+       if( !self->renderLayer )
+               return EXPP_ReturnIntError( PyExc_RuntimeError,
+                               "This render layer has been removed!" );
+       
+       name = PyString_AsString ( value );
+       if( !name )
+               return EXPP_ReturnIntError( PyExc_TypeError,
+                                             "expected string argument" );
+       
+       /* No check for doubles? - blender dosnt so we dont have to! */
+       BLI_strncpy( self->renderLayer->name, name, sizeof( self->renderLayer->name ) );
+       
+       if(self->scene->nodetree) {
+               bNode *node;
+               for(node= self->scene->nodetree->nodes.first; node; node= node->next) {
+                       if(node->type==CMP_NODE_R_LAYERS && node->id==NULL) {
+                               if(node->custom1==index)
+                                       BLI_strncpy(node->name, self->renderLayer->name, NODE_MAXSTR);
+                       }
+               }
+       }
+       
+       return 0;
+}
+
+static PyObject *RenderLayer_getLightGroup( BPy_RenderLayer * self )
+{
+       if( !self->renderLayer )
+               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                               "This render layer has been removed!" );
+       return Group_CreatePyObject( self->renderLayer->light_override );
+}
+static int RenderLayer_setLightGroup( BPy_RenderLayer * self, PyObject * value )
+{
+       if( !self->renderLayer )
+               return EXPP_ReturnIntError( PyExc_RuntimeError,
+                               "This render layer has been removed!" );
+       return GenericLib_assignData(value, (void **) &self->renderLayer->light_override, NULL, 1, ID_GR, 0);
+}
+
+
+/*****************************************************************************/
+/* Python BPy_Render getsetattr funcs:                                       */
+/*****************************************************************************/
+static int RenderLayer_setLayers( BPy_RenderLayer * self, PyObject * value, void *zlay )
+{
+       unsigned int laymask = 0;
+       
+       if( !self->renderLayer )
+               return EXPP_ReturnIntError( PyExc_RuntimeError,
+                               "This render layer has been removed!" );
+       
+       if( !PyInt_Check( value ) )
+               return EXPP_ReturnIntError( PyExc_TypeError,
+                       "expected an integer (bitmask) as argument" );
+       
+       laymask = ( unsigned int )PyInt_AS_LONG( value );
+       
+       if((laymask < 0) ||  (!zlay && laymask == 0))
+               return EXPP_ReturnIntError( PyExc_ValueError,
+                                             "layer value too low" );
+       
+       if (zlay) {
+               self->renderLayer->lay_zmask= laymask & ((1<<20) - 1);
+       } else {
+               self->renderLayer->lay= laymask & ((1<<20) - 1);
+       }
+       return 0;
+}
+
+static PyObject *RenderLayer_getLayers( BPy_RenderLayer * self, void *zlay )
+{
+       if (zlay) {
+               return PyInt_FromLong( self->renderLayer->lay_zmask );
+       } else {
+               return PyInt_FromLong( self->renderLayer->lay );
+       }
+}
+
+static PyObject *RenderLayer_getLayflagBits( BPy_RenderLayer *self, void *type )
+{
+       int itype = (int)type;
+       if( !self->renderLayer )
+               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                               "This render layer has been removed!" );
+       
+       /* use negative numbers to flip truth */
+       if (self->renderLayer->lay & itype)     Py_RETURN_TRUE;
+       else                                                            Py_RETURN_FALSE;
+}
+
+static int RenderLayer_setLayflagBits( BPy_RenderLayer *self, PyObject *value,
+               void *type )
+{
+       /* use negative numbers to flip truth */
+       int param = PyObject_IsTrue( value );
+               
+       if( !self->renderLayer )
+               return EXPP_ReturnIntError( PyExc_RuntimeError,
+                               "This render layer has been removed!" );
+       
+       if( param == -1 )
+               return EXPP_ReturnIntError( PyExc_TypeError,
+                               "expected True/False or 0/1" );
+       
+       if (param) {
+               self->renderLayer->lay |= (int)type;
+       } else {
+               self->renderLayer->lay &= ~(int)type;
+       }
+       return 0;
+}
+
+static PyObject *RenderLayer_getPassBits( BPy_RenderLayer *self, void *type )
+{
+       int itype = (int)type;
+       if( !self->renderLayer )
+               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                               "This render layer has been removed!" );
+       
+       /* use negative numbers to flip truth */
+       if (self->renderLayer->passflag & itype)        Py_RETURN_TRUE;
+       else                                                                            Py_RETURN_FALSE;
+}
+
+static int RenderLayer_setPassBits( BPy_RenderLayer *self, PyObject *value,
+               void *type )
+{
+       /* use negative numbers to flip truth */
+       int param = PyObject_IsTrue( value );
+               
+       if( !self->renderLayer )
+               return EXPP_ReturnIntError( PyExc_RuntimeError,
+                               "This render layer has been removed!" );
+       
+       if( param == -1 )
+               return EXPP_ReturnIntError( PyExc_TypeError,
+                               "expected True/False or 0/1" );
+       
+       if (param) {
+               self->renderLayer->passflag |= ((int)type);
+       } else {
+               self->renderLayer->passflag &= ~((int)type);
+       }
+       return 0;
+}
+
+static PyObject *RenderLayer_getPassXorBits( BPy_RenderLayer *self, void *type )
+{
+       if( !self->renderLayer )
+               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                               "This render layer has been removed!" );
+       
+       /* use negative numbers to flip truth */
+       if (self->renderLayer->pass_xor & (int)type)    Py_RETURN_TRUE;
+       else                                                                            Py_RETURN_FALSE;
+}
+
+static int RenderLayer_setPassXorBits( BPy_RenderLayer *self, PyObject *value,
+               void *type )
+{
+       int param = PyObject_IsTrue( value );
+               
+       if( !self->renderLayer )
+               return EXPP_ReturnIntError( PyExc_RuntimeError,
+                               "This render layer has been removed!" );
+       
+       if( param == -1 )
+               return EXPP_ReturnIntError( PyExc_TypeError,
+                               "expected True/False or 0/1" );
+       
+       if (param) {
+               self->renderLayer->passflag |= (int)type;
+       } else {
+               self->renderLayer->passflag &= ~(int)type;
+       }
+       return 0;
+}
+
+/***************************************************************************/
+/* BPy_RenderData attribute def                                            */
+/***************************************************************************/
+static PyGetSetDef BPy_RenderLayer_getseters[] = {
+       {"name",
+        (getter)RenderLayer_getName, (setter)RenderLayer_setName,
+        "",
+        (void *)NULL},
+       {"lightGroup",
+        (getter)RenderLayer_getLightGroup, (setter)RenderLayer_setLightGroup,
+        "",
+        (void *)NULL},
+       /*{"material",
+        (getter)RenderLayer_getMaterial, (setter)RenderLayer_setMaterial,
+        "",
+        (void *)NULL},*/
+       {"enable",
+        (getter)RenderLayer_getLayflagBits, (setter)RenderLayer_setLayflagBits,
+        "enable this render layer",
+        (void *)SCE_LAY_DISABLE},
+       {"enableZMask",
+        (getter)RenderLayer_getLayflagBits, (setter)RenderLayer_setLayflagBits,
+        "Only render what's in front of the solid z values",
+        (void *)SCE_LAY_ZMASK},
+       {"enableZMaskAll",
+        (getter)RenderLayer_getLayflagBits, (setter)RenderLayer_setLayflagBits,
+        "Fill in Z values for solid faces in invisible layers, for masking",
+        (void *)SCE_LAY_ALL_Z},
+         
+       {"enableSolid",
+        (getter)RenderLayer_getLayflagBits, (setter)RenderLayer_setLayflagBits,
+        "Render Solid faces in this Layer",
+        (void *)SCE_LAY_SOLID},
+       {"enableZTra",
+        (getter)RenderLayer_getLayflagBits, (setter)RenderLayer_setLayflagBits,
+        "Render Z-Transparent faces in this Layer (On top of Solid and Halos)",
+        (void *)SCE_LAY_ZTRA},
+       {"enableHalo",
+        (getter)RenderLayer_getLayflagBits, (setter)RenderLayer_setLayflagBits,
+        "Render Halos in this Layer (on top of Solid)",
+        (void *)SCE_LAY_HALO},
+       {"enableEdge",
+        (getter)RenderLayer_getLayflagBits, (setter)RenderLayer_setLayflagBits,
+        "Render Edge-enhance in this Layer (only works for Solid faces)",
+        (void *)SCE_LAY_EDGE},
+       {"enableSky",
+        (getter)RenderLayer_getLayflagBits, (setter)RenderLayer_setLayflagBits,
+        "Render Sky or backbuffer in this Layer",
+        (void *)SCE_LAY_SKY},
+       {"enableStrand",
+        (getter)RenderLayer_getLayflagBits, (setter)RenderLayer_setLayflagBits,
+        "Render Strands in this Layer",
+        (void *)SCE_LAY_STRAND},
+
+       {"layerMask",
+        (getter)RenderLayer_getLayers, (setter)RenderLayer_setLayers,
+        "",
+        (void *)0},
+       {"zLayerMask",
+        (getter)RenderLayer_getLayers, (setter)RenderLayer_setLayers,
+        "",
+        (void *)1},
+         
+       /* passes */
+       {"passCombined",
+        (getter)RenderLayer_getPassBits, (setter)RenderLayer_setPassBits,
+        "Deliver full combined RGBA buffer",
+        (void *)SCE_PASS_COMBINED},
+       {"passZ",
+        (getter)RenderLayer_getPassBits, (setter)RenderLayer_setPassBits,
+        "Deliver Z values pass",
+        (void *)SCE_PASS_Z},
+       {"passSpeed",
+        (getter)RenderLayer_getPassBits, (setter)RenderLayer_setPassBits,
+        "Deliver Speed Vector pass",
+        (void *)SCE_PASS_VECTOR},
+       {"passNormal",
+        (getter)RenderLayer_getPassBits, (setter)RenderLayer_setPassBits,
+        "Deliver Normal pass",
+        (void *)SCE_PASS_NORMAL},
+       {"passUV",
+        (getter)RenderLayer_getPassBits, (setter)RenderLayer_setPassBits,
+        "Deliver Texture UV pass",
+        (void *)SCE_PASS_UV},
+       {"passMist",
+        (getter)RenderLayer_getPassBits, (setter)RenderLayer_setPassBits,
+        "Deliver Mist factor pass (0-1)",
+        (void *)SCE_PASS_MIST},
+       {"passIndex",
+        (getter)RenderLayer_getPassBits, (setter)RenderLayer_setPassBits,
+        "Deliver Object Index pass",
+        (void *)SCE_PASS_INDEXOB},
+       {"passColor",
+        (getter)RenderLayer_getPassBits, (setter)RenderLayer_setPassBits,
+        "Deliver shade-less Color pass",
+        (void *)SCE_PASS_RGBA},
+       {"passDiffuse",
+        (getter)RenderLayer_getPassBits, (setter)RenderLayer_setPassBits,
+        "Deliver Diffuse pass",
+        (void *)SCE_PASS_DIFFUSE},
+       {"passSpecular",
+        (getter)RenderLayer_getPassBits, (setter)RenderLayer_setPassBits,
+        "Deliver Specular pass",
+        (void *)SCE_PASS_SPEC},
+       {"passShadow",
+        (getter)RenderLayer_getPassBits, (setter)RenderLayer_setPassBits,
+        "Deliver Shadow pass",
+        (void *)SCE_PASS_SHADOW},
+       {"passAO",
+        (getter)RenderLayer_getPassBits, (setter)RenderLayer_setPassBits,
+        "Deliver AO pass",
+        (void *)SCE_PASS_AO},
+       {"passReflect",
+        (getter)RenderLayer_getPassBits, (setter)RenderLayer_setPassBits,
+        "Deliver Raytraced Reflection pass",
+        (void *)SCE_PASS_REFLECT},
+       {"passRefract",
+        (getter)RenderLayer_getPassBits, (setter)RenderLayer_setPassBits,
+        "Deliver Raytraced Reflection pass",
+        (void *)SCE_PASS_REFRACT},
+       {"passRadiosiy",
+        (getter)RenderLayer_getPassBits, (setter)RenderLayer_setPassBits,
+        "Deliver Radiosity pass",
+        (void *)SCE_PASS_RADIO},
+       
+       /* xor */
+       {"passSpecularXOR",
+        (getter)RenderLayer_getPassBits, (setter)RenderLayer_setPassBits,
+        "Deliver Specular pass XOR",
+        (void *)SCE_PASS_SPEC},
+       {"passShadowXOR",
+        (getter)RenderLayer_getPassBits, (setter)RenderLayer_setPassBits,
+        "Deliver Shadow pass XOR",
+        (void *)SCE_PASS_SHADOW},
+       {"passAOXOR",
+        (getter)RenderLayer_getPassBits, (setter)RenderLayer_setPassBits,
+        "Deliver AO pass XOR",
+        (void *)SCE_PASS_AO},
+       {"passRefractXOR",
+        (getter)RenderLayer_getPassXorBits, (setter)RenderLayer_setPassXorBits,
+        "Deliver Raytraced Reflection pass XOR",
+        (void *)SCE_PASS_REFRACT},
+       {"passRadiosiyXOR",
+        (getter)RenderLayer_getPassXorBits, (setter)RenderLayer_setPassXorBits,
+        "Deliver Radiosity pass XOR",
+        (void *)SCE_PASS_RADIO},
+       
+       {NULL,NULL,NULL,NULL,NULL}
+};
+
+/* no methods */
+
+/*------------------------------------BPy_RenderData Type defintion------ */
+PyTypeObject RenderLayer_Type = {
+       PyObject_HEAD_INIT( NULL )  /* required py macro */
+       0,                          /* ob_size */
+       /*  For printing, in format "<module>.<name>" */
+       "Blender RenderLayer",       /* char *tp_name; */
+       sizeof( BPy_RenderLayer ),   /* int tp_basicsize; */
+       0,                          /* tp_itemsize;  For allocation */
+
+       /* Methods to implement standard operations */
+
+       NULL,                                           /* destructor tp_dealloc; */
+       NULL,                       /* printfunc tp_print; */
+       NULL,                       /* getattrfunc tp_getattr; */
+       NULL,                       /* setattrfunc tp_setattr; */
+       NULL,                       /* cmpfunc tp_compare; */
+       ( reprfunc ) RenderLayer_repr,     /* reprfunc tp_repr; */
+
+       /* Method suites for standard classes */
+
+       NULL,                       /* PyNumberMethods *tp_as_number; */
+       NULL,                       /* PySequenceMethods *tp_as_sequence; */
+       NULL,                       /* PyMappingMethods *tp_as_mapping; */
+
+       /* More standard operations (here for binary compatibility) */
+
+       NULL,                       /* hashfunc tp_hash; */
+       NULL,                       /* ternaryfunc tp_call; */
+       NULL,                       /* reprfunc tp_str; */
+       NULL,                       /* getattrofunc tp_getattro; */
+       NULL,                       /* setattrofunc tp_setattro; */
+
+       /* Functions to access object as input/output buffer */
+       NULL,                       /* PyBufferProcs *tp_as_buffer; */
+
+  /*** Flags to define presence of optional/expanded features ***/
+       Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
+
+       NULL,                       /*  char *tp_doc;  Documentation string */
+  /*** Assigned meaning in release 2.0 ***/
+       /* call function for all accessible objects */
+       NULL,                       /* traverseproc tp_traverse; */
+
+       /* delete references to contained objects */
+       NULL,                       /* inquiry tp_clear; */
+
+  /***  Assigned meaning in release 2.1 ***/
+  /*** rich comparisons ***/
+       NULL,                       /* richcmpfunc tp_richcompare; */
+
+  /***  weak reference enabler ***/
+       0,                          /* long tp_weaklistoffset; */
+
+  /*** Added in release 2.2 ***/
+       /*   Iterators */
+       NULL,                       /* getiterfunc tp_iter; */
+       NULL,                       /* iternextfunc tp_iternext; */
+
+  /*** Attribute descriptor and subclassing stuff ***/
+       NULL,                                           /* struct PyMethodDef *tp_methods; */
+       NULL,                       /* struct PyMemberDef *tp_members; */
+       BPy_RenderLayer_getseters,   /* struct PyGetSetDef *tp_getset; */
+       NULL,                       /* struct _typeobject *tp_base; */
+       NULL,                       /* PyObject *tp_dict; */
+       NULL,                       /* descrgetfunc tp_descr_get; */
+       NULL,                       /* descrsetfunc tp_descr_set; */
+       0,                          /* long tp_dictoffset; */
+       NULL,                       /* initproc tp_init; */
+       NULL,                       /* allocfunc tp_alloc; */
+       NULL,                       /* newfunc tp_new; */
+       /*  Low-level free-memory routine */
+       NULL,                       /* freefunc tp_free;  */
+       /* For PyObject_IS_GC */
+       NULL,                       /* inquiry tp_is_gc;  */
+       NULL,                       /* PyObject *tp_bases; */
+       /* method resolution order */
+       NULL,                       /* PyObject *tp_mro;  */
+       NULL,                       /* PyObject *tp_cache; */
+       NULL,                       /* PyObject *tp_subclasses; */
+       NULL,                       /* PyObject *tp_weaklist; */
+       NULL
+};
+
+/***************************************************************************/
+/* BPy_RenderData Callbacks                                                */
+/***************************************************************************/
+
+PyObject *RenderLayer_CreatePyObject( struct Scene * scene, struct SceneRenderLayer * renderLayer )
+{
+       BPy_RenderLayer *py_renderlayer;
+
+       py_renderlayer =
+               ( BPy_RenderLayer * ) PyObject_NEW( BPy_RenderLayer,
+                                                  &RenderLayer_Type );
+
+       if( py_renderlayer == NULL ) {
+               return ( NULL );
+       }
+       py_renderlayer->renderLayer = renderLayer;
+       py_renderlayer->scene = scene;
+
+       return ( ( PyObject * ) py_renderlayer );
+}
+
+
 /***************************************************************************/
 /* Render method def                                                       */
 /***************************************************************************/
@@ -3130,6 +3671,9 @@ PyObject *Render_Init( void )
        if( PyType_Ready( &RenderData_Type ) < 0 )
                return NULL;
 
+       if( PyType_Ready( &RenderLayer_Type ) < 0 )
+               return NULL;
+       
        submodule = Py_InitModule3( "Blender.Scene.Render",
                                    M_Render_methods, M_Render_doc );
 
index 73bf71f5c066c383327cfcc745f95c5e427497d4..1200bb87af20f62204f1a5c0ff51660b7fadf26b 100644 (file)
 #include <Python.h>
 #include "DNA_scene_types.h"
 
+PyTypeObject RenderLayer_Type;
+
 #define BPy_RenderData_Check(v)       ((v)->ob_type == &RenderData_Type)
+#define BPy_RenderLayer_Check(v)       ((v)->ob_type == &RenderLayer_Type)
 
 //------------------------------------Struct definitions-------
 typedef struct {
        PyObject_HEAD 
        struct RenderData *renderContext;
-       Scene *scene;
+       struct Scene *scene;
 } BPy_RenderData;
+
+typedef struct {
+       PyObject_HEAD 
+       struct SceneRenderLayer *renderLayer; /* this is totally weak, pointer can become invalid */
+       struct Scene *scene;
+} BPy_RenderLayer;
+
 //------------------------------------Visible prototypes-------
 PyObject *Render_Init( void );
 
 PyObject *RenderData_CreatePyObject( struct Scene *scene );
-
+PyObject *RenderLayer_CreatePyObject( struct Scene *scene, struct SceneRenderLayer * renderLayer );
 #endif                         /* EXPP_SCENERENDER_H */
index de12f75300eeed143ca88321a122614d0da7f912..ddfe2c544ab54ffc5db1d4e304cddfde18b0c04e 100644 (file)
@@ -88,10 +88,11 @@ typedef struct RenderLayer {
 } RenderLayer;
 
 typedef struct RenderResult {
+       struct RenderResult *next, *prev;
        
        /* target image size */
        int rectx, recty;
-       short crop, pad;
+       short crop, sample_nr;
        
        /* optional, 32 bits version of picture, used for ogl render and image curves */
        int *rect32;
@@ -113,7 +114,6 @@ typedef struct RenderResult {
        volatile RenderLayer *renlay;
        
        /* optional saved endresult on disk */
-       char exrfile[FILE_MAXDIR];
        void *exrhandle;
        
        /* for render results in Image, verify validity for sequences */
@@ -121,6 +121,7 @@ typedef struct RenderResult {
        
 } RenderResult;
 
+
 typedef struct RenderStats {
        int totface, totvert, totstrand, tothalo, totlamp, totpart;
        short curfield, curblur, curpart, partsdone, convertdone;
index 8b5880ff5070db3138081c258fb7e4e62bff865f..e082225c5ead71c1f4776f4501d0f16b8c3ff02f 100644 (file)
@@ -157,6 +157,7 @@ typedef struct ShadeInput
        
        int xs, ys;                             /* pixel to be rendered */
        int mask;                               /* subsample mask */
+       
        int samplenr;                   /* sample counter, to detect if we should do shadow again */
        int depth;                              /* 1 or larger on raytrace shading */
        
@@ -169,6 +170,7 @@ typedef struct ShadeInput
        /* from initialize, part or renderlayer */
        short do_preview;               /* for nodes, in previewrender */
        short thread, sample;   /* sample: ShadeSample array index */
+       
        unsigned int lay;
        int layflag, passflag, combinedflag;
        struct Group *light_override;
index 16c46ec550feed0a44e328cf5a208874d7d7189c..7b68552e5fb13f7577141f87a89416d7ab95aa8f 100644 (file)
@@ -79,8 +79,8 @@ typedef struct RenderPart
 {
        struct RenderPart *next, *prev;
        
-       /* result of part rendering */
-       RenderResult *result;
+       RenderResult *result;                   /* result of part rendering */
+       ListBase fullresult;                    /* optional full sample buffers */
        
        int *recto;                                             /* object table for objects */
        int *rectp;                                             /* polygon index table */
@@ -113,6 +113,8 @@ struct Render
        RenderResult *result;
        /* if render with single-layer option, other rendered layers are stored here */
        RenderResult *pushedresult;
+       /* a list of RenderResults, for fullsample */
+       ListBase fullresult;    
        
        /* window size, display rect, viewplane */
        int winx, winy;
@@ -174,7 +176,6 @@ struct Render
        ListBase lampren;       /* storage, for free */
        
        ListBase objecttable;
-       struct RenderBuckets *strandbuckets;
 
        struct ObjectInstanceRen *objectinstance;
        ListBase instancetable;
@@ -246,13 +247,15 @@ typedef struct ObjectRen {
        struct Scene *sce;
        int index, psysindex, flag, lay;
 
+       float boundbox[2][3];
+
        int totvert, totvlak, totstrand, tothalo;
        int vertnodeslen, vlaknodeslen, strandnodeslen, blohalen;
        struct VertTableNode *vertnodes;
        struct VlakTableNode *vlaknodes;
        struct StrandTableNode *strandnodes;
        struct HaloRen **bloha;
-       ListBase strandbufs;
+       struct StrandBuffer *strandbuf;
 
        char (*mtface)[32];
        char (*mcol)[32];
@@ -332,6 +335,8 @@ typedef struct HaloRen
     struct Material *mat;
 } HaloRen;
 
+/* ------------------------------------------------------------------------- */
+
 typedef struct StrandVert {
        float co[3];
        float strandco;
@@ -343,16 +348,22 @@ typedef struct StrandSurface {
        int (*face)[4];
        float (*co)[3];
        /* for occlusion caching */
-       float (*col)[3];                                        /* for occlusion */
+       float (*col)[3];
        /* for speedvectors */
        float (*prevco)[3], (*nextco)[3];
        int totvert, totface;
 } StrandSurface;
 
+typedef struct StrandBound {
+       int start, end;
+       float boundbox[2][3];
+} StrandBound;
+
 typedef struct StrandBuffer {
        struct StrandBuffer *next, *prev;
        struct StrandVert *vert;
-       int totvert;
+       struct StrandBound *bound;
+       int totvert, totbound;
 
        struct ObjectRen *obr;
        struct Material *ma;
index f2fae7cca84b7c222ca59a67cedfd08278343221..4ca644c63812294ed4d3cce3d6529c5d4e3c73ae 100644 (file)
@@ -91,7 +91,8 @@ void zbufshadeDA_tile(struct RenderPart *pa);
 
 void zbufshade_sss_tile(struct RenderPart *pa);
 
-void addps(struct ListBase *lb, long *rd, int obi, int facenr, int z, unsigned short mask);
+int get_sample_layers(struct RenderPart *pa, struct RenderLayer *rl, struct RenderLayer **rlpp);
+
 
 /* -------- ray.c ------- */
 
index cfcbb4e777560bcf7ae6aac641ff429095e58ead..a204aa7876b91ee3efab270e26d77dc03d1e2158 100644 (file)
@@ -85,6 +85,7 @@ void free_renderdata_vlaknodes(struct VlakTableNode *vlaknodes);
 
 void set_normalflags(struct Render *re, struct ObjectRen *obr);
 void project_renderdata(struct Render *re, void (*projectfunc)(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]);
 
 /* functions are not exported... so wrong names */
 
index e3ffe5ef28fb217ef6edd271afb6773a971a26c0..e015309784d2c2a1c3559726209fc6e7743cca13 100644 (file)
@@ -40,7 +40,9 @@ struct ObjectInstanceRen obi;
 
 /* needed to calculate shadow and AO for an entire pixel */
 typedef struct ShadeSample {
-       int tot;                                /* amount of shi in use, can be 1 for not FULL_OSA */
+       int tot;                                                /* amount of shi in use, can be 1 for not FULL_OSA */
+       
+       RenderLayer *rlpp[RE_MAX_OSA];  /* fast lookup from sample to renderlayer (fullsample buf) */
        
        /* could be malloced once */
        ShadeInput shi[RE_MAX_OSA];
index 8e34fa273426bc0028f6bdca41b992e21254b22b..ebe026e3fec55e1f564e999633f8687ec4c4585c 100644 (file)
@@ -88,13 +88,21 @@ typedef struct StrandSegment {
        int shaded;
 } StrandSegment;
 
+struct StrandShadeCache;
+typedef struct StrandShadeCache StrandShadeCache;
+
 void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint);
 void render_strand_segment(struct Render *re, float winmat[][4], struct StrandPart *spart, struct ZSpan *zspan, int totzspan, StrandSegment *sseg);
-void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], float *),  int do_pano, int do_buckets);
+void strand_minmax(struct StrandRen *strand, float *min, float *max);
 
 struct StrandSurface *cache_strand_surface(struct Render *re, struct ObjectRen *obr, struct DerivedMesh *dm, float mat[][4], int timeoffset);
 void free_strand_surface(struct Render *re);
 
+struct StrandShadeCache *strand_shade_cache_create(void);
+void strand_shade_cache_free(struct StrandShadeCache *cache);
+void strand_shade_segment(struct Render *re, struct StrandShadeCache *cache, struct StrandSegment *sseg, struct ShadeSample *ssamp, float t, float s, int addpassflag);
+void strand_shade_unref(struct StrandShadeCache *cache, struct StrandVert *svert);
+
 struct RenderBuckets *init_buckets(struct Render *re);
 void add_buckets_primitive(struct RenderBuckets *buckets, float *min, float *max, void *prim);
 void free_buckets(struct RenderBuckets *buckets);
index 8feb18a7ab8c0c4be60208f33e9c14fb746f489c..2a16bde829b1a35e28d6a178fe1f0eb72711c7b6 100644 (file)
@@ -36,6 +36,8 @@ struct LampRen;
 struct VlakRen;
 struct ListBase;
 struct ZSpan;
+struct APixstrand;
+struct StrandShadeCache;
 
 void fillrect(int *rect, int x, int y, int val);
 
@@ -51,9 +53,9 @@ void zbuffer_shadow(struct Render *re, float winmat[][4], struct LampRen *lar, i
 void zbuffer_solid(struct RenderPart *pa, struct RenderLayer *rl, void (*fillfunc)(struct RenderPart*, struct ZSpan*, int, void*), void *data);
 
 unsigned short *zbuffer_transp_shade(struct RenderPart *pa, struct RenderLayer *rl, float *pass, struct ListBase *psmlist);
-unsigned short *zbuffer_strands_shade(struct Render *re, struct RenderPart *pa, struct RenderLayer *rl, float *pass);
 void convert_zbuf_to_distbuf(struct RenderPart *pa, struct RenderLayer *rl);
 void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(void*, int, int, int, int, int));
+int zbuffer_strands_abuf(struct Render *re, struct RenderPart *pa, struct RenderLayer *rl, struct APixstrand *apixbuf, struct ListBase *apsmbase, struct StrandShadeCache *cache);
 
 typedef struct APixstr {
     unsigned short mask[4];            /* jitter mask */
@@ -64,10 +66,20 @@ typedef struct APixstr {
     struct APixstr *next;
 } APixstr;
 
+typedef struct APixstrand {
+    unsigned short mask[4];            /* jitter mask */
+    int z[4];                                  /* distance    */
+    int p[4];                                  /* index       */
+       int obi[4];                                     /* object instance */
+       int seg[4];                                     /* for strands, segment number */
+       float u[4], v[4];                       /* for strands, u,v coordinate in segment */
+    struct APixstrand *next;
+} APixstrand;
+
 typedef struct APixstrMain
 {
        struct APixstrMain *next, *prev;
-       struct APixstr *ps;
+       void *ps;
 } APixstrMain;
 
 /* span fill in method, is also used to localize data for zbuffering */
@@ -85,11 +97,13 @@ typedef struct ZSpan {
        int *rectp;                                                             /* polygon index buffer */
        int *recto;                                                             /* object buffer */
        APixstr *apixbuf, *curpstr;                             /* apixbuf for transparent */
+       APixstrand *curpstrand;                                 /* same for strands */
        struct ListBase *apsmbase;
        
        int polygon_offset;                                             /* offset in Z */
        float shad_alpha;                                               /* copy from material, used by irregular shadbuf */
        int mask, apsmcounter;                                  /* in use by apixbuf */
+       int apstrandmcounter;
 
        float clipcrop;                                                 /* for shadow, was in R global before */
 
index 7a8d151c73824fb08f4383424df12fb7be4e8a63..7b81acdbc1cb48d31b324ab6ce578aed48bb4224 100644 (file)
 #include "strand.h"
 #include "texture.h"
 #include "sss.h"
+#include "strand.h"
 #include "zbuf.h"
 
 #ifndef DISABLE_YAFRAY /* disable yafray */
@@ -1482,6 +1483,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
        ParticleCacheKey *cache=0;
        StrandBuffer *strandbuf=0;
        StrandVert *svert=0;
+       StrandBound *sbound= 0;
        StrandRen *strand=0;
        RNG *rng= 0;
        float loc[3],loc1[3],loc0[3],vel[3],mat[4][4],nmat[3][3],co[3],nor[3],time;
@@ -1491,6 +1493,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
        int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1, dosimplify = 0, dosurfacecache = 0;
        int path_possible=0, keys_possible=0, baked_keys=0, totchild=psys->totchild;
        int seed, path_nbr=0, path=0, orco1=0, adapt=0, uv[3]={0,0,0}, num;
+       int totface, *origindex = 0;
        char **uv_name=0;
 
 /* 1. check that everything is ok & updated */
@@ -1653,6 +1656,18 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                                else if((re->wrld.mode & WO_AMB_OCC) && (re->wrld.ao_gather_method == WO_AOGATHER_APPROX))
                                        if(ma->amb != 0.0f)
                                                dosurfacecache= 1;
+
+                               totface= psmd->dm->getNumFaces(psmd->dm);
+                               origindex= psmd->dm->getFaceDataArray(psmd->dm, CD_ORIGINDEX);
+                               if(origindex) {
+                                       for(a=0; a<totface; a++)
+                                               strandbuf->totbound= MAX2(strandbuf->totbound, origindex[a]);
+                                       strandbuf->totbound++;
+                               }
+                               strandbuf->totbound++;
+                               strandbuf->bound= MEM_callocN(sizeof(StrandBound)*strandbuf->totbound, "StrandBound");
+                               sbound= strandbuf->bound;
+                               sbound->start= sbound->end= 0;
                        }
                }
        }
@@ -1802,6 +1817,13 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                                cache = psys->childcache[a-totpart];
                                max_k = (int)cache->steps;
                        }
+
+                       if(strandbuf) {
+                               if(origindex[cpa->num]+1 > sbound - strandbuf->bound) {
+                                       sbound= strandbuf->bound + origindex[cpa->num]+1;
+                                       sbound->start= sbound->end= obr->totstrand;
+                               }
+                       }
                }
 
                /* surface normal shading setup */
@@ -1845,6 +1867,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                                        }
                                }
                        }
+
+                       sbound->end++;
                }
 
                /* strandco computation setup */
@@ -3704,7 +3728,7 @@ static void set_phong_threshold(ObjectRen *obr)
 }
 
 /* per face check if all samples should be taken.
-   if raytrace, do always for raytraced material, or when material full_osa set */
+   if raytrace or multisample, do always for raytraced material, or when material full_osa set */
 static void set_fullsample_flag(Render *re, ObjectRen *obr)
 {
        VlakRen *vlr;
@@ -3718,7 +3742,8 @@ static void set_fullsample_flag(Render *re, ObjectRen *obr)
        for(a=obr->totvlak-1; a>=0; a--) {
                vlr= RE_findOrAddVlak(obr, a);
                
-               if(vlr->mat->mode & MA_FULL_OSA) vlr->flag |= R_FULL_OSA;
+               if(vlr->mat->mode & MA_FULL_OSA) 
+                       vlr->flag |= R_FULL_OSA;
                else if(trace) {
                        if(vlr->mat->mode & MA_SHLESS);
                        else if(vlr->mat->mode & (MA_RAYTRANSP|MA_RAYMIRROR))
@@ -3840,6 +3865,11 @@ static void check_non_flat_quads(ObjectRen *obr)
 static void finalize_render_object(Render *re, ObjectRen *obr, int timeoffset)
 {
        Object *ob= obr->ob;
+       VertRen *ver= NULL;
+       StrandRen *strand= NULL;
+       StrandBound *sbound= NULL;
+       float min[3], max[3], smin[3], smax[3];
+       int a, b;
 
        if(obr->totvert || obr->totvlak || obr->tothalo || obr->totstrand) {
                /* the exception below is because displace code now is in init_render_mesh call, 
@@ -3857,6 +3887,36 @@ static void finalize_render_object(Render *re, ObjectRen *obr, int timeoffset)
 
                        check_non_flat_quads(obr);
                        set_fullsample_flag(re, obr);
+
+                       /* compute bounding boxes for clipping */
+                       INIT_MINMAX(min, max);
+                       for(a=0; a<obr->totvert; a++) {
+                               if((a & 255)==0) ver= obr->vertnodes[a>>8].vert;
+                               else ver++;
+
+                               DO_MINMAX(ver->co, min, max);
+                       }
+
+                       if(obr->strandbuf) {
+                               sbound= obr->strandbuf->bound;
+                               for(b=0; b<obr->strandbuf->totbound; b++, sbound++) {
+                                       INIT_MINMAX(smin, smax);
+
+                                       for(a=sbound->start; a<sbound->end; a++) {
+                                               strand= RE_findOrAddStrand(obr, a);
+                                               strand_minmax(strand, smin, smax);
+                                       }
+
+                                       VECCOPY(sbound->boundbox[0], smin);
+                                       VECCOPY(sbound->boundbox[1], smax);
+
+                                       DO_MINMAX(smin, min, max);
+                                       DO_MINMAX(smax, min, max);
+                               }
+                       }
+
+                       VECCOPY(obr->boundbox[0], min);
+                       VECCOPY(obr->boundbox[1], max);
                }
        }
 }
@@ -4673,7 +4733,7 @@ static void calculate_speedvectors(Render *re, ObjectInstanceRen *obi, float *ve
        }
 
        if(obr->strandnodes) {
-               strandbuf= obr->strandbufs.first;
+               strandbuf= obr->strandbuf;
                mesh= (strandbuf)? strandbuf->surface: NULL;
 
                /* compute speed vectors at surface vertices */
index 6d93d91ae971fdaefb234eb340638a8d0573177e..81d5c8ea9ed33f876b4d2b7096ec365650e4728c 100644 (file)
@@ -152,7 +152,6 @@ static Render *envmap_render_copy(Render *re, EnvMap *env)
        envre->totlamp= re->totlamp;
        envre->lights= re->lights;
        envre->objecttable= re->objecttable;
-       envre->strandbuckets= re->strandbuckets;
        envre->customdata_names= re->customdata_names;
        envre->raytree= re->raytree;
        envre->totinstance= re->totinstance;
@@ -173,7 +172,6 @@ static void envmap_free_render_copy(Render *envre)
        envre->totinstance= 0;
        envre->lights.first= envre->lights.last= NULL;
        envre->objecttable.first= envre->objecttable.last= NULL;
-       envre->strandbuckets= NULL;
        envre->customdata_names.first= envre->customdata_names.last= NULL;
        envre->raytree= NULL;
        envre->instancetable.first= envre->instancetable.last= NULL;
index e1d491c69d9114ec00e2e109a8f293f86d041efd..de0c11666614ad5a821f2905ce7baefc33deed29 100644 (file)
@@ -1581,7 +1581,7 @@ void cache_occ_samples(Render *re, RenderPart *pa, ShadeSample *ssamp)
        sample= cache->sample;
 
        ps.next= NULL;
-       ps.mask= 0xFFFF;
+       ps.mask= (1<<re->osa);
 
        ro= pa->recto;
        rp= pa->rectp;
index e4aa2326c0cff4bedb7a62ab113d411b9b5db27c..d3193a7eaaf43b38c653047588a4712703155c7f 100644 (file)
@@ -78,6 +78,7 @@
 #include "envmap.h"
 #include "initrender.h"
 #include "shadbuf.h"
+#include "pixelblending.h"
 #include "zbuf.h"
 
 
@@ -195,6 +196,22 @@ void RE_FreeRenderResult(RenderResult *res)
        MEM_freeN(res);
 }
 
+/* version that's compatible with fullsample buffers */
+static void free_render_result(ListBase *lb, RenderResult *rr)
+{
+       RenderResult *rrnext;
+       
+       for(; rr; rr= rrnext) {
+               rrnext= rr->next;
+               
+               if(lb && lb->first)
+                       BLI_remlink(lb, rr);
+               
+               RE_FreeRenderResult(rr);
+       }
+}
+
+
 /* all layers except the active one get temporally pushed away */
 static void push_render_result(Render *re)
 {
@@ -391,13 +408,18 @@ static int passtype_from_name(char *str)
 
 
 
-static void render_unique_exr_name(Render *re, char *str)
+static void render_unique_exr_name(Render *re, char *str, int sample)
 {
        char di[FILE_MAX], name[FILE_MAXFILE], fi[FILE_MAXFILE];
        
        BLI_strncpy(di, G.sce, FILE_MAX);
        BLI_splitdirstring(di, fi);
-       sprintf(name, "%s_%s.exr", fi, re->scene->id.name+2);
+       
+       if(sample==0)
+               sprintf(name, "%s_%s.exr", fi, re->scene->id.name+2);
+       else
+               sprintf(name, "%s_%s%d.exr", fi, re->scene->id.name+2, sample);
+
        if(G.background)
                BLI_make_file_string("/", str, "/tmp/", name);
        else
@@ -421,17 +443,22 @@ static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channel
                        IMB_exr_add_channel(rr->exrhandle, rl->name, get_pass_name(passtype, a), 0, 0, NULL);
        }
        else {
+               float *rect;
+               int x;
+               
+               rpass->rect= MEM_mapallocN(sizeof(float)*rectsize, typestr);
+               
                if(passtype==SCE_PASS_VECTOR) {
-                       float *rect;
-                       int x;
-                       
                        /* initialize to max speed */
-                       rect= rpass->rect= MEM_mapallocN(sizeof(float)*rectsize, typestr);
+                       rect= rpass->rect;
                        for(x= rectsize-1; x>=0; x--)
                                rect[x]= PASS_VECTOR_MAX;
                }
-               else
-                       rpass->rect= MEM_mapallocN(sizeof(float)*rectsize, typestr);
+               else if(passtype==SCE_PASS_Z) {
+                       rect= rpass->rect;
+                       for(x= rectsize-1; x>=0; x--)
+                               rect[x]= 10e10;
+               }
        }
 }
 
@@ -655,9 +682,8 @@ static void merge_render_result(RenderResult *rr, RenderResult *rrpart)
 }
 
 
-static void save_render_result_tile(Render *re, RenderPart *pa)
+static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart)
 {
-       RenderResult *rrpart= pa->result;
        RenderLayer *rlp;
        RenderPass *rpassp;
        int offs, partx, party;
@@ -677,23 +703,23 @@ static void save_render_result_tile(Render *re, RenderPart *pa)
                if(rlp->rectf) {
                        int a, xstride= 4;
                        for(a=0; a<xstride; a++)
-                               IMB_exr_set_channel(re->result->exrhandle, rlp->name, get_pass_name(SCE_PASS_COMBINED, a), 
-                                                               xstride, xstride*pa->rectx, rlp->rectf+a + xstride*offs);
+                               IMB_exr_set_channel(rr->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++)
-                               IMB_exr_set_channel(re->result->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a), 
-                                                                       xstride, xstride*pa->rectx, rpassp->rect+a + xstride*offs);
+                               IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a), 
+                                                                       xstride, xstride*rrpart->rectx, rpassp->rect+a + xstride*offs);
                }
                
        }
 
        party= rrpart->tilerect.ymin + rrpart->crop;
        partx= rrpart->tilerect.xmin + rrpart->crop;
-       IMB_exrtile_write_channels(re->result->exrhandle, partx, party);
+       IMB_exrtile_write_channels(rr->exrhandle, partx, party);
 
        BLI_unlock_thread(LOCK_IMAGE);
 
@@ -702,14 +728,17 @@ static void save_render_result_tile(Render *re, RenderPart *pa)
 static void save_empty_result_tiles(Render *re)
 {
        RenderPart *pa;
+       RenderResult *rr;
        
-       IMB_exrtile_clear_channels(re->result->exrhandle);
+       for(rr= re->result; rr; rr= rr->next) {
+               IMB_exrtile_clear_channels(rr->exrhandle);
                
-       for(pa= re->parts.first; pa; pa= pa->next) {
-               if(pa->ready==0) {
-                       int party= pa->disprect.ymin - re->disprect.ymin + pa->crop;
-                       int partx= pa->disprect.xmin - re->disprect.xmin + pa->crop;
-                       IMB_exrtile_write_channels(re->result->exrhandle, partx, party);
+               for(pa= re->parts.first; pa; pa= pa->next) {
+                       if(pa->ready==0) {
+                               int party= pa->disprect.ymin - re->disprect.ymin + pa->crop;
+                               int partx= pa->disprect.xmin - re->disprect.xmin + pa->crop;
+                               IMB_exrtile_write_channels(rr->exrhandle, partx, party);
+                       }
                }
        }
 }
@@ -836,7 +865,7 @@ static void renderresult_add_names(RenderResult *rr)
 
 
 /* only for temp buffer files, makes exact copy of render result */
-static void read_render_result(Render *re)
+static void read_render_result(Render *re, int sample)
 {
        RenderLayer *rl;
        RenderPass *rpass;
@@ -847,13 +876,15 @@ static void read_render_result(Render *re)
        RE_FreeRenderResult(re->result);
        re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM);
 
-       render_unique_exr_name(re, str);
+       render_unique_exr_name(re, str, sample);
        if(IMB_exr_begin_read(exrhandle, str, &rectx, &recty)==0) {
                IMB_exr_close(exrhandle);
                printf("cannot read: %s\n", str);
                return;
        }
        
+       printf("read exr tmp file: %s\n", str);
+       
        if(rectx!=re->result->rectx || recty!=re->result->recty) {
                printf("error in reading render result\n");
        }
@@ -1060,7 +1091,7 @@ void RE_InitState(Render *re, RenderData *rd, int winx, int winy, rcti *disprect
        }
        
        if(re->rectx < 2 || re->recty < 2 || (BKE_imtype_is_movie(rd->imtype) &&
-(re->rectx < 16 || re->recty < 16) )) {
+                                                                                 (re->rectx < 16 || re->recty < 16) )) {
                re->error("Image too small");
                re->ok= 0;
        }
@@ -1089,6 +1120,7 @@ void RE_InitState(Render *re, RenderData *rd, int winx, int winy, rcti *disprect
        }
 }
 
+/* part of external api, not called for regular render pipeline */
 void RE_SetDispRect (struct Render *re, rcti *disprect)
 {
        re->disprect= *disprect;
@@ -1189,13 +1221,36 @@ static int render_display_draw_enabled(Render *re)
                return 1;
 }
 
+/* allocate osa new results for samples */
+static RenderResult *new_full_sample_buffers(Render *re, ListBase *lb, rcti *partrct, int crop)
+{
+       int a;
+       
+       if(re->osa==0)
+               return new_render_result(re, partrct, crop, RR_USEMEM);
+       
+       for(a=0; a<re->osa; a++) {
+               RenderResult *rr= new_render_result(re, partrct, crop, RR_USEMEM);
+               BLI_addtail(lb, rr);
+               rr->sample_nr= a;
+       }
+       
+       return lb->first;
+}
+
+
+/* the main thread call, renders an entire part */
 static void *do_part_thread(void *pa_v)
 {
        RenderPart *pa= pa_v;
        
        /* need to return nicely all parts on esc */
        if(R.test_break()==0) {
-               pa->result= new_render_result(&R, &pa->disprect, pa->crop, RR_USEMEM);
+               
+               if(R.r.scemode & R_FULL_SAMPLE)
+                       pa->result= new_full_sample_buffers(&R, &pa->fullresult, &pa->disprect, pa->crop);
+               else
+                       pa->result= new_render_result(&R, &pa->disprect, pa->crop, RR_USEMEM);
 
                if(R.sss_points)
                        zbufshade_sss_tile(pa);
@@ -1205,8 +1260,13 @@ static void *do_part_thread(void *pa_v)
                        zbufshade_tile(pa);
                
                /* merge too on break! */
-               if(R.result->exrhandle)
-                       save_render_result_tile(&R, pa);
+               if(R.result->exrhandle) {
+                       RenderResult *rr, *rrpart;
+                       
+                       for(rr= R.result, rrpart= pa->result; rr && rrpart; rr= rr->next, rrpart= rrpart->next)
+                               save_render_result_tile(rr, rrpart);
+                       
+               }
                else if(render_display_draw_enabled(&R))
                        merge_render_result(R.result, pa->result);
        }
@@ -1380,33 +1440,52 @@ static void print_part_stats(Render *re, RenderPart *pa)
        re->i.infostr= NULL;
 }
 
+/* make osa new results for samples */
+static RenderResult *new_full_sample_buffers_exr(Render *re)
+{
+       int a;
+       
+       for(a=0; a<re->osa; a++) {
+               RenderResult *rr= new_render_result(re, &re->disprect, 0, 1);
+               BLI_addtail(&re->fullresult, rr);
+               rr->sample_nr= a;
+       }
+       
+       return re->fullresult.first;
+}
+
 static void threaded_tile_processor(Render *re)
 {
        ListBase threads;
        RenderPart *pa, *nextpa;
-       RenderResult *rr;
        rctf viewplane= re->viewplane;
        int rendering=1, counter= 1, drawtimer=0, hasdrawn, minx=0;
        
-       /* first step; the entire render result, or prepare exr buffer saving */
+       /* first step; free the entire render result, make new, and/or prepare exr buffer saving */
        RE_FreeRenderResult(re->result);
-       rr= re->result= new_render_result(re, &re->disprect, 0, re->r.scemode & R_EXR_TILE_FILE);
        
-       if(rr==NULL)
+       if(re->r.scemode & R_FULL_SAMPLE)
+               re->result= new_full_sample_buffers_exr(re);
+       else
+               re->result= new_render_result(re, &re->disprect, 0, re->r.scemode & R_EXR_TILE_FILE);
+       
+       if(re->result==NULL)
                return;
+       
        /* warning; no return here without closing exr file */
-//     if(re->re->test_break())
-//             return;
        
        initparts(re);
        
-       if(rr->exrhandle) {
+       if(re->result->exrhandle) {
+               RenderResult *rr;
                char str[FILE_MAX];
                
-               render_unique_exr_name(re, str);
+               for(rr= re->result; rr; rr= rr->next) {
+                       render_unique_exr_name(re, str, rr->sample_nr);
                
-               printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str);
-               IMB_exrtile_begin_write(rr->exrhandle, str, rr->rectx, rr->recty, rr->rectx/re->xparts, rr->recty/re->yparts);
+                       printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str);
+                       IMB_exrtile_begin_write(rr->exrhandle, str, rr->rectx, rr->recty, rr->rectx/re->xparts, rr->recty/re->yparts);
+               }
        }
        
        BLI_init_threads(&threads, do_part_thread, re->r.threads);
@@ -1461,7 +1540,7 @@ static void threaded_tile_processor(Render *re)
                                                re->display_draw(pa->result, NULL);
                                        print_part_stats(re, pa);
                                        
-                                       RE_FreeRenderResult(pa->result);
+                                       free_render_result(&pa->fullresult, pa->result);
                                        pa->result= NULL;
                                        re->i.partsdone++;
                                        hasdrawn= 1;
@@ -1485,11 +1564,20 @@ static void threaded_tile_processor(Render *re)
                
        }
        
-       if(rr->exrhandle) {
+       if(re->result->exrhandle) {
+               RenderResult *rr;
+
                save_empty_result_tiles(re);
-               IMB_exr_close(rr->exrhandle);
-               rr->exrhandle= NULL;
-               read_render_result(re);
+               
+               for(rr= re->result; rr; rr= rr->next) {
+                       IMB_exr_close(rr->exrhandle);
+                       rr->exrhandle= NULL;
+               }
+               
+               free_render_result(&re->fullresult, re->result);
+               re->result= NULL;
+               
+               read_render_result(re, 0);
        }
        
        /* unset threadsafety */
@@ -1822,11 +1910,18 @@ static void do_render_fields_blur_3d(Render *re)
 static void render_scene(Render *re, Scene *sce, int cfra)
 {
        Render *resc= RE_NewRender(sce->id.name);
+       int winx= re->winx, winy= re->winy;
        
        sce->r.cfra= cfra;
                
+       /* exception: scene uses own size (unfinished code) */
+       if(0) {
+               winx= (sce->r.size*sce->r.xsch)/100;
+               winy= (sce->r.size*sce->r.ysch)/100;
+       }
+       
        /* initial setup */
-       RE_InitState(resc, &sce->r, re->winx, re->winy, &re->disprect);
+       RE_InitState(resc, &sce->r, winx, winy, &re->disprect);
        
        /* this to enable this scene to create speed vectors */
        resc->r.scemode |= R_DOCOMP;
@@ -1837,6 +1932,10 @@ static void render_scene(Render *re, Scene *sce, int cfra)
        /* ensure scene has depsgraph, base flags etc OK. Warning... also sets G.scene */
        set_scene_bg(sce);
 
+       /* fullsample wants uniform osa levels */
+       if(resc->r.scemode & R_FULL_SAMPLE)
+               resc->r.osa= resc->osa= re->osa;
+       
        /* copy callbacks */
        resc->display_draw= re->display_draw;
        resc->test_break= re->test_break;
@@ -1909,6 +2008,72 @@ static void render_composit_stats(char *str)
        R.i.infostr= NULL;
 }
 
+/* reads all buffers, calls optional composite, merges in first result->rectf */
+static void do_merge_fullsample(Render *re, bNodeTree *ntree)
+{
+       float *rectf;
+       int sample;
+       
+       /* we accumulate in here */
+       rectf= MEM_mapallocN(re->rectx*re->recty*sizeof(float)*4, "fullsample rgba");
+       
+       for(sample=0; sample<re->osa; sample++) {
+               RenderResult rres;
+               int x, y, mask;
+               
+               /* set all involved renders on the samplebuffers (first was done by render itself) */
+               if(sample) {
+                       Render *re1;
+                       for(re1= RenderList.first; re1; re1= re1->next) {
+                               if(re1->r.scemode & R_FULL_SAMPLE)
+                                       read_render_result(re1, sample);
+                       }
+               }
+
+               /* composite */
+               if(ntree) {
+                       ntreeCompositTagRender(re->scene);
+                       ntreeCompositTagAnimated(ntree);
+                       
+                       ntreeCompositExecTree(ntree, &re->r, G.background==0);
+               }
+               
+               /* ensure we get either composited result or the active layer */
+               RE_GetResultImage(re, &rres);
+               
+               /* accumulate with filter, and clip */
+               mask= (1<<sample);
+               for(y=1; y<re->recty-1; y++) {
+                       float *rf= rectf + 4*y*re->rectx + 4;
+                       float *col= rres.rectf + 4*y*re->rectx + 4;
+                               
+                       for(x=1; x<re->rectx-1; x++, rf+=4, col+=4) {
+                               if(col[0]<0.0f) col[0]=0.0f; else if(col[0] > 1.0f) col[0]= 1.0f;
+                               if(col[1]<0.0f) col[1]=0.0f; else if(col[1] > 1.0f) col[1]= 1.0f;
+                               if(col[2]<0.0f) col[2]=0.0f; else if(col[2] > 1.0f) col[2]= 1.0f;
+                               
+                               add_filt_fmask(mask, col, rf, re->rectx);
+                       }
+               }
+               
+               /* show stuff */
+               if(sample!=re->osa-1) {
+                       /* weak... the display callback wants an active renderlayer pointer... */
+                       re->result->renlay= render_get_active_layer(re, re->result);
+                       re->display_draw(re->result, NULL);
+               }
+               
+               if(re->test_break())
+                       break;
+       }
+       
+       if(re->result->rectf) 
+               MEM_freeN(re->result->rectf);
+       re->result->rectf= rectf;
+}
+
+
+
 /* returns fully composited render-result on given time step (in RenderData) */
 static void do_render_composite_fields_blur_3d(Render *re)
 {
@@ -1928,9 +2093,12 @@ static void do_render_composite_fields_blur_3d(Render *re)
        if(re->r.scemode & R_SINGLE_LAYER)
                pop_render_result(re);
        
-       if(!re->test_break() && ntree) {
-               ntreeCompositTagRender(re->scene);
-               ntreeCompositTagAnimated(ntree);
+       if(!re->test_break()) {
+               
+               if(ntree) {
+                       ntreeCompositTagRender(re->scene);
+                       ntreeCompositTagAnimated(ntree);
+               }
                
                if(re->r.scemode & R_DOCOMP) {
                        /* checks if there are render-result nodes that need scene */
@@ -1943,11 +2111,19 @@ static void do_render_composite_fields_blur_3d(Render *re)
                                /* in case it was never initialized */
                                R.stats_draw= re->stats_draw;
                                
-                               ntreeCompositExecTree(ntree, &re->r, G.background==0);
+                               if(re->r.scemode & R_FULL_SAMPLE) 
+                                       do_merge_fullsample(re, ntree);
+                               else
+                                       ntreeCompositExecTree(ntree, &re->r, G.background==0);
+                               
                                ntree->stats_draw= NULL;
                                ntree->test_break= NULL;
                        }
                }
+               else 
+                       if(re->r.scemode & R_FULL_SAMPLE) 
+                               do_merge_fullsample(re, NULL);
+               
        }
 
        /* weak... the display callback wants an active renderlayer pointer... */
@@ -2101,14 +2277,20 @@ static int is_rendering_allowed(Render *re)
        if(re->r.scemode & R_EXR_TILE_FILE) {
                char str[FILE_MAX];
                
-               render_unique_exr_name(re, str);
+               render_unique_exr_name(re, str, 0);
                
                if (BLI_is_writable(str)==0) {
                        re->error("Can not save render buffers, check the temp default path");
                        return 0;
                }
                
+               /* no osa + fullsample won't work... */
+               if(re->osa==0)
+                       re->r.scemode &= ~R_FULL_SAMPLE;
+               
        }
+       else
+               re->r.scemode &= ~R_FULL_SAMPLE;        /* clear to be sure */
        
        if(re->r.scemode & R_DOCOMP) {
                if(re->scene->use_nodes) {
@@ -2394,7 +2576,7 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra)
 
 /* note; repeated win/disprect calc... solve that nicer, also in compo */
 
-/* only temp file! */
+/* only the temp file! */
 void RE_ReadRenderResult(Scene *scene, Scene *scenode)
 {
        Render *re;
@@ -2426,7 +2608,7 @@ void RE_ReadRenderResult(Scene *scene, Scene *scenode)
        RE_InitState(re, &scene->r, winx, winy, &disprect);
        re->scene= scene;
        
-       read_render_result(re);
+       read_render_result(re, 0);
 }
 
 void RE_set_max_threads(int threads)
index 119cceaf3c28e2f28d28fe93335382d4c391cb05..2c7d5e1d9cce1230a03bed929ce0053721ac5feb 100644 (file)
@@ -91,15 +91,6 @@ void addAlphaOverFloat(float *dest, float *source)
 void addAlphaUnderFloat(float *dest, float *source)
 {
     float mul;
-    
-    if( (-RE_EMPTY_COLOR_FLOAT < dest[3])
-        && (dest[3] <  RE_EMPTY_COLOR_FLOAT) ) {       
-        dest[0] = source[0];
-        dest[1] = source[1];
-        dest[2] = source[2];
-        dest[3] = source[3];
-        return;
-    }
 
        mul= 1.0 - dest[3];
 
index 220c06f1edefaa263ba2855e0d98fc760c2d8bfb..375d8a23a2e109b793441bf830bd6254e0bd819d 100644 (file)
@@ -348,12 +348,19 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
 static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, ShadeInput *shi, ShadeResult *shr)
 {
        RenderPass *rpass;
+
+       /* combined rgb */
+       add_filt_fmask(curmask, shr->combined, rl->rectf + 4*offset, rectx);
        
        for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
                float *fp, *col= NULL;
                int pixsize= 3;
                
                switch(rpass->passtype) {
+                       case SCE_PASS_Z:
+                               fp= rpass->rect + offset;
+                               *fp= -shi->co[2];
+                               break;
                        case SCE_PASS_RGBA:
                                col= shr->col;
                                pixsize= 4;
@@ -432,12 +439,20 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
 static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult *shr)
 {
        RenderPass *rpass;
+       float *fp;
+       
+       fp= rl->rectf + 4*offset;
+       QUATCOPY(fp, shr->combined);
        
        for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
-               float *fp, *col= NULL, uvcol[3];
+               float *col= NULL, uvcol[3];
                int a, pixsize= 3;
                
                switch(rpass->passtype) {
+                       case SCE_PASS_Z:
+                               fp= rpass->rect + offset;
+                               *fp= -shi->co[2];
+                               break;
                        case SCE_PASS_RGBA:
                                col= shr->col;
                                pixsize= 4;
@@ -497,26 +512,60 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult
        }
 }
 
+int get_sample_layers(RenderPart *pa, RenderLayer *rl, RenderLayer **rlpp)
+{
+       
+       if(pa->fullresult.first) {
+               int sample, nr= BLI_findindex(&pa->result->layers, rl);
+               
+               for(sample=0; sample<R.osa; sample++) {
+                       RenderResult *rr= BLI_findlink(&pa->fullresult, sample);
+               
+                       rlpp[sample]= BLI_findlink(&rr->layers, nr);
+               }               
+               return R.osa;
+       }
+       else {
+               rlpp[0]= rl;
+               return 1;
+       }
+}
+
+
 /* only do sky, is default in the solid layer (shade_tile) btw */
-static void sky_tile(RenderPart *pa, float *pass)
+static void sky_tile(RenderPart *pa, RenderLayer *rl)
 {
-       float col[4];
-       int x, y;
+       RenderLayer *rlpp[RE_MAX_OSA];
+       int x, y, od=0, totsample;
        
        if(R.r.alphamode!=R_ADDSKY)
                return;
        
+       totsample= get_sample_layers(pa, rl, rlpp);
+       
        for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++) {
-               for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, pass+=4) {
-                       if(pass[3]<1.0f) {
-                               if(pass[3]==0.0f)
-                                       shadeSkyPixel(pass, x, y);
-                               else {
-                                       shadeSkyPixel(col, x, y);
-                                       addAlphaOverFloat(col, pass);
-                                       QUATCOPY(pass, col);
+               for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, od+=4) {
+                       float col[4];
+                       int sample, done= 0;
+                       
+                       for(sample= 0; sample<totsample; sample++) {
+                               float *pass= rlpp[sample]->rectf + od;
+                               
+                               if(pass[3]<1.0f) {
+                                       
+                                       if(done==0) {
+                                               shadeSkyPixel(col, x, y);
+                                               done= 1;
+                                       }
+                                       
+                                       if(pass[3]==0.0f) {
+                                               QUATCOPY(pass, col);
+                                       }
+                                       else {
+                                               addAlphaUnderFloat(pass, col);
+                                       }
                                }
-                       }
+                       }                       
                }
                
                if(y&1)
@@ -528,10 +577,9 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl)
 {
        RenderResult *rr= pa->result;
        ShadeSample ssamp;
-       float *fcol, *rf, *rectf= rl->rectf;
        long *rd, *rectdaps= pa->rectdaps;
        int samp;
-       int x, y, seed, crop=0, offs=0, od, addpassflag;
+       int x, y, seed, crop=0, offs=0, od;
        
        if(R.test_break()) return; 
        
@@ -544,7 +592,6 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl)
        
        /* general shader info, passes */
        shade_sample_initialize(&ssamp, pa, rl);
-       addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED);
 
        /* occlusion caching */
        if(R.occlusiontree)
@@ -553,7 +600,6 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl)
        /* filtered render, for now we assume only 1 filter size */
        if(pa->crop) {
                crop= 1;
-               rectf+= 4*(pa->rectx + 1);
                rectdaps+= pa->rectx + 1;
                offs= pa->rectx + 1;
        }
@@ -564,28 +610,35 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl)
        rr->renlay= rl;
                                
        for(y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++, rr->renrect.ymax++) {
-               rf= rectf;
                rd= rectdaps;
                od= offs;
                
-               for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, rd++, rf+=4, od++) {
+               for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, rd++, od++) {
                        BLI_thread_srandom(pa->thread, seed++);
                        
                        if(*rd) {
                                if(shade_samples(&ssamp, (PixStr *)(*rd), x, y)) {
-                                       for(samp=0; samp<ssamp.tot; samp++) {
-                                               
-                                               fcol= ssamp.shr[samp].combined;
-                                               add_filt_fmask(ssamp.shi[samp].mask, fcol, rf, pa->rectx);
-                                               
-                                               if(addpassflag)
+                                       
+                                       /* multisample buffers or filtered mask filling? */
+                                       if(pa->fullresult.first) {
+                                               int a;
+                                               for(samp=0; samp<ssamp.tot; samp++) {
+                                                       int smask= ssamp.shi[samp].mask;
+                                                       for(a=0; a<R.osa; a++) {
+                                                               int mask= 1<<a;
+                                                               if(smask & mask)
+                                                                       add_passes(ssamp.rlpp[a], od, &ssamp.shi[samp], &ssamp.shr[samp]);
+                                                       }
+                                               }
+                                       }
+                                       else {
+                                               for(samp=0; samp<ssamp.tot; samp++)
                                                        add_filt_passes(rl, ssamp.shi[samp].mask, pa->rectx, od, &ssamp.shi[samp], &ssamp.shr[samp]);
                                        }
                                }
                        }
                }
                
-               rectf+= 4*pa->rectx;
                rectdaps+= pa->rectx;
                offs+= pa->rectx;
                
@@ -631,7 +684,7 @@ static void freeps(ListBase *lb)
        lb->first= lb->last= NULL;
 }
 
-void addps(ListBase *lb, long *rd, int obi, int facenr, int z, unsigned short mask)
+static void addps(ListBase *lb, long *rd, int obi, int facenr, int z, unsigned short mask)
 {
        PixStrMain *psm;
        PixStr *ps, *last= NULL;
@@ -916,99 +969,61 @@ void zbufshadeDA_tile(RenderPart *pa)
                                halo_tile(pa, rl->rectf, rl->lay);
 
                /* transp layer */
-               if(R.flag & R_ZTRA) {
-                       if(rl->layflag & SCE_LAY_ZTRA) {
-                               unsigned short *ztramask, *solidmask= NULL; /* 16 bits, MAX_OSA */
-                               
-                               /* allocate, but not free here, for asynchronous display of this rect in main thread */
-                               rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer");
-                               
-                               /* swap for live updates, and it is used in zbuf.c!!! */
-                               SWAP(float *, rl->acolrect, rl->rectf);
-                               ztramask= zbuffer_transp_shade(pa, rl, rl->rectf, &psmlist);
-                               SWAP(float *, rl->acolrect, rl->rectf);
-                               
-                               /* zbuffer transp only returns ztramask if there's solid rendered */
-                               if(ztramask)
-                                       solidmask= make_solid_mask(pa);
-
-                               if(ztramask && solidmask) {
-                                       unsigned short *sps= solidmask, *spz= ztramask;
-                                       unsigned short fullmask= (1<<R.osa)-1;
-                                       float *fcol= rl->rectf; float *acol= rl->acolrect;
-                                       int x;
+               if(R.flag & R_ZTRA || R.totstrand) {
+                       if(rl->layflag & (SCE_LAY_ZTRA|SCE_LAY_STRAND)) {
+                               if(pa->fullresult.first) {
+                                       zbuffer_transp_shade(pa, rl, rl->rectf, &psmlist);
+                               }
+                               else {
+                                       unsigned short *ztramask, *solidmask= NULL; /* 16 bits, MAX_OSA */
                                        
-                                       for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4, sps++, spz++) {
-                                               if(*sps == fullmask)
-                                                       addAlphaOverFloat(fcol, acol);
-                                               else
-                                                       addAlphaOverFloatMask(fcol, acol, *sps, *spz);
+                                       /* allocate, but not free here, for asynchronous display of this rect in main thread */
+                                       rl->acolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "alpha layer");
+                                       
+                                       /* swap for live updates, and it is used in zbuf.c!!! */
+                                       SWAP(float *, rl->acolrect, rl->rectf);
+                                       ztramask= zbuffer_transp_shade(pa, rl, rl->rectf, &psmlist);
+                                       SWAP(float *, rl->acolrect, rl->rectf);
+                                       
+                                       /* zbuffer transp only returns ztramask if there's solid rendered */
+                                       if(ztramask)
+                                               solidmask= make_solid_mask(pa);
+
+                                       if(ztramask && solidmask) {
+                                               unsigned short *sps= solidmask, *spz= ztramask;
+                                               unsigned short fullmask= (1<<R.osa)-1;
+                                               float *fcol= rl->rectf; float *acol= rl->acolrect;
+                                               int x;
+                                               
+                                               for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4, sps++, spz++) {
+                                                       if(*sps == fullmask)
+                                                               addAlphaOverFloat(fcol, acol);
+                                                       else
+                                                               addAlphaOverFloatMask(fcol, acol, *sps, *spz);
+                                               }
                                        }
-                               }
-                               else {
-                                       float *fcol= rl->rectf; float *acol= rl->acolrect;
-                                       int x;
-                                       for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) {
-                                               addAlphaOverFloat(fcol, acol);
+                                       else {
+                                               float *fcol= rl->rectf; float *acol= rl->acolrect;
+                                               int x;
+                                               for(x=pa->rectx*pa->recty; x>0; x--, acol+=4, fcol+=4) {
+                                                       addAlphaOverFloat(fcol, acol);
+                                               }
                                        }
+                                       if(solidmask) MEM_freeN(solidmask);
+                                       if(ztramask) MEM_freeN(ztramask);
                                }
-                               if(solidmask) MEM_freeN(solidmask);
-                               if(ztramask) MEM_freeN(ztramask);
-                       }
-               }
-
-               /* strand rendering */
-               if((rl->layflag & SCE_LAY_STRAND) && R.totstrand) {
-                       float *fcol, *scol;
-                       unsigned short *strandmask, *solidmask= NULL; /* 16 bits, MAX_OSA */
-                       int x;
-                       
-                       /* allocate, but not free here, for asynchronous display of this rect in main thread */
-                       rl->scolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "strand layer");
-
-                       /* swap for live updates, and it is used in zbuf.c!!! */
-                       SWAP(float*, rl->scolrect, rl->rectf);
-                       strandmask= zbuffer_strands_shade(&R, pa, rl, rl->rectf);
-                       SWAP(float*, rl->scolrect, rl->rectf);
-
-                       /* zbuffer strands only returns strandmask if there's solid rendered */
-                       if(strandmask)
-                               solidmask= make_solid_mask(pa);
-                       
-                       if(strandmask && solidmask) {
-                               unsigned short *sps= solidmask, *spz= strandmask;
-                               unsigned short fullmask= (1<<R.osa)-1;
-
-                               fcol= rl->rectf; scol= rl->scolrect;
-                               for(x=pa->rectx*pa->recty; x>0; x--, scol+=4, fcol+=4, sps++, spz++) {
-                                       if(*sps == fullmask)
-                                               addAlphaOverFloat(fcol, scol);
-                                       else
-                                               addAlphaOverFloatMask(fcol, scol, *sps, *spz);
-                               }
-                       }
-                       else {
-                               fcol= rl->rectf; scol= rl->scolrect;
-                               for(x=pa->rectx*pa->recty; x>0; x--, scol+=4, fcol+=4)
-                                       addAlphaOverFloat(fcol, scol);
                        }
-
-                       if(solidmask) MEM_freeN(solidmask);
-                       if(strandmask) MEM_freeN(strandmask);
                }
 
                /* sky before edge */
                if(rl->layflag & SCE_LAY_SKY)
-                       sky_tile(pa, rl->rectf);
+                       sky_tile(pa, rl);
 
                /* extra layers */
                if(rl->layflag & SCE_LAY_EDGE) 
                        if(R.r.mode & R_EDGE) 
                                edge_enhance_add(pa, rl->rectf, edgerect);
                
-               if(rl->passflag & SCE_PASS_Z)
-                       convert_zbuf_to_distbuf(pa, rl);
-               
                if(rl->passflag & SCE_PASS_VECTOR)
                        reset_sky_speed(pa, rl);
                
@@ -1046,7 +1061,6 @@ void zbufshade_tile(RenderPart *pa)
        RenderLayer *rl;
        PixStr ps;
        float *edgerect= NULL;
-       int addpassflag;
        
        /* fake pixel struct, to comply to osa render */
        ps.next= NULL;
@@ -1061,7 +1075,6 @@ void zbufshade_tile(RenderPart *pa)
                
                /* general shader info, passes */
                shade_sample_initialize(&ssamp, pa, rl);
-               addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED);
                
                zbuffer_solid(pa, rl, NULL, NULL);
                
@@ -1104,11 +1117,8 @@ void zbufshade_tile(RenderPart *pa)
                                                        ps.facenr= *rp;
                                                        ps.z= *rz;
                                                        if(shade_samples(&ssamp, &ps, x, y)) {
-                                                               QUATCOPY(fcol, ssamp.shr[0].combined);
-
-                                                               /* passes */
-                                                               if(addpassflag)
-                                                                       add_passes(rl, offs, ssamp.shi, ssamp.shr);
+                                                               /* combined and passes */
+                                                               add_passes(rl, offs, ssamp.shi, ssamp.shr);
                                                        }
                                                }
                                        }
@@ -1137,8 +1147,8 @@ void zbufshade_tile(RenderPart *pa)
                        if(rl->layflag & SCE_LAY_HALO)
                                halo_tile(pa, rl->rectf, rl->lay);
                
-               if(R.flag & R_ZTRA) {
-                       if(rl->layflag & SCE_LAY_ZTRA) {
+               if(R.flag & R_ZTRA || R.totstrand) {
+                       if(rl->layflag & (SCE_LAY_ZTRA|SCE_LAY_STRAND)) {
                                float *fcol, *acol;
                                int x;
                                
@@ -1156,28 +1166,10 @@ void zbufshade_tile(RenderPart *pa)
                                }
                        }
                }
-
-               /* strand rendering */
-               if((rl->layflag & SCE_LAY_STRAND) && R.totstrand) {
-                       float *fcol, *scol;
-                       int x;
-                       
-                       /* allocate, but not free here, for asynchronous display of this rect in main thread */
-                       rl->scolrect= MEM_callocN(4*sizeof(float)*pa->rectx*pa->recty, "strand layer");
-
-                       /* swap for live updates */
-                       SWAP(float*, rl->scolrect, rl->rectf);
-                       zbuffer_strands_shade(&R, pa, rl, rl->rectf);
-                       SWAP(float*, rl->scolrect, rl->rectf);
-
-                       fcol= rl->rectf; scol= rl->scolrect;
-                       for(x=pa->rectx*pa->recty; x>0; x--, scol+=4, fcol+=4)
-                               addAlphaOverFloat(fcol, scol);
-               }
                
                /* sky before edge */
                if(rl->layflag & SCE_LAY_SKY)
-                       sky_tile(pa, rl->rectf);
+                       sky_tile(pa, rl);
                
                if(!R.test_break()) {
                        if(rl->layflag & SCE_LAY_EDGE) 
@@ -1185,9 +1177,6 @@ void zbufshade_tile(RenderPart *pa)
                                        edge_enhance_add(pa, rl->rectf, edgerect);
                }
                
-               if(rl->passflag & SCE_PASS_Z)
-                       convert_zbuf_to_distbuf(pa, rl);
-               
                if(rl->passflag & SCE_PASS_VECTOR)
                        reset_sky_speed(pa, rl);
                
index 27daad9dc266b6c7fab217a7daec4312fedc8112..5a7495154165dca2642d976c0d979d9e7c190e58 100644 (file)
@@ -711,7 +711,7 @@ StrandBuffer *RE_addStrandBuffer(ObjectRen *obr, int totvert)
        strandbuf->totvert= totvert;
        strandbuf->obr= obr;
 
-       BLI_addtail(&obr->strandbufs, strandbuf);
+       obr->strandbuf= strandbuf;
 
        return strandbuf;
 }
@@ -842,9 +842,12 @@ void free_renderdata_tables(Render *re)
                        obr->strandnodeslen= 0;
                }
 
-               for(strandbuf=obr->strandbufs.first; strandbuf; strandbuf=strandbuf->next)
+               strandbuf= obr->strandbuf;
+               if(strandbuf) {
                        if(strandbuf->vert) MEM_freeN(strandbuf->vert);
-               BLI_freelistN(&obr->strandbufs);
+                       if(strandbuf->bound) MEM_freeN(strandbuf->bound);
+                       MEM_freeN(strandbuf);
+               }
 
                if(obr->mtface)
                        MEM_freeN(obr->mtface);
@@ -868,11 +871,6 @@ void free_renderdata_tables(Render *re)
                re->sortedhalos= NULL;
        }
 
-       if(re->strandbuckets) {
-               free_buckets(re->strandbuckets);
-               re->strandbuckets= NULL;
-       }
-
        BLI_freelistN(&re->customdata_names);
        BLI_freelistN(&re->objecttable);
        BLI_freelistN(&re->instancetable);
@@ -1290,8 +1288,6 @@ void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4],
                        
                }
        }
-
-       project_strands(re, projectfunc, do_pano, do_buckets);
 }
 
 /* ------------------------------------------------------------------------- */
@@ -1349,3 +1345,40 @@ void RE_makeRenderInstances(Render *re)
        re->instancetable= newlist;
 }
 
+int clip_render_object(float boundbox[][3], float *bounds, float winmat[][4])
+{
+       float mat[4][4], vec[4];
+       int a, fl, flag= -1;
+
+       Mat4CpyMat4(mat, winmat);
+
+       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;
+               Mat4MulVec4fl(mat, vec);
+
+               fl= 0;
+               if(bounds) {
+                       if(vec[0] > bounds[1]*vec[3]) fl |= 1;
+                       if(vec[0]< bounds[0]*vec[3]) fl |= 2;
+                       if(vec[1] > bounds[3]*vec[3]) fl |= 4;
+                       if(vec[1]< bounds[2]*vec[3]) fl |= 8;
+               }
+               else {
+                       if(vec[0] < -vec[3]) fl |= 1;
+                       if(vec[0] > vec[3]) fl |= 2;
+                       if(vec[1] < -vec[3]) fl |= 4;
+                       if(vec[1] > vec[3]) fl |= 8;
+               }
+               if(vec[2] < -vec[3]) fl |= 16;
+               if(vec[2] > vec[3]) fl |= 32;
+
+               flag &= fl;
+               if(flag==0) return 0;
+       }
+
+       return flag;
+}
+
index 3a8b0cca7fcf4e1cae9f351d5dc7622a5b0b0645..a0554cbaa56009a4341b5f6f81b71894027b4d9a 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "MTC_matrixops.h"
 #include "BLI_arithb.h"
+#include "BLI_blenlib.h"
 
 #include "DNA_curve_types.h"
 #include "DNA_group_types.h"
@@ -1214,8 +1215,9 @@ void shade_input_initialize(ShadeInput *shi, RenderPart *pa, RenderLayer *rl, in
        shi->combinedflag= ~rl->pass_xor;
        shi->mat_override= rl->mat_override;
        shi->light_override= rl->light_override;
-       
+//     shi->rl= rl;
        /* note shi.depth==0  means first hit, not raytracing */
+       
 }
 
 /* initialize per part, not per pixel! */
@@ -1230,6 +1232,8 @@ void shade_sample_initialize(ShadeSample *ssamp, RenderPart *pa, RenderLayer *rl
                memset(&ssamp->shr[a], 0, sizeof(ShadeResult));
        }
        
+       get_sample_layers(pa, rl, ssamp->rlpp);
+
        ssamp->samplenr= 0; /* counter, detect shadow-reuse for shaders */
 }
 
@@ -1279,7 +1283,8 @@ void shade_samples_fill_with_ps(ShadeSample *ssamp, PixStr *ps, int x, int y)
                                                        shade_input_copy_triangle(shi, shi-1);
                                                
                                                shi->mask= (1<<samp);
-                                               shi->samplenr= ssamp->samplenr++;
+//                                             shi->rl= ssamp->rlpp[samp];
+                                               shi->samplenr= ssamp->samplenr++;       /* this counter is not being reset per pixel */
                                                shade_input_set_viewco(shi, xs, ys, (float)ps->z);
                                                shade_input_set_uv(shi);
                                                shade_input_set_normals(shi);
index bf58c023998535a96eeba2efed4823a412393d5f..e66d12de15ba565755da8de83378aef7cca36591 100644 (file)
 #include "zbuf.h"
 
 /* to be removed */
-void merge_transp_passes(RenderLayer *rl, ShadeResult *shr);
-void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alpha);
 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);
-int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassflag);
-void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha, long *rdrect);
-void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf);
-
-/* *************** */
-
-#define BUCKETPRIMS_SIZE 256
-
-typedef struct BucketPrims {
-       struct BucketPrims *next, *prev;
-       void *prim[BUCKETPRIMS_SIZE];
-       int totprim;
-} BucketPrims;
-
-typedef struct RenderBuckets {
-       ListBase all;
-       ListBase *inside;
-       ListBase *overlap;
-       int x, y;
-       float insize[2];
-       float zmulx, zmuly, zofsx, zofsy;
-} RenderBuckets;
-
-static void add_bucket_prim(ListBase *lb, void *prim)
-{
-       BucketPrims *bpr= lb->last;
-
-       if(!bpr || bpr->totprim == BUCKETPRIMS_SIZE) {
-               bpr= MEM_callocN(sizeof(BucketPrims), "BucketPrims");
-               BLI_addtail(lb, bpr);
-       }
-
-       bpr->prim[bpr->totprim++]= prim;
-}
-
-RenderBuckets *init_buckets(Render *re)
-{
-       RenderBuckets *buckets;
-       RenderPart *pa;
-       float scalex, scaley, cropx, cropy;
-       int x, y, tempparts= 0;
-
-       buckets= MEM_callocN(sizeof(RenderBuckets), "RenderBuckets");
-
-       if(!re->parts.first) {
-               initparts(re);
-               tempparts= 1;
-       }
-
-       pa= re->parts.first;
-       if(!pa)
-               return buckets;
-       
-       x= re->xparts+1;
-       y= re->yparts+1;
-       buckets->x= x;
-       buckets->y= y;
-
-       scalex= (2.0f - re->xparts*re->partx/(float)re->winx);
-       scaley= (2.0f - re->yparts*re->party/(float)re->winy);
-
-       cropx= pa->crop/(float)re->partx;
-       cropy= pa->crop/(float)re->party;
-
-       buckets->insize[0]= 1.0f - 2.0f*cropx;
-       buckets->insize[1]= 1.0f - 2.0f*cropy;
-
-       buckets->zmulx= re->xparts*scalex;
-       buckets->zmuly= re->yparts*scaley;
-       buckets->zofsx= scalex*(1.0f - cropx);
-       buckets->zofsy= scaley*(1.0f - cropy);
-
-       buckets->inside= MEM_callocN(sizeof(ListBase)*x*y, "BucketPrimsInside");
-       buckets->overlap= MEM_callocN(sizeof(ListBase)*x*y, "BucketPrimsOverlap");
-
-       if(tempparts)
-               freeparts(re);
-
-       return buckets;
-}
-
-void add_buckets_primitive(RenderBuckets *buckets, float *min, float *max, void *prim)
-{
-       float end[3];
-       int x, y, a;
-
-       x= (int)min[0];
-       y= (int)min[1];
-
-       if(x >= 0 && x < buckets->x && y >= 0 && y < buckets->y) {
-               a= y*buckets->x + x;
-
-               end[0]= x + buckets->insize[0];
-               end[1]= y + buckets->insize[1];
-
-               if(max[0] <= end[0] && max[1] <= end[1]) {
-                       add_bucket_prim(&buckets->inside[a], prim);
-                       return;
-               }
-               else {
-                       end[0]= x + 2;
-                       end[1]= y + 2;
-
-                       if(max[0] <= end[0] && max[1] <= end[1]) {
-                               add_bucket_prim(&buckets->overlap[a], prim);
-                               return;
-                       }
-               }
-       }
-
-       add_bucket_prim(&buckets->all, prim);
-}
-
-void free_buckets(RenderBuckets *buckets)
-{
-       int a, size;
-
-       BLI_freelistN(&buckets->all);
-
-       size= buckets->x*buckets->y;
-       for(a=0; a<size; a++) {
-               BLI_freelistN(&buckets->inside[a]);
-               BLI_freelistN(&buckets->overlap[a]);
-       }
-
-       if(buckets->inside)
-               MEM_freeN(buckets->inside);
-       if(buckets->overlap)
-               MEM_freeN(buckets->overlap);
-       
-       MEM_freeN(buckets);
-}
-
-void project_hoco_to_bucket(RenderBuckets *buckets, float *hoco, float *bucketco)
-{
-       float div;
-
-       div= 1.0f/hoco[3];
-       bucketco[0]= buckets->zmulx*(0.5 + 0.5f*hoco[0]*div) + buckets->zofsx;
-       bucketco[1]= buckets->zmuly*(0.5 + 0.5f*hoco[1]*div) + buckets->zofsy;
-}
-
-typedef struct RenderPrimitiveIterator {
-       Render *re;
-       RenderBuckets *buckets;
-       ListBase *list[6];
-       int listindex, totlist;
-       BucketPrims *bpr;
-       int bprindex;
-
-       ObjectInstanceRen *obi;
-       StrandRen *strand;
-       int index, tot;
-} RenderPrimitiveIterator;
-
-RenderPrimitiveIterator *init_primitive_iterator(Render *re, RenderBuckets *buckets, RenderPart *pa)
-{
-       RenderPrimitiveIterator *iter;
-       int nr, x, y, width;
-
-       iter= MEM_callocN(sizeof(RenderPrimitiveIterator), "RenderPrimitiveIterator");
-       iter->re= re;
-
-       if(buckets) {
-               iter->buckets= buckets;
-
-               nr= BLI_findindex(&re->parts, pa);
-               width= buckets->x - 1;
-               x= (nr % width) + 1;
-               y= (nr / width) + 1;
-
-               iter->list[iter->totlist++]= &buckets->all;
-               iter->list[iter->totlist++]= &buckets->inside[y*buckets->x + x];
-               iter->list[iter->totlist++]= &buckets->overlap[y*buckets->x + x];
-               iter->list[iter->totlist++]= &buckets->overlap[y*buckets->x + (x-1)];
-               iter->list[iter->totlist++]= &buckets->overlap[(y-1)*buckets->x + (x-1)];
-               iter->list[iter->totlist++]= &buckets->overlap[(y-1)*buckets->x + x];
-       }
-       else {
-               iter->index= 0;
-               iter->obi= re->instancetable.first;
-               if(iter->obi)
-                       iter->tot= iter->obi->obr->totstrand;
-       }
-
-       return iter;
-}
-
-void *next_primitive_iterator(RenderPrimitiveIterator *iter)
-{
-       if(iter->buckets) {
-               if(iter->bpr && iter->bprindex >= iter->bpr->totprim) {
-                       iter->bpr= iter->bpr->next;
-                       iter->bprindex= 0;
-               }
-
-               while(iter->bpr == NULL) {
-                       if(iter->listindex == iter->totlist)
-                               return NULL;
-
-                       iter->bpr= iter->list[iter->listindex++]->first;
-                       iter->bprindex= 0;
-               }
-
-               return iter->bpr->prim[iter->bprindex++];
-       }
-       else {
-               if(!iter->obi)
-                       return NULL;
-
-               if(iter->index >= iter->tot) {
-                       while((iter->obi=iter->obi->next) && !iter->obi->obr->totstrand)
-                               iter->obi= iter->obi->next;
-
-                       if(iter->obi)
-                               iter->tot= iter->obi->obr->totstrand;
-                       else
-                               return NULL;
-               }
-
-               if(iter->index < iter->tot) {
-                       if((iter->index & 255)==0)
-                               iter->strand= iter->obi->obr->strandnodes[iter->index>>8].strand;
-                       else
-                               iter->strand++;
-
-                       return iter->strand;
-               }
-               else
-                       return NULL;
-       }
-}
-
-void free_primitive_iterator(RenderPrimitiveIterator *iter)
-{
-       MEM_freeN(iter);
-}
 
 /* *************** */
 
@@ -422,45 +183,6 @@ void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint)
 
 /* *************** */
 
-typedef struct StrandPart {
-       Render *re;
-       ZSpan *zspan;
-
-       RenderLayer *rl;
-       ShadeResult *result;
-       float *pass;
-       int *rectz, *outrectz;
-       long *rectdaps;
-       unsigned short *mask;
-       int rectx, recty;
-       int addpassflag, addzbuf, sample;
-
-       StrandSegment *segment;
-       GHash *hash;
-       StrandPoint point1, point2;
-       ShadeSample ssamp1, ssamp2, ssamp;
-       float t[3], s[3];
-} StrandPart;
-
-typedef struct StrandSortSegment {
-       struct StrandSortSegment *next;
-       int obi, strand, segment;
-       float z;
-} StrandSortSegment;
-
-static int compare_strand_segment(const void *poin1, const void *poin2)
-{
-       const StrandSortSegment *seg1= (const StrandSortSegment*)poin1;
-       const StrandSortSegment *seg2= (const StrandSortSegment*)poin2;
-
-       if(seg1->z < seg2->z)
-               return -1;
-       else if(seg1->z == seg2->z)
-               return 0;
-       else
-               return 1;
-}
-
 static void interpolate_vec1(float *v1, float *v2, float t, float negt, float *v)
 {
        v[0]= negt*v1[0] + t*v2[0];
@@ -481,7 +203,7 @@ static void interpolate_vec4(float *v1, float *v2, float t, float negt, float *v
        v[3]= negt*v1[3] + t*v2[3];
 }
 
-static void interpolate_shade_result(ShadeResult *shr1, ShadeResult *shr2, float t, ShadeResult *shr, int addpassflag)
+void interpolate_shade_result(ShadeResult *shr1, ShadeResult *shr2, float t, ShadeResult *shr, int addpassflag)
 {
        float negt= 1.0f - t;
 
@@ -517,20 +239,7 @@ static void interpolate_shade_result(ShadeResult *shr1, ShadeResult *shr2, float
        }
 }
 
-static void add_strand_obindex(RenderLayer *rl, int offset, ObjectRen *obr)
-{
-       RenderPass *rpass;
-       
-       for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
-               if(rpass->passtype == SCE_PASS_INDEXOB) {
-                       float *fp= rpass->rect + offset;
-                       *fp= (float)obr->ob->index;
-                       break;
-               }
-       }
-}
-
-static void strand_apply_shaderesult_alpha(ShadeResult *shr, float alpha)
+void strand_apply_shaderesult_alpha(ShadeResult *shr, float alpha)
 {
        if(alpha < 1.0f) {
                shr->combined[0] *= alpha;
@@ -547,6 +256,191 @@ static void strand_apply_shaderesult_alpha(ShadeResult *shr, float alpha)
        }
 }
 
+void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, StrandPoint *spoint)
+{
+       ShadeInput *shi= ssamp->shi;
+       ShadeResult *shr= ssamp->shr;
+       VlakRen vlr;
+
+       memset(&vlr, 0, sizeof(vlr));
+       vlr.flag= R_SMOOTH;
+       if(sseg->buffer->ma->mode & MA_TANGENT_STR)
+               vlr.flag |= R_TANGENT;
+
+       shi->vlr= &vlr;
+       shi->strand= sseg->strand;
+       shi->obi= sseg->obi;
+       shi->obr= sseg->obi->obr;
+
+       /* cache for shadow */
+       shi->samplenr= ssamp->samplenr++;
+
+       shade_input_set_strand(shi, sseg->strand, spoint);
+       shade_input_set_strand_texco(shi, sseg->strand, sseg->v[1], spoint);
+       
+       /* init material vars */
+       // note, keep this synced with render_types.h
+       memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));
+       shi->har= shi->mat->har;
+       
+       /* shade */
+       shade_samples_do_AO(ssamp);
+       shade_input_do_shade(shi, shr);
+
+       /* apply simplification */
+       strand_apply_shaderesult_alpha(shr, spoint->alpha);
+
+       /* include lamphalos for strand, since halo layer was added already */
+       if(re->flag & R_LAMPHALO)
+               if(shi->layflag & SCE_LAY_HALO)
+                       renderspothalo(shi, shr->combined, shr->combined[3]);
+       
+       shi->strand= NULL;
+}
+
+/* *************** */
+
+struct StrandShadeCache {
+       GHash *resulthash;
+       GHash *refcounthash;
+       MemArena *memarena;
+};
+
+StrandShadeCache *strand_shade_cache_create()
+{
+       StrandShadeCache *cache;
+
+       cache= MEM_callocN(sizeof(StrandShadeCache), "StrandShadeCache");
+       cache->resulthash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+       cache->refcounthash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+       cache->memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
+       
+       return cache;
+}
+
+void strand_shade_cache_free(StrandShadeCache *cache)
+{
+       BLI_ghash_free(cache->refcounthash, NULL, NULL);
+       BLI_ghash_free(cache->resulthash, NULL, (GHashValFreeFP)MEM_freeN);
+       BLI_memarena_free(cache->memarena);
+       MEM_freeN(cache);
+}
+
+static void strand_shade_get(Render *re, StrandShadeCache *cache, ShadeSample *ssamp, StrandSegment *sseg, StrandVert *svert)
+{
+       ShadeResult *hashshr;
+       StrandPoint p;
+       int *refcount;
+
+       hashshr= BLI_ghash_lookup(cache->resulthash, svert);
+       refcount= BLI_ghash_lookup(cache->refcounthash, svert);
+
+       if(!hashshr) {
+               /* not shaded yet, shade and insert into hash */
+               p.t= (sseg->v[1] == svert)? 0.0f: 1.0f;
+               strand_eval_point(sseg, &p);
+               strand_shade_point(re, ssamp, sseg, &p);
+
+               hashshr= MEM_callocN(sizeof(ShadeResult), "HashShadeResult");
+               *hashshr= ssamp->shr[0];
+               BLI_ghash_insert(cache->resulthash, svert, hashshr);
+       }
+       else
+               /* already shaded, just copy previous result from hash */
+               ssamp->shr[0]= *hashshr;
+       
+       /* lower reference count and remove if not needed anymore by any samples */
+       (*refcount)--;
+       if(*refcount == 0) {
+               BLI_ghash_remove(cache->resulthash, svert, NULL, (GHashValFreeFP)MEM_freeN);
+               BLI_ghash_remove(cache->refcounthash, svert, NULL, NULL);
+       }
+}
+
+void strand_shade_segment(Render *re, StrandShadeCache *cache, StrandSegment *sseg, ShadeSample *ssamp, float t, float s, int addpassflag)
+{
+       ShadeResult shr1, shr2;
+
+       /* get shading for two endpoints and interpolate */
+       strand_shade_get(re, cache, ssamp, sseg, sseg->v[1]);
+       shr1= ssamp->shr[0];
+       strand_shade_get(re, cache, ssamp, sseg, sseg->v[2]);
+       shr2= ssamp->shr[0];
+
+       interpolate_shade_result(&shr1, &shr2, t, ssamp->shr, addpassflag);
+
+       /* apply alpha along width */
+       if(sseg->buffer->widthfade != 0.0f) {
+               s = 1.0f - pow(fabs(s), sseg->buffer->widthfade);
+
+               strand_apply_shaderesult_alpha(ssamp->shr, s);
+       }
+}
+
+void strand_shade_unref(StrandShadeCache *cache, StrandVert *svert)
+{
+       int *refcount;
+
+       /* lower reference count and remove if not needed anymore by any samples */
+       refcount= BLI_ghash_lookup(cache->refcounthash, svert);
+
+       (*refcount)--;
+       if(*refcount == 0) {
+               BLI_ghash_remove(cache->resulthash, svert, NULL, (GHashValFreeFP)MEM_freeN);
+               BLI_ghash_remove(cache->refcounthash, svert, NULL, NULL);
+       }
+}
+
+static void strand_shade_refcount(StrandShadeCache *cache, StrandVert *svert)
+{
+       int *refcount= BLI_ghash_lookup(cache->refcounthash, svert);
+
+       if(!refcount) {
+               refcount= BLI_memarena_alloc(cache->memarena, sizeof(int));
+               *refcount= 1;
+               BLI_ghash_insert(cache->refcounthash, svert, refcount);
+       }
+       else
+               (*refcount)++;
+}
+
+/* *************** */
+
+typedef struct StrandPart {
+       Render *re;
+       ZSpan *zspan;
+
+       APixstrand *apixbuf;
+       int *rectz;
+       long *rectdaps;
+       int rectx, recty;
+       int sample;
+
+       StrandSegment *segment;
+       float t[3], s[3];
+
+       StrandShadeCache *cache;
+} StrandPart;
+
+typedef struct StrandSortSegment {
+       struct StrandSortSegment *next;
+       int obi, strand, segment;
+       float z;
+} StrandSortSegment;
+
+static int compare_strand_segment(const void *poin1, const void *poin2)
+{
+       const StrandSortSegment *seg1= (const StrandSortSegment*)poin1;
+       const StrandSortSegment *seg2= (const StrandSortSegment*)poin2;
+
+       if(seg1->z > seg2->z)
+               return -1;
+       else if(seg1->z == seg2->z)
+               return 0;
+       else
+               return 1;
+}
+
 static void do_strand_point_project(float winmat[][4], ZSpan *zspan, float *co, float *hoco, float *zco)
 {
        projectvert(co, winmat, hoco);
@@ -564,69 +458,59 @@ static void strand_project_point(float winmat[][4], float winx, float winy, Stra
        spoint->y= spoint->hoco[1]*div*winy*0.5f;
 }
 
-static void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, StrandPoint *spoint);
-
-static void strand_shade_get(StrandPart *spart, int lookup, ShadeSample *ssamp, StrandPoint *spoint, StrandVert *svert, StrandSegment *sseg)
+static APixstrand *addpsmainAstrand(ListBase *lb)
 {
-       ShadeResult *hashshr;
+       APixstrMain *psm;
 
-       if(lookup) {
-               hashshr= BLI_ghash_lookup(spart->hash, svert);
+       psm= MEM_mallocN(sizeof(APixstrMain), "addpsmainA");
+       BLI_addtail(lb, psm);
+       psm->ps= MEM_callocN(4096*sizeof(APixstrand),"pixstr");
 
-               if(!hashshr) {
-                       strand_shade_point(spart->re, ssamp, sseg, spoint);
-
-                       hashshr= MEM_callocN(sizeof(ShadeResult), "HashShadeResult");
-                       *hashshr= ssamp->shr[0];
-                       BLI_ghash_insert(spart->hash, svert, hashshr);
-               }
-               else {
-                       ssamp->shr[0]= *hashshr;
-                       BLI_ghash_remove(spart->hash, svert, NULL, (GHashValFreeFP)MEM_freeN);
-               }
-       }
-       else
-               strand_shade_point(spart->re, ssamp, sseg, spoint);
+       return psm->ps;
 }
 
-static void strand_shade_segment(StrandPart *spart)
+static APixstrand *addpsAstrand(ZSpan *zspan)
 {
-       StrandSegment *sseg= spart->segment;
-       int first, last;
-
-       if(!sseg->shaded) {
-               first= (sseg->v[1] == &sseg->strand->vert[0]);
-               last= (sseg->v[2] == &sseg->strand->vert[sseg->strand->totvert-1]);
-
-               strand_shade_get(spart, !first, &spart->ssamp1, &sseg->point1, sseg->v[1], sseg);
-               strand_shade_get(spart, !last, &spart->ssamp2, &sseg->point2, sseg->v[2], sseg);
-               sseg->shaded= 1;
+       /* make new PS */
+       if(zspan->apstrandmcounter==0) {
+               zspan->curpstrand= addpsmainAstrand(zspan->apsmbase);
+               zspan->apstrandmcounter= 4095;
+       }
+       else {
+               zspan->curpstrand++;
+               zspan->apstrandmcounter--;
        }
+       return zspan->curpstrand;
 }
 
-static void do_strand_blend(void *handle, int x, int y, float u, float v, float z)
+static void do_strand_fillac(void *handle, int x, int y, float u, float v, float z)
 {
        StrandPart *spart= (StrandPart*)handle;
-       StrandBuffer *buffer= spart->segment->buffer;
-       ShadeResult *shr;
-       float /**pass,*/ t, s;
-       int offset, zverg, bufferz;
+       StrandShadeCache *cache= spart->cache;
+       StrandSegment *sseg= spart->segment;
+       APixstrand *apn, *apnew;
+       float t, s;
+       int offset, mask, obi, strnr, seg, zverg, bufferz;
 
-       /* check again solid z-buffer */
        offset = y*spart->rectx + x;
+       obi= sseg->obi - spart->re->objectinstance;
+       strnr= sseg->strand->index + 1;
+       seg= sseg->v[1] - sseg->strand->vert;
+       mask= (1<<spart->sample);
+
+       /* check against solid z-buffer */
        zverg= (int)z;
 
        if(spart->rectdaps) {
                /* find the z of the sample */
                PixStr *ps;
                long *rd= spart->rectdaps + offset;
-               int sample= (1<<spart->sample);
                
                bufferz= 0x7FFFFFFF;
                
                if(*rd) {       
                        for(ps= (PixStr *)(*rd); ps; ps= ps->next) {
-                               if(sample & ps->mask) {
+                               if(mask & ps->mask) {
                                        bufferz= ps->z;
                                        break;
                                }
@@ -636,48 +520,37 @@ static void do_strand_blend(void *handle, int x, int y, float u, float v, float
        else
                bufferz= spart->rectz[offset];
 
-       if(zverg < bufferz) {
-               /* fill in output z-buffer if needed */
-               if(spart->addzbuf)
-                       if(zverg < spart->outrectz[offset])
-                               spart->outrectz[offset]= zverg;
-
-               /* check alpha limit */
-               shr= spart->result + offset*(spart->re->osa? spart->re->osa: 1);
-               if(shr[spart->sample].combined[3]>0.999f)
-                       return;
-
-               /* shade points if not shaded yet */
-               strand_shade_segment(spart);
+#define CHECK_ADD(n) \
+       if(apn->p[n]==strnr && apn->obi[n]==obi && apn->seg[n]==seg) \
+       { if(!(apn->mask[n] & mask)) { apn->mask[n] |= mask; apn->v[n] += t; apn->u[n] += s; } break; }
+#define CHECK_ASSIGN(n) \
+       if(apn->p[n]==0) \
+       {apn->obi[n]= obi; apn->p[n]= strnr; apn->z[n]= zverg; apn->mask[n]= mask; apn->v[n]= t; apn->u[n]= s; apn->seg[n]= seg; break; }
 
-               /* interpolate shading from two control points */
+       /* add to pixel list */
+       if(zverg < bufferz) {
                t = u*spart->t[0] + v*spart->t[1] + (1.0f-u-v)*spart->t[2];
-               interpolate_shade_result(spart->ssamp1.shr, spart->ssamp2.shr, t,
-                       spart->ssamp.shr, spart->addpassflag);
-
-               /* alpha along width */
-               if(buffer->widthfade != 0.0f) {
-                       s = fabs(u*spart->s[0] + v*spart->s[1] + (1.0f-u-v)*spart->s[2]);
-                       s = 1.0f - pow(s, buffer->widthfade);
-
-                       strand_apply_shaderesult_alpha(spart->ssamp.shr, s);
+               s = fabs(u*spart->s[0] + v*spart->s[1] + (1.0f-u-v)*spart->s[2]);
+
+               apn= spart->apixbuf + offset;
+               while(apn) {
+                       CHECK_ADD(0);
+                       CHECK_ADD(1);
+                       CHECK_ADD(2);
+                       CHECK_ADD(3);
+                       CHECK_ASSIGN(0);
+                       CHECK_ASSIGN(1);
+                       CHECK_ASSIGN(2);
+                       CHECK_ASSIGN(3);
+
+                       apnew= addpsAstrand(spart->zspan);
+                       SWAP(APixstrand, *apnew, *apn);
+                       apn->next= apnew;
+                       CHECK_ASSIGN(0);
                }
 
-               /* add in shaderesult array for part */
-               spart->ssamp.shi[0].mask= (1<<spart->sample);
-               addtosamp_shr(shr, &spart->ssamp, spart->addpassflag);
-               spart->mask[offset] |= (1<<spart->sample);
-
-#if 0
-               /* fill in pass for preview */
-               if(spart->sample == 0) {
-                       pass= spart->pass + offset*4;
-                       QUATCOPY(pass, shr->combined);
-               }
-#endif
-
-               if(spart->addpassflag & SCE_PASS_INDEXOB)
-                       add_strand_obindex(spart->rl, offset, buffer->obr);
+               strand_shade_refcount(cache, sseg->v[1]);
+               strand_shade_refcount(cache, sseg->v[2]);
        }
 }
 
@@ -701,46 +574,6 @@ static int strand_test_clip(float winmat[][4], ZSpan *zspan, float *bounds, floa
        return clipflag;
 }
 
-static void strand_shade_point(Render *re, ShadeSample *ssamp, StrandSegment *sseg, StrandPoint *spoint)
-{
-       ShadeInput *shi= ssamp->shi;
-       ShadeResult *shr= ssamp->shr;
-       VlakRen vlr;
-
-       memset(&vlr, 0, sizeof(vlr));
-       vlr.flag= R_SMOOTH;
-       if(sseg->buffer->ma->mode & MA_TANGENT_STR)
-               vlr.flag |= R_TANGENT;
-
-       shi->vlr= &vlr;
-       shi->strand= sseg->strand;
-       shi->obi= sseg->obi;
-       shi->obr= sseg->obi->obr;
-
-       /* cache for shadow */
-       shi->samplenr++;
-
-       shade_input_set_strand(shi, sseg->strand, spoint);
-       shade_input_set_strand_texco(shi, sseg->strand, sseg->v[1], spoint);
-       
-       /* init material vars */
-       // note, keep this synced with render_types.h
-       memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));
-       shi->har= shi->mat->har;
-       
-       /* shade */
-       shade_samples_do_AO(ssamp);
-       shade_input_do_shade(shi, shr);
-
-       /* apply simplification */
-       strand_apply_shaderesult_alpha(shr, spoint->alpha);
-
-       /* include lamphalos for strand, since halo layer was added already */
-       if(re->flag & R_LAMPHALO)
-               if(shi->layflag & SCE_LAY_HALO)
-                       renderspothalo(shi, shr->combined, shr->combined[3]);
-}
-
 static void do_scanconvert_strand(Render *re, StrandPart *spart, ZSpan *zspan, float t, float dt, float *co1, float *co2, float *co3, float *co4, int sample)
 {
        float jco1[3], jco2[3], jco3[3], jco4[3], jx, jy;
@@ -777,14 +610,14 @@ static void do_scanconvert_strand(Render *re, StrandPart *spart, ZSpan *zspan, f
        spart->s[1]= 1.0f;
        spart->t[2]= t;
        spart->s[2]= 1.0f;
-       zspan_scanconvert_strand(zspan, spart, jco1, jco2, jco3, do_strand_blend);
+       zspan_scanconvert_strand(zspan, spart, jco1, jco2, jco3, do_strand_fillac);
        spart->t[0]= t-dt;
        spart->s[0]= -1.0f;
        spart->t[1]= t;
        spart->s[1]= 1.0f;
        spart->t[2]= t;
        spart->s[2]= -1.0f;
-       zspan_scanconvert_strand(zspan, spart, jco1, jco3, jco4, do_strand_blend);
+       zspan_scanconvert_strand(zspan, spart, jco1, jco3, jco4, do_strand_fillac);
 }
 
 static void strand_render(Render *re, StrandSegment *sseg, float winmat[][4], StrandPart *spart, ZSpan *zspan, int totzspan, StrandPoint *p1, StrandPoint *p2)
@@ -909,148 +742,38 @@ void render_strand_segment(Render *re, float winmat[][4], StrandPart *spart, ZSp
                strand_render(re, sseg, winmat, spart, zspan, totzspan, p1, p2);
 }
 
-static void zbuffer_strands_filter(Render *re, RenderPart *pa, RenderLayer *rl, StrandPart *spart, float *pass)
-{
-       RenderResult *rr= pa->result;
-       ShadeResult *shr, *shrrect= spart->result;
-       float *passrect= pass, alpha, sampalpha;
-       long *rdrect;
-       int osa, x, y, a, crop= 0, offs=0, od;
-
-       osa= (re->osa? re->osa: 1);
-       sampalpha= 1.0f/osa;
-
-       /* filtered render, for now we assume only 1 filter size */
-       if(pa->crop) {
-               crop= 1;
-               offs= pa->rectx + 1;
-               passrect+= 4*offs;
-               shrrect+= offs*osa;
-       }
-
-       rdrect= pa->rectdaps;
-
-       /* zero alpha pixels get speed vector max again */
-       if(spart->addpassflag & SCE_PASS_VECTOR)
-               if(rl->layflag & SCE_LAY_SOLID)
-                       reset_sky_speedvectors(pa, rl, rl->scolrect);
-
-       /* init scanline updates */
-       rr->renrect.ymin= 0;
-       rr->renrect.ymax= -pa->crop;
-       rr->renlay= rl;
-       
-       /* filter the shade results */
-       for(y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++, rr->renrect.ymax++) {
-               pass= passrect;
-               shr= shrrect;
-               od= offs;
-               
-               for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, shr+=osa, pass+=4, od++) {
-                       if(spart->mask[od] == 0) {
-                               if(spart->addpassflag & SCE_PASS_VECTOR) 
-                                       add_transp_speed(rl, od, NULL, 0.0f, rdrect);
-                       }
-                       else {
-                               alpha= 0.0f;
-
-                               if(re->osa == 0) {
-                                       addAlphaUnderFloat(pass, shr->combined);
-                               }
-                               else {
-                                       /* note; cannot use pass[3] for alpha due to filtermask */
-                                       for(a=0; a<re->osa; a++) {
-                                               add_filt_fmask(1<<a, shr[a].combined, pass, rr->rectx);
-                                               alpha += shr[a].combined[3];
-                                       }
-                               }
-
-                               if(spart->addpassflag) {
-                                       alpha *= sampalpha;
-
-                                       /* merge all in one, and then add */
-                                       merge_transp_passes(rl, shr);
-                                       add_transp_passes(rl, od, shr, alpha);
-
-                                       if(spart->addpassflag & SCE_PASS_VECTOR)
-                                               add_transp_speed(rl, od, shr->winspeed, alpha, rdrect);
-                               }
-                       }
-               }
-
-               shrrect+= pa->rectx*osa;
-               passrect+= 4*pa->rectx;
-               offs+= pa->rectx;
-       }
-
-       /* disable scanline updating */
-       rr->renlay= NULL;
-}
-
 /* render call to fill in strands */
-unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *rl, float *pass)
+int zbuffer_strands_abuf(Render *re, RenderPart *pa, RenderLayer *rl, APixstrand *apixbuf, ListBase *apsmbase, StrandShadeCache *cache)
 {
-       //struct RenderPrimitiveIterator *iter;
        ObjectRen *obr;
        ObjectInstanceRen *obi;
        ZSpan zspan;
        StrandRen *strand=0;
        StrandVert *svert;
+       StrandBound *sbound;
        StrandPart spart;
        StrandSegment sseg;
        StrandSortSegment *sortsegments = NULL, *sortseg, *firstseg;
        MemArena *memarena;
        float z[4], bounds[4], winmat[4][4];
-       int a, b, i, resultsize, totsegment, clip[4];
+       int a, b, c, i, totsegment, clip[4];
 
        if(re->test_break())
-               return NULL;
+               return 0;
        if(re->totstrand == 0)
-               return NULL;
+               return 0;
 
        /* setup StrandPart */
        memset(&spart, 0, sizeof(spart));
 
        spart.re= re;
-       spart.rl= rl;
-       spart.pass= pass;
        spart.rectx= pa->rectx;
        spart.recty= pa->recty;
-       spart.rectz= pa->rectz;
+       spart.apixbuf= apixbuf;
+       spart.zspan= &zspan;
        spart.rectdaps= pa->rectdaps;
-       spart.addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED);
-       spart.addzbuf= rl->passflag & SCE_PASS_Z;
-
-       if(re->osa) resultsize= pa->rectx*pa->recty*re->osa;
-       else resultsize= pa->rectx*pa->recty;
-       spart.result= MEM_callocN(sizeof(ShadeResult)*resultsize, "StrandPartResult");
-       spart.mask= MEM_callocN(pa->rectx*pa->recty*sizeof(short), "StrandPartMask");
-
-       if(spart.addpassflag & SCE_PASS_VECTOR) {
-               /* initialize speed vectors */
-               for(a=0; a<resultsize; a++) {
-                       spart.result[a].winspeed[0]= PASS_VECTOR_MAX;
-                       spart.result[a].winspeed[1]= PASS_VECTOR_MAX;
-                       spart.result[a].winspeed[2]= PASS_VECTOR_MAX;
-                       spart.result[a].winspeed[3]= PASS_VECTOR_MAX;
-               }
-       }
-
-       if(spart.addzbuf) {
-               /* duplicate rectz so we can read from the old buffer, while
-                * writing new z values */
-               spart.rectz= MEM_dupallocN(pa->rectz);
-               spart.outrectz= pa->rectz;
-       }
-
-       shade_sample_initialize(&spart.ssamp1, pa, rl);
-       shade_sample_initialize(&spart.ssamp2, pa, rl);
-       shade_sample_initialize(&spart.ssamp, pa, rl);
-       spart.ssamp1.shi[0].sample= 0;
-       spart.ssamp2.shi[0].sample= 1;
-       spart.ssamp1.tot= 1;
-       spart.ssamp2.tot= 1;
-       spart.ssamp.tot= 1;
+       spart.rectz= pa->rectz;
+       spart.cache= cache;
 
        zbuf_alloc_span(&zspan, pa->rectx, pa->recty, re->clipcrop);
 
@@ -1065,86 +788,83 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r
        zspan.zofsx -= 0.5f;
        zspan.zofsy -= 0.5f;
 
+       zspan.apsmbase= apsmbase;
+
        /* clipping setup */
        bounds[0]= (2*pa->disprect.xmin - re->winx-1)/(float)re->winx;
        bounds[1]= (2*pa->disprect.xmax - re->winx+1)/(float)re->winx;
        bounds[2]= (2*pa->disprect.ymin - re->winy-1)/(float)re->winy;
        bounds[3]= (2*pa->disprect.ymax - re->winy+1)/(float)re->winy;
 
-       /* sort segments */
-       //iter= init_primitive_iterator(re, re->strandbuckets, pa);
-
        memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
        firstseg= NULL;
        sortseg= sortsegments;
        totsegment= 0;
 
-       //while((strand = next_primitive_iterator(iter))) {
+       /* for all object instances */
        for(obi=re->instancetable.first, i=0; obi; obi=obi->next, i++) {
                obr= obi->obr;
 
+               if(!obr->strandbuf || !(obr->strandbuf->lay & rl->lay))
+                       continue;
+
+               /* compute matrix and try clipping whole object */
                if(obi->flag & R_TRANSFORMED)
                        zbuf_make_winmat(re, obi->mat, winmat);
                else
                        zbuf_make_winmat(re, NULL, winmat);
 
-               for(a=0; a<obr->totstrand; a++) {
-                       if((a & 255)==0) strand= obr->strandnodes[a>>8].strand;
-                       else strand++;
+               if(clip_render_object(obi->obr->boundbox, bounds, winmat))
+                       continue;
 
-                       if(re->test_break())
-                               break;
-
-                       if(!(strand->buffer->lay & rl->lay))
+               /* for each bounding box containing a number of strands */
+               sbound= obr->strandbuf->bound;
+               for(c=0; c<obr->strandbuf->totbound; c++, sbound++) {
+                       if(clip_render_object(sbound->boundbox, bounds, winmat))
                                continue;
 
-#if 0
-                       if(strand->clip)
-                               continue;
-#endif
+                       /* for each strand in this bounding box */
+                       for(a=sbound->start; a<sbound->end; a++) {
+                               strand= RE_findOrAddStrand(obr, a);
+                               svert= strand->vert;
 
-                       svert= strand->vert;
+                               /* keep clipping and z depth for 4 control points */
+                               clip[1]= strand_test_clip(winmat, &zspan, bounds, svert->co, &z[1]);
+                               clip[2]= strand_test_clip(winmat, &zspan, bounds, (svert+1)->co, &z[2]);
+                               clip[0]= clip[1]; z[0]= z[1];
 
-                       /* keep clipping and z depth for 4 control points */
-                       clip[1]= strand_test_clip(winmat, &zspan, bounds, svert->co, &z[1]);
-                       clip[2]= strand_test_clip(winmat, &zspan, bounds, (svert+1)->co, &z[2]);
-                       clip[0]= clip[1]; z[0]= z[1];
+                               for(b=0; b<strand->totvert-1; b++, svert++) {
+                                       /* compute 4th point clipping and z depth */
+                                       if(b < strand->totvert-2) {
+                                               clip[3]= strand_test_clip(winmat, &zspan, bounds, (svert+2)->co, &z[3]);
+                                       }
+                                       else {
+                                               clip[3]= clip[2]; z[3]= z[2];
+                                       }
 
-                       for(b=0; b<strand->totvert-1; b++, svert++) {
-                               /* compute 4th point clipping and z depth */
-                               if(b < strand->totvert-2) {
-                                       clip[3]= strand_test_clip(winmat, &zspan, bounds, (svert+2)->co, &z[3]);
-                               }
-                               else {
-                                       clip[3]= clip[2]; z[3]= z[2];
-                               }
+                                       /* check clipping and add to sortsegments buffer */
+                                       if(!(clip[0] & clip[1] & clip[2] & clip[3])) {
+                                               sortseg= BLI_memarena_alloc(memarena, sizeof(StrandSortSegment));
+                                               sortseg->obi= i;
+                                               sortseg->strand= strand->index;
+                                               sortseg->segment= b;
 
-                               /* check clipping and add to sortsegments buffer */
-                               if(!(clip[0] & clip[1] & clip[2] & clip[3])) {
-                                       sortseg= BLI_memarena_alloc(memarena, sizeof(StrandSortSegment));
-                                       sortseg->obi= i;
-                                       sortseg->strand= strand->index;
-                                       sortseg->segment= b;
+                                               sortseg->z= 0.5f*(z[1] + z[2]);
 
-                                       sortseg->z= 0.5f*(z[1] + z[2]);
+                                               sortseg->next= firstseg;
+                                               firstseg= sortseg;
+                                               totsegment++;
+                                       }
 
-                                       sortseg->next= firstseg;
-                                       firstseg= sortseg;
-                                       totsegment++;
+                                       /* shift clipping and z depth */
+                                       clip[0]= clip[1]; z[0]= z[1];
+                                       clip[1]= clip[2]; z[1]= z[2];
+                                       clip[2]= clip[3]; z[2]= z[3];
                                }
-
-                               /* shift clipping and z depth */
-                               clip[0]= clip[1]; z[0]= z[1];
-                               clip[1]= clip[2]; z[1]= z[2];
-                               clip[2]= clip[3]; z[2]= z[3];
                        }
                }
        }
 
-#if 0
-       free_primitive_iterator(iter);
-#endif
-
        if(!re->test_break()) {
                /* convert list to array and sort */
                sortsegments= MEM_mallocN(sizeof(StrandSortSegment)*totsegment, "StrandSortSegment");
@@ -1155,8 +875,6 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r
 
        BLI_memarena_free(memarena);
 
-       spart.hash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
-
        if(!re->test_break()) {
                /* render segments in sorted order */
                sortseg= sortsegments;
@@ -1187,133 +905,15 @@ unsigned short *zbuffer_strands_shade(Render *re, RenderPart *pa, RenderLayer *r
                }
        }
 
-       // TODO printf(">>> %d\n", BLI_ghash_size(spart.hash));
-       BLI_ghash_free(spart.hash, NULL, (GHashValFreeFP)MEM_freeN);
-
-       zbuffer_strands_filter(re, pa, rl, &spart, pass);
-
-       /* free */
-       MEM_freeN(spart.result);
-
-       if(spart.addzbuf)
-               MEM_freeN(spart.rectz);
-
        if(sortsegments)
                MEM_freeN(sortsegments);
        
        zbuf_free_span(&zspan);
 
-       if(!(re->osa && (rl->layflag & SCE_LAY_SOLID))) {
-               MEM_freeN(spart.mask);
-               spart.mask= NULL;
-       }
-
-       return spart.mask;
+       return totsegment;
 }
 
-void project_strands(Render *re, void (*projectfunc)(float *, float mat[][4], float *),  int do_pano, int do_buckets)
-{
-#if 0
-       ObjectRen *obr;
-       StrandRen *strand = NULL;
-       StrandVert *svert;
-       float hoco[4], min[2], max[2], bucketco[2], vec[3];
-       int a, b;
-       /* float bmin[3], bmax[3], bpad[3], padding[2]; */
-       
-       if(re->strandbuckets) {
-               free_buckets(re->strandbuckets);
-               re->strandbuckets= NULL;
-       }
-
-       if(re->totstrand == 0)
-               return;
-       
-       if(do_buckets)
-               re->strandbuckets= init_buckets(re);
-
-       /* calculate view coordinates (and zbuffer value) */
-       for(obr=re->objecttable.first; obr; obr=obr->next) {
-               for(a=0; a<obr->totstrand; a++) {
-                       if((a & 255)==0) strand= obr->strandnodes[a>>8].strand;
-                       else strand++;
-
-                       strand->clip= ~0;
-
-#if 0
-                       if(!(strand->buffer->flag & R_STRAND_BSPLINE)) {
-                               INIT_MINMAX(bmin, bmax);
-                               svert= strand->vert;
-                               for(b=0; b<strand->totvert; b++, svert++)
-                                       DO_MINMAX(svert->co, bmin, bmax)
-
-                               bpad[0]= (bmax[0]-bmin[0])*0.2f;
-                               bpad[1]= (bmax[1]-bmin[1])*0.2f;
-                               bpad[2]= (bmax[2]-bmin[2])*0.2f;
-                       }
-                       else
-                               bpad[0]= bpad[1]= bpad[2]= 0.0f;
-
-                       ma= strand->buffer->ma;
-                       width= MAX2(ma->strand_sta, ma->strand_end);
-                       if(strand->buffer->flag & R_STRAND_B_UNITS) {
-                               bpad[0] += 0.5f*width;
-                               bpad[1] += 0.5f*width;
-                               bpad[2] += 0.5f*width;
-                       }
-#endif
-
-                       INIT_MINMAX2(min, max);
-                       svert= strand->vert;
-                       for(b=0; b<strand->totvert; b++, svert++) {
-                               //VECADD(vec, svert->co, bpad);
-
-                               /* same as VertRen */
-                               if(do_pano) {
-                                       vec[0]= re->panoco*svert->co[0] + re->panosi*svert->co[2];
-                                       vec[1]= svert->co[1];
-                                       vec[2]= -re->panosi*svert->co[0] + re->panoco*svert->co[2];
-                               }
-                               else
-                                       VECCOPY(vec, svert->co)
-
-                               /* Go from wcs to hcs ... */
-                               projectfunc(vec, re->winmat, hoco);
-                               /* ... and clip in that system. */
-                               strand->clip &= testclip(hoco);
-
-#if 0
-                               if(do_buckets) {
-                                       project_hoco_to_bucket(re->strandbuckets, hoco, bucketco);
-                                       DO_MINMAX2(bucketco, min, max);
-                               }
-#endif
-                       }
-
-#if 0
-                       if(do_buckets) {
-                               if(strand->buffer->flag & R_STRAND_BSPLINE) {
-                                       min[0] -= width;
-                                       min[1] -= width;
-                                       max[0] += width;
-                                       max[1] += width;
-                               }
-                               else {
-                                       /* catmull-rom stays within 1.2f bounds in object space,
-                                        * is this still true after projection? */
-                                       min[0] -= width + (max[0]-min[0])*0.2f;
-                                       min[1] -= width + (max[1]-min[1])*0.2f;
-                                       max[0] += width + (max[0]-min[0])*0.2f;
-                                       max[1] += width + (max[1]-min[1])*0.2f;
-                               }
-
-                               add_buckets_primitive(re->strandbuckets, min, max, strand);
-                       }
-#endif
-               }
-       }
-#endif
-}
+/* *************** */
 
 StrandSurface *cache_strand_surface(Render *re, ObjectRen *obr, DerivedMesh *dm, float mat[][4], int timeoffset)
 {
@@ -1382,3 +982,12 @@ void free_strand_surface(Render *re)
        BLI_freelistN(&re->strandsurface);
 }
 
+void strand_minmax(StrandRen *strand, float *min, float *max)
+{
+       StrandVert *svert;
+       int a;
+
+       for(a=0, svert=strand->vert; a<strand->totvert; a++, svert++)
+               DO_MINMAX(svert->co, min, max)
+}
+
index 6b103d4fce29aea66a7fe4cf8826772f31dbfaee..080a66e46a74de752f9fc97b7b95997c17d2d1c4 100644 (file)
@@ -2081,6 +2081,9 @@ void zbuffer_solid(RenderPart *pa, RenderLayer *rl, void(*fillfunc)(RenderPart*,
                        else
                                zbuf_make_winmat(&R, NULL, winmat);
 
+                       if(clip_render_object(obi->obr->boundbox, bounds, winmat))
+                               continue;
+
                        zbuf_project_cache_clear(cache, obr->totvert);
 
                        for(v=0; v<obr->totvlak; v++) {
@@ -2337,8 +2340,9 @@ void zbuffer_shadow(Render *re, float winmat[][4], LampRen *lar, int *rectz, int
        StrandSegment sseg;
        StrandRen *strand= NULL;
        StrandVert *svert;
+       StrandBound *sbound;
        float obwinmat[4][4], ho1[4], ho2[4], ho3[4], ho4[4];
-       int a, b, i, c1, c2, c3, c4, ok=1, lay= -1;
+       int a, b, c, i, c1, c2, c3, c4, ok=1, lay= -1;
 
        if(lar->mode & LA_LAYER) lay= lar->lay;
 
@@ -2374,6 +2378,9 @@ void zbuffer_shadow(Render *re, float winmat[][4], LampRen *lar, int *rectz, int
                else
                        Mat4CpyMat4(obwinmat, winmat);
 
+               if(clip_render_object(obi->obr->boundbox, NULL, obwinmat))
+                       continue;
+
                zbuf_project_cache_clear(cache, obr->totvert);
 
                /* faces */
@@ -2417,45 +2424,54 @@ void zbuffer_shadow(Render *re, float winmat[][4], LampRen *lar, int *rectz, int
                }
 
                /* strands */
-               for(a=0; a<obr->totstrand; a++) {
-                       if((a & 255)==0) strand= obr->strandnodes[a>>8].strand;
-                       else strand++;
+               if(obr->strandbuf) {
+                       /* for each bounding box containing a number of strands */
+                       sbound= obr->strandbuf->bound;
+                       for(c=0; c<obr->strandbuf->totbound; c++, sbound++) {
+                               if(clip_render_object(sbound->boundbox, NULL, obwinmat))
+                                       continue;
 
-                       sseg.obi= obi;
-                       sseg.buffer= strand->buffer;
-                       sseg.sqadaptcos= sseg.buffer->adaptcos;
-                       sseg.sqadaptcos *= sseg.sqadaptcos;
-                       sseg.strand= strand;
-                       svert= strand->vert;
+                               /* for each strand in this bounding box */
+                               for(a=sbound->start; a<sbound->end; a++) {
+                                       strand= RE_findOrAddStrand(obr, a);
+
+                                       sseg.obi= obi;
+                                       sseg.buffer= strand->buffer;
+                                       sseg.sqadaptcos= sseg.buffer->adaptcos;
+                                       sseg.sqadaptcos *= sseg.sqadaptcos;
+                                       sseg.strand= strand;
+                                       svert= strand->vert;
+
+                                       /* note, these conditions are copied in shadowbuf_autoclip() */
+                                       if(sseg.buffer->ma!= ma) {
+                                               ma= sseg.buffer->ma;
+                                               ok= 1;
+                                               if((ma->mode & MA_SHADBUF)==0) ok= 0;
+                                       }
 
-                       /* note, these conditions are copied in shadowbuf_autoclip() */
-                       if(sseg.buffer->ma!= ma) {
-                               ma= sseg.buffer->ma;
-                               ok= 1;
-                               if((ma->mode & MA_SHADBUF)==0) ok= 0;
-                       }
+                                       if(ok && (sseg.buffer->lay & lay)) {
+                                               zbuf_project_cache_clear(cache, strand->totvert);
 
-                       if(ok && (sseg.buffer->lay & lay)) {
-                               zbuf_project_cache_clear(cache, strand->totvert);
+                                               for(b=0; b<strand->totvert-1; b++, svert++) {
+                                                       sseg.v[0]= (b > 0)? (svert-1): svert;
+                                                       sseg.v[1]= svert;
+                                                       sseg.v[2]= svert+1;
+                                                       sseg.v[3]= (b < strand->totvert-2)? svert+2: svert+1;
 
-                               for(b=0; b<strand->totvert-1; b++, svert++) {
-                                       sseg.v[0]= (b > 0)? (svert-1): svert;
-                                       sseg.v[1]= svert;
-                                       sseg.v[2]= svert+1;
-                                       sseg.v[3]= (b < strand->totvert-2)? svert+2: svert+1;
+                                                       c1= zbuf_shadow_project(cache, sseg.v[0]-strand->vert, obwinmat, sseg.v[0]->co, ho1);
+                                                       c2= zbuf_shadow_project(cache, sseg.v[1]-strand->vert, obwinmat, sseg.v[1]->co, ho2);
+                                                       c3= zbuf_shadow_project(cache, sseg.v[2]-strand->vert, obwinmat, sseg.v[2]->co, ho3);
+                                                       c4= zbuf_shadow_project(cache, sseg.v[3]-strand->vert, obwinmat, sseg.v[3]->co, ho4);
 
-                                       c1= zbuf_shadow_project(cache, sseg.v[0]-strand->vert, obwinmat, sseg.v[0]->co, ho1);
-                                       c2= zbuf_shadow_project(cache, sseg.v[1]-strand->vert, obwinmat, sseg.v[1]->co, ho2);
-                                       c3= zbuf_shadow_project(cache, sseg.v[2]-strand->vert, obwinmat, sseg.v[2]->co, ho3);
-                                       c4= zbuf_shadow_project(cache, sseg.v[3]-strand->vert, obwinmat, sseg.v[3]->co, ho4);
+                                                       if(!(c1 & c2 & c3 & c4))
+                                                               render_strand_segment(re, winmat, NULL, &zspan, 1, &sseg);
+                                               }
+                                       }
 
-                                       if(!(c1 & c2 & c3 & c4))
-                                               render_strand_segment(re, winmat, NULL, &zspan, 1, &sseg);
+                                       if((a & 255)==255 && re->test_break()) 
+                                               break;
                                }
                        }
-
-                       if((a & 255)==255 && re->test_break()) 
-                               break;
                }
 
                if(re->test_break()) 
@@ -2599,6 +2615,9 @@ void zbuffer_sss(RenderPart *pa, unsigned int lay, void *handle, void (*func)(vo
                else
                        zbuf_make_winmat(&R, NULL, winmat);
 
+               if(clip_render_object(obi->obr->boundbox, bounds, winmat))
+                       continue;
+
                zbuf_project_cache_clear(cache, obr->totvert);
 
                for(v=0; v<obr->totvlak; v++) {
@@ -3286,7 +3305,6 @@ static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, un
                /* to center the sample position */
                zspan->zofsx -= 0.5f;
                zspan->zofsy -= 0.5f;
-               
        }
        
        /* we use this to test if nothing was filled in */
@@ -3303,6 +3321,9 @@ static int zbuffer_abuf(RenderPart *pa, APixstr *APixbuf, ListBase *apsmbase, un
                else
                        zbuf_make_winmat(&R, NULL, winmat);
 
+               if(clip_render_object(obi->obr->boundbox, bounds, winmat))
+                       continue;
+
                zbuf_project_cache_clear(cache, obr->totvert);
 
                for(v=0; v<obr->totvlak; v++) {
@@ -3438,12 +3459,11 @@ void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha, lo
        }
 }
 
-static void add_transp_obindex(RenderLayer *rl, int offset, int obi, int facenr)
+static void add_transp_obindex(RenderLayer *rl, int offset, int obi)
 {
        ObjectRen *obr= R.objectinstance[obi].obr;
-       VlakRen *vlr= RE_findOrAddVlak(obr, (facenr-1) & RE_QUAD_MASK);
 
-       if(vlr && obr->ob) {
+       if(obr->ob) {
                RenderPass *rpass;
                
                for(rpass= rl->passes.first; rpass; rpass= rpass->next) {
@@ -3591,21 +3611,22 @@ void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alph
                if(col) {
 
                        fp= rpass->rect + pixsize*offset;
-                       fp[0]= alpha*col[0] + (1.0f-alpha)*fp[0];
+                       fp[0]= col[0] + (1.0f-alpha)*fp[0];
                        if(pixsize==3) {
-                               fp[1]= alpha*col[1] + (1.0f-alpha)*fp[1];
-                               fp[2]= alpha*col[2] + (1.0f-alpha)*fp[2];
+                               fp[1]= col[1] + (1.0f-alpha)*fp[1];
+                               fp[2]= col[2] + (1.0f-alpha)*fp[2];
                        }
                }
        }
 }
 
-
 typedef struct ZTranspRow {
        int obi;
        int z;
        int p;
        int mask;
+       int segment;
+       float u, v;
 } ZTranspRow;
 
 static int vergzvlak(const void *a1, const void *a2)
@@ -3617,6 +3638,56 @@ static int vergzvlak(const void *a1, const void *a2)
        return 0;
 }
 
+static void shade_strand_samples(StrandShadeCache *cache, ShadeSample *ssamp, int x, int y, ZTranspRow *row, int addpassflag)
+{
+       StrandSegment sseg;
+       StrandVert *svert;
+       ObjectInstanceRen *obi;
+       ObjectRen *obr;
+
+       obi= R.objectinstance + row->obi;
+       obr= obi->obr;
+
+       sseg.obi= obi;
+       sseg.strand= RE_findOrAddStrand(obr, row->p-1);
+       sseg.buffer= sseg.strand->buffer;
+
+       svert= sseg.strand->vert + row->segment;
+       sseg.v[0]= (row->segment > 0)? (svert-1): svert;
+       sseg.v[1]= svert;
+       sseg.v[2]= svert+1;
+       sseg.v[3]= (row->segment < sseg.strand->totvert-2)? svert+2: svert+1;
+
+       ssamp->tot= 1;
+       strand_shade_segment(&R, cache, &sseg, ssamp, row->v, row->u, addpassflag);
+       ssamp->shi[0].mask= row->mask;
+}
+
+static void unref_strand_samples(StrandShadeCache *cache, ZTranspRow *row, int totface)
+{
+       StrandVert *svert;
+       ObjectInstanceRen *obi;
+       ObjectRen *obr;
+       StrandRen *strand;
+
+       /* remove references to samples that are not being rendered, but we still
+        * need to remove them so that the reference count of strand vertex shade
+        * samples correctly drops to zero */
+       while(totface > 0) {
+               totface--;
+
+               if(row[totface].segment != -1) {
+                       obi= R.objectinstance + row[totface].obi;
+                       obr= obi->obr;
+                       strand= RE_findOrAddStrand(obr, row[totface].p-1);
+                       svert= strand->vert + row[totface].segment;
+
+                       strand_shade_unref(cache, svert);
+                       strand_shade_unref(cache, svert+1);
+               }
+       }
+}
+
 static void shade_tra_samples_fill(ShadeSample *ssamp, int x, int y, int z, int obi, int facenr, int curmask)
 {
        ShadeInput *shi= ssamp->shi;
@@ -3674,8 +3745,13 @@ static void shade_tra_samples_fill(ShadeSample *ssamp, int x, int y, int z, int
        }
 }
 
-static int shade_tra_samples(ShadeSample *ssamp, int x, int y, ZTranspRow *row)
+static int shade_tra_samples(ShadeSample *ssamp, StrandShadeCache *cache, int x, int y, ZTranspRow *row, int addpassflag)
 {
+       if(row->segment != -1) {
+               shade_strand_samples(cache, ssamp, x, y, row, addpassflag);
+               return 1;
+       }
+
        shade_tra_samples_fill(ssamp, x, y, row->z, row->obi, row->p, row->mask);
        
        if(ssamp->tot) {
@@ -3710,7 +3786,7 @@ static void addvecmul(float *v1, float *v2, float fac)
        v1[2]= v1[2]+fac*v2[2];
 }
 
-int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassflag)
+static int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassflag)
 {
        int a, sample, osa = (R.osa? R.osa: 1), retval = osa;
        
@@ -3770,7 +3846,7 @@ int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassflag)
        return retval;
 }
 
-void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf)
+static void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf)
 {
        /* speed vector exception... if solid render was done, sky pixels are set to zero already */
        /* for all pixels with alpha zero, we re-initialize speed again then */
@@ -3793,23 +3869,26 @@ void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf)
 
 #define MAX_ZROW       2000
 
-/* main render call to fill in pass the full transparent layer */
+/* main render call to do the z-transparent layer */
 /* returns a mask, only if a) transp rendered and b) solid was rendered */
 unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pass, ListBase *psmlist)
 {
        RenderResult *rr= pa->result;
        ShadeSample ssamp;
        APixstr *APixbuf;      /* Zbuffer: linked list of face samples */
+       APixstrand *APixbufstrand = NULL;
        APixstr *ap, *aprect, *apn;
+       APixstrand *apstrand, *aprectstrand, *apnstrand;
        ListBase apsmbase={NULL, NULL};
        ShadeResult samp_shr[16];               /* MAX_OSA */
        ZTranspRow zrow[MAX_ZROW];
+       StrandShadeCache *sscache= NULL;
        float sampalpha, *passrect= pass;
        long *rdrect;
-       int x, y, crop=0, a, totface;
+       int x, y, crop=0, a, b, totface, totsample, doztra;
        int addpassflag, offs= 0, od, addzbuf;
        unsigned short *ztramask= NULL;
-       
+
        /* looks nicer for calling code */
        if(R.test_break())
                return NULL;
@@ -3821,14 +3900,15 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
        }
        
        APixbuf= MEM_callocN(pa->rectx*pa->recty*sizeof(APixstr), "APixbuf");
+       if(R.totstrand && (rl->layflag & SCE_LAY_STRAND)) {
+               APixbufstrand= MEM_callocN(pa->rectx*pa->recty*sizeof(APixstrand), "APixbufstrand");
+               sscache= strand_shade_cache_create();
+       }
 
        /* general shader info, passes */
        shade_sample_initialize(&ssamp, pa, rl);
        addpassflag= rl->passflag & ~(SCE_PASS_Z|SCE_PASS_COMBINED);
-       if((rl->layflag & SCE_LAY_STRAND) && R.totstrand)
-               addzbuf= 1; /* strands layer needs the z-buffer */
-       else
-               addzbuf= rl->passflag & SCE_PASS_Z;
+       addzbuf= rl->passflag & SCE_PASS_Z;
        
        if(R.osa)
                sampalpha= 1.0f/(float)R.osa;
@@ -3836,14 +3916,25 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
                sampalpha= 1.0f;
        
        /* fill the Apixbuf */
-       if(0 == zbuffer_abuf(pa, APixbuf, &apsmbase, rl->lay)) {
+       doztra= 0;
+       if(rl->layflag & SCE_LAY_ZTRA)
+               doztra+= zbuffer_abuf(pa, APixbuf, &apsmbase, rl->lay);
+       if((rl->layflag & SCE_LAY_STRAND) && APixbufstrand)
+               doztra+= zbuffer_strands_abuf(&R, pa, rl, APixbufstrand, &apsmbase, sscache);
+
+       if(doztra == 0) {
                /* nothing filled in */
                MEM_freeN(APixbuf);
+               if(APixbufstrand)
+                       MEM_freeN(APixbufstrand);
+               if(sscache)
+                       strand_shade_cache_free(sscache);
                freepsA(&apsmbase);
                return NULL;
        }
 
        aprect= APixbuf;
+       aprectstrand= APixbufstrand;
        rdrect= pa->rectdaps;
        
        /* irregular shadowb buffer creation */
@@ -3851,13 +3942,13 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
                ISB_create(pa, APixbuf);
 
        /* masks, to have correct alpha combine */
-       if(R.osa && (rl->layflag & SCE_LAY_SOLID))
+       if(R.osa && (rl->layflag & SCE_LAY_SOLID) && pa->fullresult.first==NULL)
                ztramask= MEM_callocN(pa->rectx*pa->recty*sizeof(short), "ztramask");
 
        /* zero alpha pixels get speed vector max again */
        if(addpassflag & SCE_PASS_VECTOR)
                if(rl->layflag & SCE_LAY_SOLID)
-                       reset_sky_speedvectors(pa, rl, rl->acolrect);
+                       reset_sky_speedvectors(pa, rl, rl->acolrect?rl->acolrect:rl->rectf);    /* if acolrect is set we use it */
 
        /* filtered render, for now we assume only 1 filter size */
        if(pa->crop) {
@@ -3865,6 +3956,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
                offs= pa->rectx + 1;
                passrect+= 4*offs;
                aprect+= offs;
+               aprectstrand+= offs;
        }
        
        /* init scanline updates */
@@ -3876,14 +3968,15 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
        for(y=pa->disprect.ymin+crop; y<pa->disprect.ymax-crop; y++, rr->renrect.ymax++) {
                pass= passrect;
                ap= aprect;
+               apstrand= aprectstrand;
                od= offs;
                
                if(R.test_break())
                        break;
                
-               for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, ap++, pass+=4, od++) {
+               for(x=pa->disprect.xmin+crop; x<pa->disprect.xmax-crop; x++, ap++, apstrand++, pass+=4, od++) {
                        
-                       if(ap->p[0]==0) {
+                       if(ap->p[0]==0 && (!APixbufstrand || apstrand->p[0]==0)) {
                                if(addpassflag & SCE_PASS_VECTOR) 
                                        add_transp_speed(rl, od, NULL, 0.0f, rdrect);
                        }
@@ -3898,6 +3991,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
                                                        zrow[totface].z= apn->z[a];
                                                        zrow[totface].p= apn->p[a];
                                                        zrow[totface].mask= apn->mask[a];
+                                                       zrow[totface].segment= -1;
                                                        totface++;
                                                        if(totface>=MAX_ZROW) totface= MAX_ZROW-1;
                                                }
@@ -3905,7 +3999,35 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
                                        }
                                        apn= apn->next;
                                }
-                               
+
+                               apnstrand= (APixbufstrand)? apstrand: NULL;
+                               while(apnstrand) {
+                                       for(a=0; a<4; a++) {
+                                               if(apnstrand->p[a]) {
+                                                       zrow[totface].obi= apnstrand->obi[a];
+                                                       zrow[totface].z= apnstrand->z[a];
+                                                       zrow[totface].p= apnstrand->p[a];
+                                                       zrow[totface].mask= apnstrand->mask[a];
+                                                       zrow[totface].segment= apnstrand->seg[a];
+
+                                                       if(R.osa) {
+                                                               totsample= 0;
+                                                               for(b=0; b<R.osa; b++)
+                                                                       if(zrow[totface].mask & (1<<b))
+                                                                               totsample++;
+                                                       }
+                                                       else
+                                                               totsample= 1;
+
+                                                       zrow[totface].u= apnstrand->u[a]/totsample;
+                                                       zrow[totface].v= apnstrand->v[a]/totsample;
+                                                       totface++;
+                                                       if(totface>=MAX_ZROW) totface= MAX_ZROW-1;
+                                               }
+                                       }
+                                       apnstrand= apnstrand->next;
+                               }
+
                                if(totface==2) {
                                        if(zrow[0].z < zrow[1].z) {
                                                SWAP(ZTranspRow, zrow[0], zrow[1]);
@@ -3922,19 +4044,22 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
                                                pa->rectz[od]= zrow[totface-1].z;
                                
                                if(addpassflag & SCE_PASS_INDEXOB)
-                                       add_transp_obindex(rl, od, zrow[totface-1].obi, zrow[totface-1].p);
-                               
+                                       add_transp_obindex(rl, od, zrow[totface-1].obi);
                                
                                if(R.osa==0) {
                                        while(totface>0) {
                                                totface--;
                                                
-                                               if(shade_tra_samples(&ssamp, x, y, &zrow[totface])) {
+                                               if(shade_tra_samples(&ssamp, sscache, x, y, &zrow[totface], addpassflag)) {
                                                        if(addpassflag) 
                                                                add_transp_passes(rl, od, ssamp.shr, (1.0f-pass[3])*ssamp.shr[0].combined[3]);
                                                        
                                                        addAlphaUnderFloat(pass, ssamp.shr[0].combined);
-                                                       if(pass[3]>=0.999) break;
+                                                       if(pass[3]>=0.999) {
+                                                               if(sscache)
+                                                                       unref_strand_samples(sscache, zrow, totface);
+                                                               break;
+                                                       }
                                                }
                                        }
                                        if(addpassflag & SCE_PASS_VECTOR)
@@ -3954,40 +4079,59 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
                                        while(totface>0) {
                                                totface--;
                                                
-                                               if(shade_tra_samples(&ssamp, x, y, &zrow[totface])) {
+                                               if(shade_tra_samples(&ssamp, sscache, x, y, &zrow[totface], addpassflag)) {
                                                        filled= addtosamp_shr(samp_shr, &ssamp, addpassflag);
                                                        
                                                        if(ztramask)
                                                                *sp |= zrow[totface].mask;
-                                                       if(filled==0)
+                                                       if(filled==0) {
+                                                               if(sscache)
+                                                                       unref_strand_samples(sscache, zrow, totface);
                                                                break;
-
-                                                       if(R.totstrand)
-                                                               addps(psmlist, pa->rectdaps+od, zrow[totface].obi, zrow[totface].p, zrow[totface].z, zrow[totface].mask);
+                                                       }
                                                }
                                        }
                                        
-                                       /* note; cannot use pass[3] for alpha due to filtermask */
-                                       for(a=0; a<R.osa; a++) {
-                                               add_filt_fmask(1<<a, samp_shr[a].combined, pass, rr->rectx);
-                                               alpha+= samp_shr[a].combined[3];
+                                       /* multisample buffers or filtered mask filling? */
+                                       if(pa->fullresult.first) {
+                                               for(a=0; a<R.osa; a++) {
+                                                       alpha= samp_shr[a].combined[3];
+                                                       if(alpha!=0.0f) {
+                                                               RenderLayer *rl= ssamp.rlpp[a];
+                                                               
+                                                               addAlphaOverFloat(rl->rectf + 4*od, samp_shr[a].combined);
+                               
+                                                               add_transp_passes(rl, od, &samp_shr[a], alpha);
+                                                               if(addpassflag & SCE_PASS_VECTOR)
+                                                                       add_transp_speed(rl, od, samp_shr[a].winspeed, alpha, rdrect);
+                                                       }
+                                               }
                                        }
-                                       
-                                       if(addpassflag) {
-                                               alpha*= sampalpha;
+                                       else {
+                                                       
+                                               /* note; cannot use pass[3] for alpha due to filtermask */
+                                               for(a=0; a<R.osa; a++) {
+                                                       add_filt_fmask(1<<a, samp_shr[a].combined, pass, rr->rectx);
+                                                       alpha+= samp_shr[a].combined[3];
+                                               }
                                                
-                                               /* merge all in one, and then add */
-                                               merge_transp_passes(rl, samp_shr);
-                                               add_transp_passes(rl, od, samp_shr, alpha);
+                                               if(addpassflag) {
+                                                       alpha*= sampalpha;
+                                                       
+                                                       /* merge all in one, and then add */
+                                                       merge_transp_passes(rl, samp_shr);
+                                                       add_transp_passes(rl, od, samp_shr, alpha);
 
-                                               if(addpassflag & SCE_PASS_VECTOR)
-                                                       add_transp_speed(rl, od, samp_shr[0].winspeed, alpha, rdrect);
+                                                       if(addpassflag & SCE_PASS_VECTOR)
+                                                               add_transp_speed(rl, od, samp_shr[0].winspeed, alpha, rdrect);
+                                               }
                                        }
                                }
                        }
                }
                
                aprect+= pa->rectx;
+               aprectstrand+= pa->rectx;
                passrect+= 4*pa->rectx;
                offs+= pa->rectx;
        }
@@ -3996,6 +4140,10 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas
        rr->renlay= NULL;
 
        MEM_freeN(APixbuf);
+       if(APixbufstrand)
+               MEM_freeN(APixbufstrand);
+       if(sscache)
+               strand_shade_cache_free(sscache);
        freepsA(&apsmbase);     
 
        if(R.r.mode & R_SHADOW)
index 3ea7788f87cee9b5bb9255702ab1ec53de7c6c40..c5087bd2ba5b9ed70f33b53db98436ce71ae479b 100644 (file)
@@ -4067,13 +4067,13 @@ static void editing_panel_armature_type(Object *ob, bArmature *arm)
        uiBlockBeginAlign(block);
        for(a=0; a<8; a++) {
                short dx= 18;
-               but= uiDefButBitS(block, BUT_TOGDUAL, 1<<a, REDRAWVIEW3D, "", 10+a*dx, 115, dx, 15, &arm->layer, 0, 0, 0, 0, "");
+               but= uiDefButBitS(block, BUT_TOGDUAL, 1<<a, REDRAWVIEW3D, "", 10+a*dx, 115, dx, 15, &arm->layer, 0, 0, 0, 0, "Armature layer (Hold Ctrl for locking in a proxy instance)");
                uiButSetFunc(but, armature_layer_cb, &arm->layer, (void *)(1<<a));
        }
        uiBlockBeginAlign(block);
        for(a=8; a<16; a++) {
                short dx= 18;
-               but= uiDefButBitS(block, BUT_TOGDUAL, 1<<a, REDRAWVIEW3D, "", 18+a*dx, 115, dx, 15, &arm->layer, 0, 0, 0, 0, "");
+               but= uiDefButBitS(block, BUT_TOGDUAL, 1<<a, REDRAWVIEW3D, "", 18+a*dx, 115, dx, 15, &arm->layer, 0, 0, 0, 0, "Armature layer (Hold Ctrl for locking in a proxy instance)");
                uiButSetFunc(but, armature_layer_cb, &arm->layer, (void *)(1<<a));
        }
        /* quite bad here, but I don't know a better place for copy... */
index e6046203c4f25c1234d6d6ee06ad7484c9c60e26..0ec606859818a5a24a31cdd2146ff88452e32042 100644 (file)
@@ -584,12 +584,14 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                uiBlockSetEmboss(block, UI_EMBOSS);
        }
        else {
-               short prev_proxylock;
+               short prev_proxylock, show_upbut, show_downbut;
                
                /* Up/Down buttons: 
                 *      Proxy-constraints are not allowed to occur after local (non-proxy) constraints
                 *      as that poses problems when restoring them, so disable the "up" button where
-                *      it may cause this situation.
+                *      it may cause this situation. 
+                *
+                *      Up/Down buttons should only be shown (or not greyed - todo) if they serve some purpose. 
                 */
                if (proxylocked_constraints_owner(ob, pchan)) {
                        if (con->prev) {
@@ -600,21 +602,25 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                }
                else
                        prev_proxylock= 0;
-                
-               uiBlockBeginAlign(block);
-                       uiBlockSetEmboss(block, UI_EMBOSS);
-                       
-                       /* only show buttons that will do anything valid */
-                       if ((prev_proxylock==0) && (con->prev)) {
-                               but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_UP, *xco+width-50, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint up in constraint stack");
-                               uiButSetFunc(but, constraint_moveUp, ob, con);
-                       }
                        
-                       if (con->next) {
-                               but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_DOWN, *xco+width-50+18, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint down in constraint stack");
-                               uiButSetFunc(but, constraint_moveDown, ob, con);
-                       }
-               uiBlockEndAlign(block);
+               show_upbut= ((prev_proxylock == 0) && (con->prev));
+               show_downbut= (con->next) ? 1 : 0;
+               
+               if (show_upbut || show_downbut) {
+                       uiBlockBeginAlign(block);
+                               uiBlockSetEmboss(block, UI_EMBOSS);
+                               
+                               if (show_upbut) {
+                                       but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_UP, *xco+width-50, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint up in constraint stack");
+                                       uiButSetFunc(but, constraint_moveUp, ob, con);
+                               }
+                               
+                               if (show_downbut) {
+                                       but = uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, VICON_MOVE_DOWN, *xco+width-50+18, *yco, 16, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Move constraint down in constraint stack");
+                                       uiButSetFunc(but, constraint_moveDown, ob, con);
+                               }
+                       uiBlockEndAlign(block);
+               }
                
                
                /* Close 'button' - emboss calls here disable drawing of 'button' behind X */
@@ -3734,7 +3740,7 @@ static void object_softbodies_solver(Object *ob)
                                uiBlockEndAlign(block);
 
                                uiBlockBeginAlign(block);
-                               uiDefBut(block, LABEL, 0, "Diagnosis stuff",10,60,300,20, NULL, 0.0, 0, 0, 0, "");
+                               uiDefBut(block, LABEL, 0, "Diagnosis",10,60,300,20, NULL, 0.0, 0, 0, 0, "");
                                uiDefButBitS(block, TOG, SBSO_MONITOR, B_DIFF,"Print Performance to Console", 10,40,300,20, &sb->solverflags,  0,  0, 0, 0, "Turn on SB diagnose console prints");                              
                                uiBlockEndAlign(block);
                        } 
@@ -3920,15 +3926,15 @@ static void object_softbodies(Object *ob)
                                uiDefButBitS(block, TOG, OB_SB_QUADS, B_SOFTBODY_CHANGE, "Stiff Quads",         110,50,90,20, softflag, 0, 0, 0, 0, "Adds diagonal springs on 4-gons");
                                uiDefButBitS(block, TOG, OB_SB_EDGECOLL, B_DIFF, "CEdge",               220,50,45,20, softflag, 0, 0, 0, 0, "Edge collide too"); 
                                uiDefButBitS(block, TOG, OB_SB_FACECOLL, B_DIFF, "CFace",               265,50,45,20, softflag, 0, 0, 0, 0, "Faces collide too SLOOOOOW warning "); 
-                               uiDefButF(block, NUM, B_DIFF, "E Pull:",        10,30,100,20, &sb->inspring, 0.0,  0.999, 10, 0, "Edge spring stiffness");
-                               uiDefButF(block, NUM, B_DIFF, "E Push:",        110,30,100,20, &sb->inpush, 0.0,  0.999, 10, 0, "Edge spring stiffness");
+                               uiDefButF(block, NUM, B_DIFF, "E Pull:",        10,30,100,20, &sb->inspring, 0.0,  0.999, 10, 0, "Edge spring stiffness when longer than rest length");
+                               uiDefButF(block, NUM, B_DIFF, "E Push:",        110,30,100,20, &sb->inpush, 0.0,  0.999, 10, 0, "Edge spring stiffness when shorter than rest length");
                                uiDefButF(block, NUM, B_DIFF, "E Damp:",        210,30,100,20, &sb->infrict, 0.0,  50.0, 10, 0, "Edge spring friction");
-                               uiDefButBitS(block, TOG,OB_SB_AERO_ANGLE,B_SOFTBODY_CHANGE, "N",10,10,20,20, softflag, 0, 0, 0, 0, "New aero(uses angle and lenght)");
+                               uiDefButBitS(block, TOG,OB_SB_AERO_ANGLE,B_SOFTBODY_CHANGE, "N",10,10,20,20, softflag, 0, 0, 0, 0, "New aero(uses angle and length)");
                                uiDefButS(block, NUM, B_DIFF, "Aero:",     30,10,80,20, &sb->aeroedge,  0.00,  30000.0, 10, 0, "Make edges 'sail'");
                                if(ob->type==OB_MESH) {
                                        uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Bend:", 110,10,100,20, &sb->secondspring, 0.0,  10.0, 10, 0, "Strenght of Springs over 2 Edges");
                                        if (*softflag & OB_SB_QUADS){ 
-                                       uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Shear:", 210,10,100,20, &sb->shearstiff, 0.0,  1.0, 10, 0, "Strenght of Springs over 2 Edges");
+                                       uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Shear:", 210,10,100,20, &sb->shearstiff, 0.0,  1.0, 10, 0, "Strenght of diagonal Springs");
                                        }
                                }
                                else sb->secondspring = 0;
index d06028b09bc00cafaa9134b42a5ea0435932dc85..ca9a1b31f8840679b0e25939658f3b6f56403310 100644 (file)
@@ -514,6 +514,43 @@ static char* seq_panel_blend_modes()
        return string;
 }
 
+static char* seq_panel_scenes()
+{
+       static char rstr[8192];
+       char * str;
+
+       IDnames_to_pupstring(&str, NULL, NULL, 
+                            &G.main->scene, (ID *)G.scene, NULL);
+
+       strncpy(rstr, str, 8192);
+       MEM_freeN(str);
+
+       return rstr;
+}
+
+static void seq_update_scenenr(Sequence * seq)
+{
+       Scene * sce;
+       int nr;
+       if (seq->type != SEQ_SCENE) {
+               return;
+       }
+
+       seq->scenenr = 0;
+
+       sce = G.main->scene.first;
+       nr = 1;
+       while(sce) {
+               if (sce == seq->scene) {
+                       seq->scenenr = nr;
+                       break;
+               }
+               nr++;
+               sce = sce->id.next;
+       }
+}
+
+
 static void seq_panel_editing()
 {
        Sequence *last_seq = get_last_seq();
@@ -543,12 +580,10 @@ static void seq_panel_editing()
                  10, 120, 120, 19, &last_seq->blend_mode, 
                  0,0,0,0, "Strip Blend Mode");
 
-       if (last_seq->blend_mode > 0) {
-               uiDefButF(block, NUM, B_SEQ_BUT_RELOAD, "Blend:",
-                         130, 120, 120, 19, &last_seq->blend_opacity, 
-                         0.0, 100.0, 100.0, 0, 
-                         "Blend opacity");
-       }
+       uiDefButF(block, NUM, B_SEQ_BUT_RELOAD, "Blend:",
+                 130, 120, 120, 19, &last_seq->blend_opacity, 
+                 0.0, 100.0, 100.0, 0, 
+                 "Blend opacity");
 
        uiDefButBitI(block, TOG, SEQ_MUTE,
                     B_SEQ_BUT_RELOAD_ALL, "Mute",
@@ -585,27 +620,24 @@ static void seq_panel_editing()
                                130, 60, 120, 19, &last_seq->endstill, 
                                0.0, MAXFRAMEF, 0.0, 0.0, "End still");
                } else {
-                       if (last_seq->type == SEQ_IMAGE) {
-                               uiDefButI(block, NUM, 
-                                       B_SEQ_BUT_TRANSFORM, "Start-Still", 
-                                       10, 60, 120, 20, &last_seq->startstill, 
-                                       0.0, MAXFRAMEF, 0.0, 0.0, "Start still");
-                               uiDefButI(block, NUM, 
-                                       B_SEQ_BUT_TRANSFORM, "End-Still", 
-                                       130, 60, 120, 19, &last_seq->endstill, 
-                                       0.0, MAXFRAMEF, 0.0, 0.0, "End still");
-                       } else {
-                               uiDefButI(block, NUM, 
-                                       B_SEQ_BUT_TRANSFORM, "Start-Ofs", 
-                                       10, 60, 120, 20, &last_seq->startofs, 
-                                       0.0, last_seq->len - last_seq->endofs, 
-                                       0.0, 0.0, "Start offset");
-                               uiDefButI(block, NUM, 
-                                       B_SEQ_BUT_TRANSFORM, "End-Ofs", 
-                                       130, 60, 120, 19, &last_seq->endofs, 
-                                       0.0, last_seq->len - last_seq->startofs, 
-                                       0.0, 0.0, "End offset");
-                       }
+                       uiDefButI(block, NUM, 
+                                 B_SEQ_BUT_TRANSFORM, "Start-Still", 
+                                 10, 60, 120, 20, &last_seq->startstill, 
+                                 0.0, MAXFRAMEF, 0.0, 0.0, "Start still");
+                       uiDefButI(block, NUM, 
+                                 B_SEQ_BUT_TRANSFORM, "End-Still", 
+                                 130, 60, 120, 19, &last_seq->endstill, 
+                                 0.0, MAXFRAMEF, 0.0, 0.0, "End still");
+                       uiDefButI(block, NUM, 
+                                 B_SEQ_BUT_TRANSFORM, "Start-Ofs", 
+                                 10, 40, 120, 20, &last_seq->startofs, 
+                                 0.0, last_seq->len - last_seq->endofs, 
+                                 0.0, 0.0, "Start offset");
+                       uiDefButI(block, NUM, 
+                                 B_SEQ_BUT_TRANSFORM, "End-Ofs", 
+                                 130, 40, 120, 19, &last_seq->endofs, 
+                                 0.0, last_seq->len - last_seq->startofs, 
+                                 0.0, 0.0, "End offset");
                }
        }
 
@@ -683,14 +715,14 @@ static void seq_panel_editing()
        }
 
        str = strdata;
-       yco = 40;
+       yco = 20;
 
        while ((p = strchr(str, '\n'))) {
                *p = 0;
-               uiDefBut(block, LABEL, 0, str, 10,yco,240,19, 0, 
+               uiDefBut(block, LABEL, 0, str, 10,yco,240,17, 0, 
                         0, 0, 0, 0, "");
                str = p+1;
-               yco -= 20;
+               yco -= 18;
        }
 }
 
@@ -719,7 +751,7 @@ static void seq_panel_input()
                if (se) {
                        uiDefBut(block, TEX, 
                                 B_SEQ_BUT_RELOAD_FILE, "File: ", 
-                                10, 120, 240,19, se->name, 
+                                10, 120, 190,19, se->name, 
                                 0.0, 80.0, 100, 0, "");
                }
 
@@ -728,10 +760,21 @@ static void seq_panel_input()
                   last_seq->type == SEQ_RAM_SOUND) {
                uiDefBut(block, TEX, 
                         B_SEQ_BUT_RELOAD_FILE, "File: ", 
-                        10,120,240,19, last_seq->strip->stripdata->name, 
+                        10,120,190,19, last_seq->strip->stripdata->name, 
                         0.0, 80.0, 100, 0, "");
+       } else if (last_seq->type == SEQ_SCENE) {
+               seq_update_scenenr(last_seq);
+               uiDefButI(block, MENU, B_SEQ_BUT_RELOAD_FILE, 
+                         seq_panel_scenes(), 
+                         10, 120, 190, 19, &last_seq->scenenr, 
+                         0,0,0,0, "Linked Scene");
        }
 
+       uiDefBut(block, BUT, B_SEQ_BUT_RELOAD_FILE, 
+                "Reload",
+                200,120,50,19, 0, 0, 0, 0, 0, 
+                "Reload files/scenes from disk and update strip length.");
+
        if (last_seq->type == SEQ_MOVIE 
            || last_seq->type == SEQ_IMAGE 
            || last_seq->type == SEQ_SCENE) {
@@ -1837,28 +1880,27 @@ static void render_panel_output(void)
        uiBlockEndAlign(block);
        
        uiBlockBeginAlign(block);
-       uiDefButBitI(block, TOG, R_TOUCH, B_NOP, "Touch", 10, 142, 50, 20, &G.scene->r.mode, 0.0, 0.0, 0, 0, "Create an empty file before rendering each frame, remove if cancelled (and empty)");
+       uiDefButBitI(block, TOG, R_TOUCH, B_NOP, "Touch",       10, 142, 50, 20, &G.scene->r.mode, 0.0, 0.0, 0, 0, "Create an empty file before rendering each frame, remove if cancelled (and empty)");
        uiDefButBitI(block, TOG, R_NO_OVERWRITE, B_NOP, "No Overwrite", 60, 142, 90, 20, &G.scene->r.mode, 0.0, 0.0, 0, 0, "Skip rendering frames when the file exists (image output only)");
        uiBlockEndAlign(block);
+       uiDefButBitS(block, TOG, R_BACKBUF, B_NOP,"Backbuf",    160, 142, 80, 20, &G.scene->r.bufflag, 0, 0, 0, 0, "Enable/Disable use of Backbuf image");      
        
        /* SET BUTTON */
        uiBlockBeginAlign(block);
        id= (ID *)G.scene->set;
        IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->scene), id, &(G.buts->menunr));
        if(strp[0])
-               uiDefButS(block, MENU, B_SETBROWSE, strp, 10, 114, 20, 20, &(G.buts->menunr), 0, 0, 0, 0, "Scene to link as a Set");
+               uiDefButS(block, MENU, B_SETBROWSE, strp,                       10, 114, 20, 20, &(G.buts->menunr), 0, 0, 0, 0, "Scene to link as a Set");
        MEM_freeN(strp);
 
        if(G.scene->set) {
                uiSetButLock(1, NULL);
-               uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, B_NOP, "",    31, 120, 100, 20, &(G.scene->set), "Name of the Set");
+               uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, B_NOP, "",    31, 114, 100, 20, &(G.scene->set), "Name of the Set");
                uiClearButLock();
-               uiDefIconBut(block, BUT, B_CLEARSET, ICON_X,            132, 120, 20, 20, 0, 0, 0, 0, 0, "Remove Set link");
+               uiDefIconBut(block, BUT, B_CLEARSET, ICON_X,            132, 114, 20, 20, 0, 0, 0, 0, 0, "Remove Set link");
        }
        uiBlockEndAlign(block);
 
-       uiBlockSetCol(block, TH_BUT_SETTING1);
-       uiDefButBitS(block, TOG, R_BACKBUF, B_NOP,"Backbuf",    10, 89, 80, 20, &G.scene->r.bufflag, 0, 0, 0, 0, "Enable/Disable use of Backbuf image");        
        uiDefButS(block, NUM, B_NOP, "Threads:",                                10, 63, 100, 20, &G.scene->r.threads, 1, BLENDER_MAX_THREADS, 0, 0, "Amount of threads for render (takes advantage of multi-core and multi-processor computers)");
        uiBlockSetCol(block, TH_AUTO);
                
@@ -1866,9 +1908,12 @@ static void render_panel_output(void)
        for(b=2; b>=0; b--)
                for(a=0; a<3; a++)
                        uiDefButBitS(block, TOG, 1<<(3*b+a), 800,"",    (short)(10+18*a),(short)(10+14*b),16,12, &G.winpos, 0, 0, 0, 0, "Render window placement on screen");
-       uiBlockEndAlign(block);
 
-       uiDefButBitS(block, TOG, R_EXR_TILE_FILE, B_NOP, "Save Buffers", 72, 31, 120, 19, &G.scene->r.scemode, 0.0, 0.0, 0, 0, "Save the tiles for all RenderLayers and used SceneNodes to files, to save memory");
+       uiBlockBeginAlign(block);
+       uiDefButBitS(block, TOG, R_EXR_TILE_FILE, B_REDR, "Save Buffers", 72, 31, 120, 19, &G.scene->r.scemode, 0.0, 0.0, 0, 0, "Save the tiles for all RenderLayers and used SceneNodes to files, to save memory");
+       if(G.scene->r.scemode & R_EXR_TILE_FILE)
+               uiDefButBitS(block, TOG, R_FULL_SAMPLE, B_REDR, "FullSample",    192, 31, 118, 19, &G.scene->r.scemode, 0.0, 0.0, 0, 0, "Saves for every OSA sample the entire RenderLayer results");
+       uiBlockEndAlign(block);
        
        uiDefButS(block, MENU, B_REDR, "Render Display %t|Render Window %x1|Image Editor %x0|Full Screen %x2",  
                                        72, 10, 120, 19, &G.displaymode, 0.0, (float)R_DISPLAYWIN, 0, 0, "Sets render output display");
@@ -1876,12 +1921,12 @@ static void render_panel_output(void)
        uiDefButBitS(block, TOG, R_EXTENSION, B_NOP, "Extensions", 205, 10, 105, 19, &G.scene->r.scemode, 0.0, 0.0, 0, 0, "Adds filetype extensions to the filename when rendering animations");
        
        /* Dither control */
-       uiDefButF(block, NUM,B_DIFF, "Dither:",         205,31,105,19, &G.scene->r.dither_intensity, 0.0, 2.0, 0, 0, "The amount of dithering noise present in the output image (0.0 = no dithering)");
+       uiDefButF(block, NUM,B_DIFF, "Dither:",         10,89,100,19, &G.scene->r.dither_intensity, 0.0, 2.0, 0, 0, "The amount of dithering noise present in the output image (0.0 = no dithering)");
        
        /* Toon shading buttons */
        uiBlockBeginAlign(block);
-       uiDefButBitI(block, TOG, R_EDGE, B_NOP,"Edge",   100, 89, 70, 20, &G.scene->r.mode, 0, 0, 0, 0, "Enable Toon Edge-enhance");
-       uiDefBlockBut(block, edge_render_menu, NULL, "Edge Settings", 170, 89, 140, 20, "Display Edge settings");
+       uiDefButBitI(block, TOG, R_EDGE, B_NOP,"Edge",   115, 89, 60, 20, &G.scene->r.mode, 0, 0, 0, 0, "Enable Toon Edge-enhance");
+       uiDefBlockBut(block, edge_render_menu, NULL, "Edge Settings", 175, 89, 135, 20, "Display Edge settings");
        uiBlockEndAlign(block);
        
        uiBlockBeginAlign(block);
@@ -1957,7 +2002,10 @@ static void render_panel_render(void)
 #endif /* disable yafray */
 
        uiBlockBeginAlign(block);
-       uiDefButBitI(block, TOG, R_OSA, B_DIFF, "OSA",  369,109,122,20,&G.scene->r.mode, 0, 0, 0, 0, "Enables Oversampling (Anti-aliasing)");
+       if((G.scene->r.scemode & R_FULL_SAMPLE) && (G.scene->r.scemode & R_EXR_TILE_FILE))
+               uiDefButBitI(block, TOG, R_OSA, B_DIFF, "FSA",  369,109,122,20,&G.scene->r.mode, 0, 0, 0, 0, "Saves all samples, then composites, and then merges (for best Anti-aliasing)");
+       else
+               uiDefButBitI(block, TOG, R_OSA, B_DIFF, "OSA",  369,109,122,20,&G.scene->r.mode, 0, 0, 0, 0, "Enables Oversampling (Anti-aliasing)");
        uiDefButS(block, ROW,B_DIFF,"5",                        369,88,29,20,&G.scene->r.osa,2.0,5.0, 0, 0, "Render 5 samples per pixel for smooth edges (Fast)");
        uiDefButS(block, ROW,B_DIFF,"8",                        400,88,29,20,&G.scene->r.osa,2.0,8.0, 0, 0, "Render 8 samples per pixel for smooth edges (Recommended)");
        uiDefButS(block, ROW,B_DIFF,"11",                       431,88,29,20,&G.scene->r.osa,2.0,11.0, 0, 0, "Render 11 samples per pixel for smooth edges (High Quality)");
@@ -2304,11 +2352,7 @@ static void render_panel_format(void)
 
        if(G.scene->r.quality==0) G.scene->r.quality= 90;
 
-#ifdef WITH_QUICKTIME
        if (G.scene->r.imtype == R_AVICODEC || G.scene->r.imtype == R_QUICKTIME) {
-#else /* WITH_QUICKTIME */
-       if (0) {
-#endif
                if(G.scene->r.imtype == R_QUICKTIME) {
 #ifdef WITH_QUICKTIME
 #if defined (_WIN32) || defined (__APPLE__)
@@ -2651,12 +2695,12 @@ static void render_panel_layers(void)
        
        uiDefButBitI(block, TOG, SCE_PASS_RGBA, B_SET_PASS,"Col",                               10, 10, 35, 20, &srl->passflag, 0, 0, 0, 0, "Deliver shade-less Color pass");   
        uiDefButBitI(block, TOG, SCE_PASS_DIFFUSE, B_SET_PASS,"Diff",                   45, 10, 35, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Diffuse pass");    
-       uiDefButBitI(block, BUT_TOGDUAL, SCE_PASS_SPEC, B_SET_PASS,"Spec",              80, 10, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Specular pass");   
-       uiDefButBitI(block, BUT_TOGDUAL, SCE_PASS_SHADOW, B_SET_PASS,"Shad",    120, 10, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Shadow pass");    
-       uiDefButBitI(block, BUT_TOGDUAL, SCE_PASS_AO, B_SET_PASS,"AO",                  160, 10, 30, 20, &srl->passflag, 0, 0, 0, 0, "Deliver AO pass");        
-       uiDefButBitI(block, BUT_TOGDUAL, SCE_PASS_REFLECT, B_SET_PASS,"Refl",   190, 10, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Raytraced Reflection pass");      
-       uiDefButBitI(block, BUT_TOGDUAL, SCE_PASS_REFRACT, B_SET_PASS,"Refr",   230, 10, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Raytraced Refraction pass");      
-       uiDefButBitI(block, BUT_TOGDUAL, SCE_PASS_RADIO, B_SET_PASS,"Rad",              270, 10, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Radiosity pass"); 
+       uiDefButBitI(block, BUT_TOGDUAL, SCE_PASS_SPEC, B_SET_PASS,"Spec",              80, 10, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Specular pass (Hold Ctrl to exclude from combined)");      
+       uiDefButBitI(block, BUT_TOGDUAL, SCE_PASS_SHADOW, B_SET_PASS,"Shad",    120, 10, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Shadow pass (Hold Ctrl to exclude from combined)");       
+       uiDefButBitI(block, BUT_TOGDUAL, SCE_PASS_AO, B_SET_PASS,"AO",                  160, 10, 30, 20, &srl->passflag, 0, 0, 0, 0, "Deliver AO pass (Hold Ctrl to exclude from combined)");
+       uiDefButBitI(block, BUT_TOGDUAL, SCE_PASS_REFLECT, B_SET_PASS,"Refl",   190, 10, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Raytraced Reflection pass (Hold Ctrl to exclude from combined)"); 
+       uiDefButBitI(block, BUT_TOGDUAL, SCE_PASS_REFRACT, B_SET_PASS,"Refr",   230, 10, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Raytraced Refraction pass (Hold Ctrl to exclude from combined)"); 
+       uiDefButBitI(block, BUT_TOGDUAL, SCE_PASS_RADIO, B_SET_PASS,"Rad",              270, 10, 40, 20, &srl->passflag, 0, 0, 0, 0, "Deliver Radiosity pass (Hold Ctrl to exclude from combined)");    
 }      
 
 void render_panels()
index be307a649b3199b8601d137ec08bc7fa4b605f6c..76a4f024f268bb8bb7f936010fc8782a3a43e326 100644 (file)
@@ -1175,13 +1175,13 @@ void uiblock_image_panel(uiBlock *block, Image **ima_pp, ImageUser *iuser,
                 
                 /* fields */
                 uiBlockBeginAlign(block);
-                but= uiDefButBitS(block, TOG, IMA_FIELDS, imagechanged, "Fields",      10, 90, 65, 20, &ima->flag, 0, 0, 0, 0, "Click to enable use of fields in Image");
+                but= uiDefButBitS(block, TOG, IMA_FIELDS, imagechanged, "Fields",      10, 70, 65, 20, &ima->flag, 0, 0, 0, 0, "Click to enable use of fields in Image");
                 uiButSetFunc(but, image_field_test, ima, iuser);
-                uiDefButBitS(block, TOG, IMA_STD_FIELD, B_NOP, "Odd",                  75, 90, 45, 20, &ima->flag, 0, 0, 0, 0, "Standard Field Toggle");
+                uiDefButBitS(block, TOG, IMA_STD_FIELD, B_NOP, "Odd",                  75, 70, 45, 20, &ima->flag, 0, 0, 0, 0, "Standard Field Toggle");
                 
                 uiBlockSetFunc(block, image_reload_cb, ima, iuser);
-                uiDefButBitS(block, TOG, IMA_ANTIALI, B_NOP, "Anti",                   10, 70, 45, 20, &ima->flag, 0, 0, 0, 0, "Toggles Image anti-aliasing, only works with solid colors");
-                uiDefButBitS(block, TOG, IMA_DO_PREMUL, imagechanged, "Premul",                55, 70, 65, 20, &ima->flag, 0, 0, 0, 0, "Toggles premultiplying alpha");
+                uiDefButBitS(block, TOG, IMA_ANTIALI, B_NOP, "Anti",                   10, 50, 45, 20, &ima->flag, 0, 0, 0, 0, "Toggles Image anti-aliasing, only works with solid colors");
+                uiDefButBitS(block, TOG, IMA_DO_PREMUL, imagechanged, "Premul",                55, 50, 65, 20, &ima->flag, 0, 0, 0, 0, "Toggles premultiplying alpha");
                 uiBlockEndAlign(block);
                 
                 if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
@@ -1189,21 +1189,21 @@ void uiblock_image_panel(uiBlock *block, Image **ima_pp, ImageUser *iuser,
                         
                         uiBlockBeginAlign(block);
                         uiBlockSetFunc(block, image_user_change, iuser, NULL);
-                        uiDefButBitS(block, TOG, IMA_ANIM_ALWAYS, B_NOP, "Auto Refresh",       120, 90, 190, 20, &iuser->flag, 0, 0, 0, 0, "Always refresh Image on frame changes");
+                        uiDefButBitS(block, TOG, IMA_ANIM_ALWAYS, B_NOP, "Auto Refresh",       120, 70, 190, 20, &iuser->flag, 0, 0, 0, 0, "Always refresh Image on frame changes");
                         
                         if(ima->anim) {
-                                uiDefButI(block, NUM, imagechanged, str,               120, 70,170, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use");
-                                but= uiDefBut(block, BUT, redraw, "<",         290, 70, 20, 20, 0, 0, 0, 0, 0, "Copies number of frames in movie file to Frames: button");
+                                uiDefButI(block, NUM, imagechanged, str,               120, 50,170, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use");
+                                but= uiDefBut(block, BUT, redraw, "<",         290, 50, 20, 20, 0, 0, 0, 0, 0, "Copies number of frames in movie file to Frames: button");
                                 uiButSetFunc(but, set_frames_cb, ima, iuser);
                         }
                         else 
-                                uiDefButI(block, NUM, imagechanged, str,               120, 70,190, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use");
+                                uiDefButI(block, NUM, imagechanged, str,               120, 50,190, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use");
                         
-                        uiDefButI(block, NUM, imagechanged, "Offs:",   120,50,100,20, &iuser->offset, -MAXFRAMEF, MAXFRAMEF, 0, 0, "Offsets the number of the frame to use in the animation");
-                        uiDefButS(block, NUM, imagechanged, "Fie/Ima:",        220,50,90,20, &iuser->fie_ima, 1.0, 200.0, 0, 0, "The number of fields per rendered frame (2 fields is 1 image)");
+                        uiDefButI(block, NUM, imagechanged, "Offs:",   120,30,100,20, &iuser->offset, -MAXFRAMEF, MAXFRAMEF, 0, 0, "Offsets the number of the frame to use in the animation");
+                        uiDefButS(block, NUM, imagechanged, "Fie/Ima:",        220,30,90,20, &iuser->fie_ima, 1.0, 200.0, 0, 0, "The number of fields per rendered frame (2 fields is 1 image)");
                         
-                        uiDefButI(block, NUM, imagechanged, "StartFr:",        120,30,100,20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Sets the global starting frame of the movie");
-                        uiDefButS(block, TOG, imagechanged, "Cyclic",  220,30,90,20, &iuser->cycl, 0.0, 1.0, 0, 0, "Cycle the images in the movie");
+                        uiDefButI(block, NUM, imagechanged, "StartFr:",        120,10,100,20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Sets the global starting frame of the movie");
+                        uiDefButS(block, TOG, imagechanged, "Cyclic",  220,10,90,20, &iuser->cycl, 0.0, 1.0, 0, 0, "Cycle the images in the movie");
                         
                         uiBlockSetFunc(block, NULL, iuser, NULL);
                 }
@@ -1211,9 +1211,9 @@ void uiblock_image_panel(uiBlock *block, Image **ima_pp, ImageUser *iuser,
                         
                         uiBlockBeginAlign(block);
                         uiBlockSetFunc(block, image_generated_change_cb, ima, iuser);
-                        uiDefButS(block, NUM, imagechanged, "SizeX:",  120,90,100,20, &ima->gen_x, 1.0, 5000.0, 0, 0, "Image size x");
-                        uiDefButS(block, NUM, imagechanged, "SizeY:",  220,90,90,20, &ima->gen_y, 1.0, 5000.0, 0, 0, "Image size y");
-                        uiDefButS(block, TOG, imagechanged, "UV Test grid",120,70,190,20, &ima->gen_type, 0.0, 1.0, 0, 0, "");
+                        uiDefButS(block, NUM, imagechanged, "SizeX:",  120,70,100,20, &ima->gen_x, 1.0, 5000.0, 0, 0, "Image size x");
+                        uiDefButS(block, NUM, imagechanged, "SizeY:",  220,70,90,20, &ima->gen_y, 1.0, 5000.0, 0, 0, "Image size y");
+                        uiDefButS(block, TOG, imagechanged, "UV Test grid",120,50,190,20, &ima->gen_type, 0.0, 1.0, 0, 0, "");
                         uiBlockSetFunc(block, NULL, NULL, NULL);
                 }
         }
index 3339385d565d03de35a6f93638906d2d3c064ad5..64af3041155ec0026cdc69dd5f4a160a02a2483e 100644 (file)
@@ -816,8 +816,7 @@ static void draw_channel_strips(void)
        /* Draw keyframes 
         *      1) Only channels that are visible in the Action Editor get drawn/evaluated.
         *         This is to try to optimise this for heavier data sets
-        *      2) Keyframes which are out of view horizontally could be disregarded (probably as
-        *         option - 'drop-frames' or so). Todo...
+        *      2) Keyframes which are out of view horizontally are disregarded 
         */
        y = 0.0;
        for (ale= act_data.first; ale; ale= ale->next) {
@@ -1241,12 +1240,36 @@ static void draw_keylist(gla2DDrawInfo *di, ListBase *keys, ListBase *blocks, fl
        glDisable(GL_BLEND);
 }
 
+
+static ActKeysInc *init_aki_data()
+{
+       static ActKeysInc aki;
+       
+       /* init data of static struct here */
+       if ((curarea->spacetype == SPACE_ACTION) && NLA_ACTION_SCALED)
+               aki.ob= OBACT;
+       else if (curarea->spacetype == SPACE_NLA)
+               aki.ob= NULL; // FIXME
+       else
+               aki.ob= NULL;
+               
+       aki.start= G.v2d->cur.xmin - 10;
+       aki.end= G.v2d->cur.xmax + 10;
+       
+       /* only pass pointer for Action Editor (for now) */
+       if (curarea->spacetype == SPACE_ACTION)
+               return &aki;
+       else    
+               return NULL;
+}
+
 void draw_object_channel(gla2DDrawInfo *di, Object *ob, float ypos)
 {
        ListBase keys = {0, 0};
        ListBase blocks = {0, 0};
+       ActKeysInc *aki = init_aki_data();
 
-       ob_to_keylist(ob, &keys, &blocks);
+       ob_to_keylist(ob, &keys, &blocks, aki);
        draw_keylist(di, &keys, &blocks, ypos);
        
        BLI_freelistN(&keys);
@@ -1257,8 +1280,9 @@ void draw_ipo_channel(gla2DDrawInfo *di, Ipo *ipo, float ypos)
 {
        ListBase keys = {0, 0};
        ListBase blocks = {0, 0};
+       ActKeysInc *aki = init_aki_data();
 
-       ipo_to_keylist(ipo, &keys, &blocks);
+       ipo_to_keylist(ipo, &keys, &blocks, aki);
        draw_keylist(di, &keys, &blocks, ypos);
        
        BLI_freelistN(&keys);
@@ -1269,8 +1293,9 @@ void draw_icu_channel(gla2DDrawInfo *di, IpoCurve *icu, float ypos)
 {
        ListBase keys = {0, 0};
        ListBase blocks = {0, 0};
+       ActKeysInc *aki = init_aki_data();
 
-       icu_to_keylist(icu, &keys, &blocks);
+       icu_to_keylist(icu, &keys, &blocks, aki);
        draw_keylist(di, &keys, &blocks, ypos);
        
        BLI_freelistN(&keys);
@@ -1281,8 +1306,9 @@ void draw_agroup_channel(gla2DDrawInfo *di, bActionGroup *agrp, float ypos)
 {
        ListBase keys = {0, 0};
        ListBase blocks = {0, 0};
+       ActKeysInc *aki = init_aki_data();
 
-       agroup_to_keylist(agrp, &keys, &blocks);
+       agroup_to_keylist(agrp, &keys, &blocks, aki);
        draw_keylist(di, &keys, &blocks, ypos);
        BLI_freelistN(&keys);
        BLI_freelistN(&blocks);
@@ -1291,27 +1317,28 @@ void draw_agroup_channel(gla2DDrawInfo *di, bActionGroup *agrp, float ypos)
 void draw_action_channel(gla2DDrawInfo *di, bAction *act, float ypos)
 {
        ListBase keys = {0, 0};
+       ActKeysInc *aki = init_aki_data();
 
-       action_to_keylist(act, &keys, NULL);
+       action_to_keylist(act, &keys, NULL, aki);
        draw_keylist(di, &keys, NULL, ypos);
        BLI_freelistN(&keys);
 }
 
 /* --------------- Conversion: data -> keyframe list ------------------ */
 
-void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks)
+void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
 {
        bConstraintChannel *conchan;
 
        if (ob) {
                /* Add object keyframes */
                if (ob->ipo)
-                       ipo_to_keylist(ob->ipo, keys, blocks);
+                       ipo_to_keylist(ob->ipo, keys, blocks, aki);
                
                /* Add constraint keyframes */
-               for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next){
+               for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next) {
                        if(conchan->ipo)
-                               ipo_to_keylist(conchan->ipo, keys, blocks);             
+                               ipo_to_keylist(conchan->ipo, keys, blocks, aki);                
                }
                        
                /* Add object data keyframes */
@@ -1319,7 +1346,24 @@ void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks)
        }
 }
 
-void icu_to_keylist(IpoCurve *icu, ListBase *keys, ListBase *blocks)
+static short bezt_in_aki_range (ActKeysInc *aki, BezTriple *bezt)
+{
+       /* when aki == NULL, we don't care about range */
+       if (aki == NULL) 
+               return 1;
+               
+       /* if nla-scaling is in effect, apply appropriate scaling adjustments */
+       if (aki->ob) {
+               float frame= get_action_frame_inv(aki->ob, bezt->vec[1][0]);
+               return IN_RANGE(frame, aki->start, aki->end);
+       }
+       else {
+               /* check if in range */
+               return IN_RANGE(bezt->vec[1][0], aki->start, aki->end);
+       }
+}
+
+void icu_to_keylist(IpoCurve *icu, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
 {
        BezTriple *bezt;
        ActKeyColumn *ak;
@@ -1331,8 +1375,11 @@ void icu_to_keylist(IpoCurve *icu, ListBase *keys, ListBase *blocks)
                bezt= icu->bezt;
                
                for (v=0; v<icu->totvert; v++, bezt++) {
-                       add_bezt_to_keycolumnslist(keys, bezt);
-                       if (blocks) add_bezt_to_keyblockslist(blocks, icu, v);
+                       /* only if keyframe is in range (optimisation) */
+                       if (bezt_in_aki_range(aki, bezt)) {
+                               add_bezt_to_keycolumnslist(keys, bezt);
+                               if (blocks) add_bezt_to_keyblockslist(blocks, icu, v);
+                       }
                }
                
                /* update the number of curves that elements have appeared in  */
@@ -1355,17 +1402,17 @@ void icu_to_keylist(IpoCurve *icu, ListBase *keys, ListBase *blocks)
        }
 }
 
-void ipo_to_keylist(Ipo *ipo, ListBase *keys, ListBase *blocks)
+void ipo_to_keylist(Ipo *ipo, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
 {
        IpoCurve *icu;
        
        if (ipo) {
                for (icu= ipo->curve.first; icu; icu= icu->next)
-                       icu_to_keylist(icu, keys, blocks);
+                       icu_to_keylist(icu, keys, blocks, aki);
        }
 }
 
-void agroup_to_keylist(bActionGroup *agrp, ListBase *keys, ListBase *blocks)
+void agroup_to_keylist(bActionGroup *agrp, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
 {
        bActionChannel *achan;
        bConstraintChannel *conchan;
@@ -1375,18 +1422,18 @@ void agroup_to_keylist(bActionGroup *agrp, ListBase *keys, ListBase *blocks)
                for (achan= agrp->channels.first; achan && achan!=agrp->channels.last; achan= achan->next) {
                        /* firstly, add keys from action channel's ipo block */
                        if (achan->ipo)
-                               ipo_to_keylist(achan->ipo, keys, blocks);
+                               ipo_to_keylist(achan->ipo, keys, blocks, aki);
                        
                        /* then, add keys from constraint channels */
                        for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) {
                                if (conchan->ipo)
-                                       ipo_to_keylist(conchan->ipo, keys, blocks);
+                                       ipo_to_keylist(conchan->ipo, keys, blocks, aki);
                        }
                }
        }
 }
 
-void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks)
+void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks, ActKeysInc *aki)
 {
        bActionChannel *achan;
        bConstraintChannel *conchan;
@@ -1396,12 +1443,12 @@ void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks)
                for (achan= act->chanbase.first; achan; achan= achan->next) {
                        /* firstly, add keys from action channel's ipo block */
                        if (achan->ipo)
-                               ipo_to_keylist(achan->ipo, keys, blocks);
+                               ipo_to_keylist(achan->ipo, keys, blocks, aki);
                        
                        /* then, add keys from constraint channels */
                        for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) {
                                if (conchan->ipo)
-                                       ipo_to_keylist(conchan->ipo, keys, blocks);
+                                       ipo_to_keylist(conchan->ipo, keys, blocks, aki);
                        }
                }
        }
index abe22a1804df89898ff8f2875cb8e7f278e45944..f7bbfffe1537b1c3d711b7314e653e95b986b6c5 100644 (file)
@@ -276,7 +276,7 @@ static short set_pchan_glColor (short colCode, int armflag, int boneflag, int co
        case PCHAN_COLOR_LINEBONE:
        {
                /* inner part in background color or constraint */
-               if ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS)) {
+               if ( (constflag) && ((bcolor==NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS)) ) {
                        if (constflag & PCHAN_HAS_STRIDE) glColor3ub(0, 0, 200);
                        else if (constflag & PCHAN_HAS_TARGET) glColor3ub(255, 150, 0);
                        else if (constflag & PCHAN_HAS_IK) glColor3ub(255, 255, 0);
@@ -2111,7 +2111,7 @@ static void draw_pose_paths(Object *ob)
                                        if (act) {
                                                achan= get_action_channel(act, pchan->name);
                                                if (achan) 
-                                                       ipo_to_keylist(achan->ipo, &keys, NULL);
+                                                       ipo_to_keylist(achan->ipo, &keys, NULL, NULL);
                                        }
                                        
                                        /* Draw slightly-larger yellow dots at each keyframe */
@@ -2257,17 +2257,18 @@ static void draw_ghost_poses_keys(Base *base)
        bArmature *arm= ob->data;
        bPose *posen, *poseo;
        ListBase keys= {NULL, NULL};
+       ActKeysInc aki = {0, 0, 0};
        ActKeyColumn *ak, *akn;
        float start, end, range, colfac, i;
        int cfrao, flago, ipoflago;
        
-       start = arm->ghostsf;
-       end = arm->ghostef;
+       aki.start= start = arm->ghostsf;
+       aki.end= end = arm->ghostef;
        if (end <= start)
                return;
        
        /* get keyframes - then clip to only within range */
-       action_to_keylist(act, &keys, NULL);
+       action_to_keylist(act, &keys, NULL, &aki);
        range= 0;
        for (ak= keys.first; ak; ak= akn) {
                akn= ak->next;
index 6696fd3cfe3e672388877e2d26a3047ff0928d2b..349432d87a1fef015a7c71f55dac1640d41d436d 100644 (file)
@@ -3814,7 +3814,9 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys)
        glDisable(GL_LIGHTING);
        glDisableClientState(GL_COLOR_ARRAY);
        glEnableClientState(GL_NORMAL_ARRAY);
+#if 0 /* If this is needed, it cant be enabled in wire mode, since it messes up the view - Campbell */
        glEnable(GL_DEPTH_TEST);
+#endif
 
        if(states)
                MEM_freeN(states);
index c7955fda2fccd21f336a3944f28d70244440e5fc..344fda5eef9ad07a9c7750b50b7dc206dca022ce 100644 (file)
@@ -2295,7 +2295,12 @@ static void view3d_panel_transform_spaces(short cntrl)
        for (index = V3D_MANIP_CUSTOM, ts = transform_spaces->first ; ts ; ts = ts->next, index++) {
 
                BIF_ThemeColor(TH_BUT_ACTION);
-               but = uiDefIconButS(block,ROW, REDRAWHEADERS, ICON_RIGHTARROW_THIN, xco,yco,XIC,YIC, &G.vd->twmode, 5.0, (float)index, 0, 0, "Use this Custom Transform Orientation");
+               if (G.vd->twmode == index) {
+                       but = uiDefIconButS(block,ROW, REDRAWHEADERS, ICON_CHECKBOX_HLT, xco,yco,XIC,YIC, &G.vd->twmode, 5.0, (float)index, 0, 0, "Use this Custom Transform Orientation");
+               }
+               else {
+                       but = uiDefIconButS(block,ROW, REDRAWHEADERS, ICON_CHECKBOX_DEHLT, xco,yco,XIC,YIC, &G.vd->twmode, 5.0, (float)index, 0, 0, "Use this Custom Transform Orientation");
+               }
                uiButSetFunc(but, selectTransformOrientation_func, ts, NULL);
                uiDefBut(block, TEX, 0, "", xco+=XIC, yco,100+XIC,20, &ts->name, 0, 30, 0, 0, "Edits the name of this Transform Orientation");
                but = uiDefIconBut(block, BUT, REDRAWVIEW3D, ICON_X, xco+=100+XIC,yco,XIC,YIC, 0, 0, 0, 0, 0, "Deletes this Transform Orientation");
index 138f0a438fd87debc6d0d18d7d8568b08fb8e335..11837cc34334520e8af2eaac49ab15377496f5a9 100644 (file)
@@ -1518,6 +1518,58 @@ void snap_curs_to_sel()
        allqueue(REDRAWVIEW3D, 0);
 }
 
+void snap_curs_to_active()
+{
+       float *curs;
+       curs = give_cursor();
+
+       if (G.obedit)
+       {
+               if (G.obedit->type == OB_MESH)
+               {
+                       /* check active */
+                       if (G.editMesh->selected.last) {
+                               EditSelection *ese = G.editMesh->selected.last;
+                               if ( ese->type == EDITVERT ) {
+                                       EditVert *eve = (EditVert *)ese->data;
+                                       VECCOPY(curs, eve->co);
+                               }
+                               else if ( ese->type == EDITEDGE ) {
+                                       EditEdge *eed = (EditEdge *)ese->data;
+                                       VecAddf(curs, eed->v1->co, eed->v2->co);
+                                       VecMulf(curs, 0.5f);
+                               }
+                               else if ( ese->type == EDITFACE ) {
+                                       EditFace *efa = (EditFace *)ese->data;
+                                       
+                                       if (efa->v4)
+                                       {
+                                               VecAddf(curs, efa->v1->co, efa->v2->co);
+                                               VecAddf(curs, curs, efa->v3->co);
+                                               VecAddf(curs, curs, efa->v4->co);
+                                               VecMulf(curs, 0.25f);
+                                       }
+                                       else
+                                       {
+                                               VecAddf(curs, efa->v1->co, efa->v2->co);
+                                               VecAddf(curs, curs, efa->v3->co);
+                                               VecMulf(curs, 1/3.0f);
+                                       }
+                               }
+                       }
+                       Mat4MulVecfl(G.obedit->obmat, curs);
+               }
+       }
+       else
+       {
+               if (BASACT)
+               {
+                       VECCOPY(curs, BASACT->object->obmat[3]);
+               }
+       }
+       allqueue(REDRAWVIEW3D, 0);
+}
+
 void snap_curs_to_firstsel()
 {
        TransVert *tv;
@@ -1776,7 +1828,7 @@ void snapmenu()
 {
        short event;
 
-       event = pupmenu("Snap %t|Selection -> Grid%x1|Selection -> Cursor%x2|Cursor-> Grid%x3|Cursor-> Selection%x4|Selection-> Center%x5");
+       event = pupmenu("Snap %t|Selection -> Grid%x1|Selection -> Cursor%x2|Cursor-> Grid%x3|Cursor-> Selection%x4|Selection-> Center%x5|Cursor-> Active%x6");
 
        switch (event) {
                case 1: /*Selection to grid*/
@@ -1797,6 +1849,10 @@ void snapmenu()
                    snap_to_center();
                        BIF_undo_push("Snap selection to center");
                    break;
+               case 6: /*Cursor to Active*/
+                   snap_curs_to_active();
+                       BIF_undo_push("Snap selection to center");
+                   break;
        }
 }
 
index 1c091ed39d9ad8799a74f55bfffc84b87cd1c2ed..94019cb02aa0aebbb0c1ed5fd6ee209dd757ba2f 100644 (file)
@@ -682,20 +682,20 @@ static void *get_nearest_action_key (float *selx, short *sel, short *ret_type, b
                                        case ALE_IPO:
                                        {
                                                Ipo *ipo= (Ipo *)ale->key_data;
-                                               ipo_to_keylist(ipo, &act_keys, NULL);
+                                               ipo_to_keylist(ipo, &act_keys, NULL, NULL);
                                        }
                                                break;
                                        case ALE_ICU:
                                        {
                                                IpoCurve *icu= (IpoCurve *)ale->key_data;
-                                               icu_to_keylist(icu, &act_keys, NULL);
+                                               icu_to_keylist(icu, &act_keys, NULL, NULL);
                                        }
                                                break;
                                }
                        }
                        else if (ale->type == ACTTYPE_GROUP) {
                                bActionGroup *agrp= (bActionGroup *)ale->data;
-                               agroup_to_keylist(agrp, &act_keys, NULL);
+                               agroup_to_keylist(agrp, &act_keys, NULL, NULL);
                        }
                        
                        /* loop through keyframes, finding one that was clicked on */
@@ -1130,7 +1130,7 @@ void transform_action_keys (int mode, int dummy)
                }
                break;
        }
-}
+}      
 
 /* ----------------------------------------- */
 
index 45711bc1cfaaf17a923ecb281c891862fc5f6ddc..763d974406497632ce0c9090bc4f2a848088c0b3 100644 (file)
@@ -3603,13 +3603,37 @@ void armature_flip_names(void)
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWBUTSEDIT, 0);
        allqueue(REDRAWBUTSOBJECT, 0);
-       allqueue (REDRAWACTION, 0);
+       allqueue(REDRAWACTION, 0);
        allqueue(REDRAWOOPS, 0);
        BIF_undo_push("Flip names");
+}
+
+/* context: edtimode armature */
+void armature_autoside_names(short axis)
+{
+       bArmature *arm= G.obedit->data;
+       EditBone *ebone;
+       char newname[32];
        
+       for (ebone = G.edbo.first; ebone; ebone=ebone->next) {
+               if (arm->layer & ebone->layer) {
+                       if (ebone->flag & BONE_SELECTED) {
+                               BLI_strncpy(newname, ebone->name, sizeof(newname));
+                               bone_autoside_name(newname, 1, axis, ebone->head[axis], ebone->tail[axis]);
+                               armature_bone_rename(G.obedit->data, ebone->name, newname);
+                       }
+               }
+       }
+       
+       allqueue(REDRAWVIEW3D, 0);
+       allqueue(REDRAWBUTSEDIT, 0);
+       allqueue(REDRAWBUTSOBJECT, 0);
+       allqueue(REDRAWACTION, 0);
+       allqueue(REDRAWOOPS, 0);
+       BIF_undo_push("Auto-side name");
 }
 
-/* context; editmode armature */
+/* context: editmode armature */
 EditBone *armature_bone_get_mirrored(EditBone *ebo)
 {
        EditBone *eboflip= NULL;
index b4206a510aa784aa5722cb0b0a2160638f29f1fa..6ab3d5c17c6cc6e1409cd9ca031880cabbeb993c 100644 (file)
@@ -779,7 +779,7 @@ void remove_verts_defgroup (int allverts)
        case OB_MESH:
                for (eve=G.editMesh->verts.first; eve; eve=eve->next){
                        dvert= CustomData_em_get(&G.editMesh->vdata, eve->data, CD_MDEFORMVERT);
-
+               
                        if (dvert && dvert->dw && ((eve->f & 1) || allverts)){
                                for (i=0; i<dvert->totweight; i++){
                                        /* Find group */
@@ -825,6 +825,36 @@ void remove_verts_defgroup (int allverts)
        }
 }
 
+/* Only available in editmode */
+/* removes from all defgroup, if allverts==0 only selected vertices */
+void remove_verts_defgroups(int allverts)
+{
+       Object *ob;
+       int actdef, defCount;
+       
+       if (multires_level1_test()) return;
+
+       ob= G.obedit;
+       if (ob == NULL) return;
+       
+       actdef= ob->actdef;
+       defCount= BLI_countlist(&ob->defbase);
+       
+       if (defCount == 0) {
+               error("Object has no vertex groups");
+               return;
+       }
+       
+       /* To prevent code redundancy, we just use remove_verts_defgroup, but that
+        * only operates on the active vgroup. So we iterate through all groups, by changing
+        * active group index
+        */
+       for (ob->actdef= 1; ob->actdef <= defCount; ob->actdef++)
+               remove_verts_defgroup(allverts);
+               
+       ob->actdef= actdef;
+}
+
 void vertexgroup_select_by_name(Object *ob, char *name)
 {
        bDeformGroup *curdef;
@@ -859,7 +889,7 @@ void vgroup_assign_with_menu(void)
        
        /* give user choices of adding to current/new or removing from current */
        if (defCount && ob->actdef)
-               mode = pupmenu("Vertex Groups %t|Add Selected to New Group %x1|Add Selected to Active Group %x2|Remove Selected from Active Group %x3");
+               mode = pupmenu("Vertex Groups %t|Add Selected to New Group %x1|Add Selected to Active Group %x2|Remove Selected from Active Group %x3|Remove Selected from All Groups %x4");
        else
                mode= pupmenu("Vertex Groups %t|Add Selected to New Group %x1");
        
@@ -881,6 +911,11 @@ void vgroup_assign_with_menu(void)
                        allqueue(REDRAWVIEW3D, 1);
                        BIF_undo_push("Remove from vertex group");
                        break;
+               case 4: /* remove from all groups */
+                       remove_verts_defgroups(0);
+                       allqueue(REDRAWVIEW3D, 1);
+                       BIF_undo_push("Remove from all vertex groups");
+                       break;
        }
 }
 
index b3ea3e1931c5e81e7550e92eab5426fc93aadcea..fce7fab779d4bdc1e98d417075273404e57697ff 100644 (file)
@@ -2624,10 +2624,10 @@ void insertkey_smarter(ID *id, int blocktype, char *actname, char *constname, in