Merge of trunk into blender 2.5:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 12 Nov 2008 21:16:53 +0000 (21:16 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 12 Nov 2008 21:16:53 +0000 (21:16 +0000)
svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r12987:17416

Issues:
* GHOST/X11 had conflicting changes. Some code was added in 2.5, which was
  later added in trunk also, but reverted partially, specifically revision
  16683. I have left out this reversion in the 2.5 branch since I think it is
  needed there.
  http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=16683
* Scons had various conflicting changes, I decided to go with trunk version
  for everything except priorities and some library renaming.
* In creator.c, there were various fixes and fixes for fixes related to the -w
  -W and -p options. In 2.5 -w and -W is not coded yet, and -p is done
  differently. Since this is changed so much, and I don't think those fixes
  would be needed in 2.5, I've left them out.
* Also in creator.c: there was code for a python bugfix where the screen was not
  initialized when running with -P. The code that initializes the screen there
  I had to disable, that can't work in 2.5 anymore but left it commented as a
  reminder.

Further I had to disable some new function calls. using src/ and python/, as
was done already in this branch, disabled function calls:
* bpath.c: error reporting
* BME_conversions.c: editmesh conversion functions.
* SHD_dynamic: disabled almost completely, there is no python/.
* KX_PythonInit.cpp and Ketsji/ build files: Mathutils is not there, disabled.
* text.c: clipboard copy call.
* object.c: OB_SUPPORT_MATERIAL.
* DerivedMesh.c and subsurf_ccg, stipple_quarttone.

Still to be done:
* Go over files and functions that were moved to a different location but could
  still use changes that were done in trunk.

162 files changed:
1  2 
intern/SoundSystem/SConscript
intern/boolop/SConscript
intern/bsp/SConscript
intern/ghost/GHOST_Types.h
intern/ghost/SConscript
intern/ghost/intern/GHOST_C-api.cpp
intern/ghost/intern/GHOST_SystemCarbon.cpp
intern/ghost/intern/GHOST_SystemWin32.cpp
intern/ghost/intern/GHOST_SystemX11.cpp
intern/ghost/intern/GHOST_SystemX11.h
intern/ghost/intern/GHOST_WindowWin32.cpp
intern/ghost/intern/GHOST_WindowX11.cpp
intern/ghost/intern/GHOST_WindowX11.h
intern/opennl/SConscript
intern/string/STR_String.h
source/Makefile
source/blender/CMakeLists.txt
source/blender/Makefile
source/blender/SConscript
source/blender/blenkernel/BKE_bmesh.h
source/blender/blenkernel/BKE_font.h
source/blender/blenkernel/BKE_global.h
source/blender/blenkernel/BKE_main.h
source/blender/blenkernel/BKE_scene.h
source/blender/blenkernel/BKE_screen.h
source/blender/blenkernel/CMakeLists.txt
source/blender/blenkernel/SConscript
source/blender/blenkernel/intern/BME_conversions.c
source/blender/blenkernel/intern/BME_tools.c
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/Makefile
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/blender.c
source/blender/blenkernel/intern/collision.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/displist.c
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/exotic.c
source/blender/blenkernel/intern/font.c
source/blender/blenkernel/intern/idprop.c
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/ipo.c
source/blender/blenkernel/intern/key.c
source/blender/blenkernel/intern/lattice.c
source/blender/blenkernel/intern/library.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/mball.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/multires-firstlevel.c
source/blender/blenkernel/intern/multires.c
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/packedFile.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/pointcache.c
source/blender/blenkernel/intern/property.c
source/blender/blenkernel/intern/sca.c
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/screen.c
source/blender/blenkernel/intern/script.c
source/blender/blenkernel/intern/softbody.c
source/blender/blenkernel/intern/subsurf_ccg.c
source/blender/blenkernel/intern/text.c
source/blender/blenkernel/intern/texture.c
source/blender/blenkernel/intern/world.c
source/blender/blenkernel/intern/writeavi.c
source/blender/blenkernel/intern/writeffmpeg.c
source/blender/blenkernel/intern/writeframeserver.c
source/blender/blenlib/BLI_arithb.h
source/blender/blenlib/BLI_blenlib.h
source/blender/blenlib/SConscript
source/blender/blenlib/intern/Makefile
source/blender/blenlib/intern/arithb.c
source/blender/blenlib/intern/bpath.c
source/blender/blenlib/intern/fileops.c
source/blender/blenlib/intern/freetypefont.c
source/blender/blenlib/intern/util.c
source/blender/blenloader/BLO_readfile.h
source/blender/blenloader/SConscript
source/blender/blenloader/intern/readblenentry.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/datafiles/SConscript
source/blender/editors/include/BIF_gl.h
source/blender/editors/interface/Makefile
source/blender/editors/interface/SConscript
source/blender/editors/screen/Makefile
source/blender/editors/screen/SConscript
source/blender/editors/screen/glutil.c
source/blender/editors/space_time/Makefile
source/blender/editors/space_time/SConscript
source/blender/editors/space_view3d/Makefile
source/blender/editors/space_view3d/SConscript
source/blender/imbuf/SConscript
source/blender/imbuf/intern/cineon/SConscript
source/blender/imbuf/intern/thumbs.c
source/blender/makesdna/DNA_ID.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_screen_types.h
source/blender/makesdna/DNA_space_types.h
source/blender/makesdna/DNA_view3d_types.h
source/blender/makesdna/intern/SConscript
source/blender/makesdna/intern/makesdna.c
source/blender/makesrna/intern/makesrna.c
source/blender/nodes/CMakeLists.txt
source/blender/nodes/Makefile
source/blender/nodes/SConscript
source/blender/nodes/intern/CMP_nodes/Makefile
source/blender/nodes/intern/CMP_util.h
source/blender/nodes/intern/Makefile
source/blender/nodes/intern/SHD_nodes/Makefile
source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c
source/blender/nodes/intern/SHD_util.h
source/blender/python/BPY_extern.h
source/blender/python/Makefile
source/blender/quicktime/SConscript
source/blender/quicktime/apple/quicktime_export.c
source/blender/radiosity/CMakeLists.txt
source/blender/radiosity/SConscript
source/blender/radiosity/intern/source/Makefile
source/blender/radiosity/intern/source/radfactors.c
source/blender/radiosity/intern/source/radnode.c
source/blender/radiosity/intern/source/radpreprocess.c
source/blender/radiosity/intern/source/radrender.c
source/blender/render/SConscript
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/pipeline.c
source/blender/windowmanager/SConscript
source/blender/windowmanager/intern/Makefile
source/blender/windowmanager/intern/wm_init_exit.c
source/creator/CMakeLists.txt
source/creator/Makefile
source/creator/SConscript
source/creator/creator.c
source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
source/gameengine/BlenderRoutines/CMakeLists.txt
source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
source/gameengine/BlenderRoutines/KX_BlenderGL.cpp
source/gameengine/BlenderRoutines/Makefile
source/gameengine/BlenderRoutines/SConscript
source/gameengine/Converter/BL_BlenderDataConversion.cpp
source/gameengine/Converter/CMakeLists.txt
source/gameengine/Converter/KX_BlenderSceneConverter.cpp
source/gameengine/Converter/KX_ConvertSensors.cpp
source/gameengine/Converter/Makefile
source/gameengine/Converter/SConscript
source/gameengine/GameLogic/SConscript
source/gameengine/GamePlayer/ghost/SConscript
source/gameengine/Ketsji/CMakeLists.txt
source/gameengine/Ketsji/KX_PythonInit.cpp
source/gameengine/Ketsji/Makefile
source/gameengine/Ketsji/SConscript
source/gameengine/Physics/Bullet/SConscript
source/gameengine/Physics/Sumo/SConscript
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript
source/gameengine/VideoTexture/SConscript
source/gameengine/VideoTexture/Texture.cpp

@@@ -13,4 -14,7 +14,7 @@@ if env['WITH_BF_OPENAL']
  else:
        defs = 'NO_SOUND'
  
 -env.BlenderLib ('bf_soundsystem', sources, Split(incs), Split(defs), libtype=['core','player'], priority = [20,140] )
+ if not env['WITH_BF_SDL']:
+       defs += ' DISABLE_SDL'
 +env.BlenderLib ('bf_soundsystem', sources, Split(incs), Split(defs), libtype=['core','player'], priority = [25,135] )
@@@ -8,7 -8,7 +8,7 @@@ incs += ' ../../source/blender/makesdn
  incs += ' ../../source/blender/blenlib'
  
  if (env['OURPLATFORM'] == 'win32-mingw'):
-       env.BlenderLib ('bf_bop', sources, Split(incs) , [], libtype=['common','intern'], priority = [5,50] )
 -    env.BlenderLib ('blender_bop', sources, Split(incs) , [], libtype=['common','intern'], priority = [30,85] )
++    env.BlenderLib ('blender_bop', sources, Split(incs) , [], libtype=['common','intern'], priority = [5,50] )
  else:
-       env.BlenderLib ('bf_bop', sources, Split(incs) , [], libtype='common', priority = 5 )
+     env.BlenderLib ('blender_bop', sources, Split(incs) , [], libtype='common', priority = 5 )
  
@@@ -6,7 -6,7 +6,7 @@@ sources = env.Glob('intern/*.cpp'
  incs = 'intern ../container ../moto/include ../memutil'
  
  if (env['OURPLATFORM'] == 'win32-mingw'):
-       env.BlenderLib ('bf_BSP', sources, Split(incs), [], libtype=['common','intern'], priority=[26,26] )
 -    env.BlenderLib ('blender_BSP', sources, Split(incs), [], libtype=['common','intern'], priority=[26,69] )
++    env.BlenderLib ('blender_BSP', sources, Split(incs), [], libtype=['common','intern'], priority=[26,26] )
  else:
-       env.BlenderLib ('bf_BSP', sources, Split(incs), [], libtype='core', priority=20 )
 -    env.BlenderLib ('blender_BSP', sources, Split(incs), [], libtype='core', priority=26 )
++    env.BlenderLib ('blender_BSP', sources, Split(incs), [], libtype='core', priority=20 )
  
Simple merge
@@@ -10,25 -10,23 +10,23 @@@ sources = env.Glob('intern/*.cpp'
  
  pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_Window']
  
- if window_system in ('linux2', 'openbsd3', 'sunos5', 'freebsd6'):
-       for f in pf:
-               sources.remove('intern' + os.sep + f + 'Win32.cpp')
-               sources.remove('intern' + os.sep + f + 'Carbon.cpp')
+ if window_system in ('linux2', 'openbsd3', 'sunos5', 'freebsd6', 'irix6'):
+     for f in pf:
+         sources.remove('intern' + os.sep + f + 'Win32.cpp')
+         sources.remove('intern' + os.sep + f + 'Carbon.cpp')
  elif window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross'):
-       for f in pf:
-               sources.remove('intern' + os.sep + f + 'X11.cpp')
-               sources.remove('intern' + os.sep + f + 'Carbon.cpp')
+     for f in pf:
+         sources.remove('intern' + os.sep + f + 'X11.cpp')
+         sources.remove('intern' + os.sep + f + 'Carbon.cpp')
  elif window_system == 'darwin':
-       for f in pf:
-               sources.remove('intern' + os.sep + f + 'Win32.cpp')
-               sources.remove('intern' + os.sep + f + 'X11.cpp')
+     for f in pf:
+         sources.remove('intern' + os.sep + f + 'Win32.cpp')
+         sources.remove('intern' + os.sep + f + 'X11.cpp')
  else:
-       print "Unknown window system specified."
-       Exit()
+     print "Unknown window system specified."
+     Exit()
  
  incs = '. ../string ' + env['BF_OPENGL_INC']
  if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross'):
-       incs = env['BF_WINTAB_INC'] + ' ' + incs
+     incs = env['BF_WINTAB_INC'] + ' ' + incs
 -env.BlenderLib ('bf_ghost', sources, Split(incs), defines=['_USE_MATH_DEFINES'], libtype=['core','player'], priority = [25,15] ) 
 +env.BlenderLib ('bf_ghost', sources, Split(incs), defines=['_USE_MATH_DEFINES'], libtype=['core','intern','player'], priority = [40,44,5] ) 
Simple merge
@@@ -421,8 -440,9 +440,8 @@@ bool GHOST_SystemCarbon::processEvents(
        
        do {
                GHOST_TimerManager* timerMgr = getTimerManager();
+               
                if (waitForEvent) {
 -                      GHOST_TUns64 curtime = getMilliSeconds();
                        GHOST_TUns64 next = timerMgr->nextFireTime();
                        double timeOut;
                        
  #include <config.h>
  #endif
  
 -#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
 -
  #include "GHOST_SystemWin32.h"
  
+ // win64 doesn't define GWL_USERDATA
+ #ifdef WIN32
+ #ifndef GWL_USERDATA
+ #define GWL_USERDATA GWLP_USERDATA
+ #define GWL_WNDPROC GWLP_WNDPROC
+ #endif
+ #endif
  /*
   * According to the docs the mouse wheel message is supported from windows 98 
   * upwards. Leaving WINVER at default value, the WM_MOUSEWHEEL message and the 
@@@ -103,26 -96,18 +96,29 @@@ GHOST_SystemX11
        if (!m_display) return;
        
  #ifdef __sgi
-       m_delete_window_atom = XSGIFastInternAtom(m_display, 
-                                               "WM_DELETE_WINDOW",
-                                               SGI_XA_WM_DELETE_WINDOW,
-                                               False);
+       m_delete_window_atom 
+         = XSGIFastInternAtom(m_display,
+                              "WM_DELETE_WINDOW", 
+                              SGI_XA_WM_DELETE_WINDOW, False);
  #else
-       m_delete_window_atom = XInternAtom(m_display,
-                                       "WM_DELETE_WINDOW", False);
+       m_delete_window_atom 
+         = XInternAtom(m_display, "WM_DELETE_WINDOW", True);
  #endif
  
+       m_wm_protocols= XInternAtom(m_display, "WM_PROTOCOLS", False);
+       m_wm_take_focus= XInternAtom(m_display, "WM_TAKE_FOCUS", False);
 +      m_wm_state= XInternAtom(m_display, "WM_STATE", False);
 +      m_wm_change_state= XInternAtom(m_display, "WM_CHANGE_STATE", False);
 +      m_net_state= XInternAtom(m_display, "_NET_WM_STATE", False);
 +      m_net_max_horz= XInternAtom(m_display,
 +                                      "_NET_WM_STATE_MAXIMIZED_HORZ", False);
 +      m_net_max_vert= XInternAtom(m_display,
 +                                      "_NET_WM_STATE_MAXIMIZED_VERT", False);
 +      m_net_fullscreen= XInternAtom(m_display,
 +                                      "_NET_WM_STATE_FULLSCREEN", False);
 +      m_motif= XInternAtom(m_display, "_MOTIF_WM_HINTS", False);
 +
        // compute the initial time
        timeval tv;
        if (gettimeofday(&tv,NULL) == -1) {
@@@ -193,20 -195,31 +195,43 @@@ public
                return m_display;
        }       
  
 -      /* Atom used for ICCCM. */
+               void *
+       prepareNdofInfo(
+               volatile GHOST_TEventNDOFData *current_values
+       );
+               
+       /**
+        * Returns unsinged char from CUT_BUFFER0
+        * @param flag          Flag indicates which buffer to return 0 for clipboard 1 for selection
+        * @return              Returns the Clipboard indicated by Flag
+        */
+               GHOST_TUns8*
+       getClipboard(int flag) const;
+       
+       /**
+        * Puts buffer to system clipboard
+        * @param buffer        The buffer to copy to the clipboard     
+        * @param flag          Flag indicates which buffer to set ownership of 0 for clipboard 1 for selection
+        */
+       virtual void putClipboard(GHOST_TInt8 *buffer, int flag) const;
-       
 +      /**
 +       * Atom used for ICCCM, WM-spec and Motif.
 +       * We only need get this atom at the start, it's relative
 +       * to the display not the window and are public for every
 +       * window that need it.
 +       */
 +      Atom m_wm_state;
 +      Atom m_wm_change_state;
 +      Atom m_net_state;
 +      Atom m_net_max_horz;
 +      Atom m_net_max_vert;
 +      Atom m_net_fullscreen;
 +      Atom m_motif;
+       Atom m_wm_take_focus;
+       Atom m_wm_protocols;
+       Atom m_delete_window_atom;
  private :
  
        Display * m_display;
@@@ -215,41 -207,100 +217,76 @@@ GHOST_WindowX11
  
        // create the window!
  
-       m_window = 
-               XCreateWindow(
-                       m_display, 
-                       RootWindow(m_display, m_visual->screen), 
-                       left,
-                       top,
-                       width,
-                       height,
-                       0, // no border.
-                       m_visual->depth,
-                       InputOutput, 
-                       m_visual->visual,
-                       CWBorderPixel|CWColormap|CWEventMask, 
-                       &xattributes
-               );
+       ;
+       if (parentWindow == 0) {
+               m_window = 
+                       XCreateWindow(
+                               m_display, 
+                               RootWindow(m_display, m_visual->screen), 
+                               left,
+                               top,
+                               width,
+                               height,
+                               0, // no border.
+                               m_visual->depth,
+                               InputOutput, 
+                               m_visual->visual,
+                               CWBorderPixel|CWColormap|CWEventMask, 
+                               &xattributes
+                       );
+       } else {
+               Window root_return;
+               int x_return,y_return;
+               unsigned int w_return,h_return,border_w_return,depth_return;
+               
+               XGetGeometry(m_display, parentWindow, &root_return, &x_return, &y_return,
+                       &w_return, &h_return, &border_w_return, &depth_return );
+               left = 0;
+               top = 0;
+               width = w_return;
+               height = h_return;
+               m_window = XCreateWindow(
+                               m_display, 
+                               parentWindow,  // reparent against embedder 
+                               left,
+                               top,
+                               width,
+                               height,
+                               0, // no border.
+                               m_visual->depth,
+                               InputOutput, 
+                               m_visual->visual,
+                               CWBorderPixel|CWColormap|CWEventMask, 
+                               &xattributes
+                       );
+               XSelectInput(m_display , parentWindow, SubstructureNotifyMask);
+               
+       }       
        
 -      
 -      // Are we in fullscreen mode - then include
 -      // some obscure blut code to remove decorations.
 -
 -      if (state == GHOST_kWindowStateFullScreen) {
 -
 -              MotifWmHints hints;
 -              Atom atom;
 -                                      
 -              atom = XInternAtom(m_display, "_MOTIF_WM_HINTS", False);
 -              
 -              if (atom == None) {
 -                      GHOST_PRINT("Could not intern X atom for _MOTIF_WM_HINTS.\n");
 -              } else {
 -                      hints.flags = MWM_HINTS_DECORATIONS;
 -                      hints.decorations = 0;  /* Absolutely no decorations. */
 -                      // other hints.decorations make no sense
 -                      // you can't select individual decorations
 -
 -                      XChangeProperty(m_display, m_window,
 -                              atom, atom, 32,
 -                              PropModeReplace, (unsigned char *) &hints, 4);
 -              }
 -      } else if (state == GHOST_kWindowStateMaximized) {
 -              // With this, xprop should report the following just after launch
 -              // _NET_WM_STATE(ATOM) = _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ
 -              // After demaximization the right side is empty, though (maybe not the most correct then?)
 -              Atom state, atomh, atomv;
 -
 -              state = XInternAtom(m_display, "_NET_WM_STATE", False);
 -              atomh = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
 -              atomv = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
 -              if (state == None ) {
 -                      GHOST_PRINT("Atom _NET_WM_STATE requested but not avaliable nor created.\n");
 -              } else {
 -                      XChangeProperty(m_display, m_window,
 -                              state, XA_ATOM, 32,
 -                              PropModeAppend, (unsigned char *) &atomh, 1);
 -                      XChangeProperty(m_display, m_window,
 -                              state, XA_ATOM, 32,
 -                              PropModeAppend, (unsigned char *) &atomv, 1);
 -              }
 -      }
 +      /*
 +       * One of the problem with WM-spec is that can't set a property
 +       * to a window that isn't mapped. That is why we can't "just
 +       * call setState" here.
 +       *
 +       * To fix this, we first need know that the window is really
 +       * map waiting for the MapNotify event.
 +       *
 +       * So, m_post_init indicate that we need wait for the MapNotify
 +       * event and then set the Window state to the m_post_state.
 +       */
 +      if ((state != GHOST_kWindowStateNormal) && (state != GHOST_kWindowStateMinimized)) {
 +              m_post_init = True;
 +              m_post_state = state;
 +      }
 +      else {
 +              m_post_init = False;
 +              m_post_state = GHOST_kWindowStateNormal;
 +      }
        
        // Create some hints for the window manager on how
        // we want this window treated. 
Simple merge
@@@ -6,7 -6,7 +6,7 @@@ sources = env.Glob('intern/*.c') + env.
  incs = 'extern superlu'
  
  if (env['OURPLATFORM'] == 'win32-mingw'):
-       env.BlenderLib ('blender_ONL', sources, Split(incs), [], libtype=['core','intern'], priority=[1,80] )
+     env.BlenderLib ('blender_ONL', sources, Split(incs), [], libtype=['core','intern','player'], priority=[1,80,22] )
  else:
-       env.BlenderLib ('blender_ONL', sources, Split(incs), [], libtype='core', priority=65 )
 -    env.BlenderLib ('blender_ONL', sources, Split(incs), [], libtype=['core','player'], priority=[55,22] )
++    env.BlenderLib ('blender_ONL', sources, Split(incs), [], libtype=['core','player'], priority=[65,22] )
  
Simple merge
diff --cc source/Makefile
@@@ -219,18 -229,10 +229,17 @@@ ifeq ($(WITH_OPENEXR), true
      COMLIB += $(NAN_OPENEXR_LIBS)
  endif
  
- PULIB = $(NAN_IKSOLVER)/lib/libiksolver.a
- PULIB += $(NAN_MOTO)/lib/libmoto.a
+ PULIB = $(NAN_MOTO)/lib/libmoto.a
  PULIB += $(NAN_ELBEEM)/lib/$(DEBUG_DIR)libelbeem.a
  PULIB += $(OCGDIR)/blender/readblenfile/$(DEBUG_DIR)libreadblenfile.a
- PULIB += $(OCGDIR)/blender/ed_datafiles/libed_datafiles.a
 -PULIB += $(OCGDIR)/blender/src/$(DEBUG_DIR)libsrcpublisher.a
 +PULIB += $(OCGDIR)/blender/ed_screen/libed_screen.a
 +PULIB += $(OCGDIR)/blender/ed_time/libed_time.a
 +PULIB += $(OCGDIR)/blender/ed_view3d/libed_view3d.a
 +PULIB += $(OCGDIR)/blender/ed_interface/libed_interface.a
++PULIB += $(OCGDIR)/blender/ed_datafiles/libed_datafiles.a
 +PULIB += $(OCGDIR)/blender/windowmanager/libwindowmanager.a
 +PULIB += $(OCGDIR)/blender/python/$(DEBUG_DIR)libpython.a
 +PULIB += $(OCGDIR)/blender/makesrna/$(DEBUG_DIR)librna.a
  
  ifeq ($(NAN_NO_KETSJI),true)
      PULIB += $(NAN_MOTO)/lib/libmoto.a
@@@ -24,7 -24,7 +24,7 @@@
  #
  # ***** END GPL LICENSE BLOCK *****
  
- SUBDIRS(windowmanager editors avi nodes blenkernel blenlib blenloader blenpluginapi imbuf imbuf/intern/cineon makesdna python radiosity readblenfile render yafray)
 -SUBDIRS(avi nodes blenkernel blenlib blenloader blenpluginapi imbuf imbuf/intern/cineon gpu makesdna python radiosity readblenfile render src yafray)
++SUBDIRS(windowmanager editors avi nodes blenkernel blenlib blenloader blenpluginapi imbuf imbuf/intern/cineon gpu makesdna python radiosity readblenfile render yafray)
  
  IF(WITH_INTERNATIONAL)
    SUBDIRS(ftfont)
  
  include nan_definitions.mk
  
 -DIRS = blenloader readblenfile
 +DIRS = windowmanager editors blenloader readblenfile
  DIRS += avi imbuf render radiosity blenlib blenkernel blenpluginapi
- DIRS += nodes
 -DIRS += makesdna src yafray
 +DIRS += makesdna makesrna yafray
- DIRS += python
+ DIRS += python nodes gpu
  
- ifeq ($(INTERNATIONAL), true)
+ ifeq ($(WITH_FREETYPE2), true)
        DIRS += ftfont
  endif
  
@@@ -3,33 -3,36 +3,38 @@@ Import ('env'
  import sys
  
  SConscript(['avi/SConscript',
-                       'blenkernel/SConscript',
-                       'blenlib/SConscript',
-                       'blenloader/SConscript',
-                       'blenpluginapi/SConscript',
-                       'editors/SConscript',
-                       'imbuf/SConscript',
-                       'imbuf/intern/cineon/SConscript',
-                       'makesdna/SConscript',
-                       'makesrna/SConscript',
-                       'python/SConscript',
-                       'radiosity/SConscript',
-                       'readblenfile/SConscript',
-                       'render/SConscript',
-                       'nodes/SConscript',
-                       'windowmanager/SConscript'])
- if env['WITH_BF_YAFRAY'] == 1:
-       SConscript(['yafray/SConscript'])
- if env['WITH_BF_INTERNATIONAL'] == 1:
-       SConscript (['ftfont/SConscript'])
- if env['WITH_BF_DDS'] == 1:
-       SConscript (['imbuf/intern/dds/SConscript'])
- if env['WITH_BF_OPENEXR'] == 1:
-       SConscript (['imbuf/intern/openexr/SConscript'])
- if env['WITH_BF_QUICKTIME'] == 1:
-       SConscript (['quicktime/SConscript'])
+             'blenkernel/SConscript',
+             'blenlib/SConscript',
+             'blenloader/SConscript',
+             'blenpluginapi/SConscript',
+             'gpu/SConscript',
++            'editors/SConscript',
+             'imbuf/SConscript',
+             'imbuf/intern/cineon/SConscript',
+             'makesdna/SConscript',
++            'makesrna/SConscript',
+             'radiosity/SConscript',
+             'readblenfile/SConscript',
+             'render/SConscript',
 -            'src/SConscript',
 -            'nodes/SConscript'])
++            'nodes/SConscript',
++            'windowmanager/SConscript'])
+ if env['WITH_BF_PYTHON']:
+     SConscript(['python/SConscript'])
+ if env['WITH_BF_YAFRAY']:
+     SConscript(['yafray/SConscript'])
+ if env['WITH_BF_INTERNATIONAL']:
+     SConscript (['ftfont/SConscript'])
+ if env['WITH_BF_DDS']:
+     SConscript (['imbuf/intern/dds/SConscript'])
+ if env['WITH_BF_OPENEXR']:
+     SConscript (['imbuf/intern/openexr/SConscript'])
+ if env['WITH_BF_QUICKTIME']:
+     SConscript (['quicktime/SConscript'])
index 0000000,8ec7144..71c042e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,253 +1,253 @@@
 -#include "transform.h"
+ /**
+  * BKE_bmesh.h    jan 2007
+  *
+  *    BMesh modeler structure and functions.
+  *
+  * $Id: BKE_bmesh.h,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+  *
+  * ***** 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. The Blender
+  * Foundation also sells licenses for use in proprietary software under
+  * the Blender License.  See http://www.blender.org/BL/ for information
+  * about this.        
+  *
+  * 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.
+  *
+  * The Original Code is Copyright (C) 2004 Blender Foundation.
+  * All rights reserved.
+  *
+  * The Original Code is: all of this file.
+  *
+  * Contributor(s): Geoffrey Bantle.
+  *
+  * ***** END GPL LICENSE BLOCK *****
+  */
+ #ifndef BKE_BMESH_H
+ #define BKE_BMESH_H
+ #include "DNA_listBase.h"
+ #include "BLI_ghash.h"
+ #include "BLI_mempool.h"
+ #include "BLI_memarena.h"
+ #include "DNA_image_types.h"
+ #include "BLI_editVert.h"
+ #include "BKE_DerivedMesh.h"
++//XXX #include "transform.h"
+ /*forward declerations*/
+ struct BME_Vert;
+ struct BME_Edge;
+ struct BME_Poly;
+ struct BME_Loop;
+ /*Notes on further structure Cleanup:
+       -Remove the tflags, they belong in custom data layers
+       -Remove the eflags completely, they are mostly not used
+       -Remove the selection/vis/bevel weight flag/values ect and move them to custom data
+       -Remove EID member and move to custom data
+       -Add a radial cycle length, disk cycle length and loop cycle lenght attributes to custom data and have eulers maintain/use them if present.
+       -Move data such as vertex coordinates/normals to custom data and leave pointers in structures to active layer data.
+       -Remove BME_CycleNode structure?
+ */
+ typedef struct BME_CycleNode{
+       struct BME_CycleNode *next, *prev;
+       void *data;
+ } BME_CycleNode;
+ typedef struct BME_Mesh
+ {
+       ListBase verts, edges, polys;
+       /*memory pools used for storing mesh elements*/
+       struct BLI_mempool *vpool;
+       struct BLI_mempool *epool;
+       struct BLI_mempool *ppool;
+       struct BLI_mempool *lpool;
+       /*some scratch arrays used by eulers*/
+       struct BME_Vert **vtar;
+       struct BME_Edge **edar;
+       struct BME_Loop **lpar;
+       struct BME_Poly **plar;
+       int vtarlen, edarlen, lparlen, plarlen;
+       int totvert, totedge, totpoly, totloop;                         /*record keeping*/
+       int nextv, nexte, nextp, nextl;                                         /*Next element ID for verts/edges/faces/loops. Never reused*/
+       struct CustomData vdata, edata, pdata, ldata;   /*Custom Data Layer information*/
+ } BME_Mesh;
+ typedef struct BME_Vert
+ {
+       struct BME_Vert *next, *prev;
+       int     EID;
+       float co[3];                                                                    
+       float no[3];                                                                    
+       struct BME_Edge *edge;                                                  /*first edge in the disk cycle for this vertex*/
+       void *data;                                                                             /*custom vertex data*/
+       int eflag1, eflag2;                                                             /*reserved for use by eulers*/
+       int tflag1, tflag2;                                                             /*reserved for use by tools*/
+       unsigned short flag, h;
+       float bweight;
+ } BME_Vert;
+ typedef struct BME_Edge
+ {
+       struct BME_Edge *next, *prev;
+       int EID;
+       struct BME_Vert *v1, *v2;                                               /*note that order of vertex pointers means nothing to eulers*/
+       struct BME_CycleNode d1, d2;                                    /*disk cycle nodes for v1 and v2 respectivley*/
+       struct BME_Loop *loop;                                                  /*first BME_Loop in the radial cycle around this edge*/
+       void *data;                                                                             /*custom edge data*/
+       int eflag1, eflag2;                                                             /*reserved for use by eulers*/
+       int tflag1, tflag2;                                                             /*reserved for use by tools*/
+       unsigned short flag, h;
+       float crease, bweight;
+ } BME_Edge;
+ typedef struct BME_Loop 
+ {     
+       struct BME_Loop *next, *prev;                                   /*circularly linked list around face*/
+       int EID;
+       struct BME_CycleNode radial;                                    /*circularly linked list used to find faces around an edge*/
+       struct BME_Vert *v;                                                             /*vertex that this loop starts at.*/
+       struct BME_Edge *e;                                                             /*edge this loop belongs to*/
+       struct BME_Poly *f;                                                             /*face this loop belongs to*/   
+       void *data;                                                                             /*custom per face vertex data*/
+       int eflag1, eflag2;                                                             /*reserved for use by eulers*/
+       int tflag1, tflag2;                                                             /*reserved for use by tools*/
+       unsigned short flag, h;
+ } BME_Loop;
+ typedef struct BME_Poly
+ {
+       struct BME_Poly *next, *prev;
+       int EID;
+       struct BME_Loop *loopbase;                                              /*First editloop around Polygon.*/
+       unsigned int len;                                                               /*total length of the face. Eulers should preserve this data*/
+       void *data;                                                                             /*custom face data*/
+       int eflag1, eflag2;                                                             /*reserved for use by eulers*/
+       int tflag1, tflag2;                                                             /*reserved for use by tools*/
+       unsigned short flag, h, mat_nr;
+ } BME_Poly;
+ /*EDGE UTILITIES*/
+ int BME_verts_in_edge(struct BME_Vert *v1, struct BME_Vert *v2, struct BME_Edge *e);
+ int BME_vert_in_edge(struct BME_Edge *e, BME_Vert *v);
+ struct BME_Vert *BME_edge_getothervert(struct BME_Edge *e, struct BME_Vert *v);
+ /*GENERAL CYCLE*/
+ int BME_cycle_length(void *h);
+ /*DISK CYCLE*/
+ struct BME_Edge *BME_disk_nextedge(struct BME_Edge *e, struct BME_Vert *v); 
+ struct BME_CycleNode *BME_disk_getpointer(struct BME_Edge *e, struct BME_Vert *v);
+ struct BME_Edge *BME_disk_next_edgeflag(struct BME_Edge *e, struct BME_Vert *v, int eflag, int tflag);
+ int BME_disk_count_edgeflag(struct BME_Vert *v, int eflag, int tflag);
+ /*RADIAL CYCLE*/
+ struct BME_Loop *BME_radial_nextloop(struct BME_Loop *l);
+ int BME_radial_find_face(struct BME_Edge *e,struct BME_Poly *f);
+ /*LOOP CYCLE*/
+ struct BME_Loop *BME_loop_find_loop(struct BME_Poly *f, struct BME_Vert *v);
+ /*MESH CREATION/DESTRUCTION*/
+ struct BME_Mesh *BME_make_mesh(int allocsize[4]);
+ void BME_free_mesh(struct BME_Mesh *bm);
+ /*FULL MESH VALIDATION*/
+ int BME_validate_mesh(struct BME_Mesh *bm, int halt);
+ /*ENTER/EXIT MODELLING LOOP*/
+ int BME_model_begin(struct BME_Mesh *bm);
+ void BME_model_end(struct BME_Mesh *bm);
+ /*MESH CONSTRUCTION API.*/
+ /*MAKE*/
+ struct BME_Vert *BME_MV(struct BME_Mesh *bm, float *vec);
+ struct BME_Edge *BME_ME(struct BME_Mesh *bm, struct BME_Vert *v1, struct BME_Vert *v2);
+ struct BME_Poly *BME_MF(struct BME_Mesh *bm, struct BME_Vert *v1, struct BME_Vert *v2, struct BME_Edge **elist, int len);
+ /*KILL*/
+ int BME_KV(struct BME_Mesh *bm, struct BME_Vert *v);
+ int BME_KE(struct BME_Mesh *bm, struct BME_Edge *e);
+ int BME_KF(struct BME_Mesh *bm, struct BME_Poly *bply);
+ /*SPLIT*/
+ struct BME_Vert *BME_SEMV(struct BME_Mesh *bm, struct BME_Vert *tv, struct BME_Edge *e, struct BME_Edge **re);
+ struct BME_Poly *BME_SFME(struct BME_Mesh *bm, struct BME_Poly *f, struct BME_Vert *v1, struct BME_Vert *v2, struct BME_Loop **rl);
+ /*JOIN*/
+ int BME_JEKV(struct BME_Mesh *bm, struct BME_Edge *ke, struct BME_Vert *kv);
+ struct BME_Poly *BME_JFKE(struct BME_Mesh *bm, struct BME_Poly *f1, struct BME_Poly *f2,struct BME_Edge *e); /*no reason to return BME_Poly pointer?*/
+ /*NORMAL FLIP(Is its own inverse)*/
+ int BME_loop_reverse(struct BME_Mesh *bm, struct BME_Poly *f);
+ /* bevel tool defines */
+ /* element flags */
+ #define BME_BEVEL_ORIG                        1
+ #define BME_BEVEL_BEVEL                       (1<<1)
+ #define BME_BEVEL_NONMAN              (1<<2)
+ #define BME_BEVEL_WIRE                        (1<<3)
+ /* tool options */
+ #define BME_BEVEL_SELECT              1
+ #define BME_BEVEL_VERT                        (1<<1)
+ #define BME_BEVEL_RADIUS              (1<<2)
+ #define BME_BEVEL_ANGLE                       (1<<3)
+ #define BME_BEVEL_WEIGHT              (1<<4)
+ //~ #define BME_BEVEL_EWEIGHT         (1<<4)
+ //~ #define BME_BEVEL_VWEIGHT         (1<<5)
+ #define BME_BEVEL_PERCENT             (1<<6)
+ #define BME_BEVEL_EMIN                        (1<<7)
+ #define BME_BEVEL_EMAX                        (1<<8)
+ #define BME_BEVEL_RUNNING             (1<<9)
+ #define BME_BEVEL_RES                 (1<<10)
+ typedef struct BME_TransData {
+       BME_Mesh *bm; /* the bmesh the vert belongs to */
+       BME_Vert *v;  /* pointer to the vert this tdata applies to */
+       float co[3];  /* the original coordinate */
+       float org[3]; /* the origin */
+       float vec[3]; /* a directional vector; always, always normalize! */
+       void *loc;    /* a pointer to the data to transform (likely the vert's cos) */
+       float factor; /* primary scaling factor; also accumulates number of weighted edges for beveling tool */
+       float weight; /* another scaling factor; used primarily for propogating vertex weights to transforms; */
+                     /* weight is also used across recursive bevels to help with the math */
+       float maxfactor; /* the unscaled, original factor (used only by "edge verts" in recursive beveling) */
+       float *max;   /* the maximum distance this vert can be transformed; negative is infinite
+                      * it points to the "parent" maxfactor (where maxfactor makes little sense)
+                      * where the max limit is stored (limits are stored per-corner) */
+ } BME_TransData;
+ typedef struct BME_TransData_Head {
+       GHash *gh;       /* the hash structure for element lookup */
+       MemArena *ma;    /* the memory "pool" we will be drawing individual elements from */
+       int len;
+ } BME_TransData_Head;
+ typedef struct BME_Glob { /* stored in Global G for Transform() purposes */
+       BME_Mesh *bm;
+       BME_TransData_Head *td;
+       struct TransInfo *Trans; /* a pointer to the global Trans struct */
+       int imval[2]; /* for restoring original mouse co when initTransform() is called multiple times */
+       int options;
+       int res;
+ } BME_Glob;
+ struct BME_TransData *BME_get_transdata(struct BME_TransData_Head *td, struct BME_Vert *v);
+ void BME_free_transdata(struct BME_TransData_Head *td);
+ float *BME_bevel_calc_polynormal(struct BME_Poly *f, struct BME_TransData_Head *td);
+ struct BME_Mesh *BME_bevel(struct BME_Mesh *bm, float value, int res, int options, int defgrp_index, float angle, BME_TransData_Head **rtd);
+ /*CONVERSION FUNCTIONS*/
+ struct BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em);
+ struct EditMesh *BME_bmesh_to_editmesh(struct BME_Mesh *bm, BME_TransData_Head *td);
+ struct BME_Mesh *BME_derivedmesh_to_bmesh(struct DerivedMesh *dm);
+ struct DerivedMesh *BME_bmesh_to_derivedmesh(struct BME_Mesh *bm, struct DerivedMesh *dm);
+ #endif
Simple merge
@@@ -61,28 -59,8 +61,29 @@@ struct Object
  struct bSoundListener;
  struct BMF_Font;
  struct EditMesh;
+ struct BME_Glob;
  
 +/* former global stuff. context is derived, not storage! */
 +typedef struct bContext {
 +      
 +      /* windowmanager tree context */
 +      struct wmWindowManager *wm;
 +      struct wmWindow *window;
 +      struct bScreen *screen;
 +      struct ScrArea *area;
 +      struct ARegion *region;
 +      
 +      /* data context */
 +      struct Scene *scene;
 +      struct Object *obact;
 +      struct Object *obedit;
 +      
 +      /* edit data context */
 +      struct EditMesh *editMesh;
 +      struct ListBase edbo;                   /* Armature Editmode bones */
 +      
 +} bContext;
 +
  typedef struct Global {
  
        /* active pointers */
Simple merge
@@@ -36,9 -37,10 +37,11 @@@ struct Object
  struct Base;
  struct AviCodecData;
  struct QuicktimeCodecData;
+ struct SculptData;
+ struct RenderData;
  
  /* sequence related defines */
 +
  #define WHILE_SEQ(base)       {                                                                                       \
        int totseq_, seq_; Sequence **seqar;    \
                build_seqar( base,  &seqar, &totseq_);  \
  FILE(GLOB SRC intern/*.c)
  
  SET(INC 
--  . ../../../intern/guardedalloc ../include ../blenlib ../makesdna
++  . ../../../intern/guardedalloc ../editors/include ../blenlib ../makesdna
    ../python ../render/extern/include ../../../intern/decimation/extern
-   ../imbuf ../avi ../../../intern/elbeem/extern
+   ../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern
    ../../../intern/iksolver/extern ../blenloader ../quicktime
-   ../../../intern/bmfont
-   ../nodes ../editors/include
+   ../../../intern/bmfont ../../../extern/bullet2/src
+   ../nodes ../../../extern/glew/include ../gpu
    ${SDL_INC}
    ${ZLIB_INC}
+   ${PYTHON_INC}
  )
  
  IF(WITH_VERSE)
@@@ -3,11 -3,14 +3,14 @@@ Import ('env'
  
  sources = env.Glob('intern/*.c')
  
 -incs = '. #/intern/guardedalloc ../include ../blenlib ../makesdna'
 +incs = '. #/intern/guardedalloc ../editors/include ../blenlib ../makesdna'
- incs += ' ../python ../render/extern/include #/intern/decimation/extern'
+ incs += ' ../render/extern/include #/intern/decimation/extern'
  incs += ' ../imbuf ../avi #/intern/elbeem/extern ../nodes'
- incs += ' #/intern/iksolver/extern ../blenloader ../quicktime'
+ incs += ' #/intern/iksolver/extern ../blenloader'
+ incs += ' #/extern/bullet2/src'
  incs += ' #/intern/bmfont'
+ incs += ' #/intern/opennl/extern'
+ incs += ' ../gpu #/extern/glew/include'
  
  incs += ' ' + env['BF_OPENGL_INC']
  incs += ' ' + env['BF_ZLIB_INC']
index 0000000,daf0de5..2129042
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,646 +1,646 @@@
 -#include "BIF_editmesh.h"
 -#include "editmesh.h"
+ /**
+  * BME_mesh.c    jan 2007
+  *
+  *    BMesh mesh level functions.
+  *
+  * $Id: BME_eulers.c,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+  *
+  * ***** 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.
+  * about this.        
+  *
+  * 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.
+  *
+  * The Original Code is Copyright (C) 2007 Blender Foundation.
+  * All rights reserved.
+  *
+  * The Original Code is: all of this file.
+  *
+  * Contributor(s): Geoffrey Bantle, Levi Schooley.
+  *
+  * ***** END GPL LICENSE BLOCK *****
+  */
+ #include "MEM_guardedalloc.h"
+ #include "BKE_customdata.h" 
+ #include "DNA_listBase.h"
+ #include "DNA_meshdata_types.h"
+ #include "DNA_object_types.h"
+ #include "DNA_scene_types.h"
+ #include "BKE_utildefines.h"
+ #include "BKE_mesh.h"
+ #include "BKE_bmesh.h"
+ #include "BKE_global.h"
+ #include "BKE_DerivedMesh.h"
+ #include "BKE_cdderivedmesh.h"
+ #include "BLI_blenlib.h"
+ #include "BLI_editVert.h"
+ #include "BLI_edgehash.h"
 -#include "BSE_edit.h"
++//XXX #include "BIF_editmesh.h"
++//XXX #include "editmesh.h"
+ #include "bmesh_private.h"
 -              if(eed->h & EM_FGON) e->flag |= ME_FGON;
++//XXX #include "BSE_edit.h"
+ /*merge these functions*/
+ static void BME_DMcorners_to_loops(BME_Mesh *bm, CustomData *facedata, int index, BME_Poly *f, int numCol, int numTex){
+       int i, j;
+       BME_Loop *l;
+       MTFace *texface;
+       MTexPoly *texpoly;
+       MCol *mcol;
+       MLoopCol *mloopcol;
+       MLoopUV *mloopuv;
+       for(i=0; i< numTex; i++){
+               texface = CustomData_get_layer_n(facedata, CD_MTFACE, i);
+               texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i);
+               texpoly->tpage = texface[index].tpage;
+               texpoly->flag = texface[index].flag;
+               texpoly->transp = texface[index].transp;
+               texpoly->mode = texface[index].mode;
+               texpoly->tile = texface[index].tile;
+               texpoly->unwrap = texface[index].unwrap;
+               j = 0;
+               l = f->loopbase;
+               do{
+                       mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i);
+                       mloopuv->uv[0] = texface[index].uv[j][0];
+                       mloopuv->uv[1] = texface[index].uv[j][1];
+                       j++;
+                       l = l->next;
+               }while(l!=f->loopbase);
+       }
+       for(i=0; i < numCol; i++){
+               mcol = CustomData_get_layer_n(facedata, CD_MCOL, i);
+               j = 0;
+               l = f->loopbase;
+               do{
+                       mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i);
+                       mloopcol->r = mcol[(index*4)+j].r;
+                       mloopcol->g = mcol[(index*4)+j].g;
+                       mloopcol->b = mcol[(index*4)+j].b;
+                       mloopcol->a = mcol[(index*4)+j].a;
+                       j++;
+                       l = l->next;
+               }while(l!=f->loopbase);
+       }
+ }
+ static void BME_DMloops_to_corners(BME_Mesh *bm, CustomData *facedata, int index, BME_Poly *f,int numCol, int numTex){
+       int i, j;
+       BME_Loop *l;
+       MTFace *texface;
+       MTexPoly *texpoly;
+       MCol *mcol;
+       MLoopCol *mloopcol;
+       MLoopUV *mloopuv;
+       for(i=0; i < numTex; i++){
+               texface = CustomData_get_layer_n(facedata, CD_MTFACE, i);
+               texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i);
+               
+               texface[index].tpage = texpoly->tpage;
+               texface[index].flag = texpoly->flag;
+               texface[index].transp = texpoly->transp;
+               texface[index].mode = texpoly->mode;
+               texface[index].tile = texpoly->tile;
+               texface[index].unwrap = texpoly->unwrap;
+               j = 0;
+               l = f->loopbase;
+               do{
+                       mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i);
+                       texface[index].uv[j][0] = mloopuv->uv[0];
+                       texface[index].uv[j][1] = mloopuv->uv[1];
+                       j++;
+                       l = l->next;
+               }while(l!=f->loopbase);
+       }
+       for(i=0; i < numCol; i++){
+               mcol = CustomData_get_layer_n(facedata,CD_MCOL, i);
+               j = 0;
+               l = f->loopbase;
+               do{
+                       mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i);
+                       mcol[(index*4) + j].r = mloopcol->r;
+                       mcol[(index*4) + j].g = mloopcol->g;
+                       mcol[(index*4) + j].b = mloopcol->b;
+                       mcol[(index*4) + j].a = mloopcol->a;
+                       j++;
+                       l = l->next;
+               }while(l!=f->loopbase);
+       }
+ }
+ static void BME_corners_to_loops(BME_Mesh *bm, CustomData *facedata, void *face_block, BME_Poly *f,int numCol, int numTex){
+       int i, j;
+       BME_Loop *l;
+       MTFace *texface;
+       MTexPoly *texpoly;
+       MCol *mcol;
+       MLoopCol *mloopcol;
+       MLoopUV *mloopuv;
+       for(i=0; i < numTex; i++){
+               texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i);
+               texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i);
+               
+               texpoly->tpage = texface->tpage;
+               texpoly->flag = texface->flag;
+               texpoly->transp = texface->transp;
+               texpoly->mode = texface->mode;
+               texpoly->tile = texface->tile;
+               texpoly->unwrap = texface->unwrap;
+               j = 0;
+               l = f->loopbase;
+               do{
+                       mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i);
+                       mloopuv->uv[0] = texface->uv[j][0];
+                       mloopuv->uv[1] = texface->uv[j][1];
+                       j++;
+                       l = l->next;
+               }while(l!=f->loopbase);
+       }
+       for(i=0; i < numCol; i++){
+               mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i);
+               j = 0;
+               l = f->loopbase;
+               do{
+                       mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i);
+                       mloopcol->r = mcol[j].r;
+                       mloopcol->g = mcol[j].g;
+                       mloopcol->b = mcol[j].b;
+                       mloopcol->a = mcol[j].a;
+                       j++;
+                       l = l->next;
+               }while(l!=f->loopbase);
+       }
+ }
+ static void BME_loops_to_corners(BME_Mesh *bm, CustomData *facedata, void *face_block, BME_Poly *f,int numCol, int numTex){
+       int i, j;
+       BME_Loop *l;
+       MTFace *texface;
+       MTexPoly *texpoly;
+       MCol *mcol;
+       MLoopCol *mloopcol;
+       MLoopUV *mloopuv;
+       for(i=0; i < numTex; i++){
+               texface = CustomData_em_get_n(facedata, face_block, CD_MTFACE, i);
+               texpoly = CustomData_bmesh_get_n(&bm->pdata, f->data, CD_MTEXPOLY, i);
+               
+               texface->tpage = texpoly->tpage;
+               texface->flag = texpoly->flag;
+               texface->transp = texpoly->transp;
+               texface->mode = texpoly->mode;
+               texface->tile = texpoly->tile;
+               texface->unwrap = texpoly->unwrap;
+               j = 0;
+               l = f->loopbase;
+               do{
+                       mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPUV, i);
+                       texface->uv[j][0] = mloopuv->uv[0];
+                       texface->uv[j][1] = mloopuv->uv[1];
+                       j++;
+                       l = l->next;
+               }while(l!=f->loopbase);
+       }
+       for(i=0; i < numCol; i++){
+               mcol = CustomData_em_get_n(facedata, face_block, CD_MCOL, i);
+               j = 0;
+               l = f->loopbase;
+               do{
+                       mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->data, CD_MLOOPCOL, i);
+                       mcol[j].r = mloopcol->r;
+                       mcol[j].g = mloopcol->g;
+                       mcol[j].b = mloopcol->b;
+                       mcol[j].a = mloopcol->a;
+                       j++;
+                       l = l->next;
+               }while(l!=f->loopbase);
+       }
+ }
+ /*move the EditMesh conversion functions to editmesh_tools.c*/
+ BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em) {
+       BME_Mesh *bm;
+       int allocsize[4] = {512,512,2048,512}, numTex, numCol;
+       BME_Vert *v1, *v2;
+       BME_Edge *e, *edar[4];
+       BME_Poly *f;
+       EditVert *eve;
+       EditEdge *eed;
+       EditFace *efa;
+       int len;
+       bm = BME_make_mesh(allocsize);
+       /*copy custom data layout*/
+       CustomData_copy(&em->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+       CustomData_copy(&em->edata, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+       CustomData_copy(&em->fdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
+       /*copy face corner data*/
+       CustomData_to_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata);
+       /*initialize memory pools*/
+       CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
+       CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
+       CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
+       CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
+       /*needed later*/
+       numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+       numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
+       BME_model_begin(bm);
+       /*add verts*/
+       eve= em->verts.first;
+       while(eve) {
+               v1 = BME_MV(bm,eve->co);
+               VECCOPY(v1->no,eve->no);
+               v1->flag = eve->f;
+               v1->h = eve->h;
+               v1->bweight = eve->bweight;
+               /*Copy Custom Data*/
+               CustomData_bmesh_copy_data(&em->vdata, &bm->vdata, eve->data, &v1->data);
+               eve->tmp.v = (EditVert*)v1;
+               eve = eve->next;
+       }
+       
+       /*add edges*/
+       eed= em->edges.first;
+       while(eed) {
+               v1 = (BME_Vert*)eed->v1->tmp.v;
+               v2 = (BME_Vert*)eed->v2->tmp.v;
+               e = BME_ME(bm, v1, v2);
+               e->crease = eed->crease;
+               e->bweight = eed->bweight;
+               e->flag = eed->f & SELECT;
+               if(eed->sharp) e->flag |= ME_SHARP;
+               if(eed->seam) e->flag |= ME_SEAM;
 -              eve1 = addvertlist(v1->co,NULL);
++              //XXX if(eed->h & EM_FGON) e->flag |= ME_FGON;
+               if(eed->h & 1) e->flag |= ME_HIDE;
+               eed->tmp.e = (EditEdge*)e;
+               CustomData_bmesh_copy_data(&em->edata, &bm->edata, eed->data, &e->data);
+               eed = eed->next;
+       }
+       /*add faces.*/
+       efa= em->faces.first;
+       while(efa) {
+               if(efa->v4) len = 4;
+               else len = 3;
+               
+               edar[0] = (BME_Edge*)efa->e1->tmp.e;
+               edar[1] = (BME_Edge*)efa->e2->tmp.e;
+               edar[2] = (BME_Edge*)efa->e3->tmp.e;
+               if(len == 4){
+                       edar[3] = (BME_Edge*)efa->e4->tmp.e;
+               }
+               
+               /*find v1 and v2*/
+               v1 = (BME_Vert*)efa->v1->tmp.v;
+               v2 = (BME_Vert*)efa->v2->tmp.v;
+               
+               f = BME_MF(bm,v1,v2,edar,len);
+               f->mat_nr = efa->mat_nr;
+               f->flag = efa->flag;
+               if(efa->h) {
+                       f->flag |= ME_HIDE;
+                       f->flag &= ~ME_FACE_SEL;
+               }
+               else {
+                       if(efa->f & 1) f->flag |= ME_FACE_SEL;
+                       else f->flag &= ~ME_FACE_SEL;
+               }
+               CustomData_bmesh_copy_data(&em->fdata, &bm->pdata, efa->data, &f->data);
+               BME_corners_to_loops(bm, &em->fdata, efa->data, f,numCol,numTex);
+               efa = efa->next;
+       }
+       BME_model_end(bm);
+       return bm;
+ }
+ /* adds the geometry in the bmesh to G.editMesh (does not free G.editMesh)
+  * if td != NULL, the transdata will be mapped to the EditVert's co */
+ EditMesh *BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td) {
+       BME_Vert *v1;
+       BME_Edge *e;
+       BME_Poly *f;
+       
+       BME_TransData *vtd;
+       EditMesh *em;
+       EditVert *eve1, *eve2, *eve3, *eve4, **evlist;
+       EditEdge *eed;
+       EditFace *efa;
+       int totvert, len, i, numTex, numCol;
+       em = G.editMesh;
+       if (em == NULL) return NULL;
+       CustomData_copy(&bm->vdata, &em->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+       CustomData_copy(&bm->edata, &em->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+       CustomData_copy(&bm->pdata, &em->fdata, CD_MASK_BMESH, CD_CALLOC, 0);
+       CustomData_from_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata,0);
+       numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+       numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
+       /* convert to EditMesh */
+       /* make editverts */
+       totvert = BLI_countlist(&(bm->verts));
+       evlist= (EditVert **)MEM_mallocN(totvert*sizeof(void *),"evlist");
+       for (i=0,v1=bm->verts.first;v1;v1=v1->next,i++) {
+               v1->tflag1 = i;
 -              if(!(findedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1]))){
 -                      eed= addedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1], NULL);
++              eve1 = NULL; //XXX addvertlist(v1->co,NULL);
+               if (td && (vtd = BME_get_transdata(td,v1))) {
+                       vtd->loc = eve1->co;
+               }
+               eve1->keyindex = i;
+               evlist[i]= eve1;
+               eve1->f = (unsigned char)v1->flag;
+               eve1->h = (unsigned char)v1->h;
+               eve1->bweight = v1->bweight;
+               CustomData_em_copy_data(&bm->vdata, &em->vdata, v1->data, &eve1->data);
+       }
+       
+       /* make edges */
+       for (e=bm->edges.first;e;e=e->next) {
 -                      if(e->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines!
++              if(0) { //XXX if(!(findedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1]))){
++                      eed= NULL; //XXX addedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1], NULL);
+                       eed->crease = e->crease;
+                       eed->bweight = e->bweight;
+                       if(e->flag & ME_SEAM) eed->seam = 1;
+                       if(e->flag & ME_SHARP) eed->sharp = 1;
+                       if(e->flag & SELECT) eed->f |= SELECT;
 -                              EM_select_edge(eed, eed->f & SELECT);
++                      //XXX if(e->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines!
+                       if(e->flag & ME_HIDE) eed->h |= 1;
+                       if(G.scene->selectmode==SCE_SELECT_EDGE) 
 -                      efa = addfacelist(eve1, eve2, eve3, eve4, NULL, NULL);
++                              ; //XXX EM_select_edge(eed, eed->f & SELECT);
+               
+                       CustomData_em_copy_data(&bm->edata, &em->edata, e->data, &eed->data);
+               }
+       }
+       /* make faces */
+       for (f=bm->polys.first;f;f=f->next) {
+               len = BME_cycle_length(f->loopbase);
+               if (len==3 || len==4) {
+                       eve1= evlist[f->loopbase->v->tflag1];
+                       eve2= evlist[f->loopbase->next->v->tflag1];
+                       eve3= evlist[f->loopbase->next->next->v->tflag1];
+                       if (len == 4) {
+                               eve4= evlist[f->loopbase->prev->v->tflag1];
+                       }
+                       else {
+                               eve4= NULL;
+                       }
 -                              EM_select_face(efa, 1); /* flush down */
++                      efa = NULL; //XXX addfacelist(eve1, eve2, eve3, eve4, NULL, NULL);
+                       efa->mat_nr = (unsigned char)f->mat_nr;
+                       efa->flag= f->flag & ~ME_HIDE;
+                       if(f->flag & ME_FACE_SEL) {
+                               efa->f |= SELECT;
+                       }
+                       if(f->flag & ME_HIDE) efa->h= 1;
+                       if((G.f & G_FACESELECT) && (efa->f & SELECT))
 -      countall();
++                              ; //XXX EM_select_face(efa, 1); /* flush down */
+                       CustomData_em_copy_data(&bm->pdata, &em->fdata, f->data, &efa->data);
+                       BME_loops_to_corners(bm, &em->fdata, efa->data, f,numCol,numTex);
+               }
+       }
+       MEM_freeN(evlist);
++      //XXX countall();
+       return em;
+ }
+ /* Adds the geometry found in dm to bm
+   */
+ BME_Mesh *BME_derivedmesh_to_bmesh(DerivedMesh *dm)
+ {
+       
+       BME_Mesh *bm;
+       int allocsize[4] = {512,512,2048,512};
+       MVert *mvert, *mv;
+       MEdge *medge, *me;
+       MFace *mface, *mf;
+       int totface,totedge,totvert,i,len, numTex, numCol;
+       BME_Vert *v1=NULL,*v2=NULL, **vert_array;
+       BME_Edge *e=NULL;
+       BME_Poly *f=NULL;
+       
+       EdgeHash *edge_hash = BLI_edgehash_new();
+       bm = BME_make_mesh(allocsize);
+       /*copy custom data layout*/
+       CustomData_copy(&dm->vertData, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+       CustomData_copy(&dm->edgeData, &bm->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+       CustomData_copy(&dm->faceData, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
+       /*copy face corner data*/
+       CustomData_to_bmeshpoly(&dm->faceData, &bm->pdata, &bm->ldata);
+       /*initialize memory pools*/
+       CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
+       CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
+       CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
+       CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
+       /*needed later*/
+       numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+       numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
+       totvert = dm->getNumVerts(dm);
+       totedge = dm->getNumEdges(dm);
+       totface = dm->getNumFaces(dm);
+       mvert = dm->getVertArray(dm);
+       medge = dm->getEdgeArray(dm);
+       mface = dm->getFaceArray(dm);
+       vert_array = MEM_mallocN(sizeof(*vert_array)*totvert,"BME_derivedmesh_to_bmesh BME_Vert* array");
+       BME_model_begin(bm);
+       /*add verts*/
+       for(i=0,mv = mvert; i < totvert;i++,mv++){
+               v1 = BME_MV(bm,mv->co);
+               vert_array[i] = v1;
+               v1->flag = mv->flag;
+               v1->bweight = mv->bweight/255.0f;
+               CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v1->data);
+       }
+       /*add edges*/
+       for(i=0,me = medge; i < totedge;i++,me++){
+               v1 = vert_array[me->v1];
+               v2 = vert_array[me->v2];
+               e = BME_ME(bm, v1, v2);
+               e->crease = me->crease/255.0f;
+               e->bweight = me->bweight/255.0f;
+               e->flag = (unsigned char)me->flag;
+               BLI_edgehash_insert(edge_hash,me->v1,me->v2,e);
+               CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->data);
+       }
+       /*add faces.*/
+       for(i=0,mf = mface; i < totface;i++,mf++){
+               BME_Edge *edar[4];
+               if(mf->v4) len = 4;
+               else len = 3;
+               
+               edar[0] = BLI_edgehash_lookup(edge_hash,mf->v1,mf->v2);
+               edar[1] = BLI_edgehash_lookup(edge_hash,mf->v2,mf->v3);
+               if(len == 4){
+                       edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v4);
+                       edar[3] = BLI_edgehash_lookup(edge_hash,mf->v4,mf->v1);
+               }
+               else
+                       edar[2] = BLI_edgehash_lookup(edge_hash,mf->v3,mf->v1);
+               
+               /*find v1 and v2*/
+               v1 = vert_array[mf->v1];
+               v2 = vert_array[mf->v2];
+               
+               f = BME_MF(bm,v1,v2,edar,len);
+               f->mat_nr = mf->mat_nr;
+               f->flag = mf->flag;
+               CustomData_to_bmesh_block(&dm->faceData,&bm->pdata,i,&f->data);
+               BME_DMcorners_to_loops(bm, &dm->faceData,i,f, numCol,numTex);
+       }
+       
+       BME_model_end(bm);
+       BLI_edgehash_free(edge_hash, NULL);
+       MEM_freeN(vert_array);
+       return bm;
+ }
+ DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm)
+ {
+       MFace *mface, *mf;
+       MEdge *medge, *me;
+       MVert *mvert, *mv;
+       int totface,totedge,totvert,i,bmeshok,len, numTex, numCol;
+       BME_Vert *v1=NULL;
+       BME_Edge *e=NULL, *oe=NULL;
+       BME_Poly *f=NULL;
+       
+       DerivedMesh *result;
+       EdgeHash *edge_hash = BLI_edgehash_new();
+       totvert = BLI_countlist(&(bm->verts));
+       totedge = 0;
+       
+       /*we cannot have double edges in a derived mesh!*/
+       for(i=0, v1=bm->verts.first; v1; v1=v1->next, i++) v1->tflag1 = i;
+       for(e=bm->edges.first; e; e=e->next){
+               oe = BLI_edgehash_lookup(edge_hash,e->v1->tflag1, e->v2->tflag1);
+               if(!oe){
+                       totedge++;
+                       BLI_edgehash_insert(edge_hash,e->v1->tflag1,e->v2->tflag1,e);
+                       e->tflag2 = 1;
+               }
+               else{
+                       e->tflag2 = 0;
+               }
+       }
+       
+       /*count quads and tris*/
+       totface = 0;
+       bmeshok = 1;
+       for(f=bm->polys.first;f;f=f->next){
+               len = BME_cycle_length(f->loopbase);
+               if(len == 3 || len == 4) totface++;
+       }
+       
+       /*convert back to mesh*/
+       result = CDDM_from_template(dm,totvert,totedge,totface);
+       CustomData_merge(&bm->vdata, &result->vertData, CD_MASK_BMESH, CD_CALLOC, totvert);
+       CustomData_merge(&bm->edata, &result->edgeData, CD_MASK_BMESH, CD_CALLOC, totedge);
+       CustomData_merge(&bm->pdata, &result->faceData, CD_MASK_BMESH, CD_CALLOC, totface);
+       CustomData_from_bmeshpoly(&result->faceData, &bm->pdata, &bm->ldata,totface);
+       numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
+       numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
+       /*Make Verts*/
+       mvert = CDDM_get_verts(result);
+       for(i=0,v1=bm->verts.first,mv=mvert;v1;v1=v1->next,i++,mv++){
+               VECCOPY(mv->co,v1->co);
+               mv->flag = (unsigned char)v1->flag;
+               mv->bweight = (char)(255.0*v1->bweight);
+               CustomData_from_bmesh_block(&bm->vdata, &result->vertData, &v1->data, i);
+       }
+       medge = CDDM_get_edges(result);
+       i=0;
+       for(e=bm->edges.first,me=medge;e;e=e->next){
+               if(e->tflag2){
+                       if(e->v1->tflag1 < e->v2->tflag1){
+                               me->v1 = e->v1->tflag1;
+                               me->v2 = e->v2->tflag1;
+                       }
+                       else{
+                               me->v1 = e->v2->tflag1;
+                               me->v2 = e->v1->tflag1;
+                       }
+               
+                       me->crease = (char)(255.0*e->crease);
+                       me->bweight = (char)(255.0*e->bweight);
+                       me->flag = e->flag;
+                       CustomData_from_bmesh_block(&bm->edata, &result->edgeData, &e->data, i);
+                       me++;
+                       i++;
+               }
+       }
+       if(totface){
+               mface = CDDM_get_faces(result);
+               /*make faces*/
+               for(i=0,f=bm->polys.first;f;f=f->next){
+                       mf = &mface[i];
+                       len = BME_cycle_length(f->loopbase);
+                       if(len==3 || len==4){
+                               mf->v1 = f->loopbase->v->tflag1;
+                               mf->v2 = f->loopbase->next->v->tflag1;
+                               mf->v3 = f->loopbase->next->next->v->tflag1;
+                               if(len == 4){
+                                       mf->v4 = f->loopbase->prev->v->tflag1;
+                               }
+                               /* test and rotate indexes if necessary so that verts 3 and 4 aren't index 0 */
+                               if(mf->v3 == 0 || (len == 4 && mf->v4 == 0)){
+                                       test_index_face(mf, NULL, i, len);
+                               }
+                               mf->mat_nr = (unsigned char)f->mat_nr;
+                               mf->flag = (unsigned char)f->flag;
+                               CustomData_from_bmesh_block(&bm->pdata, &result->faceData, &f->data, i);
+                               BME_DMloops_to_corners(bm, &result->faceData, i, f,numCol,numTex);
+                               i++;
+                       }
+               }
+       }
+       BLI_edgehash_free(edge_hash, NULL);
+       return result;
+ }
index 0000000,9025903..8aaa7ac
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1324 +1,1323 @@@
 -#include "blendef.h"
 -
+ /**
+  * BME_tools.c    jan 2007
+  *
+  *    Functions for changing the topology of a mesh.
+  *
+  * $Id: BME_eulers.c,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+  *
+  * ***** 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.
+  *
+  * The Original Code is Copyright (C) 2004 Blender Foundation.
+  * All rights reserved.
+  *
+  * The Original Code is: all of this file.
+  *
+  * Contributor(s): Geoffrey Bantle and Levi Schooley.
+  *
+  * ***** END GPL LICENSE BLOCK *****
+  */
+ #include <math.h>
+ #include "MEM_guardedalloc.h"
+ #include "DNA_listBase.h"
+ #include "DNA_meshdata_types.h"
+ #include "DNA_mesh_types.h"
++#include "DNA_object_types.h"
+ #include "BKE_utildefines.h"
+ #include "BKE_bmesh.h"
+ #include "BLI_arithb.h"
+ #include "BLI_blenlib.h"
+ /*split this all into a seperate bevel.c file in src*/
+ /* ------- Bevel code starts here -------- */
+ BME_TransData_Head *BME_init_transdata(int bufsize) {
+       BME_TransData_Head *td;
+       td = MEM_callocN(sizeof(BME_TransData_Head), "BMesh transdata header");
+       td->gh = BLI_ghash_new(BLI_ghashutil_ptrhash,BLI_ghashutil_ptrcmp);
+       td->ma = BLI_memarena_new(bufsize);
+       BLI_memarena_use_calloc(td->ma);
+       return td;
+ }
+ void BME_free_transdata(BME_TransData_Head *td) {
+       BLI_ghash_free(td->gh,NULL,NULL);
+       BLI_memarena_free(td->ma);
+       MEM_freeN(td);
+ }
+ BME_TransData *BME_assign_transdata(BME_TransData_Head *td, BME_Mesh *bm, BME_Vert *v,
+               float *co, float *org, float *vec, float *loc,
+               float factor, float weight, float maxfactor, float *max) {
+       BME_TransData *vtd;
+       int is_new = 0;
+       if (v == NULL) return NULL;
+       if ((vtd = BLI_ghash_lookup(td->gh, v)) == NULL && bm != NULL) {
+               vtd = BLI_memarena_alloc(td->ma, sizeof(*vtd));
+               BLI_ghash_insert(td->gh, v, vtd);
+               td->len++;
+               is_new = 1;
+       }
+       vtd->bm = bm;
+       vtd->v = v;
+       if (co != NULL) VECCOPY(vtd->co,co);
+       if (org == NULL && is_new) { VECCOPY(vtd->org,v->co); } /* default */
+       else if (org != NULL) VECCOPY(vtd->org,org);
+       if (vec != NULL) {
+               VECCOPY(vtd->vec,vec);
+               Normalize(vtd->vec);
+       }
+       vtd->loc = loc;
+       vtd->factor = factor;
+       vtd->weight = weight;
+       vtd->maxfactor = maxfactor;
+       vtd->max = max;
+       return vtd;
+ }
+ BME_TransData *BME_get_transdata(BME_TransData_Head *td, BME_Vert *v) {
+       BME_TransData *vtd;
+       vtd = BLI_ghash_lookup(td->gh, v);
+       return vtd;
+ }
+ /* a hack (?) to use the transdata memarena to allocate floats for use with the max limits */
+ float *BME_new_transdata_float(BME_TransData_Head *td) {
+       return BLI_memarena_alloc(td->ma, sizeof(float));
+ }
+ static int BME_is_nonmanifold_vert(BME_Mesh *bm, BME_Vert *v) {
+       BME_Edge *e, *oe;
+       BME_Loop *l;
+       int len, count, flag;
+       if (v->edge == NULL) {
+               /* loose vert */
+               return 1;
+       }
+       /* count edges while looking for non-manifold edges */
+       oe = v->edge;
+       for (len=0,e=v->edge; e != oe || (e == oe && len == 0); len++,e=BME_disk_nextedge(e,v)) {
+               if (e->loop == NULL) {
+                       /* loose edge */
+                       return 1;
+               }
+               if (BME_cycle_length(&(e->loop->radial)) > 2) {
+                       /* edge shared by more than two faces */
+                       return 1;
+               }
+       }
+       count = 1;
+       flag = 1;
+       e = NULL;
+       oe = v->edge;
+       l = oe->loop;
+       while(e != oe) {
+               if (l->v == v) l = l->prev;
+               else l = l->next;
+               e = l->e;
+               count++; /* count the edges */
+               if (flag && l->radial.next->data == l) {
+                       /* we've hit the edge of an open mesh, reset once */
+                       flag = 0;
+                       count = 1;
+                       oe = e;
+                       e = NULL;
+                       l = oe->loop;
+               }
+               else if (l->radial.next->data == l) {
+                       /* break the loop */
+                       e = oe;
+               }
+               else {
+                       l = l->radial.next->data;
+               }
+       }
+       if (count < len) {
+               /* vert shared by multiple regions */
+               return 1;
+       }
+       return 0;
+ }
+ /* a wrapper for BME_JFKE that [for now just] checks to
+  * make sure loop directions are compatible */
+ static BME_Poly *BME_JFKE_safe(BME_Mesh *bm, BME_Poly *f1, BME_Poly *f2, BME_Edge *e) {
+       BME_Loop *l1, *l2;
+       l1 = e->loop;
+       l2 = l1->radial.next->data;
+       if (l1->v == l2->v) {
+               BME_loop_reverse(bm, f2);
+       }
+       return BME_JFKE(bm, f1, f2, e);
+ }
+ /* a wrapper for BME_SFME that transfers element flags */
+ static BME_Poly *BME_split_face(BME_Mesh *bm, BME_Poly *f, BME_Vert *v1, BME_Vert *v2, BME_Loop **nl, BME_Edge *example) {
+       BME_Poly *nf;
+       nf = BME_SFME(bm,f,v1,v2,nl);
+       nf->flag = f->flag;
+       /* if the edge was selected, select this face, too */
+       if (example->flag & SELECT) f->flag |= ME_FACE_SEL;
+       nf->h = f->h;
+       nf->mat_nr = f->mat_nr;
+       if (nl && example) {
+               (*nl)->e->flag = example->flag;
+               (*nl)->e->h = example->h;
+               (*nl)->e->crease = example->crease;
+               (*nl)->e->bweight = example->bweight;
+       }
+       return nf;
+ }
+ static void BME_data_interp_from_verts(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Vert *v, float fac)
+ {
+       void *src[2];
+       float w[2];
+       if (v1->data && v2->data) {
+               src[0]= v1->data;
+               src[1]= v2->data;
+               w[0] = 1.0f-fac;
+               w[1] = fac;
+               CustomData_bmesh_interp(&bm->vdata, src, w, NULL, 2, v->data);
+       }
+ }
+ static void BME_data_facevert_edgesplit(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Vert *v, BME_Edge *e1, float fac){
+       void *src[2];
+       float w[2];
+       BME_Loop *l=NULL, *v1loop = NULL, *vloop = NULL, *v2loop = NULL;
+       
+       w[0] = 1.0f - fac;
+       w[1] = fac;
+       if(!e1->loop) return;
+       l = e1->loop;
+       do{
+               if(l->v == v1){ 
+                       v1loop = l;
+                       vloop = v1loop->next;
+                       v2loop = vloop->next;
+               }else if(l->v == v){
+                       v1loop = l->next;
+                       vloop = l;
+                       v2loop = l->prev;
+                       
+               }
+               src[0] = v1loop->data;
+               src[1] = v2loop->data;                                  
+               CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, vloop->data);                               
+               l = l->radial.next->data;
+       }while(l!=e1->loop);
+ }
+ /* a wrapper for BME_SEMV that transfers element flags */ /*add custom data interpolation in here!*/
+ static BME_Vert *BME_split_edge(BME_Mesh *bm, BME_Vert *v, BME_Edge *e, BME_Edge **ne, float percent) {
+       BME_Vert *nv, *v2;
+       float len;
+       v2 = BME_edge_getothervert(e,v);
+       nv = BME_SEMV(bm,v,e,ne);
+       if (nv == NULL) return NULL;
+       VECSUB(nv->co,v2->co,v->co);
+       len = VecLength(nv->co);
+       VECADDFAC(nv->co,v->co,nv->co,len*percent);
+       nv->flag = v->flag;
+       nv->bweight = v->bweight;
+       if (ne) {
+               (*ne)->flag = e->flag;
+               (*ne)->h = e->h;
+               (*ne)->crease = e->crease;
+               (*ne)->bweight = e->bweight;
+       }
+       /*v->nv->v2*/
+       BME_data_facevert_edgesplit(bm,v2, v, nv, e, 0.75);     
+       return nv;
+ }
+ static void BME_collapse_vert(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv, float fac){
+       void *src[2];
+       float w[2];
+       BME_Loop *l=NULL, *kvloop=NULL, *tvloop=NULL;
+       BME_Vert *tv = BME_edge_getothervert(ke,kv);
+       w[0] = 1.0f - fac;
+       w[1] = fac;
+       if(ke->loop){
+               l = ke->loop;
+               do{
+                       if(l->v == tv && l->next->v == kv){
+                               tvloop = l;
+                               kvloop = l->next;
+                               src[0] = kvloop->data;
+                               src[1] = tvloop->data;
+                               CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, kvloop->data);                                                              
+                       }
+                       l=l->radial.next->data;
+               }while(l!=ke->loop);
+       }
+       BME_JEKV(bm,ke,kv);
+ }
+ static int BME_bevel_is_split_vert(BME_Loop *l) {
+       /* look for verts that have already been added to the edge when
+        * beveling other polys; this can be determined by testing the
+        * vert and the edges around it for originality
+        */
+       if ((l->v->tflag1 & BME_BEVEL_ORIG)==0
+                       && (l->e->tflag1 & BME_BEVEL_ORIG)
+                       && (l->prev->e->tflag1 & BME_BEVEL_ORIG))
+       {
+               return 1;
+       }
+       return 0;
+ }
+ /* get a vector, vec, that points from v1->co to wherever makes sense to
+  * the bevel operation as a whole based on the relationship between v1 and v2
+  * (won't necessarily be a vec from v1->co to v2->co, though it probably will be);
+  * the return value is -1 for failure, 0 if we used vert co's, and 1 if we used transform origins */
+ static int BME_bevel_get_vec(float *vec, BME_Vert *v1, BME_Vert *v2, BME_TransData_Head *td) {
+       BME_TransData *vtd1, *vtd2;
+       vtd1 = BME_get_transdata(td,v1);
+       vtd2 = BME_get_transdata(td,v2);
+       if (!vtd1 || !vtd2) {
+               //printf("BME_bevel_get_vec() got called without proper BME_TransData\n");
+               return -1;
+       }
+       /* compare the transform origins to see if we can use the vert co's;
+        * if they belong to different origins, then we will use the origins to determine
+        * the vector */
+       if (VecCompare(vtd1->org,vtd2->org,0.000001f)) {
+               VECSUB(vec,v2->co,v1->co);
+               if (VecLength(vec) < 0.000001f) {
+                       VecMulf(vec,0);
+               }
+               return 0;
+       }
+       else {
+               VECSUB(vec,vtd2->org,vtd1->org);
+               if (VecLength(vec) < 0.000001f) {
+                       VecMulf(vec,0);
+               }
+               return 1;
+       }
+ }
+ /* "Projects" a vector perpendicular to vec2 against vec1, such that
+  * the projected vec1 + vec2 has a min distance of 1 from the "edge" defined by vec2.
+  * note: the direction, is_forward, is used in conjunction with up_vec to determine
+  * whether this is a convex or concave corner. If it is a concave corner, it will
+  * be projected "backwards." If vec1 is before vec2, is_forward should be 0 (we are projecting backwards).
+  * vec1 is the vector to project onto (expected to be normalized)
+  * vec2 is the direction of projection (pointing away from vec1)
+  * up_vec is used for orientation (expected to be normalized)
+  * returns the length of the projected vector that lies along vec1 */
+ static float BME_bevel_project_vec(float *vec1, float *vec2, float *up_vec, int is_forward, BME_TransData_Head *td) {
+       float factor, vec3[3], tmp[3],c1,c2;
+       Crossf(tmp,vec1,vec2);
+       Normalize(tmp);
+       factor = Inpf(up_vec,tmp);
+       if ((factor > 0 && is_forward) || (factor < 0 && !is_forward)) {
+               Crossf(vec3,vec2,tmp); /* hmm, maybe up_vec should be used instead of tmp */
+       }
+       else {
+               Crossf(vec3,tmp,vec2); /* hmm, maybe up_vec should be used instead of tmp */
+       }
+       Normalize(vec3);
+       c1 = Inpf(vec3,vec1);
+       c2 = Inpf(vec1,vec1);
+       if (fabs(c1) < 0.000001f || fabs(c2) < 0.000001f) {
+               factor = 0.0f;
+       }
+       else {
+               factor = c2/c1;
+       }
+       return factor;
+ }
+ /* BME_bevel_split_edge() is the main math work-house; its responsibilities are:
+  * using the vert and the loop passed, get or make the split vert, set its coordinates
+  * and transform properties, and set the max limits.
+  * Finally, return the split vert. */
+ static BME_Vert *BME_bevel_split_edge(BME_Mesh *bm, BME_Vert *v, BME_Vert *v1, BME_Loop *l, float *up_vec, float value, BME_TransData_Head *td) {
+       BME_TransData *vtd, *vtd1, *vtd2;
+       BME_Vert *sv, *v2, *v3, *ov;
+       BME_Loop *lv1, *lv2;
+       BME_Edge *ne, *e1, *e2;
+       float maxfactor, scale, len, dis, vec1[3], vec2[3], t_up_vec[3];
+       int is_edge, forward, is_split_vert;
+       if (l == NULL) {
+               /* what you call operator overloading in C :)
+                * I wanted to use the same function for both wire edges and poly loops
+                * so... here we walk around edges to find the needed verts */
+               forward = 1;
+               is_split_vert = 0;
+               if (v->edge == NULL) {
+                       //printf("We can't split a loose vert's edge!\n");
+                       return NULL;
+               }
+               e1 = v->edge; /* we just use the first two edges */
+               e2 = BME_disk_nextedge(v->edge, v);
+               if (e1 == e2) {
+                       //printf("You need at least two edges to use BME_bevel_split_edge()\n");
+                       return NULL;
+               }
+               v2 = BME_edge_getothervert(e1, v);
+               v3 = BME_edge_getothervert(e2, v);
+               if (v1 != v2 && v1 != v3) {
+                       //printf("Error: more than 2 edges in v's disk cycle, or v1 does not share an edge with v\n");
+                       return NULL;
+               }
+               if (v1 == v2) {
+                       v2 = v3;
+               }
+               else {
+                       e1 = e2;
+               }
+               ov = BME_edge_getothervert(e1,v);
+               sv = BME_split_edge(bm,v,e1,&ne,0);
+               //BME_data_interp_from_verts(bm, v, ov, sv, 0.25); /*this is technically wrong...*/
+               //BME_data_interp_from_faceverts(bm, v, ov, sv, 0.25);
+               //BME_data_interp_from_faceverts(bm, ov, v, sv, 0.25);
+               BME_assign_transdata(td, bm, sv, sv->co, sv->co, NULL, sv->co, 0, -1, -1, NULL); /* quick default */
+               sv->tflag1 |= BME_BEVEL_BEVEL;
+               ne->tflag1 = BME_BEVEL_ORIG; /* mark edge as original, even though it isn't */
+               BME_bevel_get_vec(vec1,v1,v,td);
+               BME_bevel_get_vec(vec2,v2,v,td);
+               Crossf(t_up_vec,vec1,vec2);
+               Normalize(t_up_vec);
+               up_vec = t_up_vec;
+       }
+       else {
+               /* establish loop direction */
+               if (l->v == v) {
+                       forward = 1;
+                       lv1 = l->next;
+                       lv2 = l->prev;
+                       v1 = l->next->v;
+                       v2 = l->prev->v;
+               }
+               else if (l->next->v == v) {
+                       forward = 0;
+                       lv1 = l;
+                       lv2 = l->next->next;
+                       v1 = l->v;
+                       v2 = l->next->next->v;
+               }
+               else {
+                       //printf("ERROR: BME_bevel_split_edge() - v must be adjacent to l\n");
+                       return NULL;
+               }
+               if (BME_bevel_is_split_vert(lv1)) {
+                       is_split_vert = 1;
+                       sv = v1;
+                       if (forward) v1 = l->next->next->v;
+                       else v1 = l->prev->v;
+               }
+               else {
+                       is_split_vert = 0;
+                       ov = BME_edge_getothervert(l->e,v);
+                       sv = BME_split_edge(bm,v,l->e,&ne,0);
+                       //BME_data_interp_from_verts(bm, v, ov, sv, 0.25); /*this is technically wrong...*/
+                       //BME_data_interp_from_faceverts(bm, v, ov, sv, 0.25);
+                       //BME_data_interp_from_faceverts(bm, ov, v, sv, 0.25);
+                       BME_assign_transdata(td, bm, sv, sv->co, sv->co, NULL, sv->co, 0, -1, -1, NULL); /* quick default */
+                       sv->tflag1 |= BME_BEVEL_BEVEL;
+                       ne->tflag1 = BME_BEVEL_ORIG; /* mark edge as original, even though it isn't */
+               }
+               if (BME_bevel_is_split_vert(lv2)) {
+                       if (forward) v2 = lv2->prev->v;
+                       else v2 = lv2->next->v;
+               }
+       }
+       is_edge = BME_bevel_get_vec(vec1,v,v1,td); /* get the vector we will be projecting onto */
+       BME_bevel_get_vec(vec2,v,v2,td); /* get the vector we will be projecting parallel to */
+       len = VecLength(vec1);
+       Normalize(vec1);
+       vtd = BME_get_transdata(td, sv);
+       vtd1 = BME_get_transdata(td, v);
+       vtd2 = BME_get_transdata(td,v1);
+       if (vtd1->loc == NULL) {
+               /* this is a vert with data only for calculating initial weights */
+               if (vtd1->weight < 0) {
+                       vtd1->weight = 0;
+               }
+               scale = vtd1->weight/vtd1->factor;
+               if (!vtd1->max) {
+                       vtd1->max = BME_new_transdata_float(td);
+                       *vtd1->max = -1;
+               }
+       }
+       else {
+               scale = vtd1->weight;
+       }
+       vtd->max = vtd1->max;
+       if (is_edge && vtd1->loc != NULL) {
+               maxfactor = vtd1->maxfactor;
+       }
+       else {
+               maxfactor = scale*BME_bevel_project_vec(vec1,vec2,up_vec,forward,td);
+               if (vtd->maxfactor > 0 && vtd->maxfactor < maxfactor) {
+                       maxfactor = vtd->maxfactor;
+               }
+       }
+       dis = (v1->tflag1 & BME_BEVEL_ORIG)? len/3 : len/2;
+       if (is_edge || dis > maxfactor*value) {
+               dis = maxfactor*value;
+       }
+       VECADDFAC(sv->co,v->co,vec1,dis);
+       VECSUB(vec1,sv->co,vtd1->org);
+       dis = VecLength(vec1);
+       Normalize(vec1);
+       BME_assign_transdata(td, bm, sv, vtd1->org, vtd1->org, vec1, sv->co, dis, scale, maxfactor, vtd->max);
+       return sv;
+ }
+ static float BME_bevel_set_max(BME_Vert *v1, BME_Vert *v2, float value, BME_TransData_Head *td) {
+       BME_TransData *vtd1, *vtd2;
+       float max, fac1, fac2, vec1[3], vec2[3], vec3[3];
+       BME_bevel_get_vec(vec1,v1,v2,td);
+       vtd1 = BME_get_transdata(td,v1);
+       vtd2 = BME_get_transdata(td,v2);
+       if (vtd1->loc == NULL) {
+               fac1 = 0;
+       }
+       else {
+               VECCOPY(vec2,vtd1->vec);
+               VecMulf(vec2,vtd1->factor);
+               if (Inpf(vec1, vec1)) {
+                       Projf(vec2,vec2,vec1);
+                       fac1 = VecLength(vec2)/value;
+               }
+               else {
+                       fac1 = 0;
+               }
+       }
+       if (vtd2->loc == NULL) {
+               fac2 = 0;
+       }
+       else {
+               VECCOPY(vec3,vtd2->vec);
+               VecMulf(vec3,vtd2->factor);
+               if (Inpf(vec1, vec1)) {
+                       Projf(vec2,vec3,vec1);
+                       fac2 = VecLength(vec2)/value;
+               }
+               else {
+                       fac2 = 0;
+               }
+       }
+       if (fac1 || fac2) {
+               max = VecLength(vec1)/(fac1 + fac2);
+               if (vtd1->max && (*vtd1->max < 0 || max < *vtd1->max)) {
+                       *vtd1->max = max;
+               }
+               if (vtd2->max && (*vtd2->max < 0 || max < *vtd2->max)) {
+                       *vtd2->max = max;
+               }
+       }
+       else {
+               max = -1;
+       }
+       return max;
+ }
+ static BME_Vert *BME_bevel_wire(BME_Mesh *bm, BME_Vert *v, float value, int res, int options, BME_TransData_Head *td) {
+       BME_Vert *ov1, *ov2, *v1, *v2;
+       ov1 = BME_edge_getothervert(v->edge, v);
+       ov2 = BME_edge_getothervert(BME_disk_nextedge(v->edge, v), v);
+       /* split the edges */
+       v1 = BME_bevel_split_edge(bm,v,ov1,NULL,NULL,value,td);
+       v1->tflag1 |= BME_BEVEL_NONMAN;
+       v2 = BME_bevel_split_edge(bm,v,ov2,NULL,NULL,value,td);
+       v2->tflag1 |= BME_BEVEL_NONMAN;
+       if (value > 0.5) {
+               BME_bevel_set_max(v1,ov1,value,td);
+               BME_bevel_set_max(v2,ov2,value,td);
+       }
+       /* remove the original vert */
+       if (res) {
+               BME_JEKV(bm,v->edge,v);
+       }
+       return v1;
+ }
+ static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int options, float *up_vec, BME_TransData_Head *td) {
+       BME_Vert *v1, *v2, *kv;
+       BME_Loop *kl=NULL, *nl;
+       BME_Edge *e;
+       BME_Poly *f;
+       f = l->f;
+       e = l->e;
+       if ((l->e->tflag1 & BME_BEVEL_BEVEL) == 0
+               && ((l->v->tflag1 & BME_BEVEL_BEVEL) || (l->next->v->tflag1 & BME_BEVEL_BEVEL)))
+       { /* sanity check */
+               return l;
+       }
+       /* checks and operations for prev edge */
+       /* first, check to see if this edge was inset previously */
+       if ((l->prev->e->tflag1 & BME_BEVEL_ORIG) == 0
+               && (l->v->tflag1 & BME_BEVEL_NONMAN) == 0) {
+               kl = l->prev->radial.next->data;
+               if (kl->v == l->v) kl = kl->prev;
+               else kl = kl->next;
+               kv = l->v;
+       }
+       else {
+               kv = NULL;
+       }
+       /* get/make the first vert to be used in SFME */
+       if (l->v->tflag1 & BME_BEVEL_NONMAN){
+               v1 = l->v;
+       }
+       else { /* we'll need to split the previous edge */
+               v1 = BME_bevel_split_edge(bm,l->v,NULL,l->prev,up_vec,value,td);
+       }
+       /* if we need to clean up geometry... */
+       if (kv) {
+               l = l->next;
+               if (kl->v == kv) {
+                       BME_split_face(bm,kl->f,kl->prev->v,kl->next->v,&nl,kl->prev->e);
+                       BME_JFKE(bm,((BME_Loop*)kl->prev->radial.next->data)->f,kl->f,kl->prev->e);
+                       BME_collapse_vert(bm, kl->e, kv, 1.0);
+                       //BME_JEKV(bm,kl->e,kv);
+                       
+               }
+               else {
+                       BME_split_face(bm,kl->f,kl->next->next->v,kl->v,&nl,kl->next->e);
+                       BME_JFKE(bm,((BME_Loop*)kl->next->radial.next->data)->f,kl->f,kl->next->e);
+                       BME_collapse_vert(bm, kl->e, kv, 1.0);
+                       //BME_JEKV(bm,kl->e,kv);
+               }
+               l = l->prev;
+       }
+       /* checks and operations for the next edge */
+       /* first, check to see if this edge was inset previously  */
+       if ((l->next->e->tflag1 & BME_BEVEL_ORIG) == 0
+               && (l->next->v->tflag1 & BME_BEVEL_NONMAN) == 0) {
+               kl = l->next->radial.next->data;
+               if (kl->v == l->next->v) kl = kl->prev;
+               else kl = kl->next;
+               kv = l->next->v;
+       }
+       else {
+               kv = NULL;
+       }
+       /* get/make the second vert to be used in SFME */
+       if (l->next->v->tflag1 & BME_BEVEL_NONMAN) {
+               v2 = l->next->v;
+       }
+       else { /* we'll need to split the next edge */
+               v2 = BME_bevel_split_edge(bm,l->next->v,NULL,l->next,up_vec,value,td);
+       }
+       /* if we need to clean up geometry... */
+       if (kv) {
+               if (kl->v == kv) {
+                       BME_split_face(bm,kl->f,kl->prev->v,kl->next->v,&nl,kl->prev->e);
+                       BME_JFKE(bm,((BME_Loop*)kl->prev->radial.next->data)->f,kl->f,kl->prev->e);
+                       BME_collapse_vert(bm, kl->e, kv, 1.0);
+                       //BME_JEKV(bm,kl->e,kv);
+               }
+               else {
+                       BME_split_face(bm,kl->f,kl->next->next->v,kl->v,&nl,kl->next->e);
+                       BME_JFKE(bm,((BME_Loop*)kl->next->radial.next->data)->f,kl->f,kl->next->e);
+                       BME_collapse_vert(bm, kl->e, kv, 1.0);
+                       //BME_JEKV(bm,kl->e,kv);
+               }
+       }
+       if ((v1->tflag1 & BME_BEVEL_NONMAN)==0 || (v2->tflag1 & BME_BEVEL_NONMAN)==0) {
+               BME_split_face(bm,f,v2,v1,&l,e);
+               l->e->tflag1 = BME_BEVEL_BEVEL;
+               l = l->radial.next->data;
+       }
+       if (l->f != f){
+               //printf("Whoops! You got something out of order in BME_bevel_edge()!\n");
+       }
+       return l;
+ }
+ static BME_Loop *BME_bevel_vert(BME_Mesh *bm, BME_Loop *l, float value, int options, float *up_vec, BME_TransData_Head *td) {
+       BME_Vert *v1, *v2;
+       BME_Poly *f;
+       /* get/make the first vert to be used in SFME */
+       /* may need to split the previous edge */
+       v1 = BME_bevel_split_edge(bm,l->v,NULL,l->prev,up_vec,value,td);
+       /* get/make the second vert to be used in SFME */
+       /* may need to split this edge (so move l) */
+       l = l->prev;
+       v2 = BME_bevel_split_edge(bm,l->next->v,NULL,l->next,up_vec,value,td);
+       l = l->next->next;
+       /* "cut off" this corner */
+       f = BME_split_face(bm,l->f,v2,v1,NULL,l->e);
+       return l;
+ }
+ /**
+  *                    BME_bevel_poly
+  *
+  *    Polygon inset tool:
+  *
+  *    Insets a polygon/face based on the tflag1's of its vertices
+  *    and edges. Used by the bevel tool only, for now.
+  *  The parameter "value" is the distance to inset (should be negative).
+  *  The parameter "options" is not currently used.
+  *
+  *    Returns -
+  *  A BME_Poly pointer to the resulting inner face.
+ */
+ static BME_Poly *BME_bevel_poly(BME_Mesh *bm, BME_Poly *f, float value, int options, BME_TransData_Head *td) {
+       BME_Loop *l, *ol;
+       BME_TransData *vtd1, *vtd2;
+       float up_vec[3], vec1[3], vec2[3], vec3[3], fac1, fac2, max = -1;
+       int len, i;
+       up_vec[0] = 0.0f;
+       up_vec[1] = 0.0f;
+       up_vec[2] = 0.0f;
+       /* find a good normal for this face (there's better ways, I'm sure) */
+       ol = f->loopbase;
+       l = ol->next;
+       for (i=0,ol=f->loopbase,l=ol->next; l->next!=ol; l=l->next) {
+               BME_bevel_get_vec(vec1,l->next->v,ol->v,td);
+               BME_bevel_get_vec(vec2,l->v,ol->v,td);
+               Crossf(vec3,vec2,vec1);
+               VECADD(up_vec,up_vec,vec3);
+               i++;
+       }
+       VecMulf(up_vec,1.0f/i);
+       Normalize(up_vec);
+       for (i=0,len=f->len; i<len; i++,l=l->next) {
+               if ((l->e->tflag1 & BME_BEVEL_BEVEL) && (l->e->tflag1 & BME_BEVEL_ORIG)) {
+                       max = 1.0f;
+                       l = BME_bevel_edge(bm, l, value, options, up_vec, td);
+               }
+               else if ((l->v->tflag1 & BME_BEVEL_BEVEL) && (l->v->tflag1 & BME_BEVEL_ORIG) && (l->prev->e->tflag1 & BME_BEVEL_BEVEL) == 0) {
+                       max = 1.0f;
+                       l = BME_bevel_vert(bm, l, value, options, up_vec, td);
+               }
+       }
+       /* max pass */
+       if (value > 0.5 && max > 0) {
+               max = -1;
+               for (i=0,len=f->len; i<len; i++,l=l->next) {
+                       if ((l->e->tflag1 & BME_BEVEL_BEVEL) || (l->e->tflag1 & BME_BEVEL_ORIG)) {
+                               BME_bevel_get_vec(vec1,l->v,l->next->v,td);
+                               vtd1 = BME_get_transdata(td,l->v);
+                               vtd2 = BME_get_transdata(td,l->next->v);
+                               if (vtd1->loc == NULL) {
+                                       fac1 = 0;
+                               }
+                               else {
+                                       VECCOPY(vec2,vtd1->vec);
+                                       VecMulf(vec2,vtd1->factor);
+                                       if (Inpf(vec1, vec1)) {
+                                               Projf(vec2,vec2,vec1);
+                                               fac1 = VecLength(vec2)/value;
+                                       }
+                                       else {
+                                               fac1 = 0;
+                                       }
+                               }
+                               if (vtd2->loc == NULL) {
+                                       fac2 = 0;
+                               }
+                               else {
+                                       VECCOPY(vec3,vtd2->vec);
+                                       VecMulf(vec3,vtd2->factor);
+                                       if (Inpf(vec1, vec1)) {
+                                               Projf(vec2,vec3,vec1);
+                                               fac2 = VecLength(vec2)/value;
+                                       }
+                                       else {
+                                               fac2 = 0;
+                                       }
+                               }
+                               if (fac1 || fac2) {
+                                       max = VecLength(vec1)/(fac1 + fac2);
+                                       if (vtd1->max && (*vtd1->max < 0 || max < *vtd1->max)) {
+                                               *vtd1->max = max;
+                                       }
+                                       if (vtd2->max && (*vtd2->max < 0 || max < *vtd2->max)) {
+                                               *vtd2->max = max;
+                                       }
+                               }
+                       }
+               }
+       }
+       return l->f;
+ }
+ static void BME_bevel_add_vweight(BME_TransData_Head *td, BME_Mesh *bm, BME_Vert *v, float weight, float factor, int options) {
+       BME_TransData *vtd;
+       if (v->tflag1 & BME_BEVEL_NONMAN) return;
+       v->tflag1 |= BME_BEVEL_BEVEL;
+       if ( (vtd = BME_get_transdata(td, v)) ) {
+               if (options & BME_BEVEL_EMIN) {
+                       vtd->factor = 1.0;
+                       if (vtd->weight < 0 || weight < vtd->weight) {
+                               vtd->weight = weight;
+                       }
+               }
+               else if (options & BME_BEVEL_EMAX) {
+                       vtd->factor = 1.0;
+                       if (weight > vtd->weight) {
+                               vtd->weight = weight;
+                       }
+               }
+               else if (vtd->weight < 0) {
+                       vtd->factor = factor;
+                       vtd->weight = weight;
+               }
+               else {
+                       vtd->factor += factor; /* increment number of edges with weights (will be averaged) */
+                       vtd->weight += weight; /* accumulate all the weights */
+               }
+       }
+       else {
+               /* we'll use vtd->loc == NULL to mark that this vert is not moving */
+               vtd = BME_assign_transdata(td, bm, v, v->co, NULL, NULL, NULL, factor, weight, -1, NULL);
+       }
+ }
+ static float BME_bevel_get_angle(BME_Mesh *bm, BME_Edge *e, BME_Vert *v) {
+       BME_Vert *v1, *v2;
+       BME_Loop *l1, *l2;
+       float vec1[3], vec2[3], vec3[3], vec4[3];
+       l1 = e->loop;
+       l2 = e->loop->radial.next->data;
+       if (l1->v == v) {
+               v1 = l1->prev->v;
+               v2 = l1->next->v;
+       }
+       else {
+               v1 = l1->next->next->v;
+               v2 = l1->v;
+       }
+       VECSUB(vec1,v1->co,v->co);
+       VECSUB(vec2,v2->co,v->co);
+       Crossf(vec3,vec1,vec2);
+       l1 = l2;
+       if (l1->v == v) {
+               v1 = l1->prev->v;
+               v2 = l1->next->v;
+       }
+       else {
+               v1 = l1->next->next->v;
+               v2 = l1->v;
+       }
+       VECSUB(vec1,v1->co,v->co);
+       VECSUB(vec2,v2->co,v->co);
+       Crossf(vec4,vec2,vec1);
+       Normalize(vec3);
+       Normalize(vec4);
+       return Inpf(vec3,vec4);
+ }
+ static int BME_face_sharededges(BME_Poly *f1, BME_Poly *f2){
+       BME_Loop *l;
+       int count = 0;
+       
+       l = f1->loopbase;
+       do{
+               if(BME_radial_find_face(l->e,f2)) count++;
+               l = l->next;
+       }while(l != f1->loopbase);
+       
+       return count;
+ }
+ /**
+  *                    BME_bevel_initialize
+  *
+  *    Prepare the mesh for beveling:
+  *
+  *    Sets the tflag1's of the mesh elements based on the options passed.
+  *
+  *    Returns -
+  *  A BME_Mesh pointer to the BMesh passed as a parameter.
+ */
+ static BME_Mesh *BME_bevel_initialize(BME_Mesh *bm, int options, int defgrp_index, float angle, BME_TransData_Head *td) {
+       BME_Vert *v;
+       BME_Edge *e;
+       BME_Poly *f;
+       BME_TransData *vtd;
+       MDeformVert *dvert;
+       MDeformWeight *dw;
+       int len;
+       float weight, threshold;
+       /* vert pass */
+       for (v=bm->verts.first; v; v=v->next) {
+               dvert = NULL;
+               dw = NULL;
+               v->tflag1 = BME_BEVEL_ORIG;
+               /* originally coded, a vertex gets tagged with BME_BEVEL_BEVEL in this pass if
+                * the vert is manifold (or is shared by only two edges - wire bevel)
+                * BME_BEVEL_SELECT is passed and the vert has v->flag&SELECT or
+                * BME_BEVEL_VWEIGHT is passed, and the vert has a defgrp and weight
+                * BME_BEVEL_ANGLE is not passed
+                * BME_BEVEL_EWEIGHT is not passed
+                */
+               /* originally coded, a vertex gets tagged with BME_BEVEL_NONMAN in this pass if
+                * the vert is loose, shared by multiple regions, or is shared by wire edges
+                * note: verts belonging to edges of open meshes are not tagged with BME_BEVEL_NONMAN
+                */
+               /* originally coded, a vertex gets a transform weight set in this pass if
+                * BME_BEVEL_VWEIGHT is passed, and the vert has a defgrp and weight
+                */
+               /* get disk cycle length */
+               if (v->edge == NULL) {
+                       len = 0;
+               }
+               else {
+                       len = BME_cycle_length(BME_disk_getpointer(v->edge,v));
+                       /* we'll assign a default transform data to every vert (except the loose ones) */
+                       vtd = BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 0, -1, -1, NULL);
+               }
+               /* check for non-manifold vert */
+               if (BME_is_nonmanifold_vert(bm,v)) {
+                       v->tflag1 |= BME_BEVEL_NONMAN;
+               }
+               /* BME_BEVEL_BEVEL tests */
+               if ((v->tflag1 & BME_BEVEL_NONMAN) == 0 || len == 2) { /* either manifold vert, or wire vert */
+                       if (((options & BME_BEVEL_SELECT) && (v->flag & SELECT))
+                               || ((options & BME_BEVEL_WEIGHT) && (options & BME_BEVEL_VERT)) /* use weights for verts */
+                               || ((options & BME_BEVEL_ANGLE) == 0
+                                       && (options & BME_BEVEL_SELECT) == 0
+                                       && (options & BME_BEVEL_WEIGHT) == 0))
+                       {
+                               if (options & BME_BEVEL_WEIGHT) {
+                                       /* do vert weight stuff */
+                                       //~ dvert = CustomData_em_get(&bm->vdata,v->data,CD_MDEFORMVERT);
+                                       //~ if (!dvert) continue;
+                                       //~ for (i = 0; i < dvert->totweight; ++i) {
+                                               //~ if(dvert->dw[i].def_nr == defgrp_index) {
+                                                       //~ dw = &dvert->dw[i];
+                                                       //~ break;
+                                               //~ }
+                                       //~ }
+                                       //~ if (!dw || dw->weight == 0.0) continue;
+                                       if (v->bweight == 0.0) continue;
+                                       vtd = BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 1.0, v->bweight, -1, NULL);
+                                       v->tflag1 |= BME_BEVEL_BEVEL;
+                               }
+                               else {
+                                       vtd = BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 1.0, 1.0, -1, NULL);
+                                       v->tflag1 |= BME_BEVEL_BEVEL;
+                               }
+                       }
+               }
+       }
+       /* edge pass */
+       threshold = (float)cos((angle + 0.00001) * M_PI / 180.0);
+       for (e=bm->edges.first; e; e=e->next) {
+               e->tflag1 = BME_BEVEL_ORIG;
+               weight = 0.0;
+               /* originally coded, an edge gets tagged with BME_BEVEL_BEVEL in this pass if
+                * BME_BEVEL_VERT is not set
+                * the edge is manifold (shared by exactly two faces)
+                * BME_BEVEL_SELECT is passed and the edge has e->flag&SELECT or
+                * BME_BEVEL_EWEIGHT is passed, and the edge has the crease set or
+                * BME_BEVEL_ANGLE is passed, and the edge is sharp enough
+                * BME_BEVEL_VWEIGHT is passed, and both verts are set for bevel
+                */
+               /* originally coded, a vertex gets tagged with BME_BEVEL_BEVEL in this pass if
+                * the vert belongs to the edge
+                * the vert is not tagged with BME_BEVEL_NONMAN
+                * the edge is eligible for bevel (even if BME_BEVEL_VERT is set, or the edge is shared by less than 2 faces)
+                */
+               /* originally coded, a vertex gets a transform weight set in this pass if
+                * the vert belongs to the edge
+                * the edge has a weight
+                */
+               /* note: edge weights are cumulative at the verts,
+                * i.e. the vert's weight is the average of the weights of its weighted edges
+                */
+               if (e->loop == NULL) {
+                       len = 0;
+                       e->v1->tflag1 |= BME_BEVEL_NONMAN;
+                       e->v2->tflag1 |= BME_BEVEL_NONMAN;
+               }
+               else {
+                       len = BME_cycle_length(&(e->loop->radial));
+               }
+               if (len > 2) {
+                       /* non-manifold edge of the worst kind */
+                       continue;
+               }
+               if ((options & BME_BEVEL_SELECT) && (e->flag & SELECT)) {
+                       weight = 1.0;
+                       /* stupid editmode doesn't always flush selections, or something */
+                       e->v1->flag |= SELECT;
+                       e->v2->flag |= SELECT;
+               }
+               else if ((options & BME_BEVEL_WEIGHT) && (options & BME_BEVEL_VERT) == 0) {
+                       weight = e->bweight;
+               }
+               else if (options & BME_BEVEL_ANGLE) {
+                       if ((e->v1->tflag1 & BME_BEVEL_NONMAN) == 0 && BME_bevel_get_angle(bm,e,e->v1) < threshold) {
+                               e->tflag1 |= BME_BEVEL_BEVEL;
+                               e->v1->tflag1 |= BME_BEVEL_BEVEL;
+                               BME_bevel_add_vweight(td, bm, e->v1, 1.0, 1.0, options);
+                       }
+                       else {
+                               BME_bevel_add_vweight(td, bm, e->v1, 0.0, 1.0, options);
+                       }
+                       if ((e->v2->tflag1 & BME_BEVEL_NONMAN) == 0 && BME_bevel_get_angle(bm,e,e->v2) < threshold) {
+                               e->tflag1 |= BME_BEVEL_BEVEL;
+                               e->v2->tflag1 |= BME_BEVEL_BEVEL;
+                               BME_bevel_add_vweight(td, bm, e->v2, 1.0, 1.0, options);
+                       }
+                       else {
+                               BME_bevel_add_vweight(td, bm, e->v2, 0.0, 1.0, options);
+                       }
+               }
+               //~ else if ((options & BME_BEVEL_VWEIGHT) && (options & BME_BEVEL_VERT) == 0) {
+                       //~ if ((e->v1->tflag1 & BME_BEVEL_BEVEL) && (e->v2->tflag1 & BME_BEVEL_BEVEL)) {
+                               //~ e->tflag1 |= BME_BEVEL_BEVEL;
+                       //~ }
+               //~ }
+               else if ((options & BME_BEVEL_SELECT) == 0
+                       && (options & BME_BEVEL_VERT) == 0)
+               {
+                       weight = 1.0;
+               }
+               if (weight > 0.0) {
+                       e->tflag1 |= BME_BEVEL_BEVEL;
+                       BME_bevel_add_vweight(td, bm, e->v1, weight, 1.0, options);
+                       BME_bevel_add_vweight(td, bm, e->v2, weight, 1.0, options);
+               }
+               if (len != 2 || options & BME_BEVEL_VERT) {
+                       e->tflag1 &= ~BME_BEVEL_BEVEL;
+               }
+       }
+       /* face pass */
+       for (f=bm->polys.first; f; f=f->next) f->tflag1 = BME_BEVEL_ORIG;
+       /*clean up edges with 2 faces that share more than one edge*/
+       for (e=bm->edges.first; e; e=e->next){
+               if(e->tflag1 & BME_BEVEL_BEVEL){
+                       int count = 0;
+                       count = BME_face_sharededges(e->loop->f, ((BME_Loop*)e->loop->radial.next->data)->f);
+                       if(count > 1){
+                               e->tflag1 &= ~BME_BEVEL_BEVEL;
+                       }       
+               }
+       }
+       return bm;
+ }
+ /* tags all elements as originals */
+ static BME_Mesh *BME_bevel_reinitialize(BME_Mesh *bm) {
+       BME_Vert *v;
+       BME_Edge *e;
+       BME_Poly *f;
+       for (v = bm->verts.first; v; v=v->next) {
+               v->tflag1 |= BME_BEVEL_ORIG;
+       }
+       for (e=bm->edges.first; e; e=e->next) {
+               e->tflag1 |= BME_BEVEL_ORIG;
+       }
+       for (f=bm->polys.first; f; f=f->next) {
+               f->tflag1 |= BME_BEVEL_ORIG;
+       }
+       return bm;
+ }
+ /**
+  *                    BME_bevel_mesh
+  *
+  *    Mesh beveling tool:
+  *
+  *    Bevels an entire mesh. It currently uses the tflag1's of
+  *    its vertices and edges to track topological changes.
+  *  The parameter "value" is the distance to inset (should be negative).
+  *  The parameter "options" is not currently used.
+  *
+  *    Returns -
+  *  A BME_Mesh pointer to the BMesh passed as a parameter.
+ */
+ static void bmesh_dissolve_disk(BME_Mesh *bm, BME_Vert *v){
+       BME_Poly *f;
+       BME_Edge *e;
+       int done, len;
+       
+       if(v->edge){
+               done = 0;
+               while(!done){
+                       done = 1;
+                       e = v->edge; /*loop the edge looking for a edge to dissolve*/
+                       do{
+                               f = NULL;
+                               len = BME_cycle_length(&(e->loop->radial));
+                               if(len == 2){
+                                       f = BME_JFKE_safe(bm,e->loop->f, ((BME_Loop*)(e->loop->radial.next->data))->f, e);
+                               }
+                               if(f){ 
+                                       done = 0;
+                                       break;
+                               }
+                               e = BME_disk_nextedge(e,v);
+                       }while(e != v->edge);
+               }
+               BME_collapse_vert(bm, v->edge, v, 1.0);
+               //BME_JEKV(bm,v->edge,v);
+       }
+ }
+ static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options, int defgrp_index, BME_TransData_Head *td) {
+       BME_Vert *v, *nv;
+       BME_Edge *e, *oe;
+       BME_Loop *l, *l2;
+       BME_Poly *f;
+       unsigned int i, len;
+       for (f=bm->polys.first; f; f=f->next) {
+               if(f->tflag1 & BME_BEVEL_ORIG) {
+                       BME_bevel_poly(bm,f,value,options,td);
+               }
+       }
+       /* here we will loop through all the verts to clean up the left over geometry */
+       /* crazy idea. when res == 0, don't remove the original geometry */
+       for (v = bm->verts.first; v; /* we may kill v, so increment in-loop */) {
+               nv = v->next;
+               if ((v->tflag1 & BME_BEVEL_NONMAN) && (v->tflag1 & BME_BEVEL_BEVEL) && (v->tflag1 & BME_BEVEL_ORIG)) {
+                       v = BME_bevel_wire(bm, v, value, res, options, td);
+               }
+               else if (res && ((v->tflag1 & BME_BEVEL_BEVEL) && (v->tflag1 & BME_BEVEL_ORIG))) {
+                       int count = 0;
+                       /* first, make sure we're not sitting on an edge to be removed */
+                       oe = v->edge;
+                       e = BME_disk_nextedge(oe,v);
+                       while ((e->tflag1 & BME_BEVEL_BEVEL) && (e->tflag1 & BME_BEVEL_ORIG)) {
+                               e = BME_disk_nextedge(e,v);
+                               if (e == oe) {
+                                       //printf("Something's wrong! We can't remove every edge here!\n");
+                                       break;
+                               }
+                       }
+                       /* look for original edges, and remove them */
+                       oe = e;
+                       while ( (e = BME_disk_next_edgeflag(oe, v, 0, BME_BEVEL_ORIG | BME_BEVEL_BEVEL)) ) {
+                               count++;
+                               /* join the faces (we'll split them later) */
+                               f = BME_JFKE_safe(bm,e->loop->f,((BME_Loop*)e->loop->radial.next->data)->f,e);
+                               if (!f){
+                                       //printf("Non-manifold geometry not getting tagged right?\n");
+                               }
+                       }
+                       /*need to do double check *before* you bevel to make sure that manifold edges are for two faces that share only *one* edge to make sure it doesnt hang here!*/
+                       /* all original edges marked to be beveled have been removed;
+                        * now we need to link up the edges for this "corner" */
+                       len = BME_cycle_length(BME_disk_getpointer(v->edge, v));
+                       for (i=0,e=v->edge; i < len; i++,e=BME_disk_nextedge(e,v)) {
+                               l = e->loop;
+                               l2 = l->radial.next->data;
+                               if (l->v != v) l = l->next;
+                               if (l2->v != v) l2 = l2->next;
+                               /* look for faces that have had the original edges removed via JFKE */
+                               if (l->f->len > 3) {
+                                       BME_split_face(bm,l->f,l->next->v,l->prev->v,&l,l->e); /* clip this corner off */
+                                       if (len > 2) {
+                                               l->e->tflag1 |= BME_BEVEL_BEVEL;
+                                       }
+                               }
+                               if (l2->f->len > 3) {
+                                       BME_split_face(bm,l2->f,l2->next->v,l2->prev->v,&l,l2->e); /* clip this corner off */
+                                       if (len > 2) {
+                                               l->e->tflag1 |= BME_BEVEL_BEVEL;
+                                       }
+                               }
+                       }
+                       bmesh_dissolve_disk(bm, v);
+               }
+               v = nv;
+       }
+       return bm;
+ }
+ static BME_Mesh *BME_tesselate(BME_Mesh *bm) {
+       BME_Loop *l, *nextloop;
+       BME_Poly *f;
+       for (f=bm->polys.first; f; f=f->next) {
+               l = f->loopbase;
+               while (l->f->len > 4) {
+                       nextloop = l->next->next->next;
+                       /* make a quad */
+                       BME_split_face(bm,l->f,l->v,nextloop->v,NULL,l->e);
+                       l = nextloop;
+               }
+       }
+       return bm;
+ }
+ /*Main bevel function:
+       Should be only one exported
+ */
+ /* options that can be passed:
+  * BME_BEVEL_VWEIGHT  <---- v, Look at vertex weights; use defgrp_index if option is present
+  * BME_BEVEL_SELECT           <---- v,e, check selection for verts and edges
+  * BME_BEVEL_ANGLE            <---- v,e, don't bevel-tag verts - tag verts per edge
+  * BME_BEVEL_VERT             <---- e, don't tag edges
+  * BME_BEVEL_EWEIGHT  <---- e, use crease flag for now
+  * BME_BEVEL_PERCENT  <---- Will need to think about this one; will probably need to incorporate into actual bevel routine
+  * BME_BEVEL_RADIUS           <---- Will need to think about this one; will probably need to incorporate into actual bevel routine
+  * All weights/limits are stored per-vertex
+  */
+ BME_Mesh *BME_bevel(BME_Mesh *bm, float value, int res, int options, int defgrp_index, float angle, BME_TransData_Head **rtd) {
+       BME_Vert *v;
+       BME_TransData_Head *td;
+       BME_TransData *vtd;
+       int i;
+       float fac=1, d;
+       td = BME_init_transdata(BLI_MEMARENA_STD_BUFSIZE);
+       BME_bevel_initialize(bm, options, defgrp_index, angle, td);
+       /* recursion math courtesy of Martin Poirier (theeth) */
+       for (i=0; i<res-1; i++) {
+               if (i==0) fac += 1.0f/3.0f; else fac += 1.0f/(3 * i * 2.0f);
+       }
+       d = 1.0f/fac;
+       /* crazy idea. if res == 0, don't remove original geometry */
+       for (i=0; i<res || (res==0 && i==0); i++) {
+               if (i != 0) BME_bevel_reinitialize(bm);
+               BME_model_begin(bm);
+               BME_bevel_mesh(bm,d,res,options,defgrp_index,td);
+               BME_model_end(bm);
+               if (i==0) d /= 3; else d /= 2;
+       }
+       BME_tesselate(bm);
+       if (rtd) {
+               *rtd = td;
+               return bm;
+       }
+       /* transform pass */
+       for (v = bm->verts.first; v; v=v->next) {
+               if ( (vtd = BME_get_transdata(td, v)) ) {
+                       if (vtd->max && (*vtd->max > 0 && value > *vtd->max)) {
+                               d = *vtd->max;
+                       }
+                       else {
+                               d = value;
+                       }
+                       VECADDFAC(v->co,vtd->org,vtd->vec,vtd->factor*d);
+               }
+               v->tflag1 = 0;
+       }
+       BME_free_transdata(td);
+       return bm;
+ }
  #include "BIF_gl.h"
  #include "BIF_glutil.h"
  
- // headers for fluidsim bobj meshes
- #include <stdlib.h>
- #include "LBM_fluidsim.h"
- #include "elbeem.h"
 +//XXX #include "multires.h"
++//
+ #include "GPU_draw.h"
+ #include "GPU_extensions.h"
+ #include "GPU_material.h"
  
  ///////////////////////////////////
  ///////////////////////////////////
@@@ -651,7 -627,7 +629,7 @@@ static void emDM_drawMappedFaces(Derive
                        if(draw) {
                                if (draw==2) { /* enabled with stipple */
                                        glEnable(GL_POLYGON_STIPPLE);
-                                       glPolygonStipple(act_face_stipple);
 -                                      glPolygonStipple(stipple_quarttone);
++                                      glPolygonStipple(0); //XXX stipple_quarttone);
                                }
                                
                                glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
                        if(draw) {
                                if (draw==2) { /* enabled with stipple */
                                        glEnable(GL_POLYGON_STIPPLE);
-                                       glPolygonStipple(act_face_stipple);
 -                                      glPolygonStipple(stipple_quarttone);
++                                      glPolygonStipple(0); //XXX stipple_quarttone);
                                }
                                glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
  
@@@ -2598,18 -2837,24 +2839,24 @@@ float *multires_render_pin(Object *ob, 
  void multires_render_final(Object *ob, Mesh *me, DerivedMesh **dm, float *vert_copy,
                           const int orig_lvl, CustomDataMask dataMask)
  {
-       if(me->mr) {
+       if(me->mr && !(me->mr->flag & MULTIRES_NO_RENDER)) {
                if((*dm)->getNumVerts(*dm) == me->totvert &&
                   (*dm)->getNumFaces(*dm) == me->totface) {
 -                      MultiresLevel *lvl= multires_level_n(me->mr, BLI_countlist(&me->mr->levels));
 +                      //XXX MultiresLevel *lvl= multires_level_n(me->mr, BLI_countlist(&me->mr->levels));
                        DerivedMesh *old= NULL;
+                       MVert *vertdup= NULL;
                        int i;
  
-                       (*dm)->copyVertArray(*dm, me->mvert);
+                       /* Copy the verts into the mesh */
+                       vertdup= (*dm)->dupVertArray(*dm);
                        (*dm)->release(*dm);
+                       for(i=0; i<me->totvert; ++i)
+                               me->mvert[i]= vertdup[i];
+                       /* Free vertdup after use*/
+                       MEM_freeN(vertdup);
+                       /* Go to the render level */
                        me->mr->newlvl= me->mr->renderlvl;
 -                      multires_set_level(ob, me, 1);
 +                      //XXX multires_set_level(ob, me, 1);
                        (*dm)= getMeshDerivedMesh(me, ob, NULL);
  
                        /* Some of the data in dm is referenced externally, so make a copy */
@@@ -62,8 -62,9 +62,9 @@@
  
  #include "BLI_arithb.h"
  #include "BLI_blenlib.h"
+ #include "BLI_ghash.h"
  
 -#include "nla.h"
 +//XXX #include "nla.h"
  
  /* *********************** NOTE ON POSE AND ACTION **********************
  
@@@ -184,9 -194,25 +194,25 @@@ bAction *copy_action (bAction *src
        if (!src) return NULL;
        
        dst= copy_libblock(src);
 -      duplicatelist(&(dst->chanbase), &(src->chanbase));
 -      duplicatelist(&(dst->groups), &(src->groups));
 -      duplicatelist(&(dst->markers), &(src->markers));
+       
 +      BLI_duplicatelist(&(dst->chanbase), &(src->chanbase));
++      BLI_duplicatelist(&(dst->groups), &(src->groups));
++      BLI_duplicatelist(&(dst->markers), &(src->markers));
        
-       for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next){
+       for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next) {
+               for (dgrp=dst->groups.first, sgrp=src->groups.first; dgrp && sgrp; dgrp=dgrp->next, sgrp=sgrp->next) {
+                       if (dchan->grp == sgrp) {
+                               dchan->grp= dgrp;
+                               
+                               if (dgrp->channels.first == schan)
+                                       dgrp->channels.first= dchan;
+                               if (dgrp->channels.last == schan)
+                                       dgrp->channels.last= dchan;
+                                       
+                               break;
+                       }
+               }
+               
                dchan->ipo = copy_ipo(dchan->ipo);
                copy_constraint_channels(&dchan->constraintChannels, &schan->constraintChannels);
        }
@@@ -263,9 -291,15 +291,15 @@@ void copy_pose(bPose **dst, bPose *src
                return;
        }
        
+       if (*dst==src) {
+               printf("copy_pose source and target are the same\n");
+               *dst=NULL;
+               return;
+       }
+       
        outPose= MEM_callocN(sizeof(bPose), "pose");
        
 -      duplicatelist(&outPose->chanbase, &src->chanbase);
 +      BLI_duplicatelist (&outPose->chanbase, &src->chanbase);
        
        if (copycon) {
                for (pchan=outPose->chanbase.first; pchan; pchan=pchan->next) {
@@@ -288,7 -322,76 +322,76 @@@ void free_pose_channels(bPose *pose
                                MEM_freeN(pchan->path);
                        free_constraints(&pchan->constraints);
                }
-               BLI_freelistN (&pose->chanbase);
+               BLI_freelistN(&pose->chanbase);
+       }
+ }
+ void free_pose(bPose *pose)
+ {
+       if (pose) {
+               /* free pose-channels */
+               free_pose_channels(pose);
+               
+               /* free pose-groups */
+               if (pose->agroups.first)
+                       BLI_freelistN(&pose->agroups);
+               
+               /* free pose */
+               MEM_freeN(pose);
+       }
+ }
+ void game_copy_pose(bPose **dst, bPose *src)
+ {
+       bPose *out;
+       bPoseChannel *pchan, *outpchan;
+       GHash *ghash;
+       
+       /* the game engine copies the current armature pose and then swaps
+        * the object pose pointer. this makes it possible to change poses
+        * without affecting the original blender data. */
+       if (!src) {
+               *dst=NULL;
+               return;
+       }
+       else if (*dst==src) {
+               printf("copy_pose source and target are the same\n");
+               *dst=NULL;
+               return;
+       }
+       
+       out= MEM_dupallocN(src);
+       out->agroups.first= out->agroups.last= NULL;
 -      duplicatelist(&out->chanbase, &src->chanbase);
++      BLI_duplicatelist(&out->chanbase, &src->chanbase);
+       /* remap pointers */
+       ghash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+       pchan= src->chanbase.first;
+       outpchan= out->chanbase.first;
+       for (; pchan; pchan=pchan->next, outpchan=outpchan->next)
+               BLI_ghash_insert(ghash, pchan, outpchan);
+       for (pchan=out->chanbase.first; pchan; pchan=pchan->next) {
+               pchan->parent= BLI_ghash_lookup(ghash, pchan->parent);
+               pchan->child= BLI_ghash_lookup(ghash, pchan->child);
+               pchan->path= NULL;
+       }
+       BLI_ghash_free(ghash, NULL, NULL);
+       
+       *dst=out;
+ }
+ void game_free_pose(bPose *pose)
+ {
+       if (pose) {
+               /* we don't free constraints, those are owned by the original pose */
+               if(pose->chanbase.first)
+                       BLI_freelistN(&pose->chanbase);
+               
+               MEM_freeN(pose);
        }
  }
  
  #include <math.h>
  #include <string.h>
  #include <stdio.h>
+ #include <float.h>
  #include "MEM_guardedalloc.h"
  
 -#include "nla.h"
 +//XXX #include "nla.h"
  
  #include "BLI_arithb.h"
  #include "BLI_blenlib.h"
@@@ -1314,9 -1427,18 +1427,18 @@@ static void pose_proxy_synchronize(Obje
        /* clear all transformation values from library */
        rest_pose(frompose);
        
-       pchan= pose->chanbase.first;
-       for(; pchan; pchan= pchan->next) {
-               if(pchan->bone->layer & layer_protected) {
+       /* copy over all of the proxy's bone groups */
+               /* TODO for later - implement 'local' bone groups as for constraints
+                *      Note: this isn't trivial, as bones reference groups by index not by pointer, 
+                *               so syncing things correctly needs careful attention
+                */
+       BLI_freelistN(&pose->agroups);
 -      duplicatelist(&pose->agroups, &frompose->agroups);
++      BLI_duplicatelist(&pose->agroups, &frompose->agroups);
+       pose->active_group= frompose->active_group;
+       
+       for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
+               if (pchan->bone->layer & layer_protected) {
+                       ListBase proxylocal_constraints = {NULL, NULL};
                        pchanp= get_pose_channel(frompose, pchan->name);
                        
                        /* copy posechannel to temp, but restore important pointers */
  #include "IMB_imbuf_types.h"
  #include "IMB_imbuf.h"
  
 -#include "DNA_mesh_types.h"
 -#include "DNA_screen_types.h"
 -
+ #include "BKE_action.h"
  #include "BKE_blender.h"
  #include "BKE_curve.h"
  #include "BKE_depsgraph.h"
@@@ -313,9 -334,10 +317,10 @@@ static void setup_app_data(bContext *C
                extern void lib_link_screen_restore(Main *, Scene *);
                
                SWAP(ListBase, G.main->screen, bfd->main->screen);
+               SWAP(ListBase, G.main->script, bfd->main->script);
                
                /* we re-use current screen */
 -              curscreen= G.curscreen;
 +              curscreen= C->screen;
                /* but use new Scene pointer */
                curscene= bfd->curscene;
                if(curscene==NULL) curscene= bfd->main->scene.first;
        }
        
        /* baseflags, groups, make depsgraph, etc */
 -      set_scene_bg(G.scene);
 +      set_scene_bg(C->scene);
  
+       /* clear BONE_UNKEYED flags, these are not valid anymore for proxies */
+       framechange_poses_clear_unkeyed();
        /* last stage of do_versions actually, that sets recalc flags for recalc poses */
        for(ob= G.main->object.first; ob; ob= ob->id.next) {
                if(ob->type==OB_ARMATURE)
@@@ -443,14 -476,23 +452,14 @@@ int BKE_read_file_from_memory(bContext 
  {
        BlendReadError bre;
        BlendFileData *bfd;
 -      
 -      if (!G.background)
 -              waitcursor(1);
 -              
 +                      
        bfd= BLO_read_from_memory(filebuf, filelength, &bre);
-       if (bfd) {              
-               setup_app_data(C, bfd, "<memory>");
+       if (bfd) {
 -              if (type_r)
 -                      *((BlenFileType*)type_r)= bfd->type;
 -              
 -              setup_app_data(bfd, "<memory2>");
++              setup_app_data(C, bfd, "<memory2>");
        } else {
 -              error("Loading failed: %s", BLO_bre_as_string(bre));
 +// XXX                error("Loading failed: %s", BLO_bre_as_string(bre));
        }
 -      
 -      if (!G.background)
 -              waitcursor(0);
 -      
 +              
        return (bfd?1:0);
  }
  
@@@ -460,13 -502,19 +469,13 @@@ int BKE_read_file_from_memfile(bContex
        BlendReadError bre;
        BlendFileData *bfd;
        
 -      if (!G.background)
 -              waitcursor(1);
 -              
        bfd= BLO_read_from_memfile(G.sce, memfile, &bre);
        if (bfd) {
-               setup_app_data(C, bfd, "<memory>");
 -              setup_app_data(bfd, "<memory1>");
++              setup_app_data(C, bfd, "<memory1>");
        } else {
 -              error("Loading failed: %s", BLO_bre_as_string(bre));
 +// XXX                error("Loading failed: %s", BLO_bre_as_string(bre));
        }
 -      
 -      if (!G.background)
 -              waitcursor(0);
 -      
 +              
        return (bfd?1:0);
  }
  
@@@ -509,8 -558,9 +519,9 @@@ static int read_undosave(bContext *C, U
  }
  
  /* name can be a dynamic string */
 -void BKE_write_undo(char *name)
 +void BKE_write_undo(bContext *C, char *name)
  {
+       uintptr_t maxmem, totmem, memused;
        int nr, success;
        UndoElem *uel;
        
                counter= counter % U.undosteps; 
        
                sprintf(numstr, "%d.blend", counter);
-               BLI_make_file_string("/", tstr, U.tempdir, numstr);
+               BLI_make_file_string("/", tstr, btempdir, numstr);
        
 -              success= BLO_write_file(tstr, G.fileflags, &err);
 +              success= BLO_write_file(C, tstr, G.fileflags, &err);
                
                strcpy(curundo->str, tstr);
        }
                
                if(curundo->prev) prevfile= &(curundo->prev->memfile);
                
 -              success= BLO_write_file_mem(prevfile, &curundo->memfile, G.fileflags, &err);
+               memused= MEM_get_memory_in_use();
-               
 +              success= BLO_write_file_mem(C, prevfile, &curundo->memfile, G.fileflags, &err);
+               curundo->undosize= MEM_get_memory_in_use() - memused;
+       }
+       if(U.undomemory != 0) {
+               /* limit to maximum memory (afterwards, we can't know in advance) */
+               totmem= 0;
+               maxmem= ((uintptr_t)U.undomemory)*1024*1024;
+               /* keep at least two (original + other) */
+               uel= undobase.last;
+               while(uel && uel->prev) {
+                       totmem+= uel->undosize;
+                       if(totmem>maxmem) break;
+                       uel= uel->prev;
+               }
+               if(uel) {
+                       if(uel->prev && uel->prev->prev)
+                               uel= uel->prev;
+                       while(undobase.first!=uel) {
+                               UndoElem *first= undobase.first;
+                               BLI_remlink(&undobase, first);
+                               /* the merge is because of compression */
+                               BLO_merge_memfile(&first->memfile, &first->next->memfile);
+                               MEM_freeN(first);
+                       }
+               }
        }
  }
  
- /* 1= an undo, -1 is a redo. we have to make sure 'curundo' remains at current situation */
+ /* 1= an undo, -1 is a redo. we have to make sure 'curundo' remains at current situation
+  * Note, ALWAYS call sound_initialize_sounds after BKE_undo_step() */
 -void BKE_undo_step(int step)
 +void BKE_undo_step(bContext *C, int step)
  {
        
        if(step==0) {
@@@ -675,7 -754,7 +715,7 @@@ void BKE_undo_save_quit(void
  
        file = open(str,O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666);
        if(file == -1) {
-               printf("Unable to save %s\n", str);
 -              error("Unable to save %s, check you have permissions", str);
++              //XXX error("Unable to save %s, check you have permissions", str);
                return;
        }
  
        
        close(file);
        
-       if(chunk) printf("Unable to save %s\n", str);
 -      if(chunk) error("Unable to save %s, internal error", str);
++      if(chunk) ; //XXX error("Unable to save %s, internal error", str);
        else printf("Saved session recovery to %s\n", str);
  }
  
index 0000000,775f1de..9db3dda
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1678 +1,1677 @@@
 -#include "mydevice.h"
+ /*  collision.c
+ *
+ *
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+ #include "MEM_guardedalloc.h"
+ #include "BKE_cloth.h"
+ #include "DNA_cloth_types.h"
+ #include "DNA_group_types.h"
+ #include "DNA_mesh_types.h"
+ #include "DNA_object_types.h"
+ #include "DNA_object_force.h"
+ #include "DNA_scene_types.h"
+ #include "BKE_DerivedMesh.h"
+ #include "BKE_global.h"
+ #include "BKE_mesh.h"
+ #include "BKE_object.h"
+ #include "BKE_modifier.h"
+ #include "BKE_utildefines.h"
+ #include "BKE_DerivedMesh.h"
+ #include "Bullet-C-Api.h"
+ #include "BLI_kdopbvh.h"
+ #include "BKE_collision.h"
+ /***********************************
+ Collision modifier code start
+ ***********************************/
+ /* step is limited from 0 (frame start position) to 1 (frame end position) */
+ void collision_move_object ( CollisionModifierData *collmd, float step, float prevstep )
+ {
+       float tv[3] = {0,0,0};
+       unsigned int i = 0;
+       for ( i = 0; i < collmd->numverts; i++ )
+       {
+               VECSUB ( tv, collmd->xnew[i].co, collmd->x[i].co );
+               VECADDS ( collmd->current_x[i].co, collmd->x[i].co, tv, prevstep );
+               VECADDS ( collmd->current_xnew[i].co, collmd->x[i].co, tv, step );
+               VECSUB ( collmd->current_v[i].co, collmd->current_xnew[i].co, collmd->current_x[i].co );
+       }
+       bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 );
+ }
+ BVHTree *bvhtree_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon )
+ {
+       BVHTree *tree;
+       float co[12];
+       int i;
+       MFace *tface = mfaces;
+       tree = BLI_bvhtree_new ( numfaces*2, epsilon, 4, 26 );
+       // fill tree
+       for ( i = 0; i < numfaces; i++, tface++ )
+       {
+               VECCOPY ( &co[0*3], x[tface->v1].co );
+               VECCOPY ( &co[1*3], x[tface->v2].co );
+               VECCOPY ( &co[2*3], x[tface->v3].co );
+               if ( tface->v4 )
+                       VECCOPY ( &co[3*3], x[tface->v4].co );
+               BLI_bvhtree_insert ( tree, i, co, ( mfaces->v4 ? 4 : 3 ) );
+       }
+       // balance tree
+       BLI_bvhtree_balance ( tree );
+       return tree;
+ }
+ void bvhtree_update_from_mvert ( BVHTree * bvhtree, MFace *faces, int numfaces, MVert *x, MVert *xnew, int numverts, int moving )
+ {
+       int i;
+       MFace *mfaces = faces;
+       float co[12], co_moving[12];
+       int ret = 0;
+       if ( !bvhtree )
+               return;
+       if ( x )
+       {
+               for ( i = 0; i < numfaces; i++, mfaces++ )
+               {
+                       VECCOPY ( &co[0*3], x[mfaces->v1].co );
+                       VECCOPY ( &co[1*3], x[mfaces->v2].co );
+                       VECCOPY ( &co[2*3], x[mfaces->v3].co );
+                       if ( mfaces->v4 )
+                               VECCOPY ( &co[3*3], x[mfaces->v4].co );
+                       // copy new locations into array
+                       if ( moving && xnew )
+                       {
+                               // update moving positions
+                               VECCOPY ( &co_moving[0*3], xnew[mfaces->v1].co );
+                               VECCOPY ( &co_moving[1*3], xnew[mfaces->v2].co );
+                               VECCOPY ( &co_moving[2*3], xnew[mfaces->v3].co );
+                               if ( mfaces->v4 )
+                                       VECCOPY ( &co_moving[3*3], xnew[mfaces->v4].co );
+                               ret = BLI_bvhtree_update_node ( bvhtree, i, co, co_moving, ( mfaces->v4 ? 4 : 3 ) );
+                       }
+                       else
+                       {
+                               ret = BLI_bvhtree_update_node ( bvhtree, i, co, NULL, ( mfaces->v4 ? 4 : 3 ) );
+                       }
+                       // check if tree is already full
+                       if ( !ret )
+                               break;
+               }
+               BLI_bvhtree_update_tree ( bvhtree );
+       }
+ }
+ /***********************************
+ Collision modifier code end
+ ***********************************/
+ /**
+ * gsl_poly_solve_cubic -
+ *
+ * copied from SOLVE_CUBIC.C --> GSL
+ */
+ #define mySWAP(a,b) do { double tmp = b ; b = a ; a = tmp ; } while(0)
+ int 
+ gsl_poly_solve_cubic (double a, double b, double c, 
+                                         double *x0, double *x1, double *x2)
+ {
+       double q = (a * a - 3 * b);
+       double r = (2 * a * a * a - 9 * a * b + 27 * c);
+       double Q = q / 9;
+       double R = r / 54;
+       double Q3 = Q * Q * Q;
+       double R2 = R * R;
+       double CR2 = 729 * r * r;
+       double CQ3 = 2916 * q * q * q;
+       if (R == 0 && Q == 0)
+       {
+               *x0 = - a / 3 ;
+               *x1 = - a / 3 ;
+               *x2 = - a / 3 ;
+               return 3 ;
+       }
+       else if (CR2 == CQ3) 
+       {
+               /* this test is actually R2 == Q3, written in a form suitable
+               for exact computation with integers */
+               /* Due to finite precision some double roots may be missed, and
+               considered to be a pair of complex roots z = x +/- epsilon i
+               close to the real axis. */
+               double sqrtQ = sqrt (Q);
+               if (R > 0)
+               {
+                       *x0 = -2 * sqrtQ  - a / 3;
+                       *x1 = sqrtQ - a / 3;
+                       *x2 = sqrtQ - a / 3;
+               }
+               else
+               {
+                       *x0 = - sqrtQ  - a / 3;
+                       *x1 = - sqrtQ - a / 3;
+                       *x2 = 2 * sqrtQ - a / 3;
+               }
+               return 3 ;
+       }
+       else if (CR2 < CQ3) /* equivalent to R2 < Q3 */
+       {
+               double sqrtQ = sqrt (Q);
+               double sqrtQ3 = sqrtQ * sqrtQ * sqrtQ;
+               double theta = acos (R / sqrtQ3);
+               double norm = -2 * sqrtQ;
+               *x0 = norm * cos (theta / 3) - a / 3;
+               *x1 = norm * cos ((theta + 2.0 * M_PI) / 3) - a / 3;
+               *x2 = norm * cos ((theta - 2.0 * M_PI) / 3) - a / 3;
+               /* Sort *x0, *x1, *x2 into increasing order */
+               if (*x0 > *x1)
+                       mySWAP(*x0, *x1) ;
+               if (*x1 > *x2)
+               {
+                       mySWAP(*x1, *x2) ;
+                       if (*x0 > *x1)
+                               mySWAP(*x0, *x1) ;
+               }
+               return 3;
+       }
+       else
+       {
+               double sgnR = (R >= 0 ? 1 : -1);
+               double A = -sgnR * pow (fabs (R) + sqrt (R2 - Q3), 1.0/3.0);
+               double B = Q / A ;
+               *x0 = A + B - a / 3;
+               return 1;
+       }
+ }
+ /**
+ * gsl_poly_solve_quadratic
+ *
+ * copied from GSL
+ */
+ int 
+ gsl_poly_solve_quadratic (double a, double b, double c, 
+                                                 double *x0, double *x1)
+ {
+       double disc = b * b - 4 * a * c;
+       if (a == 0) /* Handle linear case */
+       {
+               if (b == 0)
+               {
+                       return 0;
+               }
+               else
+               {
+                       *x0 = -c / b;
+                       return 1;
+               };
+       }
+       if (disc > 0)
+       {
+               if (b == 0)
+               {
+                       double r = fabs (0.5 * sqrt (disc) / a);
+                       *x0 = -r;
+                       *x1 =  r;
+               }
+               else
+               {
+                       double sgnb = (b > 0 ? 1 : -1);
+                       double temp = -0.5 * (b + sgnb * sqrt (disc));
+                       double r1 = temp / a ;
+                       double r2 = c / temp ;
+                       if (r1 < r2) 
+                       {
+                               *x0 = r1 ;
+                               *x1 = r2 ;
+                       } 
+                       else 
+                       {
+                               *x0 = r2 ;
+                               *x1 = r1 ;
+                       }
+               }
+               return 2;
+       }
+       else if (disc == 0) 
+       {
+               *x0 = -0.5 * b / a ;
+               *x1 = -0.5 * b / a ;
+               return 2 ;
+       }
+       else
+       {
+               return 0;
+       }
+ }
+ /*
+ * See Bridson et al. "Robust Treatment of Collision, Contact and Friction for Cloth Animation"
+ *     page 4, left column
+ */
+ int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3], double e[3], double f[3], double solution[3] )
+ {
+       int num_sols = 0;
+       // x^0 - checked 
+       double g =      a[0] * c[1] * e[2] - a[0] * c[2] * e[1] +
+               a[1] * c[2] * e[0] - a[1] * c[0] * e[2] + 
+               a[2] * c[0] * e[1] - a[2] * c[1] * e[0];
+       // x^1
+       double h = -b[2] * c[1] * e[0] + b[1] * c[2] * e[0] - a[2] * d[1] * e[0] +
+               a[1] * d[2] * e[0] + b[2] * c[0] * e[1] - b[0] * c[2] * e[1] +
+               a[2] * d[0] * e[1] - a[0] * d[2] * e[1] - b[1] * c[0] * e[2] +
+               b[0] * c[1] * e[2] - a[1] * d[0] * e[2] + a[0] * d[1] * e[2] -
+               a[2] * c[1] * f[0] + a[1] * c[2] * f[0] + a[2] * c[0] * f[1] -
+               a[0] * c[2] * f[1] - a[1] * c[0] * f[2] + a[0] * c[1] * f[2];
+       // x^2
+       double i = -b[2] * d[1] * e[0] + b[1] * d[2] * e[0] +
+               b[2] * d[0] * e[1] - b[0] * d[2] * e[1] -
+               b[1] * d[0] * e[2] + b[0] * d[1] * e[2] -
+               b[2] * c[1] * f[0] + b[1] * c[2] * f[0] -
+               a[2] * d[1] * f[0] + a[1] * d[2] * f[0] +
+               b[2] * c[0] * f[1] - b[0] * c[2] * f[1] + 
+               a[2] * d[0] * f[1] - a[0] * d[2] * f[1] -
+               b[1] * c[0] * f[2] + b[0] * c[1] * f[2] -
+               a[1] * d[0] * f[2] + a[0] * d[1] * f[2];
+       // x^3 - checked
+       double j = -b[2] * d[1] * f[0] + b[1] * d[2] * f[0] +
+               b[2] * d[0] * f[1] - b[0] * d[2] * f[1] -
+               b[1] * d[0] * f[2] + b[0] * d[1] * f[2];
+       /*
+       printf("r1: %lf\n", a[0] * c[1] * e[2] - a[0] * c[2] * e[1]);
+       printf("r2: %lf\n", a[1] * c[2] * e[0] - a[1] * c[0] * e[2]);
+       printf("r3: %lf\n", a[2] * c[0] * e[1] - a[2] * c[1] * e[0]);
+       printf("x1 x: %f, y: %f, z: %f\n", a[0], a[1], a[2]);
+       printf("x2 x: %f, y: %f, z: %f\n", c[0], c[1], c[2]);
+       printf("x3 x: %f, y: %f, z: %f\n", e[0], e[1], e[2]);
+       printf("v1 x: %f, y: %f, z: %f\n", b[0], b[1], b[2]);
+       printf("v2 x: %f, y: %f, z: %f\n", d[0], d[1], d[2]);
+       printf("v3 x: %f, y: %f, z: %f\n", f[0], f[1], f[2]);
+       printf("t^3: %lf, t^2: %lf, t^1: %lf, t^0: %lf\n", j, i, h, g);
+       
+ */
+       // Solve cubic equation to determine times t1, t2, t3, when the collision will occur.
+       if ( ABS ( j ) > DBL_EPSILON )
+       {
+               i /= j;
+               h /= j;
+               g /= j;
+               num_sols = gsl_poly_solve_cubic ( i, h, g, &solution[0], &solution[1], &solution[2] );
+       }
+       else
+       {
+               num_sols = gsl_poly_solve_quadratic ( i, h, g, &solution[0], &solution[1] );
+               solution[2] = -1.0;
+       }
+       // printf("num_sols: %d, sol1: %lf, sol2: %lf, sol3: %lf\n", num_sols, solution[0],  solution[1],  solution[2]);
+       // Discard negative solutions
+       if ( ( num_sols >= 1 ) && ( solution[0] < DBL_EPSILON ) )
+       {
+               --num_sols;
+               solution[0] = solution[num_sols];
+       }
+       if ( ( num_sols >= 2 ) && ( solution[1] < DBL_EPSILON ) )
+       {
+               --num_sols;
+               solution[1] = solution[num_sols];
+       }
+       if ( ( num_sols == 3 ) && ( solution[2] < DBL_EPSILON ) )
+       {
+               --num_sols;
+       }
+       // Sort
+       if ( num_sols == 2 )
+       {
+               if ( solution[0] > solution[1] )
+               {
+                       double tmp = solution[0];
+                       solution[0] = solution[1];
+                       solution[1] = tmp;
+               }
+       }
+       else if ( num_sols == 3 )
+       {
+               // Bubblesort
+               if ( solution[0] > solution[1] )
+               {
+                       double tmp = solution[0]; solution[0] = solution[1]; solution[1] = tmp;
+               }
+               if ( solution[1] > solution[2] )
+               {
+                       double tmp = solution[1]; solution[1] = solution[2]; solution[2] = tmp;
+               }
+               if ( solution[0] > solution[1] )
+               {
+                       double tmp = solution[0]; solution[0] = solution[1]; solution[1] = tmp;
+               }
+       }
+       return num_sols;
+ }
+ // w3 is not perfect
+ void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3 )
+ {
+       double  tempV1[3], tempV2[3], tempV4[3];
+       double  a,b,c,d,e,f;
+       VECSUB ( tempV1, p1, p3 );
+       VECSUB ( tempV2, p2, p3 );
+       VECSUB ( tempV4, pv, p3 );
+       a = INPR ( tempV1, tempV1 );
+       b = INPR ( tempV1, tempV2 );
+       c = INPR ( tempV2, tempV2 );
+       e = INPR ( tempV1, tempV4 );
+       f = INPR ( tempV2, tempV4 );
+       d = ( a * c - b * b );
+       if ( ABS ( d ) < ALMOST_ZERO )
+       {
+               *w1 = *w2 = *w3 = 1.0 / 3.0;
+               return;
+       }
+       w1[0] = ( float ) ( ( e * c - b * f ) / d );
+       if ( w1[0] < 0 )
+               w1[0] = 0;
+       w2[0] = ( float ) ( ( f - b * ( double ) w1[0] ) / c );
+       if ( w2[0] < 0 )
+               w2[0] = 0;
+       w3[0] = 1.0f - w1[0] - w2[0];
+ }
+ DO_INLINE void collision_interpolateOnTriangle ( float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3 )
+ {
+       to[0] = to[1] = to[2] = 0;
+       VECADDMUL ( to, v1, w1 );
+       VECADDMUL ( to, v2, w2 );
+       VECADDMUL ( to, v3, w3 );
+ }
+ int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end )
+ {
+       int result = 0;
+       Cloth *cloth1;
+       float w1, w2, w3, u1, u2, u3;
+       float v1[3], v2[3], relativeVelocity[3];
+       float magrelVel;
+       float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree );
+       cloth1 = clmd->clothObject;
+       for ( ; collpair != collision_end; collpair++ )
+       {
+               // only handle static collisions here
+               if ( collpair->flag & COLLISION_IN_FUTURE )
+                       continue;
+               // compute barycentric coordinates for both collision points
+               collision_compute_barycentric ( collpair->pa,
+                       cloth1->verts[collpair->ap1].txold,
+                       cloth1->verts[collpair->ap2].txold,
+                       cloth1->verts[collpair->ap3].txold,
+                       &w1, &w2, &w3 );
+               // was: txold
+               collision_compute_barycentric ( collpair->pb,
+                       collmd->current_x[collpair->bp1].co,
+                       collmd->current_x[collpair->bp2].co,
+                       collmd->current_x[collpair->bp3].co,
+                       &u1, &u2, &u3 );
+               // Calculate relative "velocity".
+               collision_interpolateOnTriangle ( v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3 );
+               collision_interpolateOnTriangle ( v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3 );
+               VECSUB ( relativeVelocity, v2, v1 );
+               // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal').
+               magrelVel = INPR ( relativeVelocity, collpair->normal );
+               // printf("magrelVel: %f\n", magrelVel);
+               // Calculate masses of points.
+               // TODO
+               // If v_n_mag < 0 the edges are approaching each other.
+               if ( magrelVel > ALMOST_ZERO )
+               {
+                       // Calculate Impulse magnitude to stop all motion in normal direction.
+                       float magtangent = 0, repulse = 0, d = 0;
+                       double impulse = 0.0;
+                       float vrel_t_pre[3];
+                       float temp[3];
+                       // calculate tangential velocity
+                       VECCOPY ( temp, collpair->normal );
+                       VecMulf ( temp, magrelVel );
+                       VECSUB ( vrel_t_pre, relativeVelocity, temp );
+                       // Decrease in magnitude of relative tangential velocity due to coulomb friction
+                       // in original formula "magrelVel" should be the "change of relative velocity in normal direction"
+                       magtangent = MIN2 ( clmd->coll_parms->friction * 0.01 * magrelVel,sqrt ( INPR ( vrel_t_pre,vrel_t_pre ) ) );
+                       // Apply friction impulse.
+                       if ( magtangent > ALMOST_ZERO )
+                       {
+                               Normalize ( vrel_t_pre );
+                               impulse = magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); // 2.0 * 
+                               VECADDMUL ( cloth1->verts[collpair->ap1].impulse, vrel_t_pre, w1 * impulse );
+                               VECADDMUL ( cloth1->verts[collpair->ap2].impulse, vrel_t_pre, w2 * impulse );
+                               VECADDMUL ( cloth1->verts[collpair->ap3].impulse, vrel_t_pre, w3 * impulse );
+                       }
+                       // Apply velocity stopping impulse
+                       // I_c = m * v_N / 2.0
+                       // no 2.0 * magrelVel normally, but looks nicer DG
+                       impulse =  magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3 );
+                       VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse );
+                       cloth1->verts[collpair->ap1].impulse_count++;
+                       VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse );
+                       cloth1->verts[collpair->ap2].impulse_count++;
+                       VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse );
+                       cloth1->verts[collpair->ap3].impulse_count++;
+                       // Apply repulse impulse if distance too short
+                       // I_r = -min(dt*kd, m(0,1d/dt - v_n))
+                       d = clmd->coll_parms->epsilon*8.0/9.0 + epsilon2*8.0/9.0 - collpair->distance;
+                       if ( ( magrelVel < 0.1*d*clmd->sim_parms->stepsPerFrame ) && ( d > ALMOST_ZERO ) )
+                       {
+                               repulse = MIN2 ( d*1.0/clmd->sim_parms->stepsPerFrame, 0.1*d*clmd->sim_parms->stepsPerFrame - magrelVel );
+                               // stay on the safe side and clamp repulse
+                               if ( impulse > ALMOST_ZERO )
+                                       repulse = MIN2 ( repulse, 5.0*impulse );
+                               repulse = MAX2 ( impulse, repulse );
+                               impulse = repulse / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); // original 2.0 / 0.25
+                               VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal,  impulse );
+                               VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal,  impulse );
+                               VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal,  impulse );
+                       }
+                       result = 1;
+               }
+       }
+       return result;
+ }
+ //Determines collisions on overlap, collisions are writen to collpair[i] and collision+number_collision_found is returned
+ CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap *overlap, CollPair *collpair )
+ {
+       ClothModifierData *clmd = ( ClothModifierData * ) md1;
+       CollisionModifierData *collmd = ( CollisionModifierData * ) md2;
+       MFace *face1=NULL, *face2 = NULL;
+       ClothVertex *verts1 = clmd->clothObject->verts;
+       double distance = 0;
+       float epsilon1 = clmd->coll_parms->epsilon;
+       float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree );
+       int i;
+       face1 = & ( clmd->clothObject->mfaces[overlap->indexA] );
+       face2 = & ( collmd->mfaces[overlap->indexB] );
+       // check all 4 possible collisions
+       for ( i = 0; i < 4; i++ )
+       {
+               if ( i == 0 )
+               {
+                       // fill faceA
+                       collpair->ap1 = face1->v1;
+                       collpair->ap2 = face1->v2;
+                       collpair->ap3 = face1->v3;
+                       // fill faceB
+                       collpair->bp1 = face2->v1;
+                       collpair->bp2 = face2->v2;
+                       collpair->bp3 = face2->v3;
+               }
+               else if ( i == 1 )
+               {
+                       if ( face1->v4 )
+                       {
+                               // fill faceA
+                               collpair->ap1 = face1->v1;
+                               collpair->ap2 = face1->v4;
+                               collpair->ap3 = face1->v3;
+                               // fill faceB
+                               collpair->bp1 = face2->v1;
+                               collpair->bp2 = face2->v2;
+                               collpair->bp3 = face2->v3;
+                       }
+                       else
+                               i++;
+               }
+               if ( i == 2 )
+               {
+                       if ( face2->v4 )
+                       {
+                               // fill faceA
+                               collpair->ap1 = face1->v1;
+                               collpair->ap2 = face1->v2;
+                               collpair->ap3 = face1->v3;
+                               // fill faceB
+                               collpair->bp1 = face2->v1;
+                               collpair->bp2 = face2->v4;
+                               collpair->bp3 = face2->v3;
+                       }
+                       else
+                               break;
+               }
+               else if ( i == 3 )
+               {
+                       if ( face1->v4 && face2->v4 )
+                       {
+                               // fill faceA
+                               collpair->ap1 = face1->v1;
+                               collpair->ap2 = face1->v4;
+                               collpair->ap3 = face1->v3;
+                               // fill faceB
+                               collpair->bp1 = face2->v1;
+                               collpair->bp2 = face2->v4;
+                               collpair->bp3 = face2->v3;
+                       }
+                       else
+                               break;
+               }
+ #ifdef WITH_BULLET
+               // calc distance + normal
+               distance = plNearestPoints (
+                       verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector );
+ #else
+               // just be sure that we don't add anything
+               distance = 2.0 * ( epsilon1 + epsilon2 + ALMOST_ZERO );
+ #endif
+               if ( distance <= ( epsilon1 + epsilon2 + ALMOST_ZERO ) )
+               {
+                       VECCOPY ( collpair->normal, collpair->vector );
+                       Normalize ( collpair->normal );
+                       collpair->distance = distance;
+                       collpair->flag = 0;
+                       collpair++;
+               }/*
+               else
+               {
+                       float w1, w2, w3, u1, u2, u3;
+                       float v1[3], v2[3], relativeVelocity[3];
+                       // calc relative velocity
+                       
+                       // compute barycentric coordinates for both collision points
+                       collision_compute_barycentric ( collpair->pa,
+                       verts1[collpair->ap1].txold,
+                       verts1[collpair->ap2].txold,
+                       verts1[collpair->ap3].txold,
+                       &w1, &w2, &w3 );
+                       // was: txold
+                       collision_compute_barycentric ( collpair->pb,
+                       collmd->current_x[collpair->bp1].co,
+                       collmd->current_x[collpair->bp2].co,
+                       collmd->current_x[collpair->bp3].co,
+                       &u1, &u2, &u3 );
+                       // Calculate relative "velocity".
+                       collision_interpolateOnTriangle ( v1, verts1[collpair->ap1].tv, verts1[collpair->ap2].tv, verts1[collpair->ap3].tv, w1, w2, w3 );
+                       collision_interpolateOnTriangle ( v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3 );
+                       VECSUB ( relativeVelocity, v2, v1 );
+                       if(sqrt(INPR(relativeVelocity, relativeVelocity)) >= distance)
+                       {
+                               // check for collision in the future
+                               collpair->flag |= COLLISION_IN_FUTURE;
+                               collpair++;
+                       }
+               }*/
+       }
+       return collpair;
+ }
+ int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end )
+ {
+       int result = 0;
+       Cloth *cloth1;
+       float w1, w2, w3, u1, u2, u3;
+       float v1[3], v2[3], relativeVelocity[3];
+       float magrelVel;
+       cloth1 = clmd->clothObject;
+       for ( ; collpair != collision_end; collpair++ )
+       {
+               // compute barycentric coordinates for both collision points
+               collision_compute_barycentric ( collpair->pa,
+                       cloth1->verts[collpair->ap1].txold,
+                       cloth1->verts[collpair->ap2].txold,
+                       cloth1->verts[collpair->ap3].txold,
+                       &w1, &w2, &w3 );
+               // was: txold
+               collision_compute_barycentric ( collpair->pb,
+                       collmd->current_x[collpair->bp1].co,
+                       collmd->current_x[collpair->bp2].co,
+                       collmd->current_x[collpair->bp3].co,
+                       &u1, &u2, &u3 );
+               // Calculate relative "velocity".
+               collision_interpolateOnTriangle ( v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3 );
+               collision_interpolateOnTriangle ( v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3 );
+               VECSUB ( relativeVelocity, v2, v1 );
+               // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal').
+               magrelVel = INPR ( relativeVelocity, collpair->normal );
+               // printf("magrelVel: %f\n", magrelVel);
+               // Calculate masses of points.
+               // TODO
+               // If v_n_mag < 0 the edges are approaching each other.
+               if ( magrelVel > ALMOST_ZERO )
+               {
+                       // Calculate Impulse magnitude to stop all motion in normal direction.
+                       float magtangent = 0;
+                       double impulse = 0.0;
+                       float vrel_t_pre[3];
+                       float temp[3];
+                       // calculate tangential velocity
+                       VECCOPY ( temp, collpair->normal );
+                       VecMulf ( temp, magrelVel );
+                       VECSUB ( vrel_t_pre, relativeVelocity, temp );
+                       // Decrease in magnitude of relative tangential velocity due to coulomb friction
+                       // in original formula "magrelVel" should be the "change of relative velocity in normal direction"
+                       magtangent = MIN2 ( clmd->coll_parms->friction * 0.01 * magrelVel,sqrt ( INPR ( vrel_t_pre,vrel_t_pre ) ) );
+                       // Apply friction impulse.
+                       if ( magtangent > ALMOST_ZERO )
+                       {
+                               Normalize ( vrel_t_pre );
+                               impulse = 2.0 * magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3 );
+                               VECADDMUL ( cloth1->verts[collpair->ap1].impulse, vrel_t_pre, w1 * impulse );
+                               VECADDMUL ( cloth1->verts[collpair->ap2].impulse, vrel_t_pre, w2 * impulse );
+                               VECADDMUL ( cloth1->verts[collpair->ap3].impulse, vrel_t_pre, w3 * impulse );
+                       }
+                       // Apply velocity stopping impulse
+                       // I_c = m * v_N / 2.0
+                       // no 2.0 * magrelVel normally, but looks nicer DG
+                       impulse =  magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3 );
+                       VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse );
+                       cloth1->verts[collpair->ap1].impulse_count++;
+                       VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse );
+                       cloth1->verts[collpair->ap2].impulse_count++;
+                       VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse );
+                       cloth1->verts[collpair->ap3].impulse_count++;
+                       // Apply repulse impulse if distance too short
+                       // I_r = -min(dt*kd, m(0,1d/dt - v_n))
+                       /*
+                       d = clmd->coll_parms->epsilon*8.0/9.0 + epsilon2*8.0/9.0 - collpair->distance;
+                       if ( ( magrelVel < 0.1*d*clmd->sim_parms->stepsPerFrame ) && ( d > ALMOST_ZERO ) )
+                       {
+                       repulse = MIN2 ( d*1.0/clmd->sim_parms->stepsPerFrame, 0.1*d*clmd->sim_parms->stepsPerFrame - magrelVel );
+                       // stay on the safe side and clamp repulse
+                       if ( impulse > ALMOST_ZERO )
+                       repulse = MIN2 ( repulse, 5.0*impulse );
+                       repulse = MAX2 ( impulse, repulse );
+                       impulse = repulse / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); // original 2.0 / 0.25
+                       VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal,  impulse );
+                       VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal,  impulse );
+                       VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal,  impulse );
+                       }
+                       */
+                       result = 1;
+               }
+       }
+       return result;
+ }
+ static float projectPointOntoLine(float *p, float *a, float *b) 
+ {
+    float ba[3], pa[3];
+    VECSUB(ba, b, a);
+    VECSUB(pa, p, a);
+    return INPR(pa, ba) / INPR(ba, ba);
+ }
+ static void calculateEENormal(float *np1, float *np2, float *np3, float *np4,float *out_normal) 
+ {
+       float line1[3], line2[3];
+       float length;
+       VECSUB(line1, np2, np1);
+       VECSUB(line2, np3, np1);
+       // printf("l1: %f, l1: %f, l2: %f, l2: %f\n", line1[0], line1[1], line2[0], line2[1]);
+       Crossf(out_normal, line1, line2);
+       
+       length = Normalize(out_normal);
+       if (length <= FLT_EPSILON)
+       { // lines are collinear
+               VECSUB(out_normal, np2, np1);
+               Normalize(out_normal);
+       }
+ }
+ static void findClosestPointsEE(float *x1, float *x2, float *x3, float *x4, float *w1, float *w2)
+ {
+       float temp[3], temp2[3];
+       
+       double a, b, c, e, f; 
+       VECSUB(temp, x2, x1);
+       a = INPR(temp, temp);
+       VECSUB(temp2, x4, x3);
+       b = -INPR(temp, temp2);
+       c = INPR(temp2, temp2);
+       VECSUB(temp2, x3, x1);
+       e = INPR(temp, temp2);
+       VECSUB(temp, x4, x3);
+       f = -INPR(temp, temp2);
+       *w1 = (e * c - b * f) / (a * c - b * b);
+       *w2 = (f - b * *w1) / c;
+ }
+ // calculates the distance of 2 edges
+ float edgedge_distance(float np11[3], float np12[3], float np21[3], float np22[3], float *out_a1, float *out_a2, float *out_normal)
+ {
+       float line1[3], line2[3], cross[3];
+       float length;
+       float temp[3], temp2[3];
+       float dist_a1, dist_a2;
+       
+       VECSUB(line1, np12, np11);
+       VECSUB(line2, np22, np21);
+       Crossf(cross, line1, line2);
+       length = INPR(cross, cross);
+       if (length < FLT_EPSILON) 
+       {
+               *out_a2 = projectPointOntoLine(np11, np21, np22);
+               if ((*out_a2 >= -FLT_EPSILON) && (*out_a2 <= 1.0 + FLT_EPSILON)) 
+               {
+                       *out_a1 = 0;
+                       calculateEENormal(np11, np12, np21, np22, out_normal);
+                       VECSUB(temp, np22, np21);
+                       VecMulf(temp, *out_a2);
+                       VECADD(temp2, temp, np21);
+                       VECADD(temp2, temp2, np11);
+                       return INPR(temp2, temp2);
+               }
+               CLAMP(*out_a2, 0.0, 1.0);
+               if (*out_a2 > .5) 
+               { // == 1.0
+                       *out_a1 = projectPointOntoLine(np22, np11, np12);
+                       if ((*out_a1 >= -FLT_EPSILON) && (*out_a1 <= 1.0 + FLT_EPSILON)) 
+                       {
+                               calculateEENormal(np11, np12, np21, np22, out_normal);
+                               // return (np22 - (np11 + (np12 - np11) * out_a1)).lengthSquared();
+                               VECSUB(temp, np12, np11);
+                               VecMulf(temp, *out_a1);
+                               VECADD(temp2, temp, np11);
+                               VECSUB(temp2, np22, temp2);
+                               return INPR(temp2, temp2);
+                       }
+               } 
+               else 
+               { // == 0.0
+                       *out_a1 = projectPointOntoLine(np21, np11, np12);
+                       if ((*out_a1 >= -FLT_EPSILON) && (*out_a1 <= 1.0 + FLT_EPSILON)) 
+                       {
+                               calculateEENormal(np11, np11, np21, np22, out_normal);
+                               // return (np21 - (np11 + (np12 - np11) * out_a1)).lengthSquared();
+                               VECSUB(temp, np12, np11);
+                               VecMulf(temp, *out_a1);
+                               VECADD(temp2, temp, np11);
+                               VECSUB(temp2, np21, temp2);
+                               return INPR(temp2, temp2);
+                       }
+               }
+               CLAMP(*out_a1, 0.0, 1.0);
+               calculateEENormal(np11, np12, np21, np22, out_normal);
+               if(*out_a1 > .5)
+               {
+                       if(*out_a2 > .5)
+                       {
+                               VECSUB(temp, np12, np22);
+                       }
+                       else
+                       {
+                               VECSUB(temp, np12, np21);
+                       }
+               }
+               else
+               {
+                       if(*out_a2 > .5)
+                       {
+                               VECSUB(temp, np11, np22);
+                       }
+                       else
+                       {
+                               VECSUB(temp, np11, np21);
+                       }
+               }
+               return INPR(temp, temp);
+       }
+       else
+       {
+               
+               // If the lines aren't parallel (but coplanar) they have to intersect
+               findClosestPointsEE(np11, np12, np21, np22, out_a1, out_a2);
+               // If both points are on the finite edges, we're done.
+               if (*out_a1 >= 0.0 && *out_a1 <= 1.0 && *out_a2 >= 0.0 && *out_a2 <= 1.0) 
+               {
+                       float p1[3], p2[3];
+                       
+                       // p1= np11 + (np12 - np11) * out_a1;
+                       VECSUB(temp, np12, np11);
+                       VecMulf(temp, *out_a1);
+                       VECADD(p1, np11, temp);
+                       
+                       // p2 = np21 + (np22 - np21) * out_a2;
+                       VECSUB(temp, np22, np21);
+                       VecMulf(temp, *out_a2);
+                       VECADD(p2, np21, temp);
+                       calculateEENormal(np11, np12, np21, np22, out_normal);
+                       VECSUB(temp, p1, p2);
+                       return INPR(temp, temp);
+               }
+               
+               /*
+               * Clamp both points to the finite edges.
+               * The one that moves most during clamping is one part of the solution.
+               */
+               dist_a1 = *out_a1;
+               CLAMP(dist_a1, 0.0, 1.0);
+               dist_a2 = *out_a2;
+               CLAMP(dist_a2, 0.0, 1.0);
+               // Now project the "most clamped" point on the other line.
+               if (dist_a1 > dist_a2) 
+               { 
+                       /* keep out_a1 */
+                       float p1[3];
+                       // p1 = np11 + (np12 - np11) * out_a1;
+                       VECSUB(temp, np12, np11);
+                       VecMulf(temp, *out_a1);
+                       VECADD(p1, np11, temp);
+                       *out_a2 = projectPointOntoLine(p1, np21, np22);
+                       CLAMP(*out_a2, 0.0, 1.0);
+                       calculateEENormal(np11, np12, np21, np22, out_normal);
+                       // return (p1 - (np21 + (np22 - np21) * out_a2)).lengthSquared();
+                       VECSUB(temp, np22, np21);
+                       VecMulf(temp, *out_a2);
+                       VECADD(temp, temp, np21);
+                       VECSUB(temp, p1, temp);
+                       return INPR(temp, temp);
+               } 
+               else 
+               {       
+                       /* keep out_a2 */
+                       float p2[3];
+                       
+                       // p2 = np21 + (np22 - np21) * out_a2;
+                       VECSUB(temp, np22, np21);
+                       VecMulf(temp, *out_a2);
+                       VECADD(p2, np21, temp);
+                       *out_a1 = projectPointOntoLine(p2, np11, np12);
+                       CLAMP(*out_a1, 0.0, 1.0);
+                       calculateEENormal(np11, np12, np21, np22, out_normal);
+                       
+                       // return ((np11 + (np12 - np11) * out_a1) - p2).lengthSquared();
+                       VECSUB(temp, np12, np11);
+                       VecMulf(temp, *out_a1);
+                       VECADD(temp, temp, np11);
+                       VECSUB(temp, temp, p2);
+                       return INPR(temp, temp);
+               }
+       }
+       
+       printf("Error in edgedge_distance: end of function\n");
+       return 0;
+ }
+ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair )
+ {
+       EdgeCollPair edgecollpair;
+       Cloth *cloth1=NULL;
+       ClothVertex *verts1=NULL;
+       unsigned int i = 0, k = 0;
+       int numsolutions = 0;
+       double x1[3], v1[3], x2[3], v2[3], x3[3], v3[3];
+       double solution[3], solution2[3];
+       MVert *verts2 = collmd->current_x; // old x
+       MVert *velocity2 = collmd->current_v; // velocity
+       float distance = 0;
+       float triA[3][3], triB[3][3];
+       int result = 0;
+       cloth1 = clmd->clothObject;
+       verts1 = cloth1->verts;
+       for(i = 0; i < 9; i++)
+       {
+               // 9 edge - edge possibilities
+               if(i == 0) // cloth edge: 1-2; coll edge: 1-2
+               {
+                       edgecollpair.p11 = collpair->ap1;
+                       edgecollpair.p12 = collpair->ap2;
+                       edgecollpair.p21 = collpair->bp1;
+                       edgecollpair.p22 = collpair->bp2;
+               }
+               else if(i == 1) // cloth edge: 1-2; coll edge: 2-3
+               {
+                       edgecollpair.p11 = collpair->ap1;
+                       edgecollpair.p12 = collpair->ap2;
+                       edgecollpair.p21 = collpair->bp2;
+                       edgecollpair.p22 = collpair->bp3;
+               }
+               else if(i == 2) // cloth edge: 1-2; coll edge: 1-3
+               {
+                       edgecollpair.p11 = collpair->ap1;
+                       edgecollpair.p12 = collpair->ap2;
+                       edgecollpair.p21 = collpair->bp1;
+                       edgecollpair.p22 = collpair->bp3;
+               }
+               else if(i == 3) // cloth edge: 2-3; coll edge: 1-2
+               {
+                       edgecollpair.p11 = collpair->ap2;
+                       edgecollpair.p12 = collpair->ap3;
+                       edgecollpair.p21 = collpair->bp1;
+                       edgecollpair.p22 = collpair->bp2;
+               }
+               else if(i == 4) // cloth edge: 2-3; coll edge: 2-3
+               {
+                       edgecollpair.p11 = collpair->ap2;
+                       edgecollpair.p12 = collpair->ap3;
+                       edgecollpair.p21 = collpair->bp2;
+                       edgecollpair.p22 = collpair->bp3;
+               }
+               else if(i == 5) // cloth edge: 2-3; coll edge: 1-3
+               {
+                       edgecollpair.p11 = collpair->ap2;
+                       edgecollpair.p12 = collpair->ap3;
+                       edgecollpair.p21 = collpair->bp1;
+                       edgecollpair.p22 = collpair->bp3;
+               }
+               else if(i ==6) // cloth edge: 1-3; coll edge: 1-2
+               {
+                       edgecollpair.p11 = collpair->ap1;
+                       edgecollpair.p12 = collpair->ap3;
+                       edgecollpair.p21 = collpair->bp1;
+                       edgecollpair.p22 = collpair->bp2;
+               }
+               else if(i ==7) // cloth edge: 1-3; coll edge: 2-3
+               {
+                       edgecollpair.p11 = collpair->ap1;
+                       edgecollpair.p12 = collpair->ap3;
+                       edgecollpair.p21 = collpair->bp2;
+                       edgecollpair.p22 = collpair->bp3;
+               }
+               else if(i == 8) // cloth edge: 1-3; coll edge: 1-3
+               {
+                       edgecollpair.p11 = collpair->ap1;
+                       edgecollpair.p12 = collpair->ap3;
+                       edgecollpair.p21 = collpair->bp1;
+                       edgecollpair.p22 = collpair->bp3;
+               }
+               /*
+               if((edgecollpair.p11 == 3) && (edgecollpair.p12 == 16))
+                       printf("Ahier!\n");
+               if((edgecollpair.p11 == 16) && (edgecollpair.p12 == 3))
+                       printf("Ahier!\n");
+               */
+               // if ( !cloth_are_edges_adjacent ( clmd, collmd, &edgecollpair ) )
+               {
+                       // always put coll points in p21/p22
+                       VECSUB ( x1, verts1[edgecollpair.p12].txold, verts1[edgecollpair.p11].txold );
+                       VECSUB ( v1, verts1[edgecollpair.p12].tv, verts1[edgecollpair.p11].tv );
+                       VECSUB ( x2, verts2[edgecollpair.p21].co, verts1[edgecollpair.p11].txold );
+                       VECSUB ( v2, velocity2[edgecollpair.p21].co, verts1[edgecollpair.p11].tv );
+                       VECSUB ( x3, verts2[edgecollpair.p22].co, verts1[edgecollpair.p11].txold );
+                       VECSUB ( v3, velocity2[edgecollpair.p22].co, verts1[edgecollpair.p11].tv );
+                       numsolutions = cloth_get_collision_time ( x1, v1, x2, v2, x3, v3, solution );
+                       if((edgecollpair.p11 == 3 && edgecollpair.p12==16)|| (edgecollpair.p11==16 && edgecollpair.p12==3))
+                       {
+                               if(edgecollpair.p21==6 || edgecollpair.p22 == 6)
+                               {
+                                       printf("dist: %f, sol[k]: %lf, sol2[k]: %lf\n", distance, solution[k], solution2[k]);
+                                       printf("a1: %f, a2: %f, b1: %f, b2: %f\n", x1[0], x2[0], x3[0], v1[0]);
+                                       printf("b21: %d, b22: %d\n", edgecollpair.p21, edgecollpair.p22);
+                               }
+                       }
+                       for ( k = 0; k < numsolutions; k++ )
+                       {
+                               // printf("sol %d: %lf\n", k, solution[k]);
+                               if ( ( solution[k] >= ALMOST_ZERO ) && ( solution[k] <= 1.0 ) && ( solution[k] >  ALMOST_ZERO))
+                               {
+                                       float a,b;
+                                       float out_normal[3];
+                                       float distance;
+                                       float impulse = 0;
+                                       float I_mag;
+                                       // move verts
+                                       VECADDS(triA[0], verts1[edgecollpair.p11].txold, verts1[edgecollpair.p11].tv, solution[k]);
+                                       VECADDS(triA[1], verts1[edgecollpair.p12].txold, verts1[edgecollpair.p12].tv, solution[k]);
+                                       VECADDS(triB[0], collmd->current_x[edgecollpair.p21].co, collmd->current_v[edgecollpair.p21].co, solution[k]);
+                                       VECADDS(triB[1], collmd->current_x[edgecollpair.p22].co, collmd->current_v[edgecollpair.p22].co, solution[k]);
+                                       // TODO: check for collisions
+                                       distance = edgedge_distance(triA[0], triA[1], triB[0], triB[1], &a, &b, out_normal);
+                                       
+                                       if ((distance <= clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree ) + ALMOST_ZERO) && (INPR(out_normal, out_normal) > 0))
+                                       {
+                                               float vrel_1_to_2[3], temp[3], temp2[3], out_normalVelocity;
+                                               float desiredVn;
+                                               VECCOPY(vrel_1_to_2, verts1[edgecollpair.p11].tv);
+                                               VecMulf(vrel_1_to_2, 1.0 - a);
+                                               VECCOPY(temp, verts1[edgecollpair.p12].tv);
+                                               VecMulf(temp, a);
+                                               VECADD(vrel_1_to_2, vrel_1_to_2, temp);
+                                               VECCOPY(temp, verts1[edgecollpair.p21].tv);
+                                               VecMulf(temp, 1.0 - b);
+                                               VECCOPY(temp2, verts1[edgecollpair.p22].tv);
+                                               VecMulf(temp2, b);
+                                               VECADD(temp, temp, temp2);
+                                               VECSUB(vrel_1_to_2, vrel_1_to_2, temp);
+                                               out_normalVelocity = INPR(vrel_1_to_2, out_normal);
+ /*
+                                               // this correction results in wrong normals sometimes?
+                                               if(out_normalVelocity < 0.0)
+                                               {
+                                                       out_normalVelocity*= -1.0;
+                                                       VecMulf(out_normal, -1.0);
+                                               }
+ */
+                                               /* Inelastic repulsion impulse. */
+                                               // Calculate which normal velocity we need. 
+                                               desiredVn = (out_normalVelocity * (float)solution[k] - (.1 * (clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree )) - sqrt(distance)) - ALMOST_ZERO);
+                                               // Now calculate what impulse we need to reach that velocity. 
+                                               I_mag = (out_normalVelocity - desiredVn) / 2.0; // / (1/m1 + 1/m2);
+                                               // Finally apply that impulse. 
+                                               impulse = (2.0 * -I_mag) / (a*a + (1.0-a)*(1.0-a) + b*b + (1.0-b)*(1.0-b));
+                                               VECADDMUL ( verts1[edgecollpair.p11].impulse, out_normal, (1.0-a) * impulse );
+                                               verts1[edgecollpair.p11].impulse_count++;
+                                               VECADDMUL ( verts1[edgecollpair.p12].impulse, out_normal, a * impulse );
+                                               verts1[edgecollpair.p12].impulse_count++;
+                                               // return true;
+                                               result = 1;
+                                               break;
+                                       }
+                                       else
+                                       {
+                                               // missing from collision.hpp
+                                       }
+                                       // mintime = MIN2(mintime, (float)solution[k]);
+                                       break;
+                               }
+                       }
+               }
+       }
+       return result;
+ }
+ int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end )
+ {
+       Cloth *cloth1;
+       cloth1 = clmd->clothObject;
+       for ( ; collpair != collision_end; collpair++ )
+       {
+               // only handle moving collisions here
+               if (!( collpair->flag & COLLISION_IN_FUTURE ))
+                       continue;
+               cloth_collision_moving_edges ( clmd, collmd, collpair);
+               // cloth_collision_moving_tris ( clmd, collmd, collpair);
+       }
+       return 1;
+ }
+ // return all collision objects in scene
+ // collision object will exclude self 
+ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj)
+ {
+       Base *base=NULL;
+       CollisionModifierData **objs = NULL;
+       Object *coll_ob = NULL;
+       CollisionModifierData *collmd = NULL;
+       int numobj = 0, maxobj = 100;
+       
+       objs = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray");
+       // check all collision objects
+       for ( base = G.scene->base.first; base; base = base->next )
+       {
+               /*Only proceed for mesh object in same layer */
+               if(!(base->object->type==OB_MESH && (base->lay & self->lay))) 
+                       continue;
+               
+               coll_ob = base->object;
+               
+               if(coll_ob == self)
+                               continue;
+               
+               if(coll_ob->pd && coll_ob->pd->deflect)
+               {
+                       collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
+               }
+               else
+                       collmd = NULL;
+               
+               if ( collmd )
+               {       
+                       if(numobj >= maxobj)
+                       {
+                               // realloc
+                               int oldmax = maxobj;
+                               CollisionModifierData **tmp;
+                               maxobj *= 2;
+                               tmp = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray");
+                               memcpy(tmp, objs, sizeof(CollisionModifierData *)*oldmax);
+                               MEM_freeN(objs);
+                               objs = tmp;
+                               
+                       }
+                       
+                       objs[numobj] = collmd;
+                       numobj++;
+               }
+               else
+               {
+                       if ( coll_ob->dup_group )
+                       {
+                               GroupObject *go;
+                               Group *group = coll_ob->dup_group;
+                               for ( go= group->gobject.first; go; go= go->next )
+                               {
+                                       coll_ob = go->ob;
+                                       collmd = NULL;
+                                       
+                                       if(coll_ob == self)
+                                               continue;
+                                       
+                                       if(coll_ob->pd && coll_ob->pd->deflect)
+                                       {
+                                               collmd = ( CollisionModifierData * ) modifiers_findByType ( coll_ob, eModifierType_Collision );
+                                       }
+                                       else
+                                               collmd = NULL;
+                                       if ( !collmd )
+                                               continue;
+                                       
+                                       if( !collmd->bvhtree)
+                                               continue;
+                                       if(numobj >= maxobj)
+                                       {
+                                               // realloc
+                                               int oldmax = maxobj;
+                                               CollisionModifierData **tmp;
+                                               maxobj *= 2;
+                                               tmp = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray");
+                                               memcpy(tmp, objs, sizeof(CollisionModifierData *)*oldmax);
+                                               MEM_freeN(objs);
+                                               objs = tmp;
+                                       }
+                                       
+                                       objs[numobj] = collmd;
+                                       numobj++;
+                               }
+                       }
+               }       
+       }
+       *numcollobj = numobj;
+       return objs;
+ }
+ void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair **collisions, CollPair **collisions_index, int numresult, BVHTreeOverlap *overlap)
+ {
+       int i;
+       
+       *collisions = ( CollPair* ) MEM_mallocN ( sizeof ( CollPair ) * numresult * 4, "collision array" ); //*4 since cloth_collision_static can return more than 1 collision
+       *collisions_index = *collisions;
+       for ( i = 0; i < numresult; i++ )
+       {
+               *collisions_index = cloth_collision ( ( ModifierData * ) clmd, ( ModifierData * ) collmd, overlap+i, *collisions_index );
+       }
+ }
+ int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, CollisionModifierData *collmd, CollPair *collisions, CollPair *collisions_index)
+ {
+       Cloth *cloth = clmd->clothObject;
+       int i=0, j = 0, numfaces = 0, numverts = 0;
+       ClothVertex *verts = NULL;
+       int ret = 0;
+       int result = 0;
+       float tnull[3] = {0,0,0};
+       
+       numfaces = clmd->clothObject->numfaces;
+       numverts = clmd->clothObject->numverts;
+  
+       verts = cloth->verts;
+       
+       // process all collisions (calculate impulses, TODO: also repulses if distance too short)
+       result = 1;
+       for ( j = 0; j < 5; j++ ) // 5 is just a value that ensures convergence
+       {
+               result = 0;
+               if ( collmd->bvhtree )
+               {
+                       result += cloth_collision_response_static ( clmd, collmd, collisions, collisions_index );
+                       // apply impulses in parallel
+                       if ( result )
+                       {
+                               for ( i = 0; i < numverts; i++ )
+                               {
+                                       // calculate "velocities" (just xnew = xold + v; no dt in v)
+                                       if ( verts[i].impulse_count )
+                                       {
+                                               VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count );
+                                               VECCOPY ( verts[i].impulse, tnull );
+                                               verts[i].impulse_count = 0;
+                                               ret++;
+                                       }
+                               }
+                       }
+               }
+       }
+       return ret;
+ }
+ // cloth - object collisions
+ int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, float dt )
+ {
+       Cloth *cloth=NULL;
+       BVHTree *cloth_bvh=NULL;
+       int i=0, numfaces = 0, numverts = 0, k, l, j;
+       int rounds = 0; // result counts applied collisions; ic is for debug output;
+       ClothVertex *verts = NULL;
+       int ret = 0, ret2 = 0;
+       CollisionModifierData **collobjs = NULL;
+       int numcollobj = 0;
+       if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) || ! ( ( ( Cloth * ) clmd->clothObject )->bvhtree ) )
+       {
+               return 0;
+       }
+       cloth = clmd->clothObject;
+       verts = cloth->verts;
+       cloth_bvh = ( BVHTree * ) cloth->bvhtree;
+       numfaces = clmd->clothObject->numfaces;
+       numverts = clmd->clothObject->numverts;
+       ////////////////////////////////////////////////////////////
+       // static collisions
+       ////////////////////////////////////////////////////////////
+       // update cloth bvh
+       bvhtree_update_from_cloth ( clmd, 1 ); // 0 means STATIC, 1 means MOVING (see later in this function)
+       bvhselftree_update_from_cloth ( clmd, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function)
+       
+       collobjs = get_collisionobjects(ob, &numcollobj);
+       
+       if(!collobjs)
+               return 0;
+       do
+       {
+               CollPair **collisions, **collisions_index;
+               
+               ret2 = 0;
+               collisions = MEM_callocN(sizeof(CollPair *) *numcollobj , "CollPair");
+               collisions_index = MEM_callocN(sizeof(CollPair *) *numcollobj , "CollPair");
+               
+               // check all collision objects
+               for(i = 0; i < numcollobj; i++)
+               {
+                       CollisionModifierData *collmd = collobjs[i];
+                       BVHTreeOverlap *overlap = NULL;
+                       int result = 0;
+                       
+                       if(!collmd->bvhtree)
+                               continue;
+                       
+                       /* move object to position (step) in time */
+                       collision_move_object ( collmd, step + dt, step );
+                       
+                       /* search for overlapping collision pairs */
+                       overlap = BLI_bvhtree_overlap ( cloth_bvh, collmd->bvhtree, &result );
+                               
+                       // go to next object if no overlap is there
+                       if(!result || !overlap)
+                       {
+                               if ( overlap )
+                                       MEM_freeN ( overlap );
+                               continue;
+                       }
+                       
+                       /* check if collisions really happen (costly near check) */
+                       cloth_bvh_objcollisions_nearcheck ( clmd, collmd, &collisions[i], &collisions_index[i], result, overlap);
+                       
+                       // resolve nearby collisions
+                       ret += cloth_bvh_objcollisions_resolve ( clmd, collmd, collisions[i],  collisions_index[i]);
+                       ret2 += ret;
+                       
+                       if ( overlap )
+                               MEM_freeN ( overlap );
+               }
+               rounds++;
+               
+               for(i = 0; i < numcollobj; i++)
+               {
+                       if ( collisions[i] ) MEM_freeN ( collisions[i] );
+               }
+                       
+               MEM_freeN(collisions);
+               MEM_freeN(collisions_index);
+               ////////////////////////////////////////////////////////////
+               // update positions
+               // this is needed for bvh_calc_DOP_hull_moving() [kdop.c]
+               ////////////////////////////////////////////////////////////
+               // verts come from clmd
+               for ( i = 0; i < numverts; i++ )
+               {
+                       if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )
+                       {
+                               if ( verts [i].flags & CLOTH_VERT_FLAG_PINNED )
+                               {
+                                       continue;
+                               }
+                       }
+                       VECADD ( verts[i].tx, verts[i].txold, verts[i].tv );
+               }
+               ////////////////////////////////////////////////////////////
+               
+               
+               ////////////////////////////////////////////////////////////
+               // Test on *simple* selfcollisions
+               ////////////////////////////////////////////////////////////
+               if ( clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF )
+               {
+                       for(l = 0; l < clmd->coll_parms->self_loop_count; l++)
+                       {
+                               // TODO: add coll quality rounds again
+                               BVHTreeOverlap *overlap = NULL;
+                               int result = 0;
+       
+                               // collisions = 1;
+                               verts = cloth->verts; // needed for openMP
+       
+                               numfaces = clmd->clothObject->numfaces;
+                               numverts = clmd->clothObject->numverts;
+       
+                               verts = cloth->verts;
+       
+                               if ( cloth->bvhselftree )
+                               {
+                                       // search for overlapping collision pairs 
+                                       overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result );
+       
+       // #pragma omp parallel for private(k, i, j) schedule(static)
+                                       for ( k = 0; k < result; k++ )
+                                       {
+                                               float temp[3];
+                                               float length = 0;
+                                               float mindistance;
+       
+                                               i = overlap[k].indexA;
+                                               j = overlap[k].indexB;
+       
+                                               mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len );
+       
+                                               if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )
+                                               {
+                                                       if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED )
+                                                                               && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) )
+                                                       {
+                                                               continue;
+                                                       }
+                                               }
+       
+                                               VECSUB ( temp, verts[i].tx, verts[j].tx );
+       
+                                               if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue;
+       
+                                               // check for adjacent points (i must be smaller j)
+                                               if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) )
+                                               {
+                                                       continue;
+                                               }
+       
+                                               length = Normalize ( temp );
+       
+                                               if ( length < mindistance )
+                                               {
+                                                       float correction = mindistance - length;
+       
+                                                       if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED )
+                                                       {
+                                                               VecMulf ( temp, -correction );
+                                                               VECADD ( verts[j].tx, verts[j].tx, temp );
+                                                       }
+                                                       else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED )
+                                                       {
+                                                               VecMulf ( temp, correction );
+                                                               VECADD ( verts[i].tx, verts[i].tx, temp );
+                                                       }
+                                                       else
+                                                       {
+                                                               VecMulf ( temp, -correction*0.5 );
+                                                               VECADD ( verts[j].tx, verts[j].tx, temp );
+       
+                                                               VECSUB ( verts[i].tx, verts[i].tx, temp );
+                                                       }
+                                                       ret = 1;
+                                                       ret2 += ret;
+                                               }
+                                               else
+                                               {
+                                                       // check for approximated time collisions
+                                               }
+                                       }
+       
+                                       if ( overlap )
+                                               MEM_freeN ( overlap );
+       
+                               }
+                       }
+                       ////////////////////////////////////////////////////////////
+                       ////////////////////////////////////////////////////////////
+                       // SELFCOLLISIONS: update velocities
+                       ////////////////////////////////////////////////////////////
+                       if ( ret2 )
+                       {
+                               for ( i = 0; i < cloth->numverts; i++ )
+                               {
+                                       if ( ! ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) )
+                                       {
+                                               VECSUB ( verts[i].tv, verts[i].tx, verts[i].txold );
+                                       }
+                               }
+                       }
+                       ////////////////////////////////////////////////////////////
+               }
+       }
+       while ( ret2 && ( clmd->coll_parms->loop_count>rounds ) );
+       
+       if(collobjs)
+               MEM_freeN(collobjs);
+       return MIN2 ( ret, 1 );
+ }
   */
  
  #include <stdio.h> 
+ #include <stddef.h>
  #include <string.h>
  #include <math.h>
++#include <float.h>
  
  #include "MEM_guardedalloc.h"
 -#include "nla.h"
 +//XXX #include "nla.h"
  
  #include "BLI_blenlib.h"
  #include "BLI_arithb.h"
  #include "BKE_library.h"
  #include "BKE_idprop.h"
  
+ #ifndef DISABLE_PYTHON
  #include "BPY_extern.h"
+ #endif
  
 -#include "blendef.h"
 -
  #ifdef HAVE_CONFIG_H
  #include <config.h>
  #endif
  #include "BKE_scene.h"
  
  #include "MEM_guardedalloc.h"
 -#include "blendef.h"
  
+ #ifndef DISABLE_PYTHON
  #include "BPY_extern.h"
+ #endif
  
   #include "depsgraph_private.h"
   
@@@ -57,7 -57,9 +57,8 @@@
  #include "BKE_action.h"
  #include "BKE_anim.h"         /* needed for where_on_path */
  #include "BKE_armature.h"
 -#include "BKE_bad_level_calls.h"
  #include "BKE_blender.h"
+ #include "BKE_collision.h"
  #include "BKE_constraint.h"
  #include "BKE_deform.h"
  #include "BKE_depsgraph.h"
  #include "BKE_curve.h"
  #include "BKE_customdata.h"
  
+ #ifndef DISABLE_PYTHON
  #include "BPY_extern.h"
+ #endif
  
 -#include "blendef.h"
 -
  #include "zlib.h"
  
  static int is_dxf(char *str);
@@@ -2428,7 -2443,8 +2437,8 @@@ int BKE_read_exotic(char *name
                                        }       
                                
                                }
 -                              waitcursor(0);
+ #endif /* DISABLE_PYTHON */
 +                              //XXX waitcursor(0);
                        }
                }
        }
@@@ -53,8 -53,8 +53,9 @@@
  #include "DNA_packedFile_types.h"
  #include "DNA_scene_types.h"
  #include "DNA_camera_types.h"
+ #include "DNA_sequence_types.h"
  #include "DNA_texture_types.h"
 +#include "DNA_sequence_types.h"
  #include "DNA_userdef_types.h"
  
  #include "BLI_arithb.h"
  /* for stamp drawing to an image */
  #include "BMF_Api.h"
  
 -#include "blendef.h"
 -#include "BSE_time.h"
 -
+ #include "GPU_extensions.h"
+ #include "GPU_draw.h"
+ #include "BLO_sys_types.h" // for intptr_t support
  /* max int, to indicate we don't store sequences in ibuf */
  #define IMA_NO_INDEX  0x7FEFEFEF
  
@@@ -271,35 -293,43 +292,43 @@@ Ipo *add_ipo (char name[], int blocktyp
        return ipo;
  }
  
- Ipo *copy_ipo(Ipo *ipo)
+ /* ---------------------- Copy --------------------------- */
+ /* duplicate an IPO block and all its data  */
+ Ipo *copy_ipo (Ipo *src)
  {
-       Ipo *ipon;
+       Ipo *dst;
        IpoCurve *icu;
        
-       if(ipo==NULL) return 0;
-       
-       ipon= copy_libblock(ipo);
+       if (src == NULL) 
+               return NULL;
        
-       BLI_duplicatelist(&(ipon->curve), &(ipo->curve));
+       dst= copy_libblock(src);
 -      duplicatelist(&dst->curve, &src->curve);
++      BLI_duplicatelist(&dst->curve, &src->curve);
  
-       for(icu= ipo->curve.first; icu; icu= icu->next) {
+       for (icu= src->curve.first; icu; icu= icu->next) {
                icu->bezt= MEM_dupallocN(icu->bezt);
-               if(icu->driver) icu->driver= MEM_dupallocN(icu->driver);
+               
+               if (icu->driver) 
+                       icu->driver= MEM_dupallocN(icu->driver);
        }
        
-       return ipon;
+       return dst;
  }
  
- /* uses id->newid to match pointers with other copied data */
- void ipo_idnew(Ipo *ipo)
+ /* ---------------------- Relink --------------------------- */
+ /* uses id->newid to match pointers with other copied data 
+  *    - called after single-user or other such
+  */
+ void ipo_idnew (Ipo *ipo)
  {
-       if(ipo) {
+       if (ipo) {
                IpoCurve *icu;
                
-               for(icu= ipo->curve.first; icu; icu= icu->next) {
-                       if(icu->driver) {
+               for (icu= ipo->curve.first; icu; icu= icu->next) {
+                       if (icu->driver)
                                ID_NEW(icu->driver->ob);
-                       }
                }
        }
  }
@@@