merge with 2.5 at 19207, plus some half-finished walker stuff
authorJoseph Eagar <joeedh@gmail.com>
Sun, 8 Mar 2009 07:15:41 +0000 (07:15 +0000)
committerJoseph Eagar <joeedh@gmail.com>
Sun, 8 Mar 2009 07:15:41 +0000 (07:15 +0000)
1  2 
projectfiles_vc9/blender/editors/ED_editors.vcproj
source/blender/blenlib/intern/arithb.c
source/blender/bmesh/bmesh_operators.h
source/blender/bmesh/bmesh_walkers.h
source/blender/bmesh/intern/bmesh_walkers.c
source/blender/editors/include/ED_mesh.h
source/blender/editors/mesh/editmesh_add.c
source/blender/makesdna/intern/SConscript
source/blender/makesrna/intern/SConscript
source/blender/render/intern/source/shadeoutput.c

index 2f7009432203c6120550ccdcb43f57e68c8191bd,e05ec40d37633631bdfcdd63624ab0662e86b334..da6f8276230383a706af7a2df1624abb64d12e34
@@@ -1,7 -1,7 +1,7 @@@
  <?xml version="1.0" encoding="Windows-1252"?>\r
  <VisualStudioProject\r
        ProjectType="Visual C++"\r
--      Version="9,00"\r
++      Version="9.00"\r
        Name="ED_editors"\r
        ProjectGUID="{FB88301F-F725-401B-ACD7-D2ABBF333B71}"\r
        RootNamespace="BL_editors"\r
                <Filter\r
                        Name="mesh"\r
                        >\r
++                      <File\r
++                              RelativePath="..\..\..\source\blender\editors\mesh\bmeshutils.c"\r
++                              >\r
++                      </File>\r
                        <File\r
                                RelativePath="..\..\..\source\blender\editors\mesh\editdeform.c"\r
                                >\r
index ebefd94da9ced801ab105c7d42d3988ae4c6f8b8,0df4792cd3d7b9c28a785310735a3790f25d01ad..a633b5811ff59cf349873dc1999230dd3faac7ac
@@@ -111,26 -111,6 +111,26 @@@ float Normalize(float *n
        return d;
  }
  
++/*original function from shadeoutput.c*/
 +double Normalize_d(double *n)
 +{
 +      double d;
 +      
 +      d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
-       /* A larger value causes normalize errors in a scaled down models with camera xtreme close */
-       if(d>1.0e-35F) {
++
++      if(d>0.00000000000000001) {
 +              d= sqrt(d);
 +
 +              n[0]/=d; 
 +              n[1]/=d; 
 +              n[2]/=d;
 +      } else {
 +              n[0]=n[1]=n[2]= 0.0;
 +              d= 0.0;
 +      }
 +      return d;
 +}
 +
  void Crossf(float *c, float *a, float *b)
  {
        c[0] = a[1] * b[2] - a[2] * b[1];
index 30e7e4c9317a9a20e798c250f9559bb962c92a81,0000000000000000000000000000000000000000..a1f0a82257bba0cbc80a84de28a3c708414a2a1b
mode 100644,000000..100644
--- /dev/null
@@@ -1,343 -1,0 +1,345 @@@
 +#ifndef BM_OPERATORS_H
 +#define BM_OPERATORS_H
 +
 +#include "BLI_memarena.h"
 +#include "BLI_ghash.h"
 +
 +#include <stdarg.h>
 +
 +#define BMOP_OPSLOT_INT                       0
 +#define BMOP_OPSLOT_FLT                       1
 +#define BMOP_OPSLOT_PNT                       2
 +#define BMOP_OPSLOT_VEC                       6
 +
 +/*after BMOP_OPSLOT_VEC, everything is 
 +  dynamically allocated arrays.  we
 +  leave a space in the identifiers
 +  for future growth.*/
 +#define BMOP_OPSLOT_PNT_BUF           7
 +
 +#define BMOP_OPSLOT_MAPPING           8
 +#define BMOP_OPSLOT_TYPES             9
 +
 +typedef struct BMOpSlot{
 +      int slottype;
 +      int len;
 +      int flag;
 +      int index; /*index within slot array*/
 +      union {
 +              int i;
 +              float f;                                        
 +              void *p;                                        
 +              float vec[3];                           /*vector*/
 +              void *buf;                              /*buffer*/
 +              GHash *ghash;
 +      } data;
 +}BMOpSlot;
 +
 +/*BMOpSlot->flag*/
 +/*is a dynamically-allocated array.  set at runtime.*/
 +#define BMOS_DYNAMIC_ARRAY    1
 +
 +/*operators represent logical, executable mesh modules.*/
 +#define BMOP_MAX_SLOTS                        16              /*way more than probably needed*/
 +
 +typedef struct BMOperator{
 +      int type;
 +      int slottype;
 +      int needflag;
 +      struct BMOpSlot slots[BMOP_MAX_SLOTS];
 +      void (*exec)(struct BMesh *bm, struct BMOperator *op);
 +      MemArena *arena;
 +}BMOperator;
 +
 +#define MAX_SLOTNAME  32
 +
 +typedef struct slottype {
 +      int type;
 +      char name[MAX_SLOTNAME];
 +} slottype;
 +
 +/*need to refactor code to use this*/
 +typedef struct BMOpDefine {
 +      char *name;
 +      slottype slottypes[BMOP_MAX_SLOTS];
 +      void (*exec)(BMesh *bm, BMOperator *op);
 +      int totslot;
 +      int flag;
 +} BMOpDefine;
 +
 +/*BMOpDefine->flag*/
 +//doesn't do anything at the moment.
 +
 +/*API for operators*/
 +
 +/*data types that use pointers (arrays, etc) should never
 +  have it set directly.  and never use BMO_Set_Pnt to
 +  pass in a list of edges or any arrays, really.*/
 +void BMO_Init_Op(struct BMOperator *op, int opcode);
 +void BMO_Exec_Op(struct BMesh *bm, struct BMOperator *op);
 +void BMO_Finish_Op(struct BMesh *bm, struct BMOperator *op);
 +BMOpSlot *BMO_GetSlot(struct BMOperator *op, int slotcode);
 +void BMO_CopySlot(struct BMOperator *source_op, struct BMOperator *dest_op, int src, int dst);
 +void BMO_Set_Float(struct BMOperator *op, int slotcode, float f);
 +void BMO_Set_Int(struct BMOperator *op, int slotcode, int i);
 +void BMO_Set_Pnt(struct BMOperator *op, int slotcode, void *p);
 +void BMO_Set_Vec(struct BMOperator *op, int slotcode, float *vec);
 +void BMO_SetFlag(struct BMesh *bm, void *element, int flag);
 +void BMO_ClearFlag(struct BMesh *bm, void *element, int flag);
 +int BMO_TestFlag(struct BMesh *bm, void *element, int flag);
 +int BMO_CountFlag(struct BMesh *bm, int flag, int type);
 +void BMO_Flag_To_Slot(struct BMesh *bm, struct BMOperator *op, int slotcode, int flag, int type);
 +void BMO_Flag_Buffer(struct BMesh *bm, struct BMOperator *op, int slotcode, int flag);
 +void BMO_Unflag_Buffer(struct BMesh *bm, struct BMOperator *op, int slotcode, int flag);
 +void BMO_HeaderFlag_To_Slot(struct BMesh *bm, struct BMOperator *op, int slotcode, int flag, int type);
 +int BMO_CountSlotBuf(struct BMesh *bm, struct BMOperator *op, int slotcode);
 +
 +/*copies data, doesn't store a reference to it.*/
 +void BMO_Insert_Mapping(BMesh *bm, BMOperator *op, int slotcode, 
 +                      void *element, void *data, int len);
 +void BMO_Insert_MapFloat(BMesh *bm, BMOperator *op, int slotcode, 
 +                      void *element, float val);
 +
 +//returns 1 if the specified element is in the map.
 +int BMO_InMap(BMesh *bm, BMOperator *op, int slotcode, void *element);
 +void *BMO_Get_MapData(BMesh *bm, BMOperator *op, int slotcode,
 +                    void *element);
 +float BMO_Get_MapFloat(BMesh *bm, BMOperator *op, int slotcode,
 +                     void *element);
 +void BMO_Mapping_To_Flag(struct BMesh *bm, struct BMOperator *op, 
 +                       int slotcode, int flag);
 +
 +/*do NOT use these for non-operator-api-allocated memory! instead
 +  use BMO_Get_MapData, which copies the data.*/
 +void BMO_Insert_MapPointer(BMesh *bm, BMOperator *op, int slotcode, 
 +                      void *element, void *val);
 +void *BMO_Get_MapPointer(BMesh *bm, BMOperator *op, int slotcode,
 +                     void *element);
 +
 +struct GHashIterator;
 +typedef struct BMOIter {
 +      BMOpSlot *slot;
 +      int cur; //for arrays
 +      struct GHashIterator giter;
 +      void *val;
 +} BMOIter;
 +
 +void *BMO_IterNew(BMOIter *iter, BMesh *bm, BMOperator *op, 
 +                int slotcode);
 +void *BMO_IterStep(BMOIter *iter);
 +
 +/*returns a pointer to the key value when iterating over mappings.
 +  remember for pointer maps this will be a pointer to a pointer.*/
 +void *BMO_IterMapVal(BMOIter *iter);
 +
 +/*formatted operator initialization/execution*/
 +int BMO_CallOpf(BMesh *bm, char *fmt, ...);
 +int BMO_InitOpf(BMesh *bm, BMOperator *op, char *fmt, ...);
 +int BMO_VInitOpf(BMesh *bm, BMOperator *op, char *fmt, va_list vlist);
 +
 +/*----------- bmop error system ----------*/
 +
 +/*pushes an error onto the bmesh error stack.
 +  if msg is null, then the default message for the errorcode is used.*/
 +void BMO_RaiseError(BMesh *bm, BMOperator *owner, int errcode, char *msg);
 +
 +/*gets the topmost error from the stack.
 +  returns error code or 0 if no error.*/
 +int BMO_GetError(BMesh *bm, char **msg, BMOperator **op);
 +
 +/*same as geterror, only pops the error off the stack as well*/
 +int BMO_PopError(BMesh *bm, char **msg, BMOperator **op);
 +void BMO_ClearStack(BMesh *bm);
 +
 +#if 0
 +//this is meant for handling errors, like self-intersection test failures.
 +//it's dangerous to handle errors in general though, so disabled for now.
 +
 +/*catches an error raised by the op pointed to by catchop.
 +  errorcode is either the errorcode, or BMERR_ALL for any 
 +  error.*/
 +int BMO_CatchOpError(BMesh *bm, BMOperator *catchop, int errorcode, char **msg);
 +#endif
 +
 +/*------ error code defines -------*/
 +
 +/*error messages*/
 +#define BMERR_SELF_INTERSECTING                       1
 +#define BMERR_DISSOLVEDISK_FAILED             2
 +#define BMERR_CONNECTVERT_FAILED              3
++#define BMERR_WALKER_FAILED                   4
 +
 +static char *bmop_error_messages[] = {
 +       0,
 +       "Self intersection error",
 +       "Could not dissolve vert",
 +       "Could not connect verts",
++       "Could not traverse mesh",
 +};
 +
 +/*------------begin operator defines (see bmesh_opdefines.c too)------------*/
 +/*split op*/
 +#define BMOP_SPLIT                            0
 +
 +enum {
 +      BMOP_SPLIT_MULTIN,
 +      BMOP_SPLIT_MULTOUT,
 +      BMOP_SPLIT_BOUNDS_EDGEMAP, //bounding edges of split faces
 +      BMOP_SPLIT_TOTSLOT,
 +};
 +
 +/*dupe op*/
 +#define BMOP_DUPE     1
 +
 +enum {
 +      BMOP_DUPE_MULTIN,
 +      BMOP_DUPE_ORIG,
 +      BMOP_DUPE_NEW,
 +      /*we need a map for verts duplicated not connected
 +        to any faces, too.*/  
 +      BMOP_DUPE_BOUNDS_EDGEMAP,
 +      BMOP_DUPE_TOTSLOT
 +};
 +
 +/*delete op*/
 +#define BMOP_DEL      2
 +
 +enum {
 +      BMOP_DEL_MULTIN,
 +      BMOP_DEL_CONTEXT,
 +      BMOP_DEL_TOTSLOT,
 +};
 +
 +#define DEL_VERTS             1
 +#define DEL_EDGES             2
 +#define DEL_ONLYFACES 3
 +#define DEL_EDGESFACES        4
 +#define DEL_FACES             5
 +#define DEL_ALL                       6
 +#define DEL_ONLYTAGGED                7
 +
 +/*BMOP_DEL_CONTEXT*/
 +enum {
 +      BMOP_DEL_VERTS = 1,
 +      BMOP_DEL_EDGESFACES,
 +      BMOP_DEL_ONLYFACES,
 +      BMOP_DEL_FACES,
 +      BMOP_DEL_ALL,
 +};
 +
 +/*editmesh->bmesh op*/
 +#define BMOP_FROM_EDITMESH            3
 +enum {
 +      BMOP_FROM_EDITMESH_EM,
 +      BMOP_FROM_EDITMESH_TOTSLOT,
 +};
 +
 +#define BMOP_TO_EDITMESH              4
 +/*bmesh->editmesh op*/
 +enum {
 +      BMOP_TO_EDITMESH_EMOUT,
 +      BMOP_TO_EDITMESH_TOTSLOT,
 +};
 +
 +/*edge subdivide op*/
 +#define BMOP_ESUBDIVIDE                       5
 +enum {
 +      BMOP_ESUBDIVIDE_EDGES,
 +      BMOP_ESUBDIVIDE_NUMCUTS,
 +      BMOP_ESUBDIVIDE_FLAG, //beauty flag in esubdivide
 +      BMOP_ESUBDIVIDE_RADIUS,
 +
 +      BMOP_ESUBDIVIDE_CUSTOMFILL_FACEMAP,
 +      BMOP_ESUBDIVIDE_PERCENT_EDGEMAP,
 +
 +      /*inner verts/new faces of completely filled faces, e.g.
 +        fully selected face.*/
 +      BMOP_ESUBDIVIDE_INNER_MULTOUT,
 +
 +      /*new edges and vertices from splitting original edges,
 +        doesn't include edges creating by connecting verts.*/
 +      BMOP_ESUBDIVIDE_SPLIT_MULTOUT,  
 +      BMOP_ESUBDIVIDE_TOTSLOT,
 +};
 +/*
 +SUBDIV_SELECT_INNER
 +SUBDIV_SELECT_ORIG
 +SUBDIV_SELECT_INNER_SEL
 +SUBDIV_SELECT_LOOPCUT
 +DOUBLEOPFILL
 +*/
 +
 +/*triangulate*/
 +#define BMOP_TRIANGULATE              6
 +
 +enum {
 +      BMOP_TRIANG_FACEIN,
 +      BMOP_TRIANG_NEW_EDGES,
 +      BMOP_TRIANG_NEW_FACES,
 +      BMOP_TRIANG_TOTSLOT,
 +};
 +
 +/*dissolve faces*/
 +#define BMOP_DISSOLVE_FACES           7
 +enum {
 +      BMOP_DISFACES_FACEIN,
 +      //list of faces that comprise regions of split faces
 +      BMOP_DISFACES_REGIONOUT,
 +      BMOP_DISFACES_TOTSLOT,
 +};
 +
 +/*dissolve verts*/
 +#define BMOP_DISSOLVE_VERTS           8
 +
 +enum {
 +      BMOP_DISVERTS_VERTIN,
 +      BMOP_DISVERTS_TOTSLOT,
 +};
 +
 +#define BMOP_MAKE_FGONS                       9
 +#define BMOP_MAKE_FGONS_TOTSLOT       0
 +
 +#define BMOP_EXTRUDE_EDGECONTEXT      10
 +enum {
 +      BMOP_EXFACE_EDGEFACEIN,
 +      BMOP_EXFACE_EXCLUDEMAP, //exclude edges from skirt connecting
 +      BMOP_EXFACE_MULTOUT, //new geometry
 +      BMOP_EXFACE_TOTSLOT,
 +};
 +
 +#define BMOP_CONNECT_VERTS            11
 +enum {
 +      BM_CONVERTS_VERTIN,
 +      BM_CONVERTS_EDGEOUT,
 +      BM_CONVERTS_TOTSLOT
 +};
 +
 +/*keep this updated!*/
 +#define BMOP_TOTAL_OPS                        12
 +/*-------------------------------end operator defines-------------------------------*/
 +
 +extern BMOpDefine *opdefines[];
 +extern int bmesh_total_ops;
 +
 +/*------specific operator helper functions-------*/
 +
 +/*executes the duplicate operation, feeding elements of 
 +  type flag etypeflag and header flag flag to it.  note,
 +  to get more useful information (such as the mapping from
 +  original to new elements) you should run the dupe op manually.*/
 +struct Object;
 +struct EditMesh;
 +
 +void BMOP_DupeFromFlag(struct BMesh *bm, int etypeflag, int flag);
 +void BM_esubdivideflag(struct Object *obedit, struct BMesh *bm, int selflag, float rad, 
 +             int flag, int numcuts, int seltype);
 +void BM_extrudefaceflag(BMesh *bm, int flag);
 +
 +/*these next two return 1 if they did anything, or zero otherwise.
 +  they're kindof a hackish way to integrate with fkey, until
 +  such time as fkey is completely bmeshafied.*/
 +int BM_DissolveFaces(struct EditMesh *em, int flag);
 +/*this doesn't display errors to the user, btw*/
 +int BM_ConnectVerts(struct EditMesh *em, int flag);
 +
 +#endif
index 5f0b1e2f25683dab74f0e474cdbfba1a189bc6b3,0000000000000000000000000000000000000000..22e92e9b6596d8fd9e9ea7896775799e402bb00c
mode 100644,000000..100644
--- /dev/null
@@@ -1,26 -1,0 +1,33 @@@
-       void   (*step) (struct BMWalker *walker);
-       int visitedmask;
 +#ifndef BM_WALKERS_H
 +#define BM_WALKERS_H
 +
++#include "BLI_ghash.h"
++
++/*
++  NOTE: do NOT modify topology while walking a mesh!
++*/
++
 +/*Walkers*/
 +typedef struct BMWalker{
 +      BLI_mempool *stack;
 +      BMesh *bm;
 +      void *currentstate;
 +      void *(*begin) (struct BMWalker *walker, void *start);
 +      void *(*yield)(struct BMWalker *walker);
- void BMWalker_Init(struct BMWalker *walker, BMesh *bm, int type, int searchmask);
++      void *(*step) (struct BMWalker *walker);
 +      int restrictflag;
++      GHash *visithash;
 +}BMWalker;
 +
- #define BM_SHELLWALKER        0
- #define BM_LOOPWALKER 1
- #define BM_RINGWALKER 2
- #define BM_UVISLANDS          3
- #define BM_MAXWALKERS 4
++void BMWalker_Init(struct BMWalker *walker,BMesh *bm,int type, int searchmask);
 +void *BMWalker_Step(struct BMWalker *walker);
 +void BMWalker_End(struct BMWalker *walker);
 +
++#define BMW_SHELL     0
++/*#define BMW_LOOP    1
++#define BMW_RING      2
++#define BMW_UVISLANDS 3*/
++#define BMW_ISLANDBOUND       1
++#define BMW_MAXWALKERS        2
 +
 +#endif
index 6e0717ce7e8194dcf3d18debdaf98405aa5d3171,0000000000000000000000000000000000000000..23efdd0b022578ba2c74004f4fb12334d13c4618
mode 100644,000000..100644
--- /dev/null
@@@ -1,286 -1,0 +1,351 @@@
- /*
 +#include <stdio.h>
 +#include <string.h>
 +#include "BLI_mempool.h"
 +
 +#include "bmesh_private.h"
 +#include "bmesh_walkers.h"
 +
 +#include "bmesh.h"
 +
++/*
++ - joeedh -
++ design notes:
++
++ * walkers should use tool flags, not header flags
++ * walkers now use ghash rather then stealing flags.
++   ghash can be rewritten to be faster if necassary.
++ * walkers should always raise BMERR_WALKER_FAILED,
++   with a custom error message.
++ * tools should ALWAYS have necassary error handling
++   for if walkers fail.
++*/
++
 +/*
 +NOTE: This code needs to be read through a couple of times!!
 +*/
 +
 +typedef struct shellWalker{
 +      struct shellWalker *prev;
 +      BMVert *base;                   
 +      BMEdge *curedge, *current;
 +} shellWalker;
 +
- static int request_walkerMask(struct BMesh *bm);
++typedef struct islandboundWalker {
++      struct islandboundWalker *prev;
++      BMEdge *base;
++      BMVert *lastv;
++      BMEdge *curedge;
++} islandboundWalker;
++
++/*  NOTE: this comment is out of date, update it - joeedh
 + *    BMWalker - change this to use the filters functions.
 + *    
 + *    A generic structure for maintaing the state and callbacks nessecary for walking over
 + *  the surface of a mesh. An example of usage:
 + *
 + *         BMEdge *edge;
 + *         BMWalker *walker = BMWalker_create(BM_SHELLWALKER, BM_SELECT);
 + *       walker->begin(walker, vert);
 + *       for(edge = BMWalker_walk(walker); edge; edge = bmeshWwalker_walk(walker)){
 + *            bmesh_select_edge(edge);
 + *       }
 + *       BMWalker_free(walker);
 + *
 + *    The above example creates a walker that walks over the surface a mesh by starting at
 + *  a vertex and traveling across its edges to other vertices, and repeating the process
 + *  over and over again until it has visited each vertex in the shell. An additional restriction
 + *  is passed into the BMWalker_create function stating that we are only interested
 + *  in walking over edges that have been flagged with the bitmask 'BM_SELECT'.
 + *
 + *
 +*/
 +
 +/*Forward declerations*/
- static void BMWalker_popState(struct BMWalker *walker);
- static void BMWalker_pushState(struct BMWalker *walker);
- static void *shellWalker_begin(struct BMWalker *walker, void *data);
- static void *shellWalker_yield(struct BMWalker *walker);
- static void shellWalker_step(struct BMWalker *walker);
 +static void *BMWalker_walk(struct BMWalker *walker);
- /*
-  *    REQUEST_WALKERMASK
-  *
-  *  Each active walker for a bmesh has its own bitmask
-  *    to use for flagging elements as visited. request_walkerMask
-  *    queries the bmesh passed in and returns the first free
-  *  bitmask. If none are free, it returns 0. The maximum number
-  *  of walkers that can be used for a single bmesh between calls to
-  *  bmesh_edit_begin() and bmesh_edit_end() is defined by the constant
-  *  BM_MAXWALKERS.
-  *
- */
- static int request_walkerMask(BMesh *bm)
- {
-       int i;
-       for(i=0; i < BM_MAXWALKERS; i++){
-               if(!(bm->walkers & (1 << i))){
-                       bm->walkers |= (1 << i);
-                       return (1 << i);
-               }
-       }
-       return 0;
- }
++static void BMWalker_popstate(struct BMWalker *walker);
++static void BMWalker_pushstate(struct BMWalker *walker);
++
++static void *shellWalker_Begin(struct BMWalker *walker, void *data);
++static void *shellWalker_Yield(struct BMWalker *walker);
++static void *shellWalker_Step(struct BMWalker *walker);
++
++static void *islandboundWalker_Begin(BMWalker *walker, void *data);
++static void *islandboundWalker_Yield(BMWalker *walker);
++static void *islandboundWalker_Step(BMWalker *walker);
++
 +struct shellWalker;
 +
 +/* Pointer hiding*/
 +typedef struct bmesh_walkerGeneric{
 +      struct bmesh_walkerGeneric *prev;
 +} bmesh_walkerGeneric;
 +
 +
- void BMWalker_init(BMWalker *walker, BMesh *bm, int type, int searchmask)
 +/*
 + * BMWalker_CREATE
 + * 
 + * Allocates and returns a new mesh walker of 
 + * a given type. The elements visited are filtered
 + * by the bitmask 'searchmask'.
 + *
 +*/
 +
-       int visitedmask = request_walkerMask(bm);
++void BMWalker_Init(BMWalker *walker, BMesh *bm, int type, int searchmask)
 +{
-       if(visitedmask){
-               memset(walker, 0, sizeof(BMWalker));
-               walker->bm = bm;
-               walker->visitedmask = visitedmask;
-               walker->restrictflag = searchmask;
-               switch(type){
-                       case BM_SHELLWALKER:
-                               walker->begin = shellWalker_begin;
-                               walker->step = shellWalker_step;
-                               walker->yield = shellWalker_yield;
-                               size = sizeof(shellWalker);             
-                               break;
-                       //case BM_LOOPWALKER:
-                       //      walker->begin = loopwalker_begin;
-                       //      walker->step = loopwalker_step;
-                       //      walker->yield = loopwalker_yield;
-                       //      size = sizeof(loopWalker);
-                       //      break;
-                       //case BM_RINGWALKER:
-                       //      walker->begin = ringwalker_begin;
-                       //      walker->step = ringwalker_step;
-                       //      walker->yield = ringwalker_yield;
-                       //      size = sizeof(ringWalker);
-                       //      break;
-                       default:
-                               break;
-               }
-               walker->stack = BLI_mempool_create(size, 100, 100);
-               walker->currentstate = NULL;
 +      int size = 0;
 +      
-  * BMWalker_END
++      memset(walker, 0, sizeof(BMWalker));
++      walker->bm = bm;
++      walker->restrictflag = searchmask;
++      walker->visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
++
++      switch(type){
++              case BMW_SHELL:
++                      walker->begin = shellWalker_Begin;
++                      walker->step = shellWalker_Step;
++                      walker->yield = shellWalker_Yield;
++                      size = sizeof(shellWalker);             
++                      break;
++              case BMW_ISLANDBOUND:
++                      walker->begin = islandboundWalker_Begin;
++                      walker->step = islandboundWalker_Step;
++                      walker->yield = islandboundWalker_Yield;
++                      size = sizeof(islandboundWalker);               
++                      break;
++              //case BMW_LOOP:
++              //      walker->begin = loopwalker_Begin;
++              //      walker->step = loopwalker_Step;
++              //      walker->yield = loopwalker_Yield;
++              //      size = sizeof(loopWalker);
++              //      break;
++              //case BMW_RING:
++              //      walker->begin = ringwalker_Begin;
++              //      walker->step = ringwalker_Step;
++              //      walker->yield = ringwalker_Yield;
++              //      size = sizeof(ringWalker);
++              //      break;
++              default:
++                      break;
 +      }
++      walker->stack = BLI_mempool_create(size, 100, 100);
++      walker->currentstate = NULL;
 +}
 +
 +/*
- void BMWalker_end(BMWalker *walker)
++ * BMWalker_End
 + *
 + * Frees a walker's stack.
 + *
 +*/
 +
-  * BMWalker_STEP
++void BMWalker_End(BMWalker *walker)
 +{
 +      BLI_mempool_destroy(walker->stack);
 +}
 +
 +
 +/*
- void *BMWalker_step(BMWalker *walker)
++ * BMWalker_Step
 + *
 +*/
 +
-       while(head = BMWalker_walk(walker)){
-               //NOTE: figure this out 
-               //if(bmesh_test_flag(head, walker->restrictflag)) return head;
-               return head;
-       }
-       return NULL;
++void *BMWalker_Step(BMWalker *walker)
 +{
 +      BMHeader *head;
 +
-               else BMWalker_popState(walker);
++      head = BMWalker_walk(walker);
++
++      return head;
 +}
 +
 +/*
 + * BMWalker_WALK
 + *
 + * Steps a mesh walker forward by one element
 + *
 + * TODO:
 + *  -add searchmask filtering
 + *
 +*/
 +
 +static void *BMWalker_walk(BMWalker *walker)
 +{
 +      void *current = NULL;
 +
 +      while(walker->currentstate){
 +              walker->step(walker);
 +              current = walker->yield(walker);
 +              if(current) return current;
-  * BMWalker_POPSTATE
++              else BMWalker_popstate(walker);
 +
 +      }
 +      return NULL;
 +}
 +
 +/*
- static void BMWalker_popState(BMWalker *walker)
++ * BMWalker_popstate
 + *
 + * Pops the current walker state off the stack
 + * and makes the previous state current
 + *
 +*/
 +
-  * BMWalker_PUSHSTATE
++static void BMWalker_popstate(BMWalker *walker)
 +{
 +      void *oldstate;
 +      oldstate = walker->currentstate;
 +      walker->currentstate 
 +              = ((bmesh_walkerGeneric*)walker->currentstate)->prev;
 +      BLI_mempool_free(walker->stack, oldstate);
 +}
 +
 +/*
- static void BMWalker_pushState(BMWalker *walker)
++ * BMWalker_pushstate
 + *
 + * Pushes the current state down the stack and allocates
 + * a new one.
 + *
 +*/
 +
- static void *shellWalker_begin(BMWalker *walker, void *data){
++static void BMWalker_pushstate(BMWalker *walker)
 +{
 +      bmesh_walkerGeneric *newstate;
 +      newstate = BLI_mempool_alloc(walker->stack);
 +      newstate->prev = walker->currentstate;
 +      walker->currentstate = newstate;
 +}
 +
 +/*    Shell Walker:
 + *
 + *    Starts at a vertex on the mesh and walks over the 'shell' it belongs 
 + *    to via visiting connected edges.
 + *
 + *    TODO:
 + *
 + *  Add restriction flag/callback for wire edges.
 + * 
 +*/
 +
-       BMWalker_pushState(walker);
++static void *shellWalker_Begin(BMWalker *walker, void *data){
 +      BMVert *v = data;
 +      shellWalker *shellWalk = NULL;
-       shellWalk->base = shellWalk->curedge = NULL;
++      BMWalker_pushstate(walker);
 +      shellWalk = walker->currentstate;
- static void *shellWalker_yield(BMWalker *walker)
++      shellWalk->base = NULL;
++      shellWalk->curedge = NULL;
 +      if(v->edge){
 +              shellWalk->base = v;
 +              shellWalk->curedge = v->edge;
 +      }
++
++      return v->edge;
 +}
- static void shellWalker_step(BMWalker *walker)
++static void *shellWalker_Yield(BMWalker *walker)
 +{
 +      shellWalker *shellWalk = walker->currentstate;
 +      return shellWalk->curedge;
 +}
 +
-       if(!(shellWalk->base->head.flag & walker->visitedmask))
-               shellWalk->base->head.flag |= walker->visitedmask;
++static void *shellWalker_Step(BMWalker *walker)
 +{
 +      BMEdge *curedge, *next = NULL;
 +      BMVert *ov = NULL;
 +      int restrictpass = 1;
 +      shellWalker *shellWalk = walker->currentstate;
-               if(!(curedge->head.flag & walker->visitedmask)){ 
-                       curedge->head.flag |= walker->visitedmask;
-                       if(walker->restrictflag && (!(curedge->head.flag & walker->restrictflag))) restrictpass = 0;
-                       if(restrictpass){
 +      
++      if (!BLI_ghash_lookup(walker->visithash, shellWalk->base))
++              BLI_ghash_insert(walker->visithash, shellWalk->base, NULL);
++
 +      /*find the next edge whose other vertex has not been visited*/
 +      curedge = shellWalk->curedge;
 +      do{
-                               BMWalker_pushState(walker);
++              if (!BLI_ghash_lookup(walker->visithash, curedge)) { 
++                      BLI_ghash_insert(walker->visithash, curedge, NULL);
++                      if(walker->restrictflag && (!BMO_TestFlag(walker->bm, curedge, walker->restrictflag))) restrictpass = 0;
++                      if(restrictpass) {
 +                              ov = BM_OtherEdgeVert(curedge, shellWalk->base);
 +                              
 +                              /*save current state*/
 +                              shellWalk->curedge = curedge;
 +                              /*push a new state onto the stack*/
- }
++                              BMWalker_pushstate(walker);
 +                              
 +                              /*populate the new state*/
 +                              ((shellWalker*)walker->currentstate)->base = ov;
 +                              ((shellWalker*)walker->currentstate)->curedge = curedge;
 +                              /*break out of loop*/
 +
 +                              next = curedge;
 +                              break;
 +                      }
 +                      curedge = bmesh_disk_nextedge(curedge, shellWalk->base);
 +              }
 +      }while(curedge != shellWalk->curedge);
 +      
 +      shellWalk->current = next;
 +      return shellWalk->current;
++}
++
++/*    Island Boundary Walker:
++ *
++ *    Starts at a edge on the mesh and walks over the boundary of an
++ *      island it belongs to.
++ *
++ *    TODO:
++ *
++ *  Add restriction flag/callback for wire edges.
++ * 
++*/
++
++static void *islandboundWalker_Begin(BMWalker *walker, void *data){
++      BMEdge *e = data;
++      islandboundWalker *iwalk = NULL;
++
++      BMWalker_pushstate(walker);
++
++      iwalk = walker->currentstate;
++      iwalk->base = iwalk->curedge = e;
++
++      return e;
++}
++
++static void *islandboundWalker_Yield(BMWalker *walker)
++{
++      islandboundWalker *iwalk = walker->currentstate;
++
++      return iwalk->curedge;
++}
++
++static void *islandboundWalker_Step(BMWalker *walker)
++{
++      islandboundWalker *iwalk = walker->currentstate, *owalk;
++      BMIter iter;
++      BMVert *v;
++      BMEdge *e = iwalk->curedge;
++      int found;
++
++      owalk = iwalk;
++
++      if (iwalk->lastv == e->v1) v = e->v2;
++      else v = e->v1;
++      
++      BMWalker_popstate(walker);
++
++      e=BMIter_New(&iter, walker->bm, BM_EDGES_OF_VERT, v);
++      for (; e; e=BMIter_Step(&iter)) {
++              if (!BMO_TestFlag(walker->bm, e, walker->restrictflag))
++                      continue;
++              if (BLI_ghash_haskey(walker->visithash, e)) continue;
++
++              BLI_ghash_insert(walker->visithash, e, NULL);
++              BMWalker_pushstate(walker);
++              
++              iwalk = walker->currentstate;
++              iwalk->base = iwalk->base;
++              iwalk->curedge = e;
++              iwalk->lastv = v;               
++              
++      }
++
++      return iwalk->curedge;
++}
index 4aa8d6a9d54d5b8c4a9e04f528ba4c14fa25fb07,4aa8d6a9d54d5b8c4a9e04f528ba4c14fa25fb07..6c8f48da251ee5075f7966ed44df430ff179bc47
@@@ -42,18 -42,18 +42,22 @@@ targetdir = root_build_dir + '/makesdna
  
  if not (root_build_dir[0]==os.sep or root_build_dir[1]==':'):
        targetdir = '#' + targetdir
++      #root_build_dir = "#"
  
  makesdna = makesdna_tool.Program (target = targetdir, source = source_files, LIBS=['bf_guardedalloc'])
  
  dna_dict = dna.Dictionary()
  dna.Depends ('dna.c', makesdna)
  dna.Depends ('dna.c', header_files)
++
++ap = os.path.abspath
++
  if env['OURPLATFORM'] != 'linuxcross':
        if USE_WINE:
--              dna.Command ('dna.c', '', 'wine ' + root_build_dir+os.sep+"makesdna $TARGET")
++              dna.Command ('dna.c', '', 'wine ' + ap(root_build_dir+os.sep+"makesdna $TARGET"))
        else:
--              dna.Command ('dna.c', '', root_build_dir+os.sep+"makesdna $TARGET")
++              dna.Command ('dna.c', '', ap(root_build_dir+os.sep+"makesdna $TARGET"))
  else:
--      dna.Command ('dna.c', '', root_build_dir+os.sep+"makesdna.exe $TARGET")
++      dna.Command ('dna.c', '', ap(root_build_dir+os.sep+"makesdna.exe $TARGET"))
  obj = ['intern/dna.c', 'intern/dna_genfile.c']
  Return ('obj')
index 330153f0a7f3304a3fd12ced02f5b8978e2457b5,330153f0a7f3304a3fd12ced02f5b8978e2457b5..ac05eab14d145657f97d58f59ce93c76296f92f0
@@@ -2,10 -2,10 +2,12 @@@
  import sys
  import os
  
++ap = os.path.abspath
++
  Import ('env')
  cflags = '-Wall'
  defines = []
--root_build_dir=env['BF_BUILDDIR']
++root_build_dir=ap(env['BF_BUILDDIR'])
  
  source_files = env.Glob('*.c')
  
@@@ -74,17 -74,17 +76,17 @@@ rna_dict = rna.Dictionary(
  rna.Depends (generated_files, makesrna)
  
  # this seems bad, how to retrieve it from scons?
--build_dir = root_build_dir + '/source/blender/makesrna/intern/'
++build_dir = ap(root_build_dir + '/source/blender/makesrna/intern') + "/"
  
  if env['OURPLATFORM'] != 'linuxcross':
--    rna.Command (generated_files, '', root_build_dir+os.sep+"makesrna " + build_dir)
++    rna.Command (generated_files, '', ap(root_build_dir+os.sep+"makesrna ") + " \"" + build_dir + "\"")
  else:
--    rna.Command (generated_files, '', root_build_dir+os.sep+"makesrna.exe "  + build_dir)
++    rna.Command (generated_files, '', ap(root_build_dir+os.sep+"makesrna.exe") + " \""  + build_dir + "\"")
        
      if USE_WINE:
--        rna.Command (generated_files, '', 'wine ' + root_build_dir+os.sep+"makesrna.exe "  + build_dir)
++        rna.Command (generated_files, '', ap('wine ' + root_build_dir+os.sep+"makesrna.exe") + " \""  + build_dir + "\"")
      else:
--        rna.Command (generated_files, '', root_build_dir+os.sep+"makesrna.exe "  + build_dir)
++        rna.Command (generated_files, '', ap(root_build_dir+os.sep+"makesrna.exe") + " \""  + build_dir + "\"")
  
  
  obj = ['intern/rna_access.c', 'intern/rna_dependency.c']
index 4c627056c1dcfb04f8eaf7784857a709b614db67,4c627056c1dcfb04f8eaf7784857a709b614db67..aafd81a5b56f0e2ab2330934c735edcca727c45d
@@@ -377,25 -377,25 +377,6 @@@ void renderspothalo(ShadeInput *shi, fl
  
  /* ---------------- shaders ----------------------- */
  
--static double Normalize_d(double *n)
--{
--      double d;
--      
--      d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
--
--      if(d>0.00000000000000001) {
--              d= sqrt(d);
--
--              n[0]/=d; 
--              n[1]/=d; 
--              n[2]/=d;
--      } else {
--              n[0]=n[1]=n[2]= 0.0;
--              d= 0.0;
--      }
--      return d;
--}
--
  /* mix of 'real' fresnel and allowing control. grad defines blending gradient */
  float fresnel_fac(float *view, float *vn, float grad, float fac)
  {