2.5
authorTon Roosendaal <ton@blender.org>
Fri, 19 Dec 2008 12:14:58 +0000 (12:14 +0000)
committerTon Roosendaal <ton@blender.org>
Fri, 19 Dec 2008 12:14:58 +0000 (12:14 +0000)
Drawing code for space_view3d module.
It's still not cleaned, have to check on context usage still.
Also missing is editmodes, armatures, and probably more.

Known issue: splitting to 2nd window gives bad opengl lighting.
Picture for fun:
http://www.blender.org/bf/rt2.jpg

Current stat: brought back almost 10k lines! :)

16 files changed:
source/blender/editors/include/BIF_retopo.h [new file with mode: 0644]
source/blender/editors/include/ED_types.h
source/blender/editors/space_view3d/Makefile
source/blender/editors/space_view3d/SConscript
source/blender/editors/space_view3d/drawmesh.c [new file with mode: 0644]
source/blender/editors/space_view3d/drawobject.c [new file with mode: 0644]
source/blender/editors/space_view3d/view3d_draw.c
source/blender/editors/space_view3d/view3d_edit.c [new file with mode: 0644]
source/blender/editors/space_view3d/view3d_header.c
source/blender/editors/space_view3d/view3d_intern.h
source/blender/editors/space_view3d/view3d_view.c
source/blender/windowmanager/SConscript
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/intern/Makefile
source/blender/windowmanager/intern/wm_init_exit.c
source/blender/windowmanager/intern/wm_subwindow.c

diff --git a/source/blender/editors/include/BIF_retopo.h b/source/blender/editors/include/BIF_retopo.h
new file mode 100644 (file)
index 0000000..cc2fda5
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * $Id$
+ *
+ * ***** 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) 2006 by Nicholas Bishop
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef BIF_RETOPO_H
+#define BIF_RETOPO_H
+
+#include "DNA_vec_types.h"
+
+/* For bglMats */
+#include "BIF_glutil.h"
+
+struct EditVert;
+struct Mesh;
+struct View3D;
+
+typedef struct RetopoViewData {
+       bglMats mats;
+
+       char queue_matrix_update;
+} RetopoViewData;
+
+typedef struct RetopoPaintPoint {
+       struct RetopoPaintPoint *next, *prev;
+       vec2s loc;
+       short index;
+       float co[3];
+       struct EditVert *eve;
+} RetopoPaintPoint;
+
+typedef struct RetopoPaintLine {
+       struct RetopoPaintLine *next, *prev;
+       ListBase points;
+       ListBase hitlist; /* RetopoPaintHit */
+       RetopoPaintPoint *cyclic;
+} RetopoPaintLine;
+
+typedef struct RetopoPaintSel {
+       struct RetopoPaintSel *next, *prev;
+       RetopoPaintLine *line;
+       char first;
+} RetopoPaintSel;
+
+typedef struct RetopoPaintData {
+       char in_drag;
+       short sloc[2];
+
+       ListBase lines;
+       ListBase intersections; /* RetopoPaintPoint */
+
+       short seldist;
+       RetopoPaintSel nearest;
+       
+       struct View3D *paint_v3d;
+} RetopoPaintData;
+
+RetopoPaintData *get_retopo_paint_data(void);
+
+char retopo_mesh_check(void);
+char retopo_curve_check(void);
+
+void retopo_end_okee(void);
+
+void retopo_free_paint_data(RetopoPaintData *rpd);
+void retopo_free_paint(void);
+
+char retopo_mesh_paint_check(void);
+void retopo_paint_view_update(struct View3D *v3d);
+void retopo_force_update(void);
+void retopo_paint_toggle(void*,void*);
+char retopo_paint(const unsigned short event);
+void retopo_draw_paint_lines(void);
+RetopoPaintData *retopo_paint_data_copy(RetopoPaintData *rpd);
+
+void retopo_toggle(void*,void*);
+void retopo_do_vert(struct View3D *v3d, float *v);
+void retopo_do_all(void);
+void retopo_do_all_cb(void *, void *);
+void retopo_queue_updates(struct View3D *v3d);
+
+void retopo_matrix_update(struct View3D *v3d);
+
+void retopo_free_view_data(struct View3D *v3d);
+
+#endif
index 7b19341fb9ed229e13f7b093b8f8cd6e79b0bbac..ec5dce0c70d39d07ab3a3ed58107ecebdfc19d99 100644 (file)
@@ -31,8 +31,9 @@
 /* **************** GENERAL EDITOR-WIDE TYPES AND DEFINES ************************** */
 
 /* old blender defines... should be depricated? */
-#define SELECT 1
-#define ACTIVE 2
+#define DESELECT 0
+#define SELECT  1
+#define ACTIVE  2
 
 
 #endif /* ED_TYPES_H */
index e097d041a372396abc4335863c8d11c522efd52e..7a5f609a187f90d1988ce0bf89dd4297a22d9686 100644 (file)
@@ -48,6 +48,7 @@ CPPFLAGS += -I../../blenlib
 CPPFLAGS += -I../../makesdna
 CPPFLAGS += -I../../imbuf
 CPPFLAGS += -I../../python
+CPPFLAGS += -I../../gpu
 CPPFLAGS += -I../../render/extern/include
 CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
 
index 5d30ae91deb998967f7137eaf247114a26f69910..77cf03820ed7f72da02d5d4d24c26d71982d1c1a 100644 (file)
@@ -6,5 +6,6 @@ sources = env.Glob('*.c')
 incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
 incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
 incs += ' ../../render/extern/include #/intern/guardedalloc #intern/bmfont'
+incs += ' ../../gpu'
 
 env.BlenderLib ( 'bf_editors_space_view3d', sources, Split(incs), [], libtype=['core','intern'], priority=[35, 40] )
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
new file mode 100644 (file)
index 0000000..01740d2
--- /dev/null
@@ -0,0 +1,579 @@
+/**
+ * $Id$
+ *
+ * ***** 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) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, full update, glsl support
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_edgehash.h"
+#include "BLI_editVert.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "DNA_image_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_property_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_bmfont.h"
+#include "BKE_context.h"
+#include "BKE_displist.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_effect.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_property.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_resources.h"
+#include "UI_interface_icons.h"
+
+#include "GPU_extensions.h"
+#include "GPU_draw.h"
+
+#include "view3d_intern.h"     // own include
+
+/***/
+
+       /* Flags for marked edges */
+enum {
+       eEdge_Visible = (1<<0),
+       eEdge_Select = (1<<1),
+};
+
+       /* Creates a hash of edges to flags indicating
+        * adjacent tface select/active/etc flags.
+        */
+static void get_marked_edge_info__orFlags(EdgeHash *eh, int v0, int v1, int flags)
+{
+       int *flags_p;
+
+       if (!BLI_edgehash_haskey(eh, v0, v1)) {
+               BLI_edgehash_insert(eh, v0, v1, 0);
+       }
+
+       flags_p = (int*) BLI_edgehash_lookup_p(eh, v0, v1);
+       *flags_p |= flags;
+}
+
+static EdgeHash *get_tface_mesh_marked_edge_info(Mesh *me)
+{
+       EdgeHash *eh = BLI_edgehash_new();
+       int i;
+       MFace *mf;
+       MTFace *tf = NULL;
+       
+       for (i=0; i<me->totface; i++) {
+               mf = &me->mface[i];
+               if (me->mtface)
+                       tf = &me->mtface[i];
+               
+               if (mf->v3) {
+                       if (!(mf->flag&ME_HIDE)) {
+                               unsigned int flags = eEdge_Visible;
+                               if (mf->flag&ME_FACE_SEL) flags |= eEdge_Select;
+
+                               get_marked_edge_info__orFlags(eh, mf->v1, mf->v2, flags);
+                               get_marked_edge_info__orFlags(eh, mf->v2, mf->v3, flags);
+                               if (mf->v4) {
+                                       get_marked_edge_info__orFlags(eh, mf->v3, mf->v4, flags);
+                                       get_marked_edge_info__orFlags(eh, mf->v4, mf->v1, flags);
+                               } else {
+                                       get_marked_edge_info__orFlags(eh, mf->v3, mf->v1, flags);
+                               }
+                       }
+               }
+       }
+
+       return eh;
+}
+
+
+static int draw_tfaces3D__setHiddenOpts(void *userData, int index)
+{
+       struct { Mesh *me; EdgeHash *eh; } *data = userData;
+       MEdge *med = &data->me->medge[index];
+       uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
+
+       if((G.f & G_DRAWSEAMS) && (med->flag&ME_SEAM)) {
+               return 0;
+       } else if(G.f & G_DRAWEDGES){ 
+               if (G.f&G_HIDDENEDGES) {
+                       return 1;
+               } else {
+                       return (flags & eEdge_Visible);
+               }
+       } else {
+               return (flags & eEdge_Select);
+       }
+}
+static int draw_tfaces3D__setSeamOpts(void *userData, int index)
+{
+       struct { Mesh *me; EdgeHash *eh; } *data = userData;
+       MEdge *med = &data->me->medge[index];
+       uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
+
+       if (med->flag&ME_SEAM) {
+               if (G.f&G_HIDDENEDGES) {
+                       return 1;
+               } else {
+                       return (flags & eEdge_Visible);
+               }
+       } else {
+               return 0;
+       }
+}
+static int draw_tfaces3D__setSelectOpts(void *userData, int index)
+{
+       struct { Mesh *me; EdgeHash *eh; } *data = userData;
+       MEdge *med = &data->me->medge[index];
+       uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
+
+       return flags & eEdge_Select;
+}
+static int draw_tfaces3D__setActiveOpts(void *userData, int index)
+{
+       struct { Mesh *me; EdgeHash *eh; } *data = userData;
+       MEdge *med = &data->me->medge[index];
+       uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
+
+       if (flags & eEdge_Select) {
+               return 1;
+       } else {
+               return 0;
+       }
+}
+static int draw_tfaces3D__drawFaceOpts(void *userData, int index)
+{
+       Mesh *me = (Mesh*)userData;
+
+       MFace *mface = &me->mface[index];
+       if (!(mface->flag&ME_HIDE) && (mface->flag&ME_FACE_SEL))
+               return 2; /* Don't set color */
+       else
+               return 0;
+}
+static void draw_tfaces3D(Object *ob, Mesh *me, DerivedMesh *dm)
+{
+       struct { Mesh *me; EdgeHash *eh; } data;
+
+       data.me = me;
+       data.eh = get_tface_mesh_marked_edge_info(me);
+
+       glEnable(GL_DEPTH_TEST);
+       glDisable(GL_LIGHTING);
+       bglPolygonOffset(1.0);
+
+               /* Draw (Hidden) Edges */
+       UI_ThemeColor(TH_EDGE_FACESEL);
+       dm->drawMappedEdges(dm, draw_tfaces3D__setHiddenOpts, &data);
+
+               /* Draw Seams */
+       if(G.f & G_DRAWSEAMS) {
+               UI_ThemeColor(TH_EDGE_SEAM);
+               glLineWidth(2);
+
+               dm->drawMappedEdges(dm, draw_tfaces3D__setSeamOpts, &data);
+
+               glLineWidth(1);
+       }
+
+       /* Draw Selected Faces */
+       if(G.f & G_DRAWFACES) {
+               glEnable(GL_BLEND);
+               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+               UI_ThemeColor4(TH_FACE_SELECT);
+
+               dm->drawMappedFacesTex(dm, draw_tfaces3D__drawFaceOpts, (void*)me);
+
+               glDisable(GL_BLEND);
+       }
+       
+       bglPolygonOffset(1.0);
+
+               /* Draw Stippled Outline for selected faces */
+       glColor3ub(255, 255, 255);
+       setlinestyle(1);
+       dm->drawMappedEdges(dm, draw_tfaces3D__setSelectOpts, &data);
+       setlinestyle(0);
+
+       dm->drawMappedEdges(dm, draw_tfaces3D__setActiveOpts, &data);
+
+       bglPolygonOffset(0.0);  // resets correctly now, even after calling accumulated offsets
+
+       BLI_edgehash_free(data.eh, NULL);
+}
+
+static Material *give_current_material_or_def(Object *ob, int matnr)
+{
+       extern Material defmaterial;    // render module abuse...
+       Material *ma= give_current_material(ob, matnr);
+
+       return ma?ma:&defmaterial;
+}
+
+static int set_draw_settings_cached(int clearcache, int textured, MTFace *texface, int lit, Object *litob, int litmatnr, int doublesided)
+{
+       static int c_textured;
+       static int c_lit;
+       static int c_doublesided;
+       static MTFace *c_texface;
+       static Object *c_litob;
+       static int c_litmatnr;
+       static int c_badtex;
+
+       if (clearcache) {
+               c_textured= c_lit= c_doublesided= -1;
+               c_texface= (MTFace*) -1;
+               c_litob= (Object*) -1;
+               c_litmatnr= -1;
+               c_badtex= 0;
+       }
+
+       if (texface) {
+               lit = lit && (lit==-1 || texface->mode&TF_LIGHT);
+               textured = textured && (texface->mode&TF_TEX);
+               doublesided = texface->mode&TF_TWOSIDE;
+       } else {
+               textured = 0;
+       }
+
+       if (doublesided!=c_doublesided) {
+               if (doublesided) glDisable(GL_CULL_FACE);
+               else glEnable(GL_CULL_FACE);
+
+               c_doublesided= doublesided;
+       }
+
+       if (textured!=c_textured || texface!=c_texface) {
+               if (textured ) {
+                       c_badtex= !GPU_set_tpage(texface);
+               } else {
+                       GPU_set_tpage(0);
+                       c_badtex= 0;
+               }
+               c_textured= textured;
+               c_texface= texface;
+       }
+
+       if (c_badtex) lit= 0;
+       if (lit!=c_lit || litob!=c_litob || litmatnr!=c_litmatnr) {
+               if (lit) {
+                       Material *ma= give_current_material_or_def(litob, litmatnr+1);
+                       float spec[4];
+
+                       spec[0]= ma->spec*ma->specr;
+                       spec[1]= ma->spec*ma->specg;
+                       spec[2]= ma->spec*ma->specb;
+                       spec[3]= 1.0;
+
+                       glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
+                       glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+                       glEnable(GL_LIGHTING);
+                       glEnable(GL_COLOR_MATERIAL);
+               }
+               else {
+                       glDisable(GL_LIGHTING); 
+                       glDisable(GL_COLOR_MATERIAL);
+               }
+               c_lit= lit;
+               c_litob= litob;
+               c_litmatnr= litmatnr;
+       }
+
+       return c_badtex;
+}
+
+/* Icky globals, fix with userdata parameter */
+
+struct TextureDrawState {
+       Object *ob;
+       int islit, istex;
+       unsigned char obcol[4];
+} Gtexdraw = {NULL, 0, 0, {0, 0, 0, 0}};
+
+static void draw_textured_begin(Scene *scene, View3D *v3d, Object *ob)
+{
+       unsigned char obcol[4];
+       int istex, solidtex= 0;
+
+       if(v3d->drawtype==OB_SOLID || (ob==G.obedit && v3d->drawtype!=OB_TEXTURE)) {
+               /* draw with default lights in solid draw mode and edit mode */
+               solidtex= 1;
+               Gtexdraw.islit= -1;
+       }
+       else
+               /* draw with lights in the scene otherwise */
+               Gtexdraw.islit= GPU_scene_object_lights(scene, ob, v3d->lay, v3d->viewmat);
+       
+       obcol[0]= CLAMPIS(ob->col[0]*255, 0, 255);
+       obcol[1]= CLAMPIS(ob->col[1]*255, 0, 255);
+       obcol[2]= CLAMPIS(ob->col[2]*255, 0, 255);
+       obcol[3]= CLAMPIS(ob->col[3]*255, 0, 255);
+       
+       glCullFace(GL_BACK); glEnable(GL_CULL_FACE);
+       if(solidtex || v3d->drawtype==OB_TEXTURE) istex= 1;
+       else istex= 0;
+
+       Gtexdraw.ob = ob;
+       Gtexdraw.istex = istex;
+       memcpy(Gtexdraw.obcol, obcol, sizeof(obcol));
+       set_draw_settings_cached(1, 0, 0, Gtexdraw.islit, 0, 0, 0);
+       glShadeModel(GL_SMOOTH);
+}
+
+static void draw_textured_end()
+{
+       /* switch off textures */
+       GPU_set_tpage(0);
+
+       glShadeModel(GL_FLAT);
+       glDisable(GL_CULL_FACE);
+
+       /* XXX, bad patch - GPU_default_lights() calls
+        * glLightfv(GL_LIGHT_POSITION, ...) which
+        * is transformed by the current matrix... we
+        * need to make sure that matrix is identity.
+        * 
+        * It would be better if drawmesh.c kept track
+        * of and restored the light settings it changed.
+        *  - zr
+        */
+       glPushMatrix();
+       glLoadIdentity();       
+       GPU_default_lights();
+       glPopMatrix();
+}
+
+
+static int draw_tface__set_draw(MTFace *tface, MCol *mcol, int matnr)
+{
+       if (tface && (tface->mode&TF_INVISIBLE)) return 0;
+
+       if (tface && set_draw_settings_cached(0, Gtexdraw.istex, tface, Gtexdraw.islit, Gtexdraw.ob, matnr, TF_TWOSIDE)) {
+               glColor3ub(0xFF, 0x00, 0xFF);
+               return 2; /* Don't set color */
+       } else if (tface && tface->mode&TF_OBCOL) {
+               glColor3ubv(Gtexdraw.obcol);
+               return 2; /* Don't set color */
+       } else if (!mcol) {
+               if (tface) glColor3f(1.0, 1.0, 1.0);
+               else {
+                       Material *ma= give_current_material(Gtexdraw.ob, matnr+1);
+                       if(ma) glColor3f(ma->r, ma->g, ma->b);
+                       else glColor3f(1.0, 1.0, 1.0);
+               }
+               return 2; /* Don't set color */
+       } else {
+               return 1; /* Set color from mcol */
+       }
+}
+
+static int draw_tface_mapped__set_draw(void *userData, int index)
+{
+       Mesh *me = (Mesh*)userData;
+       MTFace *tface = (me->mtface)? &me->mtface[index]: NULL;
+       MFace *mface = (me->mface)? &me->mface[index]: NULL;
+       MCol *mcol = (me->mcol)? &me->mcol[index]: NULL;
+       int matnr = me->mface[index].mat_nr;
+       if (mface && mface->flag&ME_HIDE) return 0;
+       return draw_tface__set_draw(tface, mcol, matnr);
+}
+
+static int draw_em_tf_mapped__set_draw(void *userData, int index)
+{
+       EditMesh *em = userData;
+       EditFace *efa= NULL; // XXX = EM_get_face_for_index(index);
+       MTFace *tface;
+       MCol *mcol;
+       int matnr;
+
+       if (efa==NULL || efa->h)
+               return 0;
+
+       tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+       mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
+       matnr = efa->mat_nr;
+
+       return draw_tface__set_draw(tface, mcol, matnr);
+}
+
+static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
+{
+       Mesh *me = (Mesh*)userData;
+       MTFace *tface = (me->mtface)? &me->mtface[index]: NULL;
+       MFace *mface = (me->mface)? &me->mface[index]: NULL;
+       
+       if ((mface->flag&ME_HIDE) || (tface && (tface->mode&TF_INVISIBLE))) 
+                       return 0;
+       
+       *drawSmooth_r = 1;
+       return 1;
+}
+
+void draw_mesh_text(Object *ob, int glsl)
+{
+       Mesh *me = ob->data;
+       DerivedMesh *ddm;
+       MFace *mf, *mface= me->mface;
+       MTFace *tface= me->mtface;
+       MCol *mcol= me->mcol;   /* why does mcol exist? */
+       bProperty *prop = get_ob_property(ob, "Text");
+       GPUVertexAttribs gattribs;
+       int a, totface= me->totface;
+
+       /* don't draw without tfaces */
+       if(!tface)
+               return;
+
+       /* don't draw when editing */
+       if(ob==G.obedit)
+               return;
+       else if(ob==OBACT)
+               if(FACESEL_PAINT_TEST)
+                       return;
+
+       ddm = mesh_get_derived_deform(ob, CD_MASK_BAREMESH);
+
+       for(a=0, mf=mface; a<totface; a++, tface++, mf++) {
+               int mode= tface->mode;
+               int matnr= mf->mat_nr;
+               int mf_smooth= mf->flag & ME_SMOOTH;
+
+               if (!(mf->flag&ME_HIDE) && !(mode&TF_INVISIBLE) && (mode&TF_BMFONT)) {
+                       float v1[3], v2[3], v3[3], v4[3];
+                       char string[MAX_PROPSTRING];
+                       int characters, i, glattrib= -1, badtex= 0;
+
+                       if(glsl) {
+                               GPU_enable_material(matnr+1, &gattribs);
+
+                               for(i=0; i<gattribs.totlayer; i++) {
+                                       if(gattribs.layer[i].type == CD_MTFACE) {
+                                               glattrib = gattribs.layer[i].glindex;
+                                               break;
+                                       }
+                               }
+                       }
+                       else {
+                               badtex = set_draw_settings_cached(0, Gtexdraw.istex, tface, Gtexdraw.islit, Gtexdraw.ob, matnr, TF_TWOSIDE);
+                               if (badtex) {
+                                       if (mcol) mcol+=4;
+                                       continue;
+                               }
+                       }
+
+                       ddm->getVertCo(ddm, mf->v1, v1);
+                       ddm->getVertCo(ddm, mf->v2, v2);
+                       ddm->getVertCo(ddm, mf->v3, v3);
+                       if (mf->v4) ddm->getVertCo(ddm, mf->v4, v4);
+
+                       // The BM_FONT handling is in the gpu module, shared with the
+                       // game engine, was duplicated previously
+
+                       set_property_valstr(prop, string);
+                       characters = strlen(string);
+                       
+                       if(!BKE_image_get_ibuf(tface->tpage, NULL))
+                               characters = 0;
+
+                       if (!mf_smooth) {
+                               float nor[3];
+
+                               CalcNormFloat(v1, v2, v3, nor);
+
+                               glNormal3fv(nor);
+                       }
+
+                       GPU_render_text(tface, tface->mode, string, characters,
+                               (unsigned int*)mcol, v1, v2, v3, (mf->v4? v4: NULL), glattrib);
+               }
+               if (mcol) {
+                       mcol+=4;
+               }
+       }
+
+       ddm->release(ddm);
+}
+
+void draw_mesh_textured(Scene *scene, View3D *v3d, Object *ob, DerivedMesh *dm, int faceselect)
+{
+       Mesh *me= ob->data;
+       
+       /* correct for negative scale */
+       if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
+       else glFrontFace(GL_CCW);
+       
+       /* draw the textured mesh */
+       draw_textured_begin(scene, v3d, ob);
+
+       if(ob==G.obedit) {
+               dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, G.editMesh);
+       } else if(faceselect) {
+               if(G.f & G_WEIGHTPAINT)
+                       dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me, 1);
+               else
+                       dm->drawMappedFacesTex(dm, draw_tface_mapped__set_draw, me);
+       }
+       else
+               dm->drawFacesTex(dm, draw_tface__set_draw);
+
+       /* draw game engine text hack */
+       if(get_ob_property(ob, "Text")) 
+               draw_mesh_text(ob, 0);
+
+       draw_textured_end();
+       
+       /* draw edges and selected faces over textured mesh */
+       if(!G.obedit && faceselect)
+               draw_tfaces3D(ob, me, dm);
+
+       /* reset from negative scale correction */
+       glFrontFace(GL_CCW);
+       
+       /* in editmode, the blend mode needs to be set incase it was ADD */
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+}
+
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
new file mode 100644 (file)
index 0000000..f5a2cd9
--- /dev/null
@@ -0,0 +1,5475 @@
+/**
+ * $Id$
+ *
+ * ***** 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) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, full recode and added functions
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <math.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "IMB_imbuf.h"
+
+
+#include "MTC_matrixops.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_constraint_types.h" // for drawing constraint
+#include "DNA_effect_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_particle_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+// FSPARTICLE
+#include "DNA_object_fluidsim.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+#include "BLI_edgehash.h"
+#include "BLI_rand.h"
+
+#include "BKE_anim.h"                  //for the where_on_path function
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_constraint.h" // for the get_constraint_target function
+#include "BKE_DerivedMesh.h"
+#include "BKE_deform.h"
+#include "BKE_displist.h"
+#include "BKE_effect.h"
+#include "BKE_font.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_lattice.h"
+#include "BKE_mesh.h"
+#include "BKE_material.h"
+#include "BKE_mball.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_particle.h"
+#include "BKE_property.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "GPU_draw.h"
+#include "GPU_material.h"
+#include "GPU_extensions.h"
+
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "UI_resources.h"
+#include "UI_interface_icons.h"
+
+#include "WM_api.h"
+
+#include "view3d_intern.h"     // own include
+
+
+/* pretty stupid */
+/*  extern Lattice *editLatt; already in BKE_lattice.h  */
+/* editcurve.c */
+extern ListBase editNurb;
+/* editmball.c */
+extern ListBase editelems;
+
+static void draw_bounding_volume(Object *ob);
+
+static void drawcube_size(float size);
+static void drawcircle_size(float size);
+static void draw_empty_sphere(float size);
+static void draw_empty_cone(float size);
+
+EditVert *EM_get_vert_for_index(int x) {return 0;}     // XXX
+EditEdge *EM_get_edge_for_index(int x) {return 0;}     // XXX
+EditFace *EM_get_face_for_index(int x) {return 0;}     // XXX
+void EM_init_index_arrays(int x, int y, int z) {} // XXX
+void EM_free_index_arrays(void) {}             // XXX
+#define EM_FGON        0
+EditFace *EM_get_actFace(int x) {return NULL;} // XXX
+int draw_armature(Base *base, int x, int y) {return 0;}        // XXX
+int em_solidoffs;      // XXX
+int em_wireoffs;
+int em_vertoffs;
+
+/* check for glsl drawing */
+
+int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt)
+{
+       if(!GPU_extensions_minimum_support())
+               return 0;
+       if(G.f & G_PICKSEL)
+               return 0;
+       if(!CHECK_OB_DRAWTEXTURE(v3d, dt))
+               return 0;
+       if(ob==OBACT && (G.f & G_WEIGHTPAINT))
+               return 0;
+       
+       return ((G.fileflags & G_FILE_GAME_MAT) &&
+          (G.fileflags & G_FILE_GAME_MAT_GLSL) && (dt >= OB_SHADED));
+}
+
+static int check_material_alpha(Base *base, Object *ob, int glsl)
+{
+       if(base->flag & OB_FROMDUPLI)
+               return 0;
+
+       if(G.f & G_PICKSEL)
+               return 0;
+                       
+       if(G.obedit && G.obedit->data==ob->data)
+               return 0;
+       
+       return (glsl || (ob->dtx & OB_DRAWTRANSP));
+}
+
+       /***/
+static unsigned int colortab[24]=
+       {0x0,           0xFF88FF, 0xFFBBFF, 
+        0x403000,      0xFFFF88, 0xFFFFBB, 
+        0x104040,      0x66CCCC, 0x77CCCC, 
+        0x104010,      0x55BB55, 0x66FF66, 
+        0xFFFFFF
+};
+
+
+static float cube[8][3] = {
+       {-1.0, -1.0, -1.0},
+       {-1.0, -1.0,  1.0},
+       {-1.0,  1.0,  1.0},
+       {-1.0,  1.0, -1.0},
+       { 1.0, -1.0, -1.0},
+       { 1.0, -1.0,  1.0},
+       { 1.0,  1.0,  1.0},
+       { 1.0,  1.0, -1.0},
+};
+
+/* ----------------- OpenGL Circle Drawing - Tables for Optimised Drawing Speed ------------------ */
+/* 32 values of sin function (still same result!) */
+static float sinval[32] = {
+       0.00000000,
+       0.20129852,
+       0.39435585,
+       0.57126821,
+       0.72479278,
+       0.84864425,
+       0.93775213,
+       0.98846832,
+       0.99871650,
+       0.96807711,
+       0.89780453,
+       0.79077573,
+       0.65137248,
+       0.48530196,
+       0.29936312,
+       0.10116832,
+       -0.10116832,
+       -0.29936312,
+       -0.48530196,
+       -0.65137248,
+       -0.79077573,
+       -0.89780453,
+       -0.96807711,
+       -0.99871650,
+       -0.98846832,
+       -0.93775213,
+       -0.84864425,
+       -0.72479278,
+       -0.57126821,
+       -0.39435585,
+       -0.20129852,
+       0.00000000
+};
+
+/* 32 values of cos function (still same result!) */
+static float cosval[32] ={
+       1.00000000,
+       0.97952994,
+       0.91895781,
+       0.82076344,
+       0.68896691,
+       0.52896401,
+       0.34730525,
+       0.15142777,
+       -0.05064916,
+       -0.25065253,
+       -0.44039415,
+       -0.61210598,
+       -0.75875812,
+       -0.87434661,
+       -0.95413925,
+       -0.99486932,
+       -0.99486932,
+       -0.95413925,
+       -0.87434661,
+       -0.75875812,
+       -0.61210598,
+       -0.44039415,
+       -0.25065253,
+       -0.05064916,
+       0.15142777,
+       0.34730525,
+       0.52896401,
+       0.68896691,
+       0.82076344,
+       0.91895781,
+       0.97952994,
+       1.00000000
+};
+
+/* flag is same as for draw_object */
+void drawaxes(float size, int flag, char drawtype)
+{
+       int axis;
+       float v1[3]= {0.0, 0.0, 0.0};
+       float v2[3]= {0.0, 0.0, 0.0};
+       float v3[3]= {0.0, 0.0, 0.0};
+
+       if(G.f & G_RENDER_SHADOW)
+               return;
+       
+       switch(drawtype) {
+       
+       case OB_PLAINAXES:
+               for (axis=0; axis<3; axis++) {
+                       float v1[3]= {0.0, 0.0, 0.0};
+                       float v2[3]= {0.0, 0.0, 0.0};
+                       
+                       glBegin(GL_LINES);
+
+                       v1[axis]= size;
+                       v2[axis]= -size;
+                       glVertex3fv(v1);
+                       glVertex3fv(v2);
+                       
+                       glEnd();
+               }
+               break;
+       case OB_SINGLE_ARROW:
+       
+               glBegin(GL_LINES);
+               /* in positive z direction only */
+               v1[2]= size;
+               glVertex3fv(v1);
+               glVertex3fv(v2);
+               glEnd();
+               
+               /* square pyramid */
+               glBegin(GL_TRIANGLES);
+               
+               v2[0]= size*0.035; v2[1] = size*0.035;
+               v3[0]= size*-0.035; v3[1] = size*0.035;
+               v2[2]= v3[2]= size*0.75;
+               
+               for (axis=0; axis<4; axis++) {
+                       if (axis % 2 == 1) {
+                               v2[0] *= -1;
+                               v3[1] *= -1;
+                       } else {
+                               v2[1] *= -1;
+                               v3[0] *= -1;
+                       }
+                       
+                       glVertex3fv(v1);
+                       glVertex3fv(v2);
+                       glVertex3fv(v3);
+                       
+               }
+               glEnd();
+               
+               break;
+       case OB_CUBE:
+               drawcube_size(size);
+               break;
+               
+       case OB_CIRCLE:
+               drawcircle_size(size);
+               break;
+       
+       case OB_EMPTY_SPHERE:
+                draw_empty_sphere(size);
+            break;
+
+       case OB_EMPTY_CONE:
+                draw_empty_cone(size);
+            break;
+
+       case OB_ARROWS:
+       default:
+               for (axis=0; axis<3; axis++) {
+                       float v1[3]= {0.0, 0.0, 0.0};
+                       float v2[3]= {0.0, 0.0, 0.0};
+                       int arrow_axis= (axis==0)?1:0;
+                       
+                       glBegin(GL_LINES);
+
+                       v2[axis]= size;
+                       glVertex3fv(v1);
+                       glVertex3fv(v2);
+                               
+                       v1[axis]= size*0.8;
+                       v1[arrow_axis]= -size*0.125;
+                       glVertex3fv(v1);
+                       glVertex3fv(v2);
+                               
+                       v1[arrow_axis]= size*0.125;
+                       glVertex3fv(v1);
+                       glVertex3fv(v2);
+
+                       glEnd();
+                               
+                       v2[axis]+= size*0.125;
+                       glRasterPos3fv(v2);
+                       
+                       // patch for 3d cards crashing on glSelect for text drawing (IBM)
+                       if((flag & DRAW_PICKING) == 0) {
+                               if (axis==0)
+                                       BMF_DrawString(G.font, "x");
+                               else if (axis==1)
+                                       BMF_DrawString(G.font, "y");
+                               else
+                                       BMF_DrawString(G.font, "z");
+                       }
+               }
+               break;
+       }
+}
+
+void drawcircball(int mode, float *cent, float rad, float tmat[][4])
+{
+       float vec[3], vx[3], vy[3];
+       int a, tot=32;
+       
+       VECCOPY(vx, tmat[0]);
+       VECCOPY(vy, tmat[1]);
+       VecMulf(vx, rad);
+       VecMulf(vy, rad);
+       
+       glBegin(mode);
+       for(a=0; a<tot; a++) {
+               vec[0]= cent[0] + *(sinval+a) * vx[0] + *(cosval+a) * vy[0];
+               vec[1]= cent[1] + *(sinval+a) * vx[1] + *(cosval+a) * vy[1];
+               vec[2]= cent[2] + *(sinval+a) * vx[2] + *(cosval+a) * vy[2];
+               glVertex3fv(vec);
+       }
+       glEnd();
+}
+
+/* circle for object centers, special_color is for library or ob users */
+static void drawcentercircle(View3D *v3d, float *vec, int selstate, int special_color)
+{
+       float size;
+       
+       size= v3d->persmat[0][3]*vec[0]+ v3d->persmat[1][3]*vec[1]+ v3d->persmat[2][3]*vec[2]+ v3d->persmat[3][3];
+       size*= v3d->pixsize*((float)U.obcenter_dia*0.5f);
+
+       /* using gldepthfunc guarantees that it does write z values, but not checks for it, so centers remain visible independt order of drawing */
+       if(v3d->zbuf)  glDepthFunc(GL_ALWAYS);
+       glEnable(GL_BLEND);
+       
+       if(special_color) {
+               if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
+
+               else glColor4ub(0x55, 0xCC, 0xCC, 155);
+       }
+       else {
+               if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
+               else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
+               else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
+       }
+       drawcircball(GL_POLYGON, vec, size, v3d->viewinv);
+       
+       UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
+       drawcircball(GL_LINE_LOOP, vec, size, v3d->viewinv);
+       
+       glDisable(GL_BLEND);
+       if(v3d->zbuf)  glDepthFunc(GL_LEQUAL);
+}
+
+
+void drawsolidcube(float size)
+{
+       float n[3];
+
+       glPushMatrix();
+       glScalef(size, size, size);
+       
+       n[0]=0; n[1]=0; n[2]=0;
+       glBegin(GL_QUADS);
+               n[0]= -1.0;
+               glNormal3fv(n); 
+               glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
+               n[0]=0;
+       glEnd();
+
+       glBegin(GL_QUADS);
+               n[1]= -1.0;
+               glNormal3fv(n); 
+               glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]);
+               n[1]=0;
+       glEnd();
+
+       glBegin(GL_QUADS);
+               n[0]= 1.0;
+               glNormal3fv(n); 
+               glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]);
+               n[0]=0;
+       glEnd();
+
+       glBegin(GL_QUADS);
+               n[1]= 1.0;
+               glNormal3fv(n); 
+               glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]);
+               n[1]=0;
+       glEnd();
+
+       glBegin(GL_QUADS);
+               n[2]= 1.0;
+               glNormal3fv(n); 
+               glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]);
+               n[2]=0;
+       glEnd();
+
+       glBegin(GL_QUADS);
+               n[2]= -1.0;
+               glNormal3fv(n); 
+               glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]);
+       glEnd();
+       
+       glPopMatrix();
+}
+
+static void drawcube(void)
+{
+
+       glBegin(GL_LINE_STRIP);
+               glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
+               glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
+               glVertex3fv(cube[7]); glVertex3fv(cube[4]);
+       glEnd();
+
+       glBegin(GL_LINE_STRIP);
+               glVertex3fv(cube[1]); glVertex3fv(cube[5]);
+       glEnd();
+
+       glBegin(GL_LINE_STRIP);
+               glVertex3fv(cube[2]); glVertex3fv(cube[6]);
+       glEnd();
+
+       glBegin(GL_LINE_STRIP);
+               glVertex3fv(cube[3]); glVertex3fv(cube[7]);
+       glEnd();
+}
+
+/* draws a cube on given the scaling of the cube, assuming that 
+ * all required matrices have been set (used for drawing empties)
+ */
+static void drawcube_size(float size)
+{
+       glBegin(GL_LINE_STRIP);
+               glVertex3f(-size,-size,-size); glVertex3f(-size,-size,size);glVertex3f(-size,size,size); glVertex3f(-size,size,-size);
+               glVertex3f(-size,-size,-size); glVertex3f(size,-size,-size);glVertex3f(size,-size,size); glVertex3f(size,size,size);
+               glVertex3f(size,size,-size); glVertex3f(size,-size,-size);
+       glEnd();
+
+       glBegin(GL_LINE_STRIP);
+               glVertex3f(-size,-size,size); glVertex3f(size,-size,size);
+       glEnd();
+
+       glBegin(GL_LINE_STRIP);
+               glVertex3f(-size,size,size); glVertex3f(size,size,size);
+       glEnd();
+
+       glBegin(GL_LINE_STRIP);
+               glVertex3f(-size,size,-size); glVertex3f(size,size,-size);
+       glEnd();
+}
+
+/* this is an unused (old) cube-drawing function based on a given size */
+#if 0
+static void drawcube_size(float *size)
+{
+
+       glPushMatrix();
+       glScalef(size[0],  size[1],  size[2]);
+       
+
+       glBegin(GL_LINE_STRIP);
+               glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
+               glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
+               glVertex3fv(cube[7]); glVertex3fv(cube[4]);
+       glEnd();
+
+       glBegin(GL_LINE_STRIP);
+               glVertex3fv(cube[1]); glVertex3fv(cube[5]);
+       glEnd();
+
+       glBegin(GL_LINE_STRIP);
+               glVertex3fv(cube[2]); glVertex3fv(cube[6]);
+       glEnd();
+
+       glBegin(GL_LINE_STRIP);
+               glVertex3fv(cube[3]); glVertex3fv(cube[7]);
+       glEnd();
+       
+       glPopMatrix();
+}
+#endif
+
+static void drawshadbuflimits(Lamp *la, float mat[][4])
+{
+       float sta[3], end[3], lavec[3];
+
+       lavec[0]= -mat[2][0];
+       lavec[1]= -mat[2][1];
+       lavec[2]= -mat[2][2];
+       Normalize(lavec);
+
+       sta[0]= mat[3][0]+ la->clipsta*lavec[0];
+       sta[1]= mat[3][1]+ la->clipsta*lavec[1];
+       sta[2]= mat[3][2]+ la->clipsta*lavec[2];
+
+       end[0]= mat[3][0]+ la->clipend*lavec[0];
+       end[1]= mat[3][1]+ la->clipend*lavec[1];
+       end[2]= mat[3][2]+ la->clipend*lavec[2];
+
+
+       glBegin(GL_LINE_STRIP);
+               glVertex3fv(sta);
+               glVertex3fv(end);
+       glEnd();
+
+       glPointSize(3.0);
+       bglBegin(GL_POINTS);
+       bglVertex3fv(sta);
+       bglVertex3fv(end);
+       bglEnd();
+       glPointSize(1.0);
+}
+
+
+
+static void spotvolume(float *lvec, float *vvec, float inp)
+{
+       /* camera is at 0,0,0 */
+       float temp[3],plane[3],mat1[3][3],mat2[3][3],mat3[3][3],mat4[3][3],q[4],co,si,angle;
+
+       Normalize(lvec);
+       Normalize(vvec);                                /* is this the correct vector ? */
+
+       Crossf(temp,vvec,lvec);         /* equation for a plane through vvec en lvec */
+       Crossf(plane,lvec,temp);                /* a plane perpendicular to this, parrallel with lvec */
+
+       Normalize(plane);
+
+       /* now we've got two equations: one of a cone and one of a plane, but we have
+       three unknowns. We remove one unkown by rotating the plane to z=0 (the plane normal) */
+
+       /* rotate around cross product vector of (0,0,1) and plane normal, dot product degrees */
+       /* according definition, we derive cross product is (plane[1],-plane[0],0), en cos = plane[2]);*/
+
+       /* translating this comment to english didnt really help me understanding the math! :-) (ton) */
+       
+       q[1] = plane[1] ; 
+       q[2] = -plane[0] ; 
+       q[3] = 0 ;
+       Normalize(&q[1]);
+
+       angle = saacos(plane[2])/2.0;
+       co = cos(angle);
+       si = sqrt(1-co*co);
+
+       q[0] =  co;
+       q[1] *= si;
+       q[2] *= si;
+       q[3] =  0;
+
+       QuatToMat3(q,mat1);
+
+       /* rotate lamp vector now over acos(inp) degrees */
+
+       vvec[0] = lvec[0] ; 
+       vvec[1] = lvec[1] ; 
+       vvec[2] = lvec[2] ;
+
+       Mat3One(mat2);
+       co = inp;
+       si = sqrt(1-inp*inp);
+
+       mat2[0][0] =  co;
+       mat2[1][0] = -si;
+       mat2[0][1] =  si;
+       mat2[1][1] =  co;
+       Mat3MulMat3(mat3,mat2,mat1);
+
+       mat2[1][0] =  si;
+       mat2[0][1] = -si;
+       Mat3MulMat3(mat4,mat2,mat1);
+       Mat3Transp(mat1);
+
+       Mat3MulMat3(mat2,mat1,mat3);
+       Mat3MulVecfl(mat2,lvec);
+       Mat3MulMat3(mat2,mat1,mat4);
+       Mat3MulVecfl(mat2,vvec);
+
+       return;
+}
+
+static void drawlamp(const bContext *C, Scene *scene, View3D *v3d, Object *ob)
+{
+       Lamp *la;
+       float vec[3], lvec[3], vvec[3], circrad, x,y,z;
+       float pixsize, lampsize;
+       float imat[4][4], curcol[4];
+       char col[4];
+
+       if(G.f & G_RENDER_SHADOW)
+               return;
+       
+       la= ob->data;
+       
+       /* we first draw only the screen aligned & fixed scale stuff */
+       glPushMatrix();
+       wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
+
+       /* lets calculate the scale: */
+       pixsize= v3d->persmat[0][3]*ob->obmat[3][0]+ v3d->persmat[1][3]*ob->obmat[3][1]+ v3d->persmat[2][3]*ob->obmat[3][2]+ v3d->persmat[3][3];
+       pixsize*= v3d->pixsize;
+       lampsize= pixsize*((float)U.obcenter_dia*0.5f);
+
+       /* and view aligned matrix: */
+       Mat4CpyMat4(imat, v3d->viewinv);
+       Normalize(imat[0]);
+       Normalize(imat[1]);
+       
+       /* for AA effects */
+       glGetFloatv(GL_CURRENT_COLOR, curcol);
+       curcol[3]= 0.6;
+       glColor4fv(curcol);
+       
+       if(ob->id.us>1) {
+               if (ob==OBACT || (ob->flag & SELECT)) glColor4ub(0x88, 0xFF, 0xFF, 155);
+               else glColor4ub(0x77, 0xCC, 0xCC, 155);
+       }
+       
+       /* Inner Circle */
+       VECCOPY(vec, ob->obmat[3]);
+       glEnable(GL_BLEND);
+       drawcircball(GL_LINE_LOOP, vec, lampsize, imat);
+       glDisable(GL_BLEND);
+       drawcircball(GL_POLYGON, vec, lampsize, imat);
+       
+       /* restore */
+       if(ob->id.us>1)
+               glColor4fv(curcol);
+               
+       /* Outer circle */
+       circrad = 3.0f*lampsize;
+       drawcircball(GL_LINE_LOOP, vec, circrad, imat);
+       
+       setlinestyle(3);
+
+       /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
+       if (la->type!=LA_HEMI) {
+               if ((la->mode & LA_SHAD_RAY) ||
+                       ((la->mode & LA_SHAD_BUF) && (la->type==LA_SPOT)) )
+               {
+                       drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f*pixsize, imat);
+               }
+       }
+       
+       /* draw the pretty sun rays */
+       if(la->type==LA_SUN) {
+               float v1[3], v2[3], mat[3][3];
+               short axis;
+               
+               /* setup a 45 degree rotation matrix */
+               VecRotToMat3(imat[2], M_PI/4.0f, mat);
+               
+               /* vectors */
+               VECCOPY(v1, imat[0]);
+               VecMulf(v1, circrad*1.2f);
+               VECCOPY(v2, imat[0]);
+               VecMulf(v2, circrad*2.5f);
+               
+               /* center */
+               glTranslatef(vec[0], vec[1], vec[2]);
+               
+               setlinestyle(3);
+               
+               glBegin(GL_LINES);
+               for (axis=0; axis<8; axis++) {
+                       glVertex3fv(v1);
+                       glVertex3fv(v2);
+                       Mat3MulVecfl(mat, v1);
+                       Mat3MulVecfl(mat, v2);
+               }
+               glEnd();
+               
+               glTranslatef(-vec[0], -vec[1], -vec[2]);
+
+       }               
+       
+       if (la->type==LA_LOCAL) {
+               if(la->mode & LA_SPHERE) {
+                       drawcircball(GL_LINE_LOOP, vec, la->dist, imat);
+               }
+               /* yafray: for photonlight also draw lightcone as for spot */
+       }
+       
+       glPopMatrix();  /* back in object space */
+       vec[0]= vec[1]= vec[2]= 0.0f;
+       
+       if ((la->type==LA_SPOT) || (la->type==LA_YF_PHOTON)) {  
+               lvec[0]=lvec[1]= 0.0; 
+               lvec[2] = 1.0;
+               x = v3d->persmat[0][2];
+               y = v3d->persmat[1][2];
+               z = v3d->persmat[2][2];
+               vvec[0]= x*ob->obmat[0][0] + y*ob->obmat[0][1] + z*ob->obmat[0][2];
+               vvec[1]= x*ob->obmat[1][0] + y*ob->obmat[1][1] + z*ob->obmat[1][2];
+               vvec[2]= x*ob->obmat[2][0] + y*ob->obmat[2][1] + z*ob->obmat[2][2];
+
+               y = cos( M_PI*la->spotsize/360.0 );
+               spotvolume(lvec, vvec, y);
+               x = -la->dist;
+               lvec[0] *=  x ; 
+               lvec[1] *=  x ; 
+               lvec[2] *=  x;
+               vvec[0] *= x ; 
+               vvec[1] *= x ; 
+               vvec[2] *= x;
+
+               /* draw the angled sides of the cone */
+               glBegin(GL_LINE_STRIP);
+                       glVertex3fv(vvec);
+                       glVertex3fv(vec);
+                       glVertex3fv(lvec);
+               glEnd();
+               
+               z = x*sqrt(1.0 - y*y);
+               x *= y;
+
+               /* draw the circle/square at the end of the cone */
+               glTranslatef(0.0, 0.0 ,  x);
+               if(la->mode & LA_SQUARE) {
+                       vvec[0]= fabs(z);
+                       vvec[1]= fabs(z);
+                       vvec[2]= 0.0;
+                       glBegin(GL_LINE_LOOP);
+                               glVertex3fv(vvec);
+                               vvec[1]= -fabs(z);
+                               glVertex3fv(vvec);
+                               vvec[0]= -fabs(z);
+                               glVertex3fv(vvec);
+                               vvec[1]= fabs(z);
+                               glVertex3fv(vvec);
+                       glEnd();
+               }
+               else circ(0.0, 0.0, fabs(z));
+               
+               /* draw the circle/square representing spotbl */
+               if(la->type==LA_SPOT) {
+                       float spotblcirc = fabs(z)*(1 - pow(la->spotblend, 2));
+                       /* make sure the line is always visible - prevent it from reaching the outer border (or 0) 
+                        * values are kinda arbitrary - just what seemed to work well */
+                       if (spotblcirc == 0) spotblcirc = 0.15;
+                       else if (spotblcirc == fabs(z)) spotblcirc = fabs(z) - 0.07;
+                       circ(0.0, 0.0, spotblcirc);
+               }
+               
+       }
+       else if ELEM(la->type, LA_HEMI, LA_SUN) {
+               
+               /* draw the line from the circle along the dist */
+               glBegin(GL_LINE_STRIP);
+                       vec[2] = -circrad;
+                       glVertex3fv(vec); 
+                       vec[2]= -la->dist; 
+                       glVertex3fv(vec);
+               glEnd();
+               
+               if(la->type==LA_HEMI) {
+                       /* draw the hemisphere curves */
+                       short axis, steps, dir;
+                       float outdist, zdist, mul;
+                       vec[0]=vec[1]=vec[2]= 0.0;
+                       outdist = 0.14; mul = 1.4; dir = 1;
+                       
+                       setlinestyle(4);
+                       /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */
+                       for (axis=0; axis<4; axis++) {
+                               float v[3]= {0.0, 0.0, 0.0};
+                               zdist = 0.02;
+                               
+                               glBegin(GL_LINE_STRIP);
+                               
+                               for (steps=0; steps<6; steps++) {
+                                       if (axis == 0 || axis == 1) {           /* x axis up, x axis down */    
+                                               /* make the arcs start at the edge of the energy circle */
+                                               if (steps == 0) v[0] = dir*circrad;
+                                               else v[0] = v[0] + dir*(steps*outdist);
+                                       } else if (axis == 2 || axis == 3) {            /* y axis up, y axis down */
+                                               /* make the arcs start at the edge of the energy circle */
+                                               if (steps == 0) v[1] = dir*circrad;
+                                               else v[1] = v[1] + dir*(steps*outdist); 
+                                       }
+               
+                                       v[2] = v[2] - steps*zdist;
+                                       
+                                       glVertex3fv(v);
+                                       
+                                       zdist = zdist * mul;
+                               }
+                               
+                               glEnd();
+                               /* flip the direction */
+                               dir = -dir;
+                       }
+               }
+       } else if(la->type==LA_AREA) {
+               setlinestyle(3);
+               if(la->area_shape==LA_AREA_SQUARE) 
+                       fdrawbox(-la->area_size*0.5, -la->area_size*0.5, la->area_size*0.5, la->area_size*0.5);
+               else if(la->area_shape==LA_AREA_RECT) 
+                       fdrawbox(-la->area_size*0.5, -la->area_sizey*0.5, la->area_size*0.5, la->area_sizey*0.5);
+
+               glBegin(GL_LINE_STRIP); 
+               glVertex3f(0.0,0.0,-circrad);
+               glVertex3f(0.0,0.0,-la->dist);
+               glEnd();
+       }
+       
+       /* and back to viewspace */
+       wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
+       VECCOPY(vec, ob->obmat[3]);
+
+       setlinestyle(0);
+       
+       if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF) ) {
+               drawshadbuflimits(la, ob->obmat);
+       }
+       
+       UI_GetThemeColor4ubv(TH_LAMP, col);
+       glColor4ub(col[0], col[1], col[2], col[3]);
+        
+       glEnable(GL_BLEND);
+       
+       if (vec[2]>0) vec[2] -= circrad;
+       else vec[2] += circrad;
+       
+       glBegin(GL_LINE_STRIP);
+               glVertex3fv(vec); 
+               vec[2]= 0; 
+               glVertex3fv(vec);
+       glEnd();
+       
+       glPointSize(2.0);
+       glBegin(GL_POINTS);
+               glVertex3fv(vec);
+       glEnd();
+       glPointSize(1.0);
+       
+       glDisable(GL_BLEND);
+       
+       /* restore for drawing extra stuff */
+       glColor3fv(curcol);
+
+}
+
+static void draw_limit_line(float sta, float end, unsigned int col)
+{
+       glBegin(GL_LINES);
+       glVertex3f(0.0, 0.0, -sta);
+       glVertex3f(0.0, 0.0, -end);
+       glEnd();
+
+       glPointSize(3.0);
+       glBegin(GL_POINTS);
+       cpack(col);
+       glVertex3f(0.0, 0.0, -sta);
+       glVertex3f(0.0, 0.0, -end);
+       glEnd();
+       glPointSize(1.0);
+}              
+
+
+/* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
+/* qdn: now also enabled for Blender to set focus point for defocus composit node */
+static void draw_focus_cross(float dist, float size)
+{
+       glBegin(GL_LINES);
+       glVertex3f(-size, 0.f, -dist);
+       glVertex3f(size, 0.f, -dist);
+       glVertex3f(0.f, -size, -dist);
+       glVertex3f(0.f, size, -dist);
+       glEnd();
+}
+
+/* flag similar to draw_object() */
+static void drawcamera(const bContext *C, Scene *scene, View3D *v3d, Object *ob, int flag)
+{
+       /* a standing up pyramid with (0,0,0) as top */
+       Camera *cam;
+       World *wrld;
+       float vec[8][4], tmat[4][4], fac, facx, facy, depth;
+       int i;
+
+       if(G.f & G_RENDER_SHADOW)
+               return;
+
+       cam= ob->data;
+       
+       glDisable(GL_LIGHTING);
+       glDisable(GL_CULL_FACE);
+       
+       if(v3d->persp>=2 && cam->type==CAM_ORTHO && ob==v3d->camera) {
+               facx= 0.5*cam->ortho_scale*1.28;
+               facy= 0.5*cam->ortho_scale*1.024;
+               depth= -cam->clipsta-0.1;
+       }
+       else {
+               fac= cam->drawsize;
+               if(v3d->persp>=2 && ob==v3d->camera) fac= cam->clipsta+0.1; /* that way it's always visible */
+               
+               depth= - fac*cam->lens/16.0;
+               facx= fac*1.28;
+               facy= fac*1.024;
+       }
+       
+       vec[0][0]= 0.0; vec[0][1]= 0.0; vec[0][2]= 0.001;       /* GLBUG: for picking at iris Entry (well thats old!) */
+       vec[1][0]= facx; vec[1][1]= facy; vec[1][2]= depth;
+       vec[2][0]= facx; vec[2][1]= -facy; vec[2][2]= depth;
+       vec[3][0]= -facx; vec[3][1]= -facy; vec[3][2]= depth;
+       vec[4][0]= -facx; vec[4][1]= facy; vec[4][2]= depth;
+
+       glBegin(GL_LINE_LOOP);
+               glVertex3fv(vec[1]); 
+               glVertex3fv(vec[2]); 
+               glVertex3fv(vec[3]); 
+               glVertex3fv(vec[4]);
+       glEnd();
+       
+
+       if(v3d->persp>=2 && ob==v3d->camera) return;
+       
+       glBegin(GL_LINE_STRIP);
+               glVertex3fv(vec[2]); 
+               glVertex3fv(vec[0]);
+               glVertex3fv(vec[1]);
+               glVertex3fv(vec[4]);
+               glVertex3fv(vec[0]);
+               glVertex3fv(vec[3]); 
+       glEnd();
+
+
+       /* arrow on top */
+       vec[0][2]= depth;
+
+       
+       /* draw an outline arrow for inactive cameras and filled
+        * for active cameras. We actually draw both outline+filled
+        * for active cameras so the wire can be seen side-on */        
+       for (i=0;i<2;i++) {
+               if (i==0) glBegin(GL_LINE_LOOP);
+               else if (i==1 && (ob == v3d->camera)) glBegin(GL_TRIANGLES);
+               else break;
+               
+               vec[0][0]= -0.7*cam->drawsize;
+               vec[0][1]= 1.1*cam->drawsize;
+               glVertex3fv(vec[0]);
+               
+               vec[0][0]= 0.0; 
+               vec[0][1]= 1.8*cam->drawsize;
+               glVertex3fv(vec[0]);
+               
+               vec[0][0]= 0.7*cam->drawsize; 
+               vec[0][1]= 1.1*cam->drawsize;
+               glVertex3fv(vec[0]);
+       
+               glEnd();
+       }
+
+       if(flag==0) {
+               if(cam->flag & (CAM_SHOWLIMITS+CAM_SHOWMIST)) {
+                       wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
+                       Mat4CpyMat4(vec, ob->obmat);
+                       Mat4Ortho(vec);
+                       wmMultMatrix(CTX_wm_window(C), vec);
+
+                       MTC_Mat4SwapMat4(v3d->persmat, tmat);
+                       wmGetSingleMatrix(CTX_wm_window(C), v3d->persmat);
+
+                       if(cam->flag & CAM_SHOWLIMITS) {
+                               draw_limit_line(cam->clipsta, cam->clipend, 0x77FFFF);
+                               /* qdn: was yafray only, now also enabled for Blender to be used with defocus composit node */
+                               draw_focus_cross(dof_camera(ob), cam->drawsize);
+                       }
+
+                       wrld= scene->world;
+                       if(cam->flag & CAM_SHOWMIST) 
+                               if(wrld) draw_limit_line(wrld->miststa, wrld->miststa+wrld->mistdist, 0xFFFFFF);
+                               
+                       MTC_Mat4SwapMat4(v3d->persmat, tmat);
+               }
+       }
+}
+
+static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel)
+{
+       BPoint *bp = lt->def;
+       float *co = dl?dl->verts:NULL;
+       int u, v, w;
+
+       UI_ThemeColor(sel?TH_VERTEX_SELECT:TH_VERTEX);
+       glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
+       bglBegin(GL_POINTS);
+
+       for(w=0; w<lt->pntsw; w++) {
+               int wxt = (w==0 || w==lt->pntsw-1);
+               for(v=0; v<lt->pntsv; v++) {
+                       int vxt = (v==0 || v==lt->pntsv-1);
+                       for(u=0; u<lt->pntsu; u++, bp++, co+=3) {
+                               int uxt = (u==0 || u==lt->pntsu-1);
+                               if(!(lt->flag & LT_OUTSIDE) || uxt || vxt || wxt) {
+                                       if(bp->hide==0) {
+                                               if((bp->f1 & SELECT)==sel) {
+                                                       bglVertex3fv(dl?co:bp->vec);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       glPointSize(1.0);
+       bglEnd();       
+}
+
+void lattice_foreachScreenVert(void (*func)(void *userData, BPoint *bp, int x, int y), void *userData)
+{
+       ARegion *ar= NULL;      // XXX
+       View3D *v3d= NULL; // XXX
+       BPoint *bp = editLatt->def;
+       DispList *dl = find_displist(&G.obedit->disp, DL_VERTS);
+       float *co = dl?dl->verts:NULL;
+       float pmat[4][4], vmat[4][4];
+       int i, N = editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
+       short s[2];
+
+       view3d_get_object_project_mat(v3d, G.obedit, pmat, vmat);
+
+       for (i=0; i<N; i++, bp++, co+=3) {
+               if (bp->hide==0) {
+                       view3d_project_short_clip(ar, v3d, dl?co:bp->vec, s, pmat, vmat);
+                       func(userData, bp, s[0], s[1]);
+               }
+       }
+}
+
+static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol)
+{
+       int index = ((w*lt->pntsv + v)*lt->pntsu) + u;
+
+       if(use_wcol) {
+#if 0
+               XXX
+               float col[3];
+               MDeformWeight *mdw= get_defweight (lt->dvert+index, use_wcol-1);
+               
+               weight_to_rgb(mdw?mdw->weight:0.0f, col, col+1, col+2);
+               glColor3fv(col);
+#endif
+       }
+       
+       if (dl) {
+               glVertex3fv(&dl->verts[index*3]);
+       } else {
+               glVertex3fv(lt->def[index].vec);
+       }
+}
+
+/* lattice color is hardcoded, now also shows weightgroup values in edit mode */
+static void drawlattice(View3D *v3d, Object *ob)
+{
+       Lattice *lt;
+       DispList *dl;
+       int u, v, w;
+       int use_wcol= 0;
+
+       lt= (ob==G.obedit)?editLatt:ob->data;
+       
+       /* now we default make displist, this will modifiers work for non animated case */
+       if(ob->disp.first==NULL)
+               lattice_calc_modifiers(ob);
+       dl= find_displist(&ob->disp, DL_VERTS);
+       
+       if(ob==G.obedit) {
+               cpack(0x004000);
+               
+               if(ob->defbase.first && lt->dvert) {
+                       use_wcol= ob->actdef;
+                       glShadeModel(GL_SMOOTH);
+               }
+       }
+       
+       glBegin(GL_LINES);
+       for(w=0; w<lt->pntsw; w++) {
+               int wxt = (w==0 || w==lt->pntsw-1);
+               for(v=0; v<lt->pntsv; v++) {
+                       int vxt = (v==0 || v==lt->pntsv-1);
+                       for(u=0; u<lt->pntsu; u++) {
+                               int uxt = (u==0 || u==lt->pntsu-1);
+
+                               if(w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
+                                       drawlattice__point(lt, dl, u, v, w-1, use_wcol);
+                                       drawlattice__point(lt, dl, u, v, w, use_wcol);
+                               }
+                               if(v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
+                                       drawlattice__point(lt, dl, u, v-1, w, use_wcol);
+                                       drawlattice__point(lt, dl, u, v, w, use_wcol);
+                               }
+                               if(u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
+                                       drawlattice__point(lt, dl, u-1, v, w, use_wcol);
+                                       drawlattice__point(lt, dl, u, v, w, use_wcol);
+                               }
+                       }
+               }
+       }               
+       glEnd();
+       
+       /* restoration for weight colors */
+       if(use_wcol)
+               glShadeModel(GL_FLAT);
+
+       if(ob==G.obedit) {
+               if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
+               
+               lattice_draw_verts(lt, dl, 0);
+               lattice_draw_verts(lt, dl, 1);
+               
+               if(v3d->zbuf) glEnable(GL_DEPTH_TEST); 
+       }
+}
+
+/* ***************** ******************** */
+
+static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
+{
+       struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
+       ARegion *ar= NULL; // XXX
+       View3D *v3d= NULL; // XXX
+       EditVert *eve = EM_get_vert_for_index(index);
+       short s[2];
+
+       if (eve->h==0) {
+               if (data->clipVerts) {
+                       view3d_project_short_clip(ar, v3d, co, s, data->pmat, data->vmat);
+               } else {
+                       view3d_project_short_noclip(ar, co, s, data->pmat);
+               }
+
+               data->func(data->userData, eve, s[0], s[1], index);
+       }
+}
+void mesh_foreachScreenVert(void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts)
+{
+       struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
+       View3D *v3d= NULL; // XXX
+       DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
+
+       data.func = func;
+       data.userData = userData;
+       data.clipVerts = clipVerts;
+
+       view3d_get_object_project_mat(v3d, G.obedit, data.pmat, data.vmat);
+
+       EM_init_index_arrays(1, 0, 0);
+       dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data);
+       EM_free_index_arrays();
+
+       dm->release(dm);
+}
+
+static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co)
+{
+       struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData;
+       ARegion *ar= NULL; // XXX
+       View3D *v3d= NULL; // XXX
+       EditEdge *eed = EM_get_edge_for_index(index);
+       short s[2][2];
+
+       if (eed->h==0) {
+               if (data->clipVerts==1) {
+                       view3d_project_short_clip(ar, v3d, v0co, s[0], data->pmat, data->vmat);
+                       view3d_project_short_clip(ar, v3d, v1co, s[1], data->pmat, data->vmat);
+               } else {
+                       view3d_project_short_noclip(ar, v0co, s[0], data->pmat);
+                       view3d_project_short_noclip(ar, v1co, s[1], data->pmat);
+
+                       if (data->clipVerts==2) {
+                if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<ar->winx && s[0][1]<ar->winy)) 
+                                       if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<ar->winx && s[1][1]<ar->winy)) 
+                                               return;
+                       }
+               }
+
+               data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index);
+       }
+}
+void mesh_foreachScreenEdge(void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts)
+{
+       struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } data;
+       View3D *v3d= NULL; // XXX
+       DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
+
+       data.func = func;
+       data.userData = userData;
+       data.clipVerts = clipVerts;
+
+       view3d_get_object_project_mat(v3d, G.obedit, data.pmat, data.vmat);
+
+       EM_init_index_arrays(0, 1, 0);
+       dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data);
+       EM_free_index_arrays();
+
+       dm->release(dm);
+}
+
+static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *no)
+{
+       struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; float pmat[4][4], vmat[4][4]; } *data = userData;
+       ARegion *ar= NULL; // XXX
+       View3D *v3d= NULL; // XXX
+       EditFace *efa = EM_get_face_for_index(index);
+       short s[2];
+
+       if (efa && efa->h==0 && efa->fgonf!=EM_FGON) {
+               view3d_project_short_clip(ar, v3d, cent, s, data->pmat, data->vmat);
+
+               data->func(data->userData, efa, s[0], s[1], index);
+       }
+}
+void mesh_foreachScreenFace(void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData)
+{
+       struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; float pmat[4][4], vmat[4][4]; } data;
+       DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
+       View3D *v3d= NULL; // XXX
+
+       data.func = func;
+       data.userData = userData;
+
+       view3d_get_object_project_mat(v3d, G.obedit, data.pmat, data.vmat);
+
+       EM_init_index_arrays(0, 0, 1);
+       dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data);
+       EM_free_index_arrays();
+
+       dm->release(dm);
+}
+
+void nurbs_foreachScreenVert(void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData)
+{
+       ARegion *ar= NULL; // XXX
+       View3D *v3d= NULL; // XXX
+       float pmat[4][4], vmat[4][4];
+       short s[2];
+       Nurb *nu;
+       int i;
+
+       view3d_get_object_project_mat(v3d, G.obedit, pmat, vmat);
+
+       for (nu= editNurb.first; nu; nu=nu->next) {
+               if((nu->type & 7)==CU_BEZIER) {
+                       for (i=0; i<nu->pntsu; i++) {
+                               BezTriple *bezt = &nu->bezt[i];
+
+                               if(bezt->hide==0) {
+                                       if (G.f & G_HIDDENHANDLES) {
+                                               view3d_project_short_clip(ar, v3d, bezt->vec[1], s, pmat, vmat);
+                                               if (s[0] != IS_CLIPPED)
+                                                       func(userData, nu, NULL, bezt, 1, s[0], s[1]);
+                                       } else {
+                                               view3d_project_short_clip(ar, v3d, bezt->vec[0], s, pmat, vmat);
+                                               if (s[0] != IS_CLIPPED)
+                                                       func(userData, nu, NULL, bezt, 0, s[0], s[1]);
+                                               view3d_project_short_clip(ar, v3d, bezt->vec[1], s, pmat, vmat);
+                                               if (s[0] != IS_CLIPPED)
+                                                       func(userData, nu, NULL, bezt, 1, s[0], s[1]);
+                                               view3d_project_short_clip(ar, v3d, bezt->vec[2], s, pmat, vmat);
+                                               if (s[0] != IS_CLIPPED)
+                                                       func(userData, nu, NULL, bezt, 2, s[0], s[1]);
+                                       }
+                               }
+                       }
+               }
+               else {
+                       for (i=0; i<nu->pntsu*nu->pntsv; i++) {
+                               BPoint *bp = &nu->bp[i];
+
+                               if(bp->hide==0) {
+                                       view3d_project_short_clip(ar, v3d, bp->vec, s, pmat, vmat);
+                                       func(userData, nu, bp, NULL, -1, s[0], s[1]);
+                               }
+                       }
+               }
+       }
+}
+
+/* ************** DRAW MESH ****************** */
+
+/* First section is all the "simple" draw routines, 
+ * ones that just pass some sort of primitive to GL,
+ * with perhaps various options to control lighting,
+ * color, etc.
+ *
+ * These routines should not have user interface related
+ * logic!!!
+ */
+
+static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
+{
+       Scene *scene= NULL; // XXX
+       EditFace *efa = EM_get_face_for_index(index);
+
+       if (efa->h==0 && efa->fgonf!=EM_FGON) {
+               glVertex3fv(cent);
+               glVertex3f(     cent[0] + no[0]*scene->editbutsize,
+                                       cent[1] + no[1]*scene->editbutsize,
+                                       cent[2] + no[2]*scene->editbutsize);
+       }
+}
+static void draw_dm_face_normals(DerivedMesh *dm) {
+       glBegin(GL_LINES);
+       dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, 0);
+       glEnd();
+}
+
+static void draw_dm_face_centers__mapFunc(void *userData, int index, float *cent, float *no)
+{
+       EditFace *efa = EM_get_face_for_index(index);
+       int sel = *((int*) userData);
+
+       if (efa->h==0 && efa->fgonf!=EM_FGON && (efa->f&SELECT)==sel) {
+               bglVertex3fv(cent);
+       }
+}
+static void draw_dm_face_centers(DerivedMesh *dm, int sel)
+{
+       bglBegin(GL_POINTS);
+       dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &sel);
+       bglEnd();
+}
+
+static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
+{
+       Scene *scene= NULL; // XXX
+       EditVert *eve = EM_get_vert_for_index(index);
+
+       if (eve->h==0) {
+               glVertex3fv(co);
+
+               if (no_f) {
+                       glVertex3f(     co[0] + no_f[0]*scene->editbutsize,
+                                               co[1] + no_f[1]*scene->editbutsize,
+                                               co[2] + no_f[2]*scene->editbutsize);
+               } else {
+                       glVertex3f(     co[0] + no_s[0]*scene->editbutsize/32767.0f,
+                                               co[1] + no_s[1]*scene->editbutsize/32767.0f,
+                                               co[2] + no_s[2]*scene->editbutsize/32767.0f);
+               }
+       }
+}
+static void draw_dm_vert_normals(DerivedMesh *dm) {
+       glBegin(GL_LINES);
+       dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, NULL);
+       glEnd();
+}
+
+       /* Draw verts with color set based on selection */
+static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
+{
+       struct { int sel; EditVert *eve_act; } * data = userData;
+       EditVert *eve = EM_get_vert_for_index(index);
+
+       if (eve->h==0 && (eve->f&SELECT)==data->sel) {
+               /* draw active larger - need to stop/start point drawing for this :/ */
+               if (eve==data->eve_act) {
+                       float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
+                       UI_ThemeColor4(TH_EDITMESH_ACTIVE);
+                       
+                       bglEnd();
+                       
+                       glPointSize(size);
+                       bglBegin(GL_POINTS);
+                       bglVertex3fv(co);
+                       bglEnd();
+                       
+                       UI_ThemeColor4(data->sel?TH_VERTEX_SELECT:TH_VERTEX);
+                       glPointSize(size);
+                       bglBegin(GL_POINTS);
+               } else {
+                       bglVertex3fv(co);
+               }
+       }
+}
+static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act)
+{
+       struct { int sel; EditVert *eve_act; } data;
+       data.sel = sel;
+       data.eve_act = eve_act;
+       
+       bglBegin(GL_POINTS);
+       dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data);
+       bglEnd();
+}
+
+       /* Draw edges with color set based on selection */
+static int draw_dm_edges_sel__setDrawOptions(void *userData, int index)
+{
+       EditEdge *eed = EM_get_edge_for_index(index);
+       //unsigned char **cols = userData, *col;
+       struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } * data = userData;
+       unsigned char *col;
+
+       if (eed->h==0) {
+               if (eed==data->eed_act) {
+                       glColor4ubv(data->actCol);
+               } else {
+                       if (eed->f&SELECT) {
+                               col = data->selCol;
+                       } else {
+                               col = data->baseCol;
+                       }
+                       /* no alpha, this is used so a transparent color can disable drawing unselected edges in editmode  */
+                       if (col[3]==0) return 0;
+                       
+                       glColor4ubv(col);
+               }
+               return 1;
+       } else {
+               return 0;
+       }
+}
+static void draw_dm_edges_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditEdge *eed_act) 
+{
+       struct { unsigned char *baseCol, *selCol, *actCol; EditEdge *eed_act; } data;
+       
+       data.baseCol = baseCol;
+       data.selCol = selCol;
+       data.actCol = actCol;
+       data.eed_act = eed_act;
+       dm->drawMappedEdges(dm, draw_dm_edges_sel__setDrawOptions, &data);
+}
+
+       /* Draw edges */
+static int draw_dm_edges__setDrawOptions(void *userData, int index)
+{
+       return EM_get_edge_for_index(index)->h==0;
+}
+static void draw_dm_edges(DerivedMesh *dm) 
+{
+       dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, NULL);
+}
+
+       /* Draw edges with color interpolated based on selection */
+static int draw_dm_edges_sel_interp__setDrawOptions(void *userData, int index)
+{
+       return EM_get_edge_for_index(index)->h==0;
+}
+static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int index, float t)
+{
+       EditEdge *eed = EM_get_edge_for_index(index);
+       unsigned char **cols = userData;
+       unsigned char *col0 = cols[(eed->v1->f&SELECT)?1:0];
+       unsigned char *col1 = cols[(eed->v2->f&SELECT)?1:0];
+
+       glColor4ub(     col0[0] + (col1[0]-col0[0])*t,
+                               col0[1] + (col1[1]-col0[1])*t,
+                               col0[2] + (col1[2]-col0[2])*t,
+                               col0[3] + (col1[3]-col0[3])*t);
+}
+static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol)
+{
+       unsigned char *cols[2];
+       cols[0] = baseCol;
+       cols[1] = selCol;
+       dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols);
+}
+
+       /* Draw only seam edges */
+static int draw_dm_edges_seams__setDrawOptions(void *userData, int index)
+{
+       EditEdge *eed = EM_get_edge_for_index(index);
+
+       return (eed->h==0 && eed->seam);
+}
+static void draw_dm_edges_seams(DerivedMesh *dm)
+{
+       dm->drawMappedEdges(dm, draw_dm_edges_seams__setDrawOptions, NULL);
+}
+
+       /* Draw only sharp edges */
+static int draw_dm_edges_sharp__setDrawOptions(void *userData, int index)
+{
+       EditEdge *eed = EM_get_edge_for_index(index);
+
+       return (eed->h==0 && eed->sharp);
+}
+static void draw_dm_edges_sharp(DerivedMesh *dm)
+{
+       dm->drawMappedEdges(dm, draw_dm_edges_sharp__setDrawOptions, NULL);
+}
+
+
+       /* Draw faces with color set based on selection
+        * return 2 for the active face so it renders with stipple enabled */
+static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *drawSmooth_r)
+{
+       struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
+       EditFace *efa = EM_get_face_for_index(index);
+       unsigned char *col;
+       
+       if (efa->h==0) {
+               if (efa == data->efa_act) {
+                       glColor4ubv(data->cols[2]);
+                       return 2; /* stipple */
+               } else {
+                       col = data->cols[(efa->f&SELECT)?1:0];
+                       if (col[3]==0) return 0;
+                       glColor4ubv(col);
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+/* also draws the active face */
+static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
+{
+       struct { unsigned char *cols[3]; EditFace *efa_act; } data;
+       data.cols[0] = baseCol;
+       data.cols[1] = selCol;
+       data.cols[2] = actCol;
+       data.efa_act = efa_act;
+       
+       dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0);
+}
+
+static int draw_dm_creases__setDrawOptions(void *userData, int index)
+{
+       EditEdge *eed = EM_get_edge_for_index(index);
+
+       if (eed->h==0 && eed->crease!=0.0) {
+               UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->crease);
+               return 1;
+       } else {
+               return 0;
+       }
+}
+static void draw_dm_creases(DerivedMesh *dm)
+{
+       glLineWidth(3.0);
+       dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, NULL);
+       glLineWidth(1.0);
+}
+
+static int draw_dm_bweights__setDrawOptions(void *userData, int index)
+{
+       EditEdge *eed = EM_get_edge_for_index(index);
+
+       if (eed->h==0 && eed->bweight!=0.0) {
+               UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, eed->bweight);
+               return 1;
+       } else {
+               return 0;
+       }
+}
+static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
+{
+       EditVert *eve = EM_get_vert_for_index(index);
+
+       if (eve->h==0 && eve->bweight!=0.0) {
+               UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_SELECT, eve->bweight);
+               bglVertex3fv(co);
+       }
+}
+static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
+{
+       if (scene->selectmode & SCE_SELECT_VERTEX) {
+               glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
+               bglBegin(GL_POINTS);
+               dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
+               bglEnd();
+       }
+       else {
+               glLineWidth(3.0);
+               dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, NULL);
+               glLineWidth(1.0);
+       }
+}
+
+/* Second section of routines: Combine first sets to form fancy
+ * drawing routines (for example rendering twice to get overlays).
+ *
+ * Also includes routines that are basic drawing but are too
+ * specialized to be split out (like drawing creases or measurements).
+ */
+
+/* EditMesh drawing routines*/
+
+static void draw_em_fancy_verts(Scene *scene, View3D *v3d, EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act)
+{
+       int sel;
+
+       if(v3d->zbuf) glDepthMask(0);           // disable write in zbuffer, zbuf select
+
+       for (sel=0; sel<2; sel++) {
+               char col[4], fcol[4];
+               int pass;
+
+               UI_GetThemeColor3ubv(sel?TH_VERTEX_SELECT:TH_VERTEX, col);
+               UI_GetThemeColor3ubv(sel?TH_FACE_DOT:TH_WIRE, fcol);
+
+               for (pass=0; pass<2; pass++) {
+                       float size = UI_GetThemeValuef(TH_VERTEX_SIZE);
+                       float fsize = UI_GetThemeValuef(TH_FACEDOT_SIZE);
+
+                       if (pass==0) {
+                               if(v3d->zbuf && !(v3d->flag&V3D_ZBUF_SELECT)) {
+                                       glDisable(GL_DEPTH_TEST);
+                                               
+                                       glEnable(GL_BLEND);
+                               } else {
+                                       continue;
+                               }
+
+                               size = (size>2.1?size/2.0:size);
+                               fsize = (fsize>2.1?fsize/2.0:fsize);
+                               col[3] = fcol[3] = 100;
+                       } else {
+                               col[3] = fcol[3] = 255;
+                       }
+                               
+                       if(scene->selectmode & SCE_SELECT_VERTEX) {
+                               glPointSize(size);
+                               glColor4ubv((GLubyte *)col);
+                               draw_dm_verts(cageDM, sel, eve_act);
+                       }
+                       
+                       if( CHECK_OB_DRAWFACEDOT(scene, v3d, G.obedit->dt) ) {
+                               glPointSize(fsize);
+                               glColor4ubv((GLubyte *)fcol);
+                               draw_dm_face_centers(cageDM, sel);
+                       }
+                       
+                       if (pass==0) {
+                               glDisable(GL_BLEND);
+                               glEnable(GL_DEPTH_TEST);
+                       }
+               }
+       }
+
+       if(v3d->zbuf) glDepthMask(1);
+       glPointSize(1.0);
+}
+
+static void draw_em_fancy_edges(Scene *scene, View3D *v3d, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
+{
+       int pass;
+       unsigned char wireCol[4], selCol[4], actCol[4];
+
+       /* since this function does transparant... */
+       UI_GetThemeColor4ubv(TH_EDGE_SELECT, (char *)selCol);
+       UI_GetThemeColor4ubv(TH_WIRE, (char *)wireCol);
+       UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)actCol);
+       
+       /* when sel only is used, dont render wire, only selected, this is used for
+        * textured draw mode when the 'edges' option is disabled */
+       if (sel_only)
+               wireCol[3] = 0;
+
+       for (pass=0; pass<2; pass++) {
+                       /* show wires in transparant when no zbuf clipping for select */
+               if (pass==0) {
+                       if (v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0) {
+                               glEnable(GL_BLEND);
+                               glDisable(GL_DEPTH_TEST);
+                               selCol[3] = 85;
+                               if (!sel_only) wireCol[3] = 85;
+                       } else {
+                               continue;
+                       }
+               } else {
+                       selCol[3] = 255;
+                       if (!sel_only) wireCol[3] = 255;
+               }
+
+               if(scene->selectmode == SCE_SELECT_FACE) {
+                       draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
+               }       
+               else if( (G.f & G_DRAWEDGES) || (scene->selectmode & SCE_SELECT_EDGE) ) {       
+                       if(cageDM->drawMappedEdgesInterp && (scene->selectmode & SCE_SELECT_VERTEX)) {
+                               glShadeModel(GL_SMOOTH);
+                               draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
+                               glShadeModel(GL_FLAT);
+                       } else {
+                               draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
+                       }
+               }
+               else {
+                       if (!sel_only) {
+                               glColor4ubv(wireCol);
+                               draw_dm_edges(cageDM);
+                       }
+               }
+
+               if (pass==0) {
+                       glDisable(GL_BLEND);
+                       glEnable(GL_DEPTH_TEST);
+               }
+       }
+}      
+
+static void draw_em_measure_stats(View3D *v3d, Object *ob, EditMesh *em)
+{
+       EditEdge *eed;
+       EditFace *efa;
+       float v1[3], v2[3], v3[3], v4[3];
+       float fvec[3];
+       char val[32]; /* Stores the measurement display text here */
+       char conv_float[5]; /* Use a float conversion matching the grid size */
+       float area, col[3]; /* area of the face,  color of the text to draw */
+       
+       if(G.f & (G_RENDER_OGL|G_RENDER_SHADOW))
+               return;
+
+       /* make the precission of the pronted value proportionate to the gridsize */
+       if ((v3d->grid) < 0.01)
+               strcpy(conv_float, "%.6f");
+       else if ((v3d->grid) < 0.1)
+               strcpy(conv_float, "%.5f");
+       else if ((v3d->grid) < 1.0)
+               strcpy(conv_float, "%.4f");
+       else if ((v3d->grid) < 10.0)
+               strcpy(conv_float, "%.3f");
+       else
+               strcpy(conv_float, "%.2f");
+       
+       
+       if(v3d->zbuf && (v3d->flag & V3D_ZBUF_SELECT)==0)
+               glDisable(GL_DEPTH_TEST);
+
+       if(v3d->zbuf) bglPolygonOffset(5.0);
+       
+       if(G.f & G_DRAW_EDGELEN) {
+               UI_GetThemeColor3fv(TH_TEXT, col);
+               /* make color a bit more red */
+               if(col[0]> 0.5) {col[1]*=0.7; col[2]*= 0.7;}
+               else col[0]= col[0]*0.7 + 0.3;
+               glColor3fv(col);
+               
+               for(eed= em->edges.first; eed; eed= eed->next) {
+                       /* draw non fgon edges, or selected edges, or edges next to selected verts while draging */
+                       if((eed->h != EM_FGON) && ((eed->f & SELECT) || (G.moving && ((eed->v1->f & SELECT) || (eed->v2->f & SELECT)) ))) {
+                               VECCOPY(v1, eed->v1->co);
+                               VECCOPY(v2, eed->v2->co);
+                               
+                               glRasterPos3f( 0.5*(v1[0]+v2[0]),  0.5*(v1[1]+v2[1]),  0.5*(v1[2]+v2[2]));
+                               
+                               if(v3d->flag & V3D_GLOBAL_STATS) {
+                                       Mat4MulVecfl(ob->obmat, v1);
+                                       Mat4MulVecfl(ob->obmat, v2);
+                               }
+                               
+                               sprintf(val, conv_float, VecLenf(v1, v2));
+                               BMF_DrawString( G.fonts, val);
+                       }
+               }
+       }
+
+       if(G.f & G_DRAW_FACEAREA) {
+// XXX         extern int faceselectedOR(EditFace *efa, int flag);             // editmesh.h shouldn't be in this file... ok for now?
+               
+               UI_GetThemeColor3fv(TH_TEXT, col);
+               /* make color a bit more green */
+               if(col[1]> 0.5) {col[0]*=0.7; col[2]*= 0.7;}
+               else col[1]= col[1]*0.7 + 0.3;
+               glColor3fv(col);
+               
+               for(efa= em->faces.first; efa; efa= efa->next) {
+                       if((efa->f & SELECT)) { // XXX || (G.moving && faceselectedOR(efa, SELECT)) ) {
+                               VECCOPY(v1, efa->v1->co);
+                               VECCOPY(v2, efa->v2->co);
+                               VECCOPY(v3, efa->v3->co);
+                               if (efa->v4) {
+                                       VECCOPY(v4, efa->v4->co);
+                               }
+                               if(v3d->flag & V3D_GLOBAL_STATS) {
+                                       Mat4MulVecfl(ob->obmat, v1);
+                                       Mat4MulVecfl(ob->obmat, v2);
+                                       Mat4MulVecfl(ob->obmat, v3);
+                                       if (efa->v4) Mat4MulVecfl(ob->obmat, v4);
+                               }
+                               
+                               if (efa->v4)
+                                       area=  AreaQ3Dfl(v1, v2, v3, v4);
+                               else
+                                       area = AreaT3Dfl(v1, v2, v3);
+
+                               sprintf(val, conv_float, area);
+                               glRasterPos3fv(efa->cent);
+                               BMF_DrawString( G.fonts, val);
+                       }
+               }
+       }
+
+       if(G.f & G_DRAW_EDGEANG) {
+               EditEdge *e1, *e2, *e3, *e4;
+               
+               UI_GetThemeColor3fv(TH_TEXT, col);
+               /* make color a bit more blue */
+               if(col[2]> 0.5) {col[0]*=0.7; col[1]*= 0.7;}
+               else col[2]= col[2]*0.7 + 0.3;
+               glColor3fv(col);
+               
+               for(efa= em->faces.first; efa; efa= efa->next) {
+                       VECCOPY(v1, efa->v1->co);
+                       VECCOPY(v2, efa->v2->co);
+                       VECCOPY(v3, efa->v3->co);
+                       if(efa->v4) {
+                               VECCOPY(v4, efa->v4->co); 
+                       }
+                       else {
+                               VECCOPY(v4, v3);
+                       }
+                       if(v3d->flag & V3D_GLOBAL_STATS) {
+                               Mat4MulVecfl(ob->obmat, v1);
+                               Mat4MulVecfl(ob->obmat, v2);
+                               Mat4MulVecfl(ob->obmat, v3);
+                               Mat4MulVecfl(ob->obmat, v4);
+                       }
+                       
+                       e1= efa->e1;
+                       e2= efa->e2;
+                       e3= efa->e3;
+                       if(efa->e4) e4= efa->e4; else e4= e3;
+                       
+                       /* Calculate the angles */
+                               
+                       if( (e4->f & e1->f & SELECT) || (G.moving && (efa->v1->f & SELECT)) ) {
+                               /* Vec 1 */
+                               sprintf(val,"%.3f", VecAngle3(v4, v1, v2));
+                               VecLerpf(fvec, efa->cent, efa->v1->co, 0.8);
+                               glRasterPos3fv(fvec);
+                               BMF_DrawString( G.fonts, val);
+                       }
+                       if( (e1->f & e2->f & SELECT) || (G.moving && (efa->v2->f & SELECT)) ) {
+                               /* Vec 2 */
+                               sprintf(val,"%.3f", VecAngle3(v1, v2, v3));
+                               VecLerpf(fvec, efa->cent, efa->v2->co, 0.8);
+                               glRasterPos3fv(fvec);
+                               BMF_DrawString( G.fonts, val);
+                       }
+                       if( (e2->f & e3->f & SELECT) || (G.moving && (efa->v3->f & SELECT)) ) {
+                               /* Vec 3 */
+                               if(efa->v4) 
+                                       sprintf(val,"%.3f", VecAngle3(v2, v3, v4));
+                               else
+                                       sprintf(val,"%.3f", VecAngle3(v2, v3, v1));
+                               VecLerpf(fvec, efa->cent, efa->v3->co, 0.8);
+                               glRasterPos3fv(fvec);
+                               BMF_DrawString( G.fonts, val);
+                       }
+                               /* Vec 4 */
+                       if(efa->v4) {
+                               if( (e3->f & e4->f & SELECT) || (G.moving && (efa->v4->f & SELECT)) ) {
+                                       sprintf(val,"%.3f", VecAngle3(v3, v4, v1));
+                                       VecLerpf(fvec, efa->cent, efa->v4->co, 0.8);
+                                       glRasterPos3fv(fvec);
+                                       BMF_DrawString( G.fonts, val);
+                               }
+                       }
+               }
+       }    
+       
+       if(v3d->zbuf) {
+               glEnable(GL_DEPTH_TEST);
+               bglPolygonOffset(0.0);
+       }
+}
+
+static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth_r)
+{
+       EditFace *efa = EM_get_face_for_index(index);
+
+       if (efa->h==0) {
+               GPU_enable_material(efa->mat_nr+1, NULL);
+               return 1;
+       }
+       else
+               return 0;
+}
+
+static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
+{
+       EditFace *efa = EM_get_face_for_index(index);
+
+       return (efa->h==0);
+}
+
+static void draw_em_fancy(Scene *scene, View3D *v3d, Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt)
+{
+       Mesh *me = ob->data;
+       EditFace *efa_act = EM_get_actFace(0); /* annoying but active faces is stored differently */
+       EditEdge *eed_act = NULL;
+       EditVert *eve_act = NULL;
+       
+       if (G.editMesh->selected.last) {
+               EditSelection *ese = G.editMesh->selected.last;
+               /* face is handeled above */
+               /*if (ese->type == EDITFACE ) {
+                       efa_act = (EditFace *)ese->data;
+               } else */ if ( ese->type == EDITEDGE ) {
+                       eed_act = (EditEdge *)ese->data;
+               } else if ( ese->type == EDITVERT ) {
+                       eve_act = (EditVert *)ese->data;
+               }
+       }
+       
+       EM_init_index_arrays(1, 1, 1);
+
+       if(dt>OB_WIRE) {
+               if(CHECK_OB_DRAWTEXTURE(v3d, dt)) {
+                       if(draw_glsl_material(scene, ob, v3d, dt)) {
+                               glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
+
+                               finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material,
+                                       draw_em_fancy__setGLSLFaceOpts, NULL);
+                               GPU_disable_material();
+
+                               glFrontFace(GL_CCW);
+                       }
+                       else {
+                               draw_mesh_textured(scene, v3d, ob, finalDM, 0);
+                       }
+               }
+               else {
+                       glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED);
+
+                       glEnable(GL_LIGHTING);
+                       glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
+
+                       finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, 0, 0);
+
+                       glFrontFace(GL_CCW);
+                       glDisable(GL_LIGHTING);
+               }
+                       
+               // Setup for drawing wire over, disable zbuffer
+               // write to show selected edge wires better
+               UI_ThemeColor(TH_WIRE);
+
+               bglPolygonOffset(1.0);
+               glDepthMask(0);
+       } 
+       else {
+               if (cageDM!=finalDM) {
+                       UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
+                       finalDM->drawEdges(finalDM, 1);
+               }
+       }
+       
+       if((G.f & (G_DRAWFACES)) || FACESEL_PAINT_TEST) {       /* transp faces */
+               unsigned char col1[4], col2[4], col3[4];
+                       
+               UI_GetThemeColor4ubv(TH_FACE, (char *)col1);
+               UI_GetThemeColor4ubv(TH_FACE_SELECT, (char *)col2);
+               UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
+               
+               glEnable(GL_BLEND);
+               glDepthMask(0);         // disable write in zbuffer, needed for nice transp
+               
+               /* dont draw unselected faces, only selected, this is MUCH nicer when texturing */
+               if CHECK_OB_DRAWTEXTURE(v3d, dt)
+                       col1[3] = 0;
+               
+               draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
+
+               glDisable(GL_BLEND);
+               glDepthMask(1);         // restore write in zbuffer
+       } else if (efa_act) {
+               /* even if draw faces is off it would be nice to draw the stipple face
+                * Make all other faces zero alpha except for the active
+                * */
+               unsigned char col1[4], col2[4], col3[4];
+               col1[3] = col2[3] = 0; /* dont draw */
+               UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, (char *)col3);
+               
+               glEnable(GL_BLEND);
+               glDepthMask(0);         // disable write in zbuffer, needed for nice transp
+               
+               draw_dm_faces_sel(cageDM, col1, col2, col3, efa_act);
+
+               glDisable(GL_BLEND);
+               glDepthMask(1);         // restore write in zbuffer
+               
+       }
+
+       /* here starts all fancy draw-extra over */
+       if((G.f & G_DRAWEDGES)==0 && CHECK_OB_DRAWTEXTURE(v3d, dt)) {
+               /* we are drawing textures and 'G_DRAWEDGES' is disabled, dont draw any edges */
+               
+               /* only draw selected edges otherwise there is no way of telling if a face is selected */
+               draw_em_fancy_edges(scene, v3d, cageDM, 1, eed_act);
+               
+       } else {
+               if(G.f & G_DRAWSEAMS) {
+                       UI_ThemeColor(TH_EDGE_SEAM);
+                       glLineWidth(2);
+       
+                       draw_dm_edges_seams(cageDM);
+       
+                       glColor3ub(0,0,0);
+                       glLineWidth(1);
+               }
+               
+               if(G.f & G_DRAWSHARP) {
+                       UI_ThemeColor(TH_EDGE_SHARP);
+                       glLineWidth(2);
+       
+                       draw_dm_edges_sharp(cageDM);
+       
+                       glColor3ub(0,0,0);
+                       glLineWidth(1);
+               }
+       
+               if(G.f & G_DRAWCREASES) {
+                       draw_dm_creases(cageDM);
+               }
+               if(G.f & G_DRAWBWEIGHTS) {
+                       draw_dm_bweights(scene, cageDM);
+               }
+       
+               draw_em_fancy_edges(scene, v3d, cageDM, 0, eed_act);
+       }
+       if(ob==G.obedit) {
+// XXX         retopo_matrix_update(v3d);
+
+               draw_em_fancy_verts(scene, v3d, em, cageDM, eve_act);
+
+               if(G.f & G_DRAWNORMALS) {
+                       UI_ThemeColor(TH_NORMAL);
+                       draw_dm_face_normals(cageDM);
+               }
+               if(G.f & G_DRAW_VNORMALS) {
+                       UI_ThemeColor(TH_NORMAL);
+                       draw_dm_vert_normals(cageDM);
+               }
+
+               if(G.f & (G_DRAW_EDGELEN|G_DRAW_FACEAREA|G_DRAW_EDGEANG))
+                       draw_em_measure_stats(v3d, ob, em);
+       }
+
+       if(dt>OB_WIRE) {
+               glDepthMask(1);
+               bglPolygonOffset(0.0);
+               GPU_disable_material();
+       }
+
+       EM_free_index_arrays();
+}
+
+/* Mesh drawing routines */
+
+static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
+{
+       
+       if(v3d->transp==0) {    // not when we draw the transparent pass
+               glLineWidth(2.0);
+               glDepthMask(0);
+               
+               /* if transparent, we cannot draw the edges for solid select... edges have no material info.
+                  drawFacesSolid() doesn't draw the transparent faces */
+               if(ob->dtx & OB_DRAWTRANSP) {
+                       glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
+                       dm->drawFacesSolid(dm, GPU_enable_material);
+                       glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+                       GPU_disable_material();
+               }
+               else {
+                       dm->drawEdges(dm, 0);
+               }
+                                       
+               glLineWidth(1.0);
+               glDepthMask(1);
+       }
+}
+
+static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
+{
+       *drawSmooth_r = 1;
+       return 1;
+}
+
+static void draw_mesh_fancy(Scene *scene, View3D *v3d, Base *base, int dt, int flag)
+{
+       Object *ob= base->object;
+       Mesh *me = ob->data;
+       Material *ma= give_current_material(ob, 1);
+       int hasHaloMat = (ma && (ma->mode&MA_HALO));
+       int draw_wire = 0;
+       int totvert, totedge, totface;
+       DispList *dl;
+       DerivedMesh *dm= mesh_get_derived_final(ob, get_viewedit_datamask());
+
+       if(!dm)
+               return;
+       
+       if (ob->dtx&OB_DRAWWIRE) {
+               draw_wire = 2; /* draw wire after solid using zoffset and depth buffer adjusment */
+       }
+       
+       totvert = dm->getNumVerts(dm);
+       totedge = dm->getNumEdges(dm);
+       totface = dm->getNumFaces(dm);
+       
+       /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */
+       if(dt!=OB_SHADED)
+               glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
+
+               // Unwanted combination.
+       if (ob==OBACT && FACESEL_PAINT_TEST) draw_wire = 0;
+
+       if(dt==OB_BOUNDBOX) {
+               draw_bounding_volume(ob);
+       }
+       else if(hasHaloMat || (totface==0 && totedge==0)) {
+               glPointSize(1.5);
+               dm->drawVerts(dm);
+               glPointSize(1.0);
+       }
+       else if(dt==OB_WIRE || totface==0) {
+               draw_wire = 1; /* draw wire only, no depth buffer stuff  */
+       }
+       else if(        (ob==OBACT && (G.f & G_TEXTUREPAINT || FACESEL_PAINT_TEST)) ||
+                               CHECK_OB_DRAWTEXTURE(v3d, dt))
+       {
+               int faceselect= (ob==OBACT && FACESEL_PAINT_TEST);
+
+               if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&G_PICKSEL || FACESEL_PAINT_TEST) && !draw_wire) {
+                       draw_mesh_object_outline(v3d, ob, dm);
+               }
+
+               if(draw_glsl_material(scene, ob, v3d, dt)) {
+                       glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
+
+                       dm->drawFacesGLSL(dm, GPU_enable_material);
+//                     if(get_ob_property(ob, "Text"))
+// XXX                         draw_mesh_text(ob, 1);
+                       GPU_disable_material();
+
+                       glFrontFace(GL_CCW);
+               }
+               else {
+                       draw_mesh_textured(scene, v3d, ob, dm, faceselect);
+               }
+
+               if(!faceselect) {
+                       if(base->flag & SELECT)
+                               UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
+                       else
+                               UI_ThemeColor(TH_WIRE);
+
+                       dm->drawLooseEdges(dm);
+               }
+       }
+       else if(dt==OB_SOLID) {
+               if((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire)
+                       draw_mesh_object_outline(v3d, ob, dm);
+
+               glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED );
+
+               glEnable(GL_LIGHTING);
+               glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
+
+               dm->drawFacesSolid(dm, GPU_enable_material);
+               GPU_disable_material();
+
+               glFrontFace(GL_CCW);
+               glDisable(GL_LIGHTING);
+
+               if(base->flag & SELECT) {
+                       UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
+               } else {
+                       UI_ThemeColor(TH_WIRE);
+               }
+               dm->drawLooseEdges(dm);
+       }
+       else if(dt==OB_SHADED) {
+               int do_draw= 1; /* to resolve all G.f settings below... */
+               
+               if(ob==OBACT) {
+                       do_draw= 0;
+                       if( (G.f & G_WEIGHTPAINT)) {
+                               /* enforce default material settings */
+                               GPU_enable_material(0, NULL);
+                               
+                               /* but set default spec */
+                               glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
+                               glEnable(GL_COLOR_MATERIAL);    /* according manpages needed */
+                               glColor3ub(120, 120, 120);
+                               glDisable(GL_COLOR_MATERIAL);
+                               /* diffuse */
+                               glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+                               glEnable(GL_LIGHTING);
+                               glEnable(GL_COLOR_MATERIAL);
+
+                               dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1);
+                               glDisable(GL_COLOR_MATERIAL);
+                               glDisable(GL_LIGHTING);
+
+                               GPU_disable_material();
+                       }
+                       else if((G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) && me->mcol) {
+                               dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1);
+                       }
+                       else if(G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) {
+                               glColor3f(1.0f, 1.0f, 1.0f);
+                               dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0);
+                       }
+                       else do_draw= 1;
+               }
+               if(do_draw) {
+                       dl = ob->disp.first;
+                       if (!dl || !dl->col1) {
+                               /* release and reload derivedmesh because it might be freed in
+                                  shadeDispList due to a different datamask */
+                               dm->release(dm);
+                               shadeDispList(base);
+                               dl = find_displist(&ob->disp, DL_VERTCOL);
+                               dm= mesh_get_derived_final(ob, get_viewedit_datamask());
+                       }
+
+                       if ((v3d->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) {
+                               draw_mesh_object_outline(v3d, ob, dm);
+                       }
+
+                               /* False for dupliframe objects */
+                       if (dl) {
+                               unsigned int *obCol1 = dl->col1;
+                               unsigned int *obCol2 = dl->col2;
+
+                               dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2);
+                       }
+
+                       if(base->flag & SELECT) {
+                               UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
+                       } else {
+                               UI_ThemeColor(TH_WIRE);
+                       }
+                       dm->drawLooseEdges(dm);
+               }
+       }
+       
+       /* set default draw color back for wire or for draw-extra later on */
+       if (dt!=OB_WIRE) {
+               if(base->flag & SELECT) {
+                       if(ob==OBACT && ob->flag & OB_FROMGROUP) 
+                               UI_ThemeColor(TH_GROUP_ACTIVE);
+                       else if(ob->flag & OB_FROMGROUP) 
+                               UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
+                       else if(flag!=DRAW_CONSTCOLOR)
+                               UI_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
+                       else
+                               glColor3ub(80,80,80);
+               } else {
+                       if (ob->flag & OB_FROMGROUP) 
+                               UI_ThemeColor(TH_GROUP);
+                       else {
+                               if(ob->dtx & OB_DRAWWIRE && flag==DRAW_CONSTCOLOR)
+                                       glColor3ub(80,80,80);
+                               else
+                                       UI_ThemeColor(TH_WIRE);
+                       }
+               }
+       }
+       if (draw_wire) {
+                       /* If drawing wire and drawtype is not OB_WIRE then we are
+                               * overlaying the wires.
+                               *
+                               * UPDATE bug #10290 - With this wire-only objects can draw
+                               * behind other objects depending on their order in the scene. 2x if 0's below. undo'ing zr's commit: r4059
+                               * 
+                               * if draw wire is 1 then just drawing wire, no need for depth buffer stuff,
+                               * otherwise this wire is to overlay solid mode faces so do some depth buffer tricks.
+                               */
+               if (dt!=OB_WIRE && draw_wire==2) {
+                       bglPolygonOffset(1.0);
+                       glDepthMask(0); // disable write in zbuffer, selected edge wires show better
+               }
+               
+               dm->drawEdges(dm, (dt==OB_WIRE || totface==0));
+               
+               if (dt!=OB_WIRE && draw_wire==2) {
+                       glDepthMask(1);
+                       bglPolygonOffset(0.0);
+               }
+       }
+
+       dm->release(dm);
+}
+
+/* returns 1 if nothing was drawn, for detecting to draw an object center */
+static int draw_mesh_object(Scene *scene, View3D *v3d, Base *base, int dt, int flag)
+{
+       Object *ob= base->object;
+       Mesh *me= ob->data;
+       int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha;
+       
+       if(G.obedit && ob!=G.obedit && ob->data==G.obedit->data) {
+               if(ob_get_key(ob));
+               else drawlinked= 1;
+       }
+       
+       if(ob==G.obedit || drawlinked) {
+               DerivedMesh *finalDM, *cageDM;
+               
+               if (G.obedit!=ob)
+                       finalDM = cageDM = editmesh_get_derived_base();
+               else
+                       cageDM = editmesh_get_derived_cage_and_final(&finalDM,
+                                                       get_viewedit_datamask());
+
+               if(dt>OB_WIRE) {
+                       // no transp in editmode, the fancy draw over goes bad then
+                       glsl = draw_glsl_material(scene, ob, v3d, dt);
+                       GPU_set_object_materials(scene, ob, glsl, NULL);
+               }
+
+               draw_em_fancy(scene, v3d, ob, G.editMesh, cageDM, finalDM, dt);
+
+               if (G.obedit!=ob && finalDM)
+                       finalDM->release(finalDM);
+       }
+//     else if(!G.obedit && (G.f & G_SCULPTMODE) &&(scene->sculptdata.flags & SCULPT_DRAW_FAST) &&
+//             OBACT==ob && !sculpt_modifiers_active(ob)) {
+// XXX         sculptmode_draw_mesh(0);
+//     }
+       else {
+               /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */
+               if(me->totface<=4 || boundbox_clip(v3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) {
+                       glsl = draw_glsl_material(scene, ob, v3d, dt);
+                       check_alpha = check_material_alpha(base, ob, glsl);
+
+                       if(dt==OB_SOLID || glsl) {
+                               GPU_set_object_materials(scene, ob, glsl,
+                                       (check_alpha)? &do_alpha_pass: NULL);
+                       }
+
+                       draw_mesh_fancy(scene, v3d, base, dt, flag);
+                       
+                       if(me->totvert==0) retval= 1;
+               }
+       }
+       
+       /* GPU_set_object_materials checked if this is needed */
+       if(do_alpha_pass) add_view3d_after(v3d, base, V3D_TRANSP, flag);
+       
+       return retval;
+}
+
+/* ************** DRAW DISPLIST ****************** */
+
+static int draw_index_wire= 1;
+static int index3_nors_incr= 1;
+
+/* returns 1 when nothing was drawn */
+static int drawDispListwire(ListBase *dlbase)
+{
+       DispList *dl;
+       int parts, nr;
+       float *data;
+
+       if(dlbase==NULL) return 1;
+       
+       glDisableClientState(GL_NORMAL_ARRAY);
+       glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
+
+       for(dl= dlbase->first; dl; dl= dl->next) {
+               if(dl->parts==0 || dl->nr==0)
+                       continue;
+               
+               data= dl->verts;
+       
+               switch(dl->type) {
+               case DL_SEGM:
+                       
+                       glVertexPointer(3, GL_FLOAT, 0, data);
+                       
+                       for(parts=0; parts<dl->parts; parts++)
+                               glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
+                               
+                       break;
+               case DL_POLY:
+                       
+                       glVertexPointer(3, GL_FLOAT, 0, data);
+                       
+                       for(parts=0; parts<dl->parts; parts++)
+                               glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
+                       
+                       break;
+               case DL_SURF:
+                       
+                       glVertexPointer(3, GL_FLOAT, 0, data);
+                       
+                       for(parts=0; parts<dl->parts; parts++) {
+                               if(dl->flag & DL_CYCL_U) 
+                                       glDrawArrays(GL_LINE_LOOP, parts*dl->nr, dl->nr);
+                               else
+                                       glDrawArrays(GL_LINE_STRIP, parts*dl->nr, dl->nr);
+                       }
+                       
+                       for(nr=0; nr<dl->nr; nr++) {
+                               int ofs= 3*dl->nr;
+                               
+                               data= (  dl->verts )+3*nr;
+                               parts= dl->parts;
+
+                               if(dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
+                               else glBegin(GL_LINE_STRIP);
+                               
+                               while(parts--) {
+                                       glVertex3fv(data);
+                                       data+=ofs;
+                               }
+                               glEnd();
+                               
+                               /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
+//                             glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr);
+//                             if(dl->flag & DL_CYCL_V) 
+//                                     glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
+//                             else
+//                                     glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
+                       }
+                       break;
+                       
+               case DL_INDEX3:
+                       if(draw_index_wire) {
+                               glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+                               glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
+                       }
+                       break;
+                       
+               case DL_INDEX4:
+                       if(draw_index_wire) {
+                               glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+                               glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
+                       }
+                       break;
+               }
+       }
+       
+       glEnableClientState(GL_NORMAL_ARRAY);
+       glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
+       
+       return 0;
+}
+
+static void drawDispListsolid(ListBase *lb, Object *ob, int glsl)
+{
+       DispList *dl;
+       GPUVertexAttribs gattribs;
+       float *data, curcol[4];
+       float *ndata;
+       
+       if(lb==NULL) return;
+       
+       /* for drawing wire */
+       glGetFloatv(GL_CURRENT_COLOR, curcol);
+
+       glEnable(GL_LIGHTING);
+       
+       if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
+       else glFrontFace(GL_CCW);
+       
+       if(ob->type==OB_MBALL) {        // mball always smooth shaded
+               glShadeModel(GL_SMOOTH);
+       }
+       
+       dl= lb->first;
+       while(dl) {
+               data= dl->verts;
+               ndata= dl->nors;
+
+               switch(dl->type) {
+               case DL_SEGM:
+                       if(ob->type==OB_SURF) {
+                               int nr;
+
+                               glDisable(GL_LIGHTING);
+                               glColor3fv(curcol);
+                               
+                               // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+                               // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
+
+                               glBegin(GL_LINE_STRIP);
+                               for(nr= dl->nr; nr; nr--, data+=3)
+                                       glVertex3fv(data);
+                               glEnd();
+
+                               glEnable(GL_LIGHTING);
+                       }
+                       break;
+               case DL_POLY:
+                       if(ob->type==OB_SURF) {
+                               int nr;
+                               
+                               UI_ThemeColor(TH_WIRE);
+                               glDisable(GL_LIGHTING);
+                               
+                               /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
+                               //glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+                               //glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
+                               
+                               glBegin(GL_LINE_LOOP);
+                               for(nr= dl->nr; nr; nr--, data+=3)
+                                       glVertex3fv(data);
+                               glEnd();
+                               
+                               glEnable(GL_LIGHTING);
+                               break;
+                       }
+               case DL_SURF:
+                       
+                       if(dl->index) {
+                               GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
+                               
+                               if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
+                               else glShadeModel(GL_FLAT);
+                               
+                               glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+                               glNormalPointer(GL_FLOAT, 0, dl->nors);
+                               glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
+                               GPU_disable_material();
+                       }                       
+                       break;
+
+               case DL_INDEX3:
+                       GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
+                       
+                       glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+                       
+                       /* voor polys only one normal needed */
+                       if(index3_nors_incr==0) {
+                               glDisableClientState(GL_NORMAL_ARRAY);
+                               glNormal3fv(ndata);
+                       }
+                       else
+                               glNormalPointer(GL_FLOAT, 0, dl->nors);
+                       
+                       glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
+                       GPU_disable_material();
+                       
+                       if(index3_nors_incr==0)
+                               glEnableClientState(GL_NORMAL_ARRAY);
+
+                       break;
+
+               case DL_INDEX4:
+                       GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL);
+                       
+                       glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+                       glNormalPointer(GL_FLOAT, 0, dl->nors);
+                       glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
+
+                       GPU_disable_material();
+                       
+                       break;
+               }
+               dl= dl->next;
+       }
+
+       glShadeModel(GL_FLAT);
+       glDisable(GL_LIGHTING);
+       glFrontFace(GL_CCW);
+}
+
+static void drawDispListshaded(ListBase *lb, Object *ob)
+{
+       DispList *dl, *dlob;
+       unsigned int *cdata;
+
+       if(lb==NULL) return;
+
+       glShadeModel(GL_SMOOTH);
+       glDisableClientState(GL_NORMAL_ARRAY);
+       glEnableClientState(GL_COLOR_ARRAY);
+       
+       dl= lb->first;
+       dlob= ob->disp.first;
+       while(dl && dlob) {
+               
+               cdata= dlob->col1;
+               if(cdata==NULL) break;
+               
+               switch(dl->type) {
+               case DL_SURF:
+                       if(dl->index) {
+                               glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+                               glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
+                               glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index);
+                       }                       
+                       break;
+
+               case DL_INDEX3:
+                       
+                       glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+                       glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
+                       glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index);
+                       break;
+
+               case DL_INDEX4:
+                       
+                       glVertexPointer(3, GL_FLOAT, 0, dl->verts);
+                       glColorPointer(4, GL_UNSIGNED_BYTE, 0, cdata);
+                       glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index);
+                       break;
+               }
+               
+               dl= dl->next;
+               dlob= dlob->next;
+       }
+       
+       glShadeModel(GL_FLAT);
+       glEnableClientState(GL_NORMAL_ARRAY);
+       glDisableClientState(GL_COLOR_ARRAY);
+}
+
+/* returns 1 when nothing was drawn */
+static int drawDispList(Scene *scene, View3D *v3d, Base *base, int dt)
+{
+       Object *ob= base->object;
+       ListBase *lb=0;
+       DispList *dl;
+       Curve *cu;
+       int solid, retval= 0;
+       
+       solid= (dt > OB_WIRE);
+
+       switch(ob->type) {
+       case OB_FONT:
+       case OB_CURVE:
+               cu= ob->data;
+               
+               lb= &cu->disp;
+               
+               if(solid) {
+                       dl= lb->first;
+                       if(dl==NULL) return 1;
+                       
+                       if(dl->nors==0) addnormalsDispList(ob, lb);
+                       index3_nors_incr= 0;
+                       
+                       if( displist_has_faces(lb)==0) {
+                               draw_index_wire= 0;
+                               drawDispListwire(lb);
+                               draw_index_wire= 1;
+                       }
+                       else {
+                               if(draw_glsl_material(scene, ob, v3d, dt)) {
+                                       GPU_set_object_materials(scene, ob, 1, NULL);
+                                       drawDispListsolid(lb, ob, 1);
+                               }
+                               else if(dt == OB_SHADED) {
+                                       if(ob->disp.first==0) shadeDispList(base);
+                                       drawDispListshaded(lb, ob);
+                               }
+                               else {
+                                       GPU_set_object_materials(scene, ob, 0, NULL);
+                                       glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
+                                       drawDispListsolid(lb, ob, 0);
+                               }
+                               if(ob==G.obedit && cu->bevobj==NULL && cu->taperobj==NULL && cu->ext1 == 0.0 && cu->ext2 == 0.0) {
+                                       cpack(0);
+                                       draw_index_wire= 0;
+                                       drawDispListwire(lb);
+                                       draw_index_wire= 1;
+                               }
+                       }
+                       index3_nors_incr= 1;
+               }
+               else {
+                       draw_index_wire= 0;
+                       retval= drawDispListwire(lb);
+                       draw_index_wire= 1;
+               }
+               break;
+       case OB_SURF:
+       
+               lb= &((Curve *)ob->data)->disp;
+               
+               if(solid) {
+                       dl= lb->first;
+                       if(dl==NULL) return 1;
+                       
+                       if(dl->nors==NULL) addnormalsDispList(ob, lb);
+                       
+                       if(draw_glsl_material(scene, ob, v3d, dt)) {
+                               GPU_set_object_materials(scene, ob, 1, NULL);
+                               drawDispListsolid(lb, ob, 1);
+                       }
+                       else if(dt==OB_SHADED) {
+                               if(ob->disp.first==NULL) shadeDispList(base);
+                               drawDispListshaded(lb, ob);
+                       }
+                       else {
+                               GPU_set_object_materials(scene, ob, 0, NULL);
+                               glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
+                       
+                               drawDispListsolid(lb, ob, 0);
+                       }
+               }
+               else {
+                       retval= drawDispListwire(lb);
+               }
+               break;
+       case OB_MBALL:
+               
+               if( is_basis_mball(ob)) {
+                       lb= &ob->disp;
+                       if(lb->first==NULL) makeDispListMBall(ob);
+                       if(lb->first==NULL) return 1;
+                       
+                       if(solid) {
+                               
+                               if(draw_glsl_material(scene, ob, v3d, dt)) {
+                                       GPU_set_object_materials(scene, ob, 1, NULL);
+                                       drawDispListsolid(lb, ob, 1);
+                               }
+                               else if(dt == OB_SHADED) {
+                                       dl= lb->first;
+                                       if(dl && dl->col1==0) shadeDispList(base);
+                                       drawDispListshaded(lb, ob);
+                               }
+                               else {
+                                       GPU_set_object_materials(scene, ob, 0, NULL);
+                                       glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
+                               
+                                       drawDispListsolid(lb, ob, 0);
+                               }
+                       }
+                       else{
+                               /* MetaBalls use DL_INDEX4 type of DispList */
+                               retval= drawDispListwire(lb);
+                       }
+               }
+               break;
+       }
+       
+       return retval;
+}
+
+/* unified drawing of all new particle systems draw types except dupli ob & group      */
+/* mostly tries to use vertex arrays for speed                                                                         */
+
+/* 1. check that everything is ok & updated */
+/* 2. start initialising things                                */
+/* 3. initialize according to draw type                */
+/* 4. allocate drawing data arrays                     */
+/* 5. start filling the arrays                         */
+/* 6. draw the arrays                                          */
+/* 7. clean up                                                         */
+static void draw_new_particle_system(const bContext *C, View3D *v3d, Base *base, ParticleSystem *psys, int dt)
+{
+       Object *ob=base->object;
+       ParticleSystemModifierData *psmd;
+       ParticleSettings *part;
+       ParticleData *pars, *pa;
+       ParticleKey state, *states=0;
+       ParticleCacheKey *cache=0;
+       Material *ma;
+       Object *bb_ob=0;
+       float vel[3], vec[3], vec2[3], imat[4][4], onevec[3]={0.0f,0.0f,0.0f}, bb_center[3];
+       float timestep, pixsize=1.0, pa_size, pa_time, r_tilt;
+       float cfra=bsystem_time(ob,(float)CFRA,0.0);
+       float *vdata=0, *vedata=0, *cdata=0, *ndata=0, *vd=0, *ved=0, *cd=0, *nd=0, xvec[3], yvec[3], zvec[3];
+       float ma_r=0.0f, ma_g=0.0f, ma_b=0.0f;
+       int a, k, k_max=0, totpart, totpoint=0, draw_as, path_nbr=0;
+       int path_possible=0, keys_possible=0, draw_keys=0, totchild=0;
+       int select=ob->flag&SELECT, create_cdata=0;
+       GLint polygonmode[2];
+       char val[32];
+
+/* 1. */
+       if(psys==0)
+               return;
+
+       part=psys->part;
+       pars=psys->particles;
+
+       if(part==0 || !psys_check_enabled(ob, psys))
+               return;
+
+       if(pars==0) return;
+
+       if(!G.obedit && psys_in_edit_mode(psys)
+               && psys->flag & PSYS_HAIR_DONE && part->draw_as==PART_DRAW_PATH)
+               return;
+               
+       if(part->draw_as==PART_DRAW_NOT) return;
+
+/* 2. */
+       if(part->phystype==PART_PHYS_KEYED){
+               if(psys->flag & PSYS_FIRST_KEYED){
+                       if(psys->flag&PSYS_KEYED){
+                               select=psys_count_keyed_targets(ob,psys);
+                               if(psys->totkeyed==0)
+                                       return;
+                       }
+               }
+               else
+                       return;
+       }
+
+       if(select){
+               select=0;
+               if(psys_get_current(ob)==psys)
+                       select=1;
+       }
+
+       psys->flag|=PSYS_DRAWING;
+
+       if(part->type==PART_HAIR && !psys->childcache)
+               totchild=0;
+       else
+               totchild=psys->totchild*part->disp/100;
+       
+       ma= give_current_material(ob,part->omat);
+
+       if(ma) {
+               ma_r = ma->r;
+               ma_g = ma->g;
+               ma_b = ma->b;
+       }
+
+       if(v3d->zbuf) glDepthMask(1);
+
+       if(select)
+               cpack(0xFFFFFF);
+       else if((ma) && (part->draw&PART_DRAW_MAT_COL)) {
+               glColor3f(ma->r,ma->g,ma->b);
+               create_cdata = 1;
+       }
+       else
+               cpack(0);
+
+       psmd= psys_get_modifier(ob,psys);
+
+       timestep= psys_get_timestep(part);
+
+       wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
+
+       if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) {
+               float mat[4][4];
+               Mat4MulMat4(mat, psys->imat, ob->obmat);
+               wmMultMatrix(CTX_wm_window(C), mat);
+       }
+
+       totpart=psys->totpart;
+       draw_as=part->draw_as;
+
+       if(part->flag&PART_GLOB_TIME)
+               cfra=bsystem_time(0,(float)CFRA,0.0);
+
+       if(psys->pathcache){
+               path_possible=1;
+               keys_possible=1;
+       }
+       if(draw_as==PART_DRAW_PATH && path_possible==0)
+               draw_as=PART_DRAW_DOT;
+
+       if(draw_as!=PART_DRAW_PATH && keys_possible && part->draw&PART_DRAW_KEYS){
+               path_nbr=part->keys_step;
+               draw_keys=1;
+       }
+
+/* 3. */
+       switch(draw_as){
+               case PART_DRAW_DOT:
+                       if(part->draw_size)
+                               glPointSize(part->draw_size);
+                       else
+                               glPointSize(2.0); /* default dot size */
+                       break;
+               case PART_DRAW_CIRC:
+                       /* calculate view aligned matrix: */
+                       Mat4CpyMat4(imat, v3d->viewinv);
+                       Normalize(imat[0]);
+                       Normalize(imat[1]);
+                       /* no break! */
+               case PART_DRAW_CROSS:
+               case PART_DRAW_AXIS:
+                       /* lets calculate the scale: */
+                       pixsize= v3d->persmat[0][3]*ob->obmat[3][0]+ v3d->persmat[1][3]*ob->obmat[3][1]+ v3d->persmat[2][3]*ob->obmat[3][2]+ v3d->persmat[3][3];
+                       pixsize*= v3d->pixsize;
+                       if(part->draw_size==0.0)
+                               pixsize*=2.0;
+                       else
+                               pixsize*=part->draw_size;
+                       break;
+               case PART_DRAW_OB:
+                       if(part->dup_ob==0)
+                               draw_as=PART_DRAW_DOT;
+                       else
+                               draw_as=0;
+                       break;
+               case PART_DRAW_GR:
+                       if(part->dup_group==0)
+                               draw_as=PART_DRAW_DOT;
+                       else
+                               draw_as=0;
+                       break;
+               case PART_DRAW_BB:
+                       if(v3d->camera==0 && part->bb_ob==0){
+// XXX                         error("Billboards need an active camera or a target object!");
+
+                               draw_as=part->draw_as=PART_DRAW_DOT;
+
+                               if(part->draw_size)
+                                       glPointSize(part->draw_size);
+                               else
+                                       glPointSize(2.0); /* default dot size */
+                       }
+                       else if(part->bb_ob)
+                               bb_ob=part->bb_ob;
+                       else
+                               bb_ob=v3d->camera;
+
+                       if(part->bb_align<PART_BB_VIEW)
+                               onevec[part->bb_align]=1.0f;
+                       break;
+               case PART_DRAW_PATH:
+                       break;
+       }
+       if(part->draw & PART_DRAW_SIZE && part->draw_as!=PART_DRAW_CIRC){
+               Mat4CpyMat4(imat, v3d->viewinv);
+               Normalize(imat[0]);
+               Normalize(imat[1]);
+       }
+
+/* 4. */
+       if(draw_as && draw_as!=PART_DRAW_PATH){
+               if(draw_as!=PART_DRAW_CIRC){
+                       switch(draw_as){
+                               case PART_DRAW_AXIS:
+                               case PART_DRAW_CROSS:
+                                       if(draw_as!=PART_DRAW_CROSS || create_cdata)
+                                               cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_cdata");
+                                       vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_vdata");
+                                       break;
+                               case PART_DRAW_LINE:
+                                       if(create_cdata)
+                                               cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_cdata");
+                                       vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_vdata");
+                                       break;
+                               case PART_DRAW_BB:
+                                       if(create_cdata)
+                                               cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_cdata");
+                                       vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata");
+                                       ndata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata");
+                                       break;
+                               default:
+                                       if(create_cdata)
+                                               cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_cdata");
+                                       vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_vdata");
+                       }
+               }
+
+               if(part->draw&PART_DRAW_VEL && draw_as!=PART_DRAW_LINE)
+                       vedata=MEM_callocN((totpart+totchild)*2*3*(path_nbr+1)*sizeof(float), "particle_vedata");
+
+               vd=vdata;
+               ved=vedata;
+               cd=cdata;
+               nd=ndata;
+
+               psys->lattice=psys_get_lattice(ob,psys);
+       }
+
+       if(draw_as){
+/* 5. */
+               for(a=0,pa=pars; a<totpart+totchild; a++, pa++){
+                       if(a<totpart){
+                               if(totchild && (part->draw&PART_DRAW_PARENT)==0) continue;
+                               if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue;
+
+                               pa_time=(cfra-pa->time)/pa->lifetime;
+                               pa_size=pa->size;
+
+                               if((part->flag&PART_ABS_TIME)==0){                              
+                                       if(ma && ma->ipo){
+                                               IpoCurve *icu;
+
+                                               /* correction for lifetime */
+                                               calc_ipo(ma->ipo, 100.0f*pa_time);
+
+                                               for(icu = ma->ipo->curve.first; icu; icu=icu->next) {
+                                                       if(icu->adrcode == MA_COL_R)
+                                                               ma_r = icu->curval;
+                                                       else if(icu->adrcode == MA_COL_G)
+                                                               ma_g = icu->curval;
+                                                       else if(icu->adrcode == MA_COL_B)
+                                                               ma_b = icu->curval;
+                                               }
+                                       }
+                                       if(part->ipo) {
+                                               IpoCurve *icu;
+
+                                               /* correction for lifetime */
+                                               calc_ipo(part->ipo, 100*pa_time);
+
+                                               for(icu = part->ipo->curve.first; icu; icu=icu->next) {
+                                                       if(icu->adrcode == PART_SIZE)
+                                                               pa_size = icu->curval;
+                                               }
+                                       }
+                               }
+
+                               r_tilt=1.0f+pa->r_ave[0];
+
+                               if(path_nbr){
+                                       cache=psys->pathcache[a];
+                                       k_max=(int)(cache->steps);
+                               }
+                       }
+                       else{
+                               ChildParticle *cpa= &psys->child[a-totpart];
+
+                               pa_time=psys_get_child_time(psys,cpa,cfra);
+
+                               if((part->flag&PART_ABS_TIME)==0) {
+                                       if(ma && ma->ipo){
+                                               IpoCurve *icu;
+
+                                               /* correction for lifetime */
+                                               calc_ipo(ma->ipo, 100.0f*pa_time);
+
+                                               for(icu = ma->ipo->curve.first; icu; icu=icu->next) {
+                                                       if(icu->adrcode == MA_COL_R)
+                                                               ma_r = icu->curval;
+                                                       else if(icu->adrcode == MA_COL_G)
+                                                               ma_g = icu->curval;
+                                                       else if(icu->adrcode == MA_COL_B)
+                                                               ma_b = icu->curval;
+                                               }
+                                       }
+                               }
+
+                               pa_size=psys_get_child_size(psys,cpa,cfra,0);
+
+                               r_tilt=2.0f*cpa->rand[2];
+                               if(path_nbr){
+                                       cache=psys->childcache[a-totpart];
+                                       k_max=(int)(cache->steps);
+                               }
+                       }
+
+                       if(draw_as!=PART_DRAW_PATH){
+                               int next_pa=0;
+                               for(k=0; k<=path_nbr; k++){
+                                       if(draw_keys){
+                                               state.time=(float)k/(float)path_nbr;
+                                               psys_get_particle_on_path(ob,psys,a,&state,1);
+                                       }
+                                       else if(path_nbr){
+                                               if(k<=k_max){
+                                                       VECCOPY(state.co,(cache+k)->co);
+                                                       VECCOPY(state.vel,(cache+k)->vel);
+                                                       QUATCOPY(state.rot,(cache+k)->rot);
+                                               }
+                                               else
+                                                       continue;       
+                                       }
+                                       else{
+                                               state.time=cfra;
+                                               if(psys_get_particle_state(ob,psys,a,&state,0)==0){
+                                                       next_pa=1;
+                                                       break;
+                                               }
+                                       }
+
+                                       switch(draw_as){
+                                               case PART_DRAW_DOT:
+                                                       if(cd) {
+                                                               cd[0]=ma_r;
+                                                               cd[1]=ma_g;
+                                                               cd[2]=ma_b;
+                                                               cd+=3;
+                                                       }
+                                                       if(vd){
+                                                               VECCOPY(vd,state.co) vd+=3;
+                                                       }
+                                                       break;
+                                               case PART_DRAW_CROSS:
+                                               case PART_DRAW_AXIS:
+                                                       vec[0]=2.0f*pixsize;
+                                                       vec[1]=vec[2]=0.0;
+                                                       QuatMulVecf(state.rot,vec);
+                                                       if(draw_as==PART_DRAW_AXIS){
+                                                               cd[1]=cd[2]=cd[4]=cd[5]=0.0;
+                                                               cd[0]=cd[3]=1.0;
+                                                               cd[6]=cd[8]=cd[9]=cd[11]=0.0;
+                                                               cd[7]=cd[10]=1.0;
+                                                               cd[13]=cd[12]=cd[15]=cd[16]=0.0;
+                                                               cd[14]=cd[17]=1.0;
+                                                               cd+=18;
+
+                                                               VECCOPY(vec2,state.co);
+                                                       }
+                                                       else {
+                                                               if(cd) {
+                                                                       cd[0]=cd[3]=cd[6]=cd[9]=cd[12]=cd[15]=ma_r;
+                                                                       cd[1]=cd[4]=cd[7]=cd[10]=cd[13]=cd[16]=ma_g;
+                                                                       cd[2]=cd[5]=cd[8]=cd[11]=cd[14]=cd[17]=ma_b;
+                                                                       cd+=18;
+                                                               }
+                                                               VECSUB(vec2,state.co,vec);
+                                                       }
+
+                                                       VECADD(vec,state.co,vec);
+                                                       VECCOPY(vd,vec); vd+=3;
+                                                       VECCOPY(vd,vec2); vd+=3;
+                                                               
+                                                       vec[1]=2.0f*pixsize;
+                                                       vec[0]=vec[2]=0.0;
+                                                       QuatMulVecf(state.rot,vec);
+                                                       if(draw_as==PART_DRAW_AXIS){
+                                                               VECCOPY(vec2,state.co);
+                                                       }               
+                                                       else VECSUB(vec2,state.co,vec);
+
+                                                       VECADD(vec,state.co,vec);
+                                                       VECCOPY(vd,vec); vd+=3;
+                                                       VECCOPY(vd,vec2); vd+=3;
+
+                                                       vec[2]=2.0f*pixsize;
+                                                       vec[0]=vec[1]=0.0;
+                                                       QuatMulVecf(state.rot,vec);
+                                                       if(draw_as==PART_DRAW_AXIS){
+                                                               VECCOPY(vec2,state.co);
+                                                       }
+                                                       else VECSUB(vec2,state.co,vec);
+
+                                                       VECADD(vec,state.co,vec);
+
+                                                       VECCOPY(vd,vec); vd+=3;
+                                                       VECCOPY(vd,vec2); vd+=3;
+                                                       break;
+                                               case PART_DRAW_LINE:
+                                                       VECCOPY(vec,state.vel);
+                                                       Normalize(vec);
+                                                       if(part->draw & PART_DRAW_VEL_LENGTH)
+                                                               VecMulf(vec,VecLength(state.vel));
+                                                       VECADDFAC(vd,state.co,vec,-part->draw_line[0]); vd+=3;
+                                                       VECADDFAC(vd,state.co,vec,part->draw_line[1]); vd+=3;
+                                                       if(cd) {
+                                                               cd[0]=cd[3]=ma_r;
+                                                               cd[1]=cd[4]=ma_g;
+                                                               cd[2]=cd[5]=ma_b;
+                                                               cd+=3;
+                                                       }
+                                                       break;
+                                               case PART_DRAW_CIRC:
+                                                       if(create_cdata)
+                                                               glColor3f(ma_r,ma_g,ma_b);
+                                                       drawcircball(GL_LINE_LOOP, state.co, pixsize, imat);
+                                                       break;
+                                               case PART_DRAW_BB:
+                                                       if(cd) {
+                                                               cd[0]=cd[3]=cd[6]=cd[9]=ma_r;
+                                                               cd[1]=cd[4]=cd[7]=cd[10]=ma_g;
+                                                               cd[2]=cd[5]=cd[8]=cd[11]=ma_b;
+                                                               cd+=12;
+                                                       }
+                                                       if(part->draw&PART_DRAW_BB_LOCK && part->bb_align==PART_BB_VIEW){
+                                                               VECCOPY(xvec,bb_ob->obmat[0]);
+                                                               Normalize(xvec);
+                                                               VECCOPY(yvec,bb_ob->obmat[1]);
+                                                               Normalize(yvec);
+                                                               VECCOPY(zvec,bb_ob->obmat[2]);
+                                                               Normalize(zvec);
+                                                       }
+                                                       else if(part->bb_align==PART_BB_VEL){
+                                                               float temp[3];
+                                                               VECCOPY(temp,state.vel);
+                                                               Normalize(temp);
+                                                               VECSUB(zvec,bb_ob->obmat[3],state.co);
+                                                               if(part->draw&PART_DRAW_BB_LOCK){
+                                                                       float fac=-Inpf(zvec,temp);
+                                                                       VECADDFAC(zvec,zvec,temp,fac);
+                                                               }
+                                                               Normalize(zvec);
+                                                               Crossf(xvec,temp,zvec);
+                                                               Normalize(xvec);
+                                                               Crossf(yvec,zvec,xvec);
+                                                       }
+                                                       else{
+                                                               VECSUB(zvec,bb_ob->obmat[3],state.co);
+                                                               if(part->draw&PART_DRAW_BB_LOCK)
+                                                                       zvec[part->bb_align]=0.0f;
+                                                               Normalize(zvec);
+
+                                                               if(part->bb_align<PART_BB_VIEW)
+                                                                       Crossf(xvec,onevec,zvec);
+                                                               else
+                                                                       Crossf(xvec,bb_ob->obmat[1],zvec);
+                                                               Normalize(xvec);
+                                                               Crossf(yvec,zvec,xvec);
+                                                       }
+
+                                                       VECCOPY(vec,xvec);
+                                                       VECCOPY(vec2,yvec);
+
+                                                       VecMulf(xvec,cos(part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt)*(float)M_PI));
+                                                       VecMulf(vec2,sin(part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt)*(float)M_PI));
+                                                       VECADD(xvec,xvec,vec2);
+
+                                                       VecMulf(yvec,cos(part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt)*(float)M_PI));
+                                                       VecMulf(vec,-sin(part->bb_tilt*(1.0f-part->bb_rand_tilt*r_tilt)*(float)M_PI));
+                                                       VECADD(yvec,yvec,vec);
+
+                                                       VecMulf(xvec,pa_size);
+                                                       VecMulf(yvec,pa_size);
+
+                                                       VECADDFAC(bb_center,state.co,xvec,part->bb_offset[0]);
+                                                       VECADDFAC(bb_center,bb_center,yvec,part->bb_offset[1]);
+
+                                                       VECADD(vd,bb_center,xvec);
+                                                       VECADD(vd,vd,yvec); vd+=3;
+
+                                                       VECSUB(vd,bb_center,xvec);
+                                                       VECADD(vd,vd,yvec); vd+=3;
+
+                                                       VECSUB(vd,bb_center,xvec);
+                                                       VECSUB(vd,vd,yvec); vd+=3;
+
+                                                       VECADD(vd,bb_center,xvec);
+                                                       VECSUB(vd,vd,yvec); vd+=3;
+
+                                                       VECCOPY(nd, zvec); nd+=3;
+                                                       VECCOPY(nd, zvec); nd+=3;
+                                                       VECCOPY(nd, zvec); nd+=3;
+                                                       VECCOPY(nd, zvec); nd+=3;
+                                                       break;
+                                       }
+
+                                       if(vedata){
+                                               VECCOPY(ved,state.co);
+                                               ved+=3;
+                                               VECCOPY(vel,state.vel);
+                                               VecMulf(vel,timestep);
+                                               VECADD(ved,state.co,vel);
+                                               ved+=3;
+                                       }
+
+                                       if(part->draw & PART_DRAW_SIZE){
+                                               setlinestyle(3);
+                                               drawcircball(GL_LINE_LOOP, state.co, pa_size, imat);
+                                               setlinestyle(0);
+                                       }
+
+                                       totpoint++;
+                               }
+                               if(next_pa)
+                                               continue;
+                               if(part->draw&PART_DRAW_NUM && !(G.f & G_RENDER_SHADOW)){
+                                       /* in path drawing state.co is the end point */
+                                       glRasterPos3f(state.co[0],  state.co[1],  state.co[2]);
+                                       sprintf(val," %i",a);
+                                       BMF_DrawString(G.font, val);
+                               }
+                       }
+               }
+/* 6. */
+
+               glGetIntegerv(GL_POLYGON_MODE, polygonmode);
+               glDisableClientState(GL_NORMAL_ARRAY);
+
+               if(draw_as != PART_DRAW_CIRC){
+                       if(draw_as==PART_DRAW_PATH){
+                               ParticleCacheKey **cache, *path;
+                               float *cd2=0,*cdata2=0;
+
+                               glEnableClientState(GL_VERTEX_ARRAY);
+
+                               if(dt > OB_WIRE) {
+                                       glEnableClientState(GL_NORMAL_ARRAY);
+
+                                       if(part->draw&PART_DRAW_MAT_COL)
+                                               glEnableClientState(GL_COLOR_ARRAY);
+
+                                       glEnable(GL_LIGHTING);
+                                       glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+                                       glEnable(GL_COLOR_MATERIAL);
+                               }
+                               else {
+                                       glDisableClientState(GL_NORMAL_ARRAY);
+
+                                       glDisable(GL_COLOR_MATERIAL);
+                                       glDisable(GL_LIGHTING);
+                                       UI_ThemeColor(TH_WIRE);
+                               }
+
+                               if(totchild && (part->draw&PART_DRAW_PARENT)==0)
+                                       totpart=0;
+
+                               cache=psys->pathcache;
+                               for(a=0, pa=psys->particles; a<totpart; a++, pa++){
+                                       path=cache[a];
+                                       glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
+
+                                       if(dt > OB_WIRE) {
+                                               glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
+                                               if(part->draw&PART_DRAW_MAT_COL)
+                                                       glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
+                                       }
+
+                                       glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
+                               }
+                               
+                               cache=psys->childcache;
+                               for(a=0; a<totchild; a++){
+                                       path=cache[a];
+                                       glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
+
+                                       if(dt > OB_WIRE) {
+                                               glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
+                                               if(part->draw&PART_DRAW_MAT_COL)
+                                                       glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
+                                       }
+
+                                       glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
+                               }
+
+                               if(dt > OB_WIRE) {
+                                       if(part->draw&PART_DRAW_MAT_COL)
+                                               glDisable(GL_COLOR_ARRAY);
+                                       glDisable(GL_COLOR_MATERIAL);
+                               }
+
+                               if(cdata2)
+                                       MEM_freeN(cdata2);
+                               cd2=cdata2=0;
+
+                               glLineWidth(1.0f);
+
+                               /* draw particle edit mode key points*/
+                       }
+
+                       if(draw_as!=PART_DRAW_PATH){
+                               glDisableClientState(GL_COLOR_ARRAY);
+
+                               if(vdata){
+                                       glEnableClientState(GL_VERTEX_ARRAY);
+                                       glVertexPointer(3, GL_FLOAT, 0, vdata);
+                               }
+                               else
+                                       glDisableClientState(GL_VERTEX_ARRAY);
+
+                               if(ndata && dt>OB_WIRE){
+                                       glEnableClientState(GL_NORMAL_ARRAY);
+                                       glNormalPointer(GL_FLOAT, 0, ndata);
+                                       glEnable(GL_LIGHTING);
+                               }
+                               else{
+                                       glDisableClientState(GL_NORMAL_ARRAY);
+                                       glDisable(GL_LIGHTING);
+                               }
+
+                               if(cdata){
+                                       glEnableClientState(GL_COLOR_ARRAY);
+                                       glColorPointer(3, GL_FLOAT, 0, cdata);
+                               }
+
+                               switch(draw_as){
+                                       case PART_DRAW_AXIS:
+                                       case PART_DRAW_CROSS:
+                                               glDrawArrays(GL_LINES, 0, 6*totpoint);
+                                               break;
+                                       case PART_DRAW_LINE:
+                                               glDrawArrays(GL_LINES, 0, 2*totpoint);
+                                               break;
+                                       case PART_DRAW_BB:
+                                               if(dt<=OB_WIRE)
+                                                       glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+
+                                               glDrawArrays(GL_QUADS, 0, 4*totpoint);
+                                               break;
+                                       default:
+                                               glDrawArrays(GL_POINTS, 0, totpoint);
+                                               break;
+                               }
+                       }
+
+               }
+               if(vedata){
+                       glDisableClientState(GL_COLOR_ARRAY);
+                       cpack(0xC0C0C0);
+                       
+                       glEnableClientState(GL_VERTEX_ARRAY);
+                       glVertexPointer(3, GL_FLOAT, 0, vedata);
+                       
+                       glDrawArrays(GL_LINES, 0, 2*totpoint);
+               }
+
+               glPolygonMode(GL_FRONT, polygonmode[0]);
+               glPolygonMode(GL_BACK, polygonmode[1]);
+       }
+
+/* 7. */
+       
+       glDisable(GL_LIGHTING);
+       glDisableClientState(GL_COLOR_ARRAY);
+       glEnableClientState(GL_NORMAL_ARRAY);
+
+       if(states)
+               MEM_freeN(states);
+       if(vdata)
+               MEM_freeN(vdata);
+       if(vedata)
+               MEM_freeN(vedata);
+       if(cdata)
+               MEM_freeN(cdata);
+       if(ndata)
+               MEM_freeN(ndata);
+
+       psys->flag &= ~PSYS_DRAWING;
+
+       if(psys->lattice){
+               end_latt_deform();
+               psys->lattice=0;
+       }
+
+       wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
+       wmMultMatrix(CTX_wm_window(C), ob->obmat);      // bring back local matrix for dtx
+}
+
+static void draw_particle_edit(const bContext *C, Scene *scene, View3D *v3d, Object *ob, ParticleSystem *psys, int dt)
+{
+       ParticleEdit *edit = psys->edit;
+       ParticleData *pa;
+       ParticleCacheKey **path;
+       ParticleEditKey *key;
+       ParticleEditSettings *pset = NULL; // XXX PE_settings();
+       int i, k, totpart = psys->totpart, totchild=0, timed = pset->draw_timed;
+       char nosel[4], sel[4];
+       float sel_col[3];
+       float nosel_col[3];
+       char val[32];
+
+       /* create path and child path cache if it doesn't exist already */
+       if(psys->pathcache==0){
+// XXX         PE_hide_keys_time(psys,CFRA);
+               psys_cache_paths(ob,psys,CFRA,0);
+       }
+       if(psys->pathcache==0)
+               return;
+
+       if(pset->flag & PE_SHOW_CHILD && psys->part->draw_as == PART_DRAW_PATH) {
+               if(psys->childcache==0)
+                       psys_cache_child_paths(ob, psys, CFRA, 0);
+       }
+       else if(!(pset->flag & PE_SHOW_CHILD) && psys->childcache)
+               free_child_path_cache(psys);
+
+       /* opengl setup */
+       if((v3d->flag & V3D_ZBUF_SELECT)==0)
+               glDisable(GL_DEPTH_TEST);
+
+       wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
+
+       /* get selection theme colors */
+       UI_GetThemeColor3ubv(TH_VERTEX_SELECT, sel);
+       UI_GetThemeColor3ubv(TH_VERTEX, nosel);
+       sel_col[0]=(float)sel[0]/255.0f;
+       sel_col[1]=(float)sel[1]/255.0f;
+       sel_col[2]=(float)sel[2]/255.0f;
+       nosel_col[0]=(float)nosel[0]/255.0f;
+       nosel_col[1]=(float)nosel[1]/255.0f;
+       nosel_col[2]=(float)nosel[2]/255.0f;
+
+       if(psys->childcache)
+               totchild = psys->totchildcache;
+
+       /* draw paths */
+       if(timed)
+               glEnable(GL_BLEND);
+
+       glEnableClientState(GL_VERTEX_ARRAY);
+
+       if(dt > OB_WIRE) {
+               /* solid shaded with lighting */
+               glEnableClientState(GL_NORMAL_ARRAY);
+               glEnableClientState(GL_COLOR_ARRAY);
+
+               glEnable(GL_COLOR_MATERIAL);
+               glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+       }
+       else {
+               /* flat wire color */
+               glDisableClientState(GL_NORMAL_ARRAY);
+               glDisable(GL_LIGHTING);
+               UI_ThemeColor(TH_WIRE);
+       }
+
+       /* only draw child paths with lighting */
+       if(dt > OB_WIRE)
+               glEnable(GL_LIGHTING);
+
+       if(psys->part->draw_as == PART_DRAW_PATH) {
+               for(i=0, path=psys->childcache; i<totchild; i++,path++){
+                       glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->co);
+                       if(dt > OB_WIRE) {
+                               glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel);
+                               glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col);
+                       }
+
+                       glDrawArrays(GL_LINE_STRIP, 0, (int)(*path)->steps + 1);
+               }
+       }
+
+       if(dt > OB_WIRE)
+               glDisable(GL_LIGHTING);
+
+       if(pset->brushtype == PE_BRUSH_WEIGHT) {
+               glLineWidth(2.0f);
+               glEnableClientState(GL_COLOR_ARRAY);
+               glDisable(GL_LIGHTING);
+       }
+
+       /* draw parents last without lighting */
+       for(i=0, pa=psys->particles, path = psys->pathcache; i<totpart; i++, pa++, path++){
+               glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->co);
+               if(dt > OB_WIRE)
+                       glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel);
+               if(dt > OB_WIRE || pset->brushtype == PE_BRUSH_WEIGHT)
+                       glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col);
+
+               glDrawArrays(GL_LINE_STRIP, 0, (int)(*path)->steps + 1);
+       }
+
+       /* draw edit vertices */
+       if(scene->selectmode!=SCE_SELECT_PATH){
+               glDisableClientState(GL_NORMAL_ARRAY);
+               glEnableClientState(GL_COLOR_ARRAY);
+               glDisable(GL_LIGHTING);
+               glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
+
+               if(scene->selectmode==SCE_SELECT_POINT){
+                       float *cd=0,*cdata=0;
+                       cd=cdata=MEM_callocN(edit->totkeys*(timed?4:3)*sizeof(float), "particle edit color data");
+
+                       for(i=0, pa=psys->particles; i<totpart; i++, pa++){
+                               for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++){
+                                       if(key->flag&PEK_SELECT){
+                                               VECCOPY(cd,sel_col);
+                                       }
+                                       else{
+                                               VECCOPY(cd,nosel_col);
+                                       }
+                                       if(timed)
+                                               *(cd+3) = (key->flag&PEK_HIDE)?0.0f:1.0f;
+                                       cd += (timed?4:3);
+                               }
+                       }
+                       cd=cdata;
+                       for(i=0, pa=psys->particles; i<totpart; i++, pa++){
+                               if((pa->flag & PARS_HIDE)==0){
+                                       glVertexPointer(3, GL_FLOAT, sizeof(ParticleEditKey), edit->keys[i]->world_co);
+                                       glColorPointer((timed?4:3), GL_FLOAT, (timed?4:3)*sizeof(float), cd);
+                                       glDrawArrays(GL_POINTS, 0, pa->totkey);
+                               }
+                               cd += (timed?4:3) * pa->totkey;
+
+                               if((pset->flag&PE_SHOW_TIME) && (pa->flag&PARS_HIDE)==0 && !(G.f & G_RENDER_SHADOW)){
+                                       for(k=0, key=edit->keys[i]+k; k<pa->totkey; k++, key++){
+                                               if(key->flag & PEK_HIDE) continue;
+
+                                               glRasterPos3fv(key->world_co);
+                                               sprintf(val," %.1f",*key->time);
+                                               BMF_DrawString(G.font, val);
+                                       }
+                               }
+                       }
+                       if(cdata)
+                               MEM_freeN(cdata);
+                       cd=cdata=0;
+               }
+               else if(scene->selectmode == SCE_SELECT_END){
+                       for(i=0, pa=psys->particles; i<totpart; i++, pa++){
+                               if((pa->flag & PARS_HIDE)==0){
+                                       key = edit->keys[i] + pa->totkey - 1;
+                                       if(key->flag & PEK_SELECT)
+                                               glColor3fv(sel_col);
+                                       else
+                                               glColor3fv(nosel_col);
+                                       /* has to be like this.. otherwise selection won't work, have try glArrayElement later..*/
+                                       glBegin(GL_POINTS);
+                                       glVertex3fv(key->world_co);
+                                       glEnd();
+
+                                       if((pset->flag & PE_SHOW_TIME) && !(G.f & G_RENDER_SHADOW)){
+                                               glRasterPos3fv(key->world_co);
+                                               sprintf(val," %.1f",*key->time);
+                                               BMF_DrawString(G.font, val);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       glDisable(GL_BLEND);
+       glDisable(GL_LIGHTING);
+       glDisable(GL_COLOR_MATERIAL);
+       glDisableClientState(GL_COLOR_ARRAY);
+       glEnableClientState(GL_NORMAL_ARRAY);
+       glEnable(GL_DEPTH_TEST);
+       glLineWidth(1.0f);
+
+       wmMultMatrix(CTX_wm_window(C), ob->obmat);      // bring back local matrix for dtx
+       glPointSize(1.0);
+}
+
+unsigned int nurbcol[8]= {
+       0, 0x9090, 0x409030, 0x603080, 0, 0x40fff0, 0x40c033, 0xA090F0 };
+
+static void tekenhandlesN(Nurb *nu, short sel)
+{
+       BezTriple *bezt;
+       float *fp;
+       unsigned int *col;
+       int a;
+       
+       if(nu->hide || (G.f & G_HIDDENHANDLES)) return;
+       
+       glBegin(GL_LINES); 
+       
+       if( (nu->type & 7)==1) {
+               if(sel) col= nurbcol+4;
+               else col= nurbcol;
+
+               bezt= nu->bezt;
+               a= nu->pntsu;
+               while(a--) {
+                       if(bezt->hide==0) {
+                               if( (bezt->f2 & SELECT)==sel) {
+                                       fp= bezt->vec[0];
+                                       
+                                       cpack(col[bezt->h1]);
+                                       glVertex3fv(fp);
+                                       glVertex3fv(fp+3); 
+
+                                       cpack(col[bezt->h2]);
+                                       glVertex3fv(fp+3); 
+                                       glVertex3fv(fp+6); 
+                               }
+                               else if( (bezt->f1 & SELECT)==sel) {
+                                       fp= bezt->vec[0];
+                                       
+                                       cpack(col[bezt->h1]);
+                                       glVertex3fv(fp); 
+                                       glVertex3fv(fp+3); 
+                               }
+                               else if( (bezt->f3 & SELECT)==sel) {
+                                       fp= bezt->vec[1];
+                                       
+                                       cpack(col[bezt->h2]);
+                                       glVertex3fv(fp); 
+                                       glVertex3fv(fp+3); 
+                               }
+                       }
+                       bezt++;
+               }
+       }
+       glEnd();
+}
+
+static void tekenvertsN(Nurb *nu, short sel)
+{
+       BezTriple *bezt;
+       BPoint *bp;
+       float size;
+       int a;
+
+       if(nu->hide) return;
+
+       if(sel) UI_ThemeColor(TH_VERTEX_SELECT);
+       else UI_ThemeColor(TH_VERTEX);
+
+       size= UI_GetThemeValuef(TH_VERTEX_SIZE);
+       glPointSize(size);
+       
+       bglBegin(GL_POINTS);
+       
+       if((nu->type & 7)==1) {
+
+               bezt= nu->bezt;
+               a= nu->pntsu;
+               while(a--) {
+                       if(bezt->hide==0) {
+                               if (G.f & G_HIDDENHANDLES) {
+                                       if((bezt->f2 & SELECT)==sel) bglVertex3fv(bezt->vec[1]);
+                               } else {
+                                       if((bezt->f1 & SELECT)==sel) bglVertex3fv(bezt->vec[0]);
+                                       if((bezt->f2 & SELECT)==sel) bglVertex3fv(bezt->vec[1]);
+                                       if((bezt->f3 & SELECT)==sel) bglVertex3fv(bezt->vec[2]);
+                               }
+                       }
+                       bezt++;
+               }
+       }
+       else {
+               bp= nu->bp;
+               a= nu->pntsu*nu->pntsv;
+               while(a--) {
+                       if(bp->hide==0) {
+                               if((bp->f1 & SELECT)==sel) bglVertex3fv(bp->vec);
+                       }
+                       bp++;
+               }
+       }
+       
+       bglEnd();
+       glPointSize(1.0);
+}
+
+static void draw_editnurb(Object *ob, Nurb *nurb, int sel)
+{
+       Nurb *nu;
+       BPoint *bp, *bp1;
+       int a, b, ofs;
+       
+       nu= nurb;
+       while(nu) {
+               if(nu->hide==0) {
+                       switch(nu->type & 7) {
+                       case CU_POLY:
+                               cpack(nurbcol[3]);
+                               bp= nu->bp;
+                               for(b=0; b<nu->pntsv; b++) {
+                                       if(nu->flagu & 1) glBegin(GL_LINE_LOOP);
+                                       else glBegin(GL_LINE_STRIP);
+
+                                       for(a=0; a<nu->pntsu; a++, bp++) {
+                                               glVertex3fv(bp->vec);
+                                       }
+
+                                       glEnd();
+                               }
+                               break;
+                       case CU_NURBS:
+
+                               bp= nu->bp;
+                               for(b=0; b<nu->pntsv; b++) {
+                                       bp1= bp;
+                                       bp++;
+                                       for(a=nu->pntsu-1; a>0; a--, bp++) {
+                                               if(bp->hide==0 && bp1->hide==0) {
+                                                       if(sel) {
+                                                               if( (bp->f1 & SELECT) && ( bp1->f1 & SELECT ) ) {
+                                                                       cpack(nurbcol[5]);
+               
+                                                                       glBegin(GL_LINE_STRIP);
+                                                                       glVertex3fv(bp->vec); 
+                                                                       glVertex3fv(bp1->vec);
+                                                                       glEnd();
+                                                               }
+                                                       }
+                                                       else {
+                                                               if( (bp->f1 & SELECT) && ( bp1->f1 & SELECT) );
+                                                               else {
+                                                                       cpack(nurbcol[1]);
+               
+                                                                       glBegin(GL_LINE_STRIP);
+                                                                       glVertex3fv(bp->vec); 
+                                                                       glVertex3fv(bp1->vec);
+                                                                       glEnd();
+                                                               }
+                                                       }
+                                               }
+                                               bp1= bp;
+                                       }
+                               }
+                               if(nu->pntsv > 1) {     /* surface */
+
+                                       ofs= nu->pntsu;
+                                       for(b=0; b<nu->pntsu; b++) {
+                                               bp1= nu->bp+b;
+                                               bp= bp1+ofs;
+                                               for(a=nu->pntsv-1; a>0; a--, bp+=ofs) {
+                                                       if(bp->hide==0 && bp1->hide==0) {
+                                                               if(sel) {
+                                                                       if( (bp->f1 & SELECT) && ( bp1->f1 & SELECT) ) {
+                                                                               cpack(nurbcol[7]);
+                       
+                                                                               glBegin(GL_LINE_STRIP);
+                                                                               glVertex3fv(bp->vec); 
+                                                                               glVertex3fv(bp1->vec);
+                                                                               glEnd();
+                                                                       }
+                                                               }
+                                                               else {
+                                                                       if( (bp->f1 & SELECT) && ( bp1->f1 & SELECT) );
+                                                                       else {
+                                                                               cpack(nurbcol[3]);
+                       
+                                                                               glBegin(GL_LINE_STRIP);
+                                                                               glVertex3fv(bp->vec); 
+                                                                               glVertex3fv(bp1->vec);
+                                                                               glEnd();
+                                                                       }
+                                                               }
+                                                       }
+                                                       bp1= bp;
+                                               }
+                                       }
+
+                               }
+                               break;
+                       }
+               }
+               nu= nu->next;
+       }
+}
+
+static void drawnurb(Scene *scene, View3D *v3d, Base *base, Nurb *nurb, int dt)
+{
+       Object *ob= base->object;
+       Curve *cu = ob->data;
+       Nurb *nu;
+       BevList *bl;
+
+// XXX retopo_matrix_update(v3d);
+
+       /* DispList */
+       UI_ThemeColor(TH_WIRE);
+       drawDispList(scene, v3d, base, dt);
+
+       if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
+       
+       /* first non-selected handles */
+       for(nu=nurb; nu; nu=nu->next) {
+               if((nu->type & 7)==CU_BEZIER) {
+                       tekenhandlesN(nu, 0);
+               }
+       }
+       draw_editnurb(ob, nurb, 0);
+       draw_editnurb(ob, nurb, 1);
+       /* selected handles */
+       for(nu=nurb; nu; nu=nu->next) {
+               if((nu->type & 7)==1) tekenhandlesN(nu, 1);
+               tekenvertsN(nu, 0);
+       }
+       
+       if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
+
+       /*      direction vectors for 3d curve paths
+               when at its lowest, dont render normals */
+       if(cu->flag & CU_3D && scene->editbutsize > 0.0015) {
+               UI_ThemeColor(TH_WIRE);
+               for (bl=cu->bev.first,nu=nurb; nu && bl; bl=bl->next,nu=nu->next) {
+                       BevPoint *bevp= (BevPoint *)(bl+1);             
+                       int nr= bl->nr;
+                       int skip= nu->resolu/16;
+                       
+                       while (nr-->0) { /* accounts for empty bevel lists */
+                               float fac= bevp->radius * scene->editbutsize;
+                               float ox,oy,oz; // Offset perpendicular to the curve
+                               float dx,dy,dz; // Delta along the curve
+                               
+                               ox = fac*bevp->mat[0][0];
+                               oy = fac*bevp->mat[0][1];
+                               oz = fac*bevp->mat[0][2];
+                       
+                               dx = fac*bevp->mat[2][0];
+                               dy = fac*bevp->mat[2][1];
+                               dz = fac*bevp->mat[2][2];
+
+                               glBegin(GL_LINE_STRIP);
+                               glVertex3f(bevp->x - ox - dx, bevp->y - oy - dy, bevp->z - oz - dz);
+                               glVertex3f(bevp->x, bevp->y, bevp->z);
+                               glVertex3f(bevp->x + ox - dx, bevp->y + oy - dy, bevp->z + oz - dz);
+                               glEnd();
+                               
+                               bevp += skip+1;
+                               nr -= skip;
+                       }
+               }
+       }
+
+       if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
+       
+       for(nu=nurb; nu; nu=nu->next) {
+               tekenvertsN(nu, 1);
+       }
+       
+       if(v3d->zbuf) glEnable(GL_DEPTH_TEST); 
+}
+
+/* draw a sphere for use as an empty drawtype */
+static void draw_empty_sphere (float size)
+{
+       float cent=0;
+       GLUquadricObj *qobj = gluNewQuadric(); 
+       gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
+               
+       glPushMatrix();
+       glTranslatef(cent, cent, cent);
+       glScalef(size, size, size);
+       gluSphere(qobj, 1.0, 8, 5);
+               
+       glPopMatrix();
+       
+       gluDeleteQuadric(qobj); 
+}
+
+/* draw a cone for use as an empty drawtype */
+static void draw_empty_cone (float size)
+{
+       float cent=0;
+    float radius;
+       GLUquadricObj *qobj = gluNewQuadric(); 
+       gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
+       
+       
+       glPushMatrix();
+       
+       radius = size;
+       glTranslatef(cent,cent, cent);
+       glScalef(radius, 2.0*size, radius);
+       glRotatef(-90., 1.0, 0.0, 0.0);
+       gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
+
+       glPopMatrix();
+       
+       gluDeleteQuadric(qobj); 
+}
+
+/* draw points on curve speed handles */
+static void curve_draw_speed(Scene *scene, Object *ob)
+{
+       Curve *cu= ob->data;
+       IpoCurve *icu;
+       BezTriple *bezt;
+       float loc[4], dir[3];
+       int a;
+       
+       if(cu->ipo==NULL)
+               return;
+       
+       icu= cu->ipo->curve.first; 
+       if(icu==NULL || icu->totvert<2)
+               return;
+       
+       glPointSize( UI_GetThemeValuef(TH_VERTEX_SIZE) );
+       bglBegin(GL_POINTS);
+
+       for(a=0, bezt= icu->bezt; a<icu->totvert; a++, bezt++) {
+               if( where_on_path(ob, bezt->vec[1][1], loc, dir)) {
+                       UI_ThemeColor((bezt->f2 & SELECT) && ob==OBACT?TH_VERTEX_SELECT:TH_VERTEX);
+                       bglVertex3fv(loc);
+               }
+       }
+
+       glPointSize(1.0);
+       bglEnd();
+}
+
+
+static void tekentextcurs(void)
+{
+       cpack(0);
+       
+       set_inverted_drawing(1);
+       glBegin(GL_QUADS);
+       glVertex2fv(G.textcurs[0]);
+       glVertex2fv(G.textcurs[1]);
+       glVertex2fv(G.textcurs[2]);
+       glVertex2fv(G.textcurs[3]);
+       glEnd();
+       set_inverted_drawing(0);
+}
+
+static void drawspiral(float *cent, float rad, float tmat[][4], int start)
+{
+       float vec[3], vx[3], vy[3];
+       int a, tot=32;
+       char inverse=0;
+               
+       if (start < 0) {
+               inverse = 1;
+               start *= -1;
+       }
+
+       VECCOPY(vx, tmat[0]);
+       VECCOPY(vy, tmat[1]);
+       VecMulf(vx, rad);
+       VecMulf(vy, rad);
+
+       VECCOPY(vec, cent);
+
+       if (inverse==0) {
+               for(a=0; a<tot; a++) {
+                       if (a+start>31)
+                               start=-a + 1;
+                       glBegin(GL_LINES);                                                      
+                       glVertex3fv(vec);
+                       vec[0]= cent[0] + *(sinval+a+start) * (vx[0] * (float)a/(float)tot) + *(cosval+a+start) * (vy[0] * (float)a/(float)tot);
+                       vec[1]= cent[1] + *(sinval+a+start) * (vx[1] * (float)a/(float)tot) + *(cosval+a+start) * (vy[1] * (float)a/(float)tot);
+                       vec[2]= cent[2] + *(sinval+a+start) * (vx[2] * (float)a/(float)tot) + *(cosval+a+start) * (vy[2] * (float)a/(float)tot);
+                       glVertex3fv(vec);
+                       glEnd();
+               }
+       }
+       else {
+               a=0;
+               vec[0]= cent[0] + *(sinval+a+start) * (vx[0] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[0] * (float)(-a+31)/(float)tot);
+               vec[1]= cent[1] + *(sinval+a+start) * (vx[1] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[1] * (float)(-a+31)/(float)tot);
+               vec[2]= cent[2] + *(sinval+a+start) * (vx[2] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[2] * (float)(-a+31)/(float)tot);
+               for(a=0; a<tot; a++) {
+                       if (a+start>31)
+                               start=-a + 1;
+                       glBegin(GL_LINES);                                                      
+                       glVertex3fv(vec);
+                       vec[0]= cent[0] + *(sinval+a+start) * (vx[0] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[0] * (float)(-a+31)/(float)tot);
+                       vec[1]= cent[1] + *(sinval+a+start) * (vx[1] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[1] * (float)(-a+31)/(float)tot);
+                       vec[2]= cent[2] + *(sinval+a+start) * (vx[2] * (float)(-a+31)/(float)tot) + *(cosval+a+start) * (vy[2] * (float)(-a+31)/(float)tot);
+                       glVertex3fv(vec);
+                       glEnd();
+               }
+       }
+}
+
+/* draws a circle on x-z plane given the scaling of the circle, assuming that 
+ * all required matrices have been set (used for drawing empties)
+ */
+static void drawcircle_size(float size)
+{
+    float x, y;
+       short degrees;
+
+       glBegin(GL_LINE_LOOP);
+    
+       /* coordinates are: cos(degrees*11.25)=x, sin(degrees*11.25)=y, 0.0f=z */
+       for (degrees=0; degrees<32; degrees++) {
+               x= *(cosval + degrees);
+               y= *(sinval + degrees);
+               
+               glVertex3f(x*size, 0.0f, y*size);
+       }
+       
+       glEnd();
+
+}
+
+/* needs fixing if non-identity matrice used */
+static void drawtube(float *vec, float radius, float height, float tmat[][4])
+{
+       float cur[3];
+       drawcircball(GL_LINE_LOOP, vec, radius, tmat);
+
+       VecCopyf(cur,vec);
+       cur[2]+=height;
+
+       drawcircball(GL_LINE_LOOP, cur, radius, tmat);
+
+       glBegin(GL_LINES);
+               glVertex3f(vec[0]+radius,vec[1],vec[2]);
+               glVertex3f(cur[0]+radius,cur[1],cur[2]);
+               glVertex3f(vec[0]-radius,vec[1],vec[2]);
+               glVertex3f(cur[0]-radius,cur[1],cur[2]);
+               glVertex3f(vec[0],vec[1]+radius,vec[2]);
+               glVertex3f(cur[0],cur[1]+radius,cur[2]);
+               glVertex3f(vec[0],vec[1]-radius,vec[2]);
+               glVertex3f(cur[0],cur[1]-radius,cur[2]);
+       glEnd();
+}
+/* needs fixing if non-identity matrice used */
+static void drawcone(float *vec, float radius, float height, float tmat[][4])
+{
+       float cur[3];
+
+       VecCopyf(cur,vec);
+       cur[2]+=height;
+
+       drawcircball(GL_LINE_LOOP, cur, radius, tmat);
+
+       glBegin(GL_LINES);
+               glVertex3f(vec[0],vec[1],vec[2]);
+               glVertex3f(cur[0]+radius,cur[1],cur[2]);
+               glVertex3f(vec[0],vec[1],vec[2]);
+               glVertex3f(cur[0]-radius,cur[1],cur[2]);
+               glVertex3f(vec[0],vec[1],vec[2]);
+               glVertex3f(cur[0],cur[1]+radius,cur[2]);
+               glVertex3f(vec[0],vec[1],vec[2]);
+               glVertex3f(cur[0],cur[1]-radius,cur[2]);
+       glEnd();
+}
+/* return 1 if nothing was drawn */
+static int drawmball(const bContext *C, Scene *scene, View3D *v3d, Base *base, int dt)
+{
+       Object *ob= base->object;
+       MetaBall *mb;
+       MetaElem *ml;
+       float imat[4][4], tmat[4][4];
+       int code= 1;
+       
+       mb= ob->data;
+
+       if(ob==G.obedit) {
+               UI_ThemeColor(TH_WIRE);
+               if((G.f & G_PICKSEL)==0 ) drawDispList(scene, v3d, base, dt);
+               ml= editelems.first;
+       }
+       else {
+               if((base->flag & OB_FROMDUPLI)==0) 
+                       drawDispList(scene, v3d, base, dt);
+               ml= mb->elems.first;
+       }
+
+       if(ml==NULL) return 1;
+       
+       /* in case solid draw, reset wire colors */
+       if(ob!=G.obedit && (ob->flag & SELECT)) {
+               if(ob==OBACT) UI_ThemeColor(TH_ACTIVE);
+               else UI_ThemeColor(TH_SELECT);
+       }
+       else UI_ThemeColor(TH_WIRE);
+
+       wmGetMatrix(CTX_wm_window(C), tmat);
+       Mat4Invert(imat, tmat);
+       Normalize(imat[0]);
+       Normalize(imat[1]);
+       
+       while(ml) {
+       
+               /* draw radius */
+               if(ob==G.obedit) {
+                       if((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) cpack(0xA0A0F0);
+                       else cpack(0x3030A0);
+                       
+                       if(G.f & G_PICKSEL) {
+                               ml->selcol1= code;
+                               glLoadName(code++);
+                       }
+               }
+               drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad, imat);
+
+               /* draw stiffness */
+               if(ob==G.obedit) {
+                       if((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) cpack(0xA0F0A0);
+                       else cpack(0x30A030);
+                       
+                       if(G.f & G_PICKSEL) {
+                               ml->selcol2= code;
+                               glLoadName(code++);
+                       }
+                       drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad*atan(ml->s)/M_PI_2, imat);
+               }
+               
+               ml= ml->next;
+       }
+       return 0;
+}
+
+static void draw_forcefield(const bContext *C, Scene *scene, Object *ob)
+{
+       PartDeflect *pd= ob->pd;
+       float imat[4][4], tmat[4][4];
+       float vec[3]= {0.0, 0.0, 0.0};
+       int curcol;
+       float size;
+
+       if(G.f & G_RENDER_SHADOW)
+               return;
+       
+       if(ob!=G.obedit && (ob->flag & SELECT)) {
+               if(ob==OBACT) curcol= TH_ACTIVE;
+               else curcol= TH_SELECT;
+       }
+       else curcol= TH_WIRE;
+       
+       /* scale size of circle etc with the empty drawsize */
+       if (ob->type == OB_EMPTY) size = ob->empty_drawsize;
+       else size = 1.0;
+       
+       /* calculus here, is reused in PFIELD_FORCE */
+       wmGetMatrix(CTX_wm_window(C), tmat);
+       Mat4Invert(imat, tmat);
+//     Normalize(imat[0]);             // we don't do this because field doesnt scale either... apart from wind!
+//     Normalize(imat[1]);
+       
+       if (pd->forcefield == PFIELD_WIND) {
+               float force_val;
+               
+               Mat4One(tmat);
+               UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
+               
+               if (has_ipo_code(ob->ipo, OB_PD_FSTR))
+                       force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra);
+               else 
+                       force_val = pd->f_strength;
+               force_val*= 0.1;
+               drawcircball(GL_LINE_LOOP, vec, size, tmat);
+               vec[2]= 0.5*force_val;
+               drawcircball(GL_LINE_LOOP, vec, size, tmat);
+               vec[2]= 1.0*force_val;
+               drawcircball(GL_LINE_LOOP, vec, size, tmat);
+               vec[2]= 1.5*force_val;
+               drawcircball(GL_LINE_LOOP, vec, size, tmat);
+               vec[2] = 0; /* reset vec for max dist circle */
+               
+       }
+       else if (pd->forcefield == PFIELD_FORCE) {
+               float ffall_val;
+
+               if (has_ipo_code(ob->ipo, OB_PD_FFALL)) 
+                       ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, scene->r.cfra);
+               else 
+                       ffall_val = pd->f_power;
+
+               UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
+               drawcircball(GL_LINE_LOOP, vec, size, imat);
+               UI_ThemeColorBlend(curcol, TH_BACK, 0.9 - 0.4 / pow(1.5, (double)ffall_val));
+               drawcircball(GL_LINE_LOOP, vec, size*1.5, imat);
+               UI_ThemeColorBlend(curcol, TH_BACK, 0.9 - 0.4 / pow(2.0, (double)ffall_val));
+               drawcircball(GL_LINE_LOOP, vec, size*2.0, imat);
+       }
+       else if (pd->forcefield == PFIELD_VORTEX) {
+               float ffall_val, force_val;
+
+               Mat4One(tmat);
+               if (has_ipo_code(ob->ipo, OB_PD_FFALL)) 
+                       ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, scene->r.cfra);
+               else 
+                       ffall_val = pd->f_power;
+
+               if (has_ipo_code(ob->ipo, OB_PD_FSTR))
+                       force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra);
+               else 
+                       force_val = pd->f_strength;
+
+               UI_ThemeColorBlend(curcol, TH_BACK, 0.7);
+               if (force_val < 0) {
+                       drawspiral(vec, size*1.0, tmat, 1);
+                       drawspiral(vec, size*1.0, tmat, 16);
+               }
+               else {
+                       drawspiral(vec, size*1.0, tmat, -1);
+                       drawspiral(vec, size*1.0, tmat, -16);
+               }
+       }
+       else if (pd->forcefield == PFIELD_GUIDE && ob->type==OB_CURVE) {
+               Curve *cu= ob->data;
+               if((cu->flag & CU_PATH) && cu->path && cu->path->data) {
+                       float mindist, guidevec1[4], guidevec2[3];
+
+                       if (has_ipo_code(ob->ipo, OB_PD_FSTR))
+                               mindist = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, scene->r.cfra);
+                       else 
+                               mindist = pd->f_strength;
+
+                       /*path end*/
+                       setlinestyle(3);
+                       where_on_path(ob, 1.0f, guidevec1, guidevec2);
+                       UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
+                       drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat);
+
+                       /*path beginning*/
+                       setlinestyle(0);
+                       where_on_path(ob, 0.0f, guidevec1, guidevec2);
+                       UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
+                       drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat);
+                       
+                       VECCOPY(vec, guidevec1);        /* max center */
+               }
+       }
+
+       setlinestyle(3);
+       UI_ThemeColorBlend(curcol, TH_BACK, 0.5);
+
+       if(pd->falloff==PFIELD_FALL_SPHERE){
+               /* as last, guide curve alters it */
+               if(pd->flag & PFIELD_USEMAX)
+                       drawcircball(GL_LINE_LOOP, vec, pd->maxdist, imat);             
+
+               if(pd->flag & PFIELD_USEMIN)
+                       drawcircball(GL_LINE_LOOP, vec, pd->mindist, imat);
+       }
+       else if(pd->falloff==PFIELD_FALL_TUBE){
+               float radius,distance;
+
+               Mat4One(tmat);
+
+               vec[0]=vec[1]=0.0f;
+               radius=(pd->flag&PFIELD_USEMAXR)?pd->maxrad:1.0f;
+               distance=(pd->flag&PFIELD_USEMAX)?pd->maxdist:0.0f;
+               vec[2]=distance;
+               distance=(pd->flag&PFIELD_POSZ)?-distance:-2.0f*distance;
+
+               if(pd->flag & (PFIELD_USEMAX|PFIELD_USEMAXR))
+                       drawtube(vec,radius,distance,tmat);
+
+               radius=(pd->flag&PFIELD_USEMINR)?pd->minrad:1.0f;
+               distance=(pd->flag&PFIELD_USEMIN)?pd->mindist:0.0f;
+               vec[2]=distance;
+               distance=(pd->flag&PFIELD_POSZ)?-distance:-2.0f*distance;
+
+               if(pd->flag & (PFIELD_USEMIN|PFIELD_USEMINR))
+                       drawtube(vec,radius,distance,tmat);
+       }
+       else if(pd->falloff==PFIELD_FALL_CONE){
+               float radius,distance;
+
+               Mat4One(tmat);
+
+               radius=(pd->flag&PFIELD_USEMAXR)?pd->maxrad:1.0f;
+               radius*=(float)M_PI/180.0f;
+               distance=(pd->flag&PFIELD_USEMAX)?pd->maxdist:0.0f;
+
+               if(pd->flag & (PFIELD_USEMAX|PFIELD_USEMAXR)){
+                       drawcone(vec,distance*sin(radius),distance*cos(radius),tmat);
+                       if((pd->flag & PFIELD_POSZ)==0)
+                               drawcone(vec,distance*sin(radius),-distance*cos(radius),tmat);
+               }
+
+               radius=(pd->flag&PFIELD_USEMINR)?pd->minrad:1.0f;
+               radius*=(float)M_PI/180.0f;
+               distance=(pd->flag&PFIELD_USEMIN)?pd->mindist:0.0f;
+
+               if(pd->flag & (PFIELD_USEMIN|PFIELD_USEMINR)){
+                       drawcone(vec,distance*sin(radius),distance*cos(radius),tmat);
+                       if((pd->flag & PFIELD_POSZ)==0)
+                               drawcone(vec,distance*sin(radius),-distance*cos(radius),tmat);
+               }
+       }
+       setlinestyle(0);
+}
+
+static void draw_box(float vec[8][3])
+{
+       glBegin(GL_LINE_STRIP);
+       glVertex3fv(vec[0]); glVertex3fv(vec[1]);glVertex3fv(vec[2]); glVertex3fv(vec[3]);
+       glVertex3fv(vec[0]); glVertex3fv(vec[4]);glVertex3fv(vec[5]); glVertex3fv(vec[6]);
+       glVertex3fv(vec[7]); glVertex3fv(vec[4]);
+       glEnd();
+
+       glBegin(GL_LINES);
+       glVertex3fv(vec[1]); glVertex3fv(vec[5]);
+       glVertex3fv(vec[2]); glVertex3fv(vec[6]);
+       glVertex3fv(vec[3]); glVertex3fv(vec[7]);
+       glEnd();
+}
+
+/* uses boundbox, function used by Ketsji */
+void get_local_bounds(Object *ob, float *center, float *size)
+{
+       BoundBox *bb= object_get_boundbox(ob);
+       
+       if(bb==NULL) {
+               center[0]= center[1]= center[2]= 0.0;
+               VECCOPY(size, ob->size);
+       }
+       else {
+               size[0]= 0.5*fabs(bb->vec[0][0] - bb->vec[4][0]);
+               size[1]= 0.5*fabs(bb->vec[0][1] - bb->vec[2][1]);
+               size[2]= 0.5*fabs(bb->vec[0][2] - bb->vec[1][2]);
+               
+               center[0]= (bb->vec[0][0] + bb->vec[4][0])/2.0;
+               center[1]= (bb->vec[0][1] + bb->vec[2][1])/2.0;
+               center[2]= (bb->vec[0][2] + bb->vec[1][2])/2.0;
+       }
+}
+
+
+
+static void draw_bb_quadric(BoundBox *bb, short type)
+{
+       float size[3], cent[3];
+       GLUquadricObj *qobj = gluNewQuadric(); 
+       
+       gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
+       
+       size[0]= 0.5*fabs(bb->vec[0][0] - bb->vec[4][0]);
+       size[1]= 0.5*fabs(bb->vec[0][1] - bb->vec[2][1]);
+       size[2]= 0.5*fabs(bb->vec[0][2] - bb->vec[1][2]);
+       
+       cent[0]= (bb->vec[0][0] + bb->vec[4][0])/2.0;
+       cent[1]= (bb->vec[0][1] + bb->vec[2][1])/2.0;
+       cent[2]= (bb->vec[0][2] + bb->vec[1][2])/2.0;
+       
+       glPushMatrix();
+       if(type==OB_BOUND_SPHERE) {
+               glTranslatef(cent[0], cent[1], cent[2]);
+               glScalef(size[0], size[1], size[2]);
+               gluSphere(qobj, 1.0, 8, 5);
+       }       
+       else if(type==OB_BOUND_CYLINDER) {
+               float radius = size[0] > size[1] ? size[0] : size[1];
+               glTranslatef(cent[0], cent[1], cent[2]-size[2]);
+               glScalef(radius, radius, 2.0*size[2]);
+               gluCylinder(qobj, 1.0, 1.0, 1.0, 8, 1);
+       }
+       else if(type==OB_BOUND_CONE) {
+               float radius = size[0] > size[1] ? size[0] : size[1];
+               glTranslatef(cent[0], cent[2]-size[2], cent[1]);
+               glScalef(radius, 2.0*size[2], radius);
+               glRotatef(-90., 1.0, 0.0, 0.0);
+               gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
+       }
+       glPopMatrix();
+       
+       gluDeleteQuadric(qobj); 
+}
+
+static void draw_bounding_volume(Object *ob)
+{
+       BoundBox *bb=0;
+       
+       if(ob->type==OB_MESH) {
+               bb= mesh_get_bb(ob);
+       }
+       else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
+               bb= ( (Curve *)ob->data )->bb;
+       }
+       else if(ob->type==OB_MBALL) {
+               bb= ob->bb;
+               if(bb==0) {
+                       makeDispListMBall(ob);
+                       bb= ob->bb;
+               }
+       }
+       else {
+               drawcube();
+               return;
+       }
+       
+       if(bb==0) return;
+       
+       if(ob->boundtype==OB_BOUND_BOX) draw_box(bb->vec);
+       else draw_bb_quadric(bb, ob->boundtype);
+       
+}
+
+static void drawtexspace(Object *ob)
+{
+       float vec[8][3], loc[3], size[3];
+       
+       if(ob->type==OB_MESH) {
+               mesh_get_texspace(ob->data, loc, NULL, size);
+       }
+       else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) {
+               Curve *cu= ob->data;
+               VECCOPY(size, cu->size);
+               VECCOPY(loc, cu->loc);
+       }
+       else if(ob->type==OB_MBALL) {
+               MetaBall *mb= ob->data;
+               VECCOPY(size, mb->size);
+               VECCOPY(loc, mb->loc);
+       }
+       else return;
+       
+       vec[0][0]=vec[1][0]=vec[2][0]=vec[3][0]= loc[0]-size[0];
+       vec[4][0]=vec[5][0]=vec[6][0]=vec[7][0]= loc[0]+size[0];
+       
+       vec[0][1]=vec[1][1]=vec[4][1]=vec[5][1]= loc[1]-size[1];
+       vec[2][1]=vec[3][1]=vec[6][1]=vec[7][1]= loc[1]+size[1];
+
+       vec[0][2]=vec[3][2]=vec[4][2]=vec[7][2]= loc[2]-size[2];
+       vec[1][2]=vec[2][2]=vec[5][2]=vec[6][2]= loc[2]+size[2];
+       
+       setlinestyle(2);
+
+       draw_box(vec);
+
+       setlinestyle(0);
+}
+
+/* draws wire outline */
+static void drawSolidSelect(View3D *v3d, Base *base) 
+{
+       Object *ob= base->object;
+       
+       glLineWidth(2.0);
+       glDepthMask(0);
+       
+       if(ELEM3(ob->type, OB_FONT,OB_CURVE, OB_SURF)) {
+               Curve *cu = ob->data;
+               if (displist_has_faces(&cu->disp) && boundbox_clip(v3d, ob->obmat, cu->bb)) {
+                       draw_index_wire= 0;
+                       drawDispListwire(&cu->disp);
+                       draw_index_wire= 1;
+               }
+       } else if (ob->type==OB_MBALL) {
+               if((base->flag & OB_FROMDUPLI)==0) 
+                       drawDispListwire(&ob->disp);
+       }
+       else if(ob->type==OB_ARMATURE) {
+               if(!(ob->flag & OB_POSEMODE))
+                       draw_armature(base, OB_WIRE, 0);
+       }
+
+       glLineWidth(1.0);
+       glDepthMask(1);
+}
+
+static void drawWireExtra(Scene *scene, View3D *v3d, Object *ob) 
+{
+       if(ob!=G.obedit && (ob->flag & SELECT)) {
+               if(ob==OBACT) {
+                       if(ob->flag & OB_FROMGROUP) UI_ThemeColor(TH_GROUP_ACTIVE);
+                       else UI_ThemeColor(TH_ACTIVE);
+               }
+               else if(ob->flag & OB_FROMGROUP)
+                       UI_ThemeColorShade(TH_GROUP_ACTIVE, -16);
+               else
+                       UI_ThemeColor(TH_SELECT);
+       }
+       else {
+               if(ob->flag & OB_FROMGROUP)
+                       UI_ThemeColor(TH_GROUP);
+               else {
+                       if(ob->dtx & OB_DRAWWIRE) {
+                               glColor3ub(80,80,80);
+                       } else {
+                               UI_ThemeColor(TH_WIRE);
+                       }
+               }
+       }
+       
+       bglPolygonOffset(1.0);
+       glDepthMask(0); // disable write in zbuffer, selected edge wires show better
+       
+       if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
+               Curve *cu = ob->data;
+               if (boundbox_clip(v3d, ob->obmat, cu->bb)) {
+                       if (ob->type==OB_CURVE)
+                               draw_index_wire= 0;
+                       drawDispListwire(&cu->disp);
+                       if (ob->type==OB_CURVE)
+                               draw_index_wire= 1;
+               }
+       } else if (ob->type==OB_MBALL) {
+               drawDispListwire(&ob->disp);
+       }
+
+       glDepthMask(1);
+       bglPolygonOffset(0.0);
+}
+
+/* should be called in view space */
+static void draw_hooks(Object *ob)
+{
+       ModifierData *md;
+       float vec[3];
+       
+       for (md=ob->modifiers.first; md; md=md->next) {
+               if (md->type==eModifierType_Hook) {
+                       HookModifierData *hmd = (HookModifierData*) md;
+
+                       VecMat4MulVecfl(vec, ob->obmat, hmd->cent);
+
+                       if(hmd->object) {
+                               setlinestyle(3);
+                               glBegin(GL_LINES);
+                               glVertex3fv(hmd->object->obmat[3]);
+                               glVertex3fv(vec);
+                               glEnd();
+                               setlinestyle(0);
+                       }
+
+                       glPointSize(3.0);
+                       bglBegin(GL_POINTS);
+                       bglVertex3fv(vec);
+                       bglEnd();
+                       glPointSize(1.0);
+               }
+       }
+}
+
+//<rcruiz>
+void drawRBpivot(bRigidBodyJointConstraint *data)
+{
+       float radsPerDeg = 6.283185307179586232f / 360.f;
+       int axis;
+       float v1[3]= {data->pivX, data->pivY, data->pivZ};
+       float eu[3]= {radsPerDeg*data->axX, radsPerDeg*data->axY, radsPerDeg*data->axZ};
+       float mat[4][4];
+
+       if(G.f & G_RENDER_SHADOW)
+               return;
+
+       EulToMat4(eu,mat);
+       glLineWidth (4.0f);
+       setlinestyle(2);
+       for (axis=0; axis<3; axis++) {
+                       float dir[3] = {0,0,0};
+                       float v[3]= {data->pivX, data->pivY, data->pivZ};
+
+                       dir[axis] = 1.f;
+                       glBegin(GL_LINES);
+                       Mat4MulVecfl(mat,dir);
+                       v[0] += dir[0];
+                       v[1] += dir[1];
+                       v[2] += dir[2];
+                       glVertex3fv(v1);
+                       glVertex3fv(v);                 
+                       glEnd();
+                       glRasterPos3fv(v);
+                       if (axis==0)
+                               BMF_DrawString(G.font, "px");
+                       else if (axis==1)
+                               BMF_DrawString(G.font, "py");
+                       else
+                               BMF_DrawString(G.font, "pz");                   
+       }
+       glLineWidth (1.0f);
+       setlinestyle(0);
+}
+
+/* flag can be DRAW_PICKING    and/or DRAW_CONSTCOLOR, DRAW_SCENESET */
+void draw_object(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
+{
+       static int warning_recursive= 0;
+       Object *ob;
+       Curve *cu;
+       float cfraont;
+       float vec1[3], vec2[3];
+       unsigned int col=0;
+       int sel, drawtype, colindex= 0, ipoflag;
+       int i, selstart, selend, empty_object=0;
+       short dt, dtx, zbufoff= 0;
+
+       /* only once set now, will be removed too, should become a global standard */
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+       ob= base->object;
+
+       if (ob!=G.obedit) {
+               if (ob->restrictflag & OB_RESTRICT_VIEW) 
+                       return;
+       }
+
+       /* xray delay? */
+       if((flag & DRAW_PICKING)==0 && (base->flag & OB_FROMDUPLI)==0) {
+               /* don't do xray in particle mode, need the z-buffer */
+               if(!(G.f & G_PARTICLEEDIT)) {
+                       /* xray and transp are set when it is drawing the 2nd/3rd pass */
+                       if(!v3d->xray && !v3d->transp && (ob->dtx & OB_DRAWXRAY)) {
+                               add_view3d_after(v3d, base, V3D_XRAY, flag);
+                               return;
+                       }
+               }
+       }
+
+       /* draw keys? */
+       if(base==(scene->basact) || (base->flag & (SELECT+BA_WAS_SEL))) {
+               if(flag==0 && warning_recursive==0 && ob!=G.obedit) {
+                       if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
+                               ListBase elems;
+                               CfraElem *ce;
+                               float temp[7][3];
+
+                               warning_recursive= 1;
+
+                               elems.first= elems.last= 0;
+                               // warning: no longer checks for certain ob-keys only... (so does this need to use the proper ipokeys then?)
+                               make_cfra_list(ob->ipo, &elems); 
+
+                               cfraont= (scene->r.cfra);
+                               drawtype= v3d->drawtype;
+                               if(drawtype>OB_WIRE) v3d->drawtype= OB_WIRE;
+                               sel= base->flag;
+                               memcpy(temp, &ob->loc, 7*3*sizeof(float));
+
+                               ipoflag= ob->ipoflag;
+                               ob->ipoflag &= ~OB_OFFS_OB;
+
+                               set_no_parent_ipo(1);
+                               disable_speed_curve(1);
+
+                               if ((ob->ipoflag & OB_DRAWKEYSEL)==0) {
+                                       ce= elems.first;
+                                       while(ce) {
+                                               if(!ce->sel) {
+                                                       (scene->r.cfra)= ce->cfra/scene->r.framelen;
+
+                                                       base->flag= 0;
+
+                                                       where_is_object_time(ob, (scene->r.cfra));
+                                                       draw_object(C, scene, ar, v3d, base, 0);
+                                               }
+                                               ce= ce->next;
+                                       }
+                               }
+
+                               ce= elems.first;
+                               while(ce) {
+                                       if(ce->sel) {
+                                               (scene->r.cfra)= ce->cfra/scene->r.framelen;
+
+                                               base->flag= SELECT;
+
+                                               where_is_object_time(ob, (scene->r.cfra));
+                                               draw_object(C, scene, ar, v3d, base, 0);
+                                       }
+                                       ce= ce->next;
+                               }
+
+                               set_no_parent_ipo(0);
+                               disable_speed_curve(0);
+
+                               base->flag= sel;
+                               ob->ipoflag= ipoflag;
+
+                               /* restore icu->curval */
+                               (scene->r.cfra)= cfraont;
+
+                               memcpy(&ob->loc, temp, 7*3*sizeof(float));
+                               where_is_object(ob);
+                               v3d->drawtype= drawtype;
+
+                               BLI_freelistN(&elems);
+
+                               warning_recursive= 0;
+                       }
+               }
+       }
+
+       /* patch? children objects with a timeoffs change the parents. How to solve! */
+       /* if( ((int)ob->ctime) != F_(scene->r.cfra)) where_is_object(ob); */
+
+       wmMultMatrix(CTX_wm_window(C), ob->obmat);
+
+       /* which wire color */
+       if((flag & DRAW_CONSTCOLOR) == 0) {
+               project_short(ar, v3d, ob->obmat[3], &base->sx);
+
+               if((G.moving & G_TRANSFORM_OBJ) && (base->flag & (SELECT+BA_WAS_SEL))) UI_ThemeColor(TH_TRANSFORM);
+               else {
+
+                       if(ob->type==OB_LAMP) UI_ThemeColor(TH_LAMP);
+                       else UI_ThemeColor(TH_WIRE);
+
+                       if((scene->basact)==base) {
+                               if(base->flag & (SELECT+BA_WAS_SEL)) UI_ThemeColor(TH_ACTIVE);
+                       }
+                       else {
+                               if(base->flag & (SELECT+BA_WAS_SEL)) UI_ThemeColor(TH_SELECT);
+                       }
+
+                       // no theme yet
+                       if(ob->id.lib) {
+                               if(base->flag & (SELECT+BA_WAS_SEL)) colindex = 4;
+                               else colindex = 3;
+                       }
+                       else if(warning_recursive==1) {
+                               if(base->flag & (SELECT+BA_WAS_SEL)) {
+                                       if(scene->basact==base) colindex = 8;
+                                       else colindex= 7;
+                               }
+                               else colindex = 6;
+                       }
+                       else if(ob->flag & OB_FROMGROUP) {
+                               if(base->flag & (SELECT+BA_WAS_SEL)) {
+                                       if(scene->basact==base) UI_ThemeColor(TH_GROUP_ACTIVE);
+                                       else UI_ThemeColorShade(TH_GROUP_ACTIVE, -16); 
+                               }
+                               else UI_ThemeColor(TH_GROUP);
+                               colindex= 0;
+                       }
+
+               }       
+
+               if(colindex) {
+                       col= colortab[colindex];
+                       cpack(col);
+               }
+       }
+
+       /* maximum drawtype */
+       dt= MIN2(v3d->drawtype, ob->dt);
+       if(v3d->zbuf==0 && dt>OB_WIRE) dt= OB_WIRE;
+       dtx= 0;
+
+       /* faceselect exception: also draw solid when dt==wire, except in editmode */
+       if(ob==OBACT && (G.f & (G_VERTEXPAINT+G_TEXTUREPAINT+G_WEIGHTPAINT))) {
+               if(ob->type==OB_MESH) {
+
+                       if(ob==G.obedit);
+                       else {
+                               if(dt<OB_SOLID)
+                                       zbufoff= 1;
+
+                               dt= OB_SHADED;
+                               glEnable(GL_DEPTH_TEST);
+                       }
+               }
+               else {
+                       if(dt<OB_SOLID) {
+                               dt= OB_SOLID;
+                               glEnable(GL_DEPTH_TEST);
+                               zbufoff= 1;
+                       }
+               }
+       }
+       
+       /* draw-extra supported for boundbox drawmode too */
+       if(dt>=OB_BOUNDBOX ) {
+
+               dtx= ob->dtx;
+               if(G.obedit==ob) {
+                       // the only 2 extra drawtypes alowed in editmode
+                       dtx= dtx & (OB_DRAWWIRE|OB_TEXSPACE);
+               }
+
+               if(G.f & G_DRAW_EXT) {
+                       if(ob->type==OB_EMPTY || ob->type==OB_CAMERA || ob->type==OB_LAMP) dt= OB_WIRE;
+               }
+       }
+
+       /* draw outline for selected solid objects, mesh does itself */
+       if((v3d->flag & V3D_SELECT_OUTLINE) && ob->type!=OB_MESH) {
+               if(dt>OB_WIRE && dt<OB_TEXTURE && ob!=G.obedit && (flag && DRAW_SCENESET)==0) {
+                       if (!(ob->dtx&OB_DRAWWIRE) && (ob->flag&SELECT) && !(flag&DRAW_PICKING)) {
+                               drawSolidSelect(v3d, base);
+                       }
+               }
+       }
+
+       switch( ob->type) {
+               case OB_MESH:
+                       if (!(base->flag&OB_RADIO)) {
+                               empty_object= draw_mesh_object(scene, v3d, base, dt, flag);
+                               if(flag!=DRAW_CONSTCOLOR) dtx &= ~OB_DRAWWIRE; // mesh draws wire itself
+                       }
+
+                       break;
+               case OB_FONT:
+                       cu= ob->data;
+                       if (cu->disp.first==NULL) makeDispListCurveTypes(ob, 0);
+                       if(ob==G.obedit) {
+                               tekentextcurs();
+
+                               if (cu->flag & CU_FAST) {
+                                       cpack(0xFFFFFF);
+                                       set_inverted_drawing(1);
+                                       drawDispList(scene, v3d, base, OB_WIRE);
+                                       set_inverted_drawing(0);
+                               } else {
+                                       drawDispList(scene, v3d, base, dt);
+                               }
+
+                               if (cu->linewidth != 0.0) {
+                                       cpack(0xff44ff);
+                                       UI_ThemeColor(TH_WIRE);
+                                       VECCOPY(vec1, ob->orig);
+                                       VECCOPY(vec2, ob->orig);
+                                       vec1[0] += cu->linewidth;
+                                       vec2[0] += cu->linewidth;
+                                       vec1[1] += cu->linedist * cu->fsize;
+                                       vec2[1] -= cu->lines * cu->linedist * cu->fsize;
+                                       setlinestyle(3);
+                                       glBegin(GL_LINE_STRIP); 
+                                       glVertex2fv(vec1); 
+                                       glVertex2fv(vec2); 
+                                       glEnd();
+                                       setlinestyle(0);
+                               }
+
+                               setlinestyle(3);
+                               for (i=0; i<cu->totbox; i++) {
+                                       if (cu->tb[i].w != 0.0) {
+                                               if (i == (cu->actbox-1))
+                                                       UI_ThemeColor(TH_ACTIVE);
+                                               else
+                                                       UI_ThemeColor(TH_WIRE);
+                                               vec1[0] = cu->tb[i].x;
+                                               vec1[1] = cu->tb[i].y + cu->fsize;
+                                               vec1[2] = 0.001;
+                                               glBegin(GL_LINE_STRIP);
+                                               glVertex3fv(vec1);
+                                               vec1[0] += cu->tb[i].w;
+                                               glVertex3fv(vec1);
+                                               vec1[1] -= cu->tb[i].h;
+                                               glVertex3fv(vec1);
+                                               vec1[0] -= cu->tb[i].w;
+                                               glVertex3fv(vec1);
+                                               vec1[1] += cu->tb[i].h;
+                                               glVertex3fv(vec1);
+                                               glEnd();
+                                       }
+                               }
+                               setlinestyle(0);
+
+
+                               if (getselection(&selstart, &selend) && selboxes) {
+                                       float selboxw;
+
+                                       cpack(0xffffff);
+                                       set_inverted_drawing(1);                
+                                       for (i=0; i<(selend-selstart+1); i++) {
+                                               SelBox *sb = &(selboxes[i]);
+
+                                               if (i<(selend-selstart)) {
+                                                       if (selboxes[i+1].y == sb->y)
+                                                               selboxw= selboxes[i+1].x - sb->x;
+                                                       else
+                                                               selboxw= sb->w;
+                                               }
+                                               else {
+                                                       selboxw= sb->w;
+                                               }
+                                               glBegin(GL_QUADS);
+                                               glVertex3f(sb->x, sb->y, 0.001);
+                                               glVertex3f(sb->x+selboxw, sb->y, 0.001);                                
+                                               glVertex3f(sb->x+selboxw, sb->y+sb->h, 0.001);
+                                               glVertex3f(sb->x, sb->y+sb->h, 0.001);
+                                               glEnd();
+                                       }
+                                       set_inverted_drawing(0);                        
+                               }
+                       }
+                       else if(dt==OB_BOUNDBOX) 
+                               draw_bounding_volume(ob);
+                       else if(boundbox_clip(v3d, ob->obmat, cu->bb)) 
+                               empty_object= drawDispList(scene, v3d, base, dt);
+
+                       break;
+               case OB_CURVE:
+               case OB_SURF:
+                       cu= ob->data;
+                       /* still needed for curves hidden in other layers. depgraph doesnt handle that yet */
+                       if (cu->disp.first==NULL) makeDispListCurveTypes(ob, 0);
+
+                       if(ob==G.obedit) {
+                               drawnurb(scene, v3d, base, editNurb.first, dt);
+                       }
+                       else if(dt==OB_BOUNDBOX) 
+                               draw_bounding_volume(ob);
+                       else if(boundbox_clip(v3d, ob->obmat, cu->bb)) {
+                               empty_object= drawDispList(scene, v3d, base, dt);
+                               
+                               if(cu->path)
+                                       curve_draw_speed(scene, ob);
+                       }                       
+                       break;
+               case OB_MBALL:
+                       if(ob==G.obedit) 
+                               drawmball(C, scene, v3d, base, dt);
+                       else if(dt==OB_BOUNDBOX) 
+                               draw_bounding_volume(ob);
+                       else 
+                               empty_object= drawmball(C, scene, v3d, base, dt);
+                       break;
+               case OB_EMPTY:
+                       drawaxes(ob->empty_drawsize, flag, ob->empty_drawtype);
+                       break;
+               case OB_LAMP:
+                       drawlamp(C, scene, v3d, ob);
+                       if(dtx || (base->flag & SELECT)) wmMultMatrix(CTX_wm_window(C), ob->obmat);
+                       break;
+               case OB_CAMERA:
+                       drawcamera(C, scene, v3d, ob, flag);
+                       break;
+               case OB_LATTICE:
+                       drawlattice(v3d, ob);
+                       break;
+               case OB_ARMATURE:
+                       if(dt>OB_WIRE) GPU_enable_material(0, NULL); // we use default material
+                       empty_object= draw_armature(base, dt, flag);
+                       if(dt>OB_WIRE) GPU_disable_material();
+                       break;
+               default:
+                       drawaxes(1.0, flag, OB_ARROWS);
+       }
+       if(ob->pd && ob->pd->forcefield) draw_forcefield(C, scene, ob);
+
+       /* code for new particle system */
+       if(             (warning_recursive==0) &&
+                       (ob->particlesystem.first) &&
+                       (flag & DRAW_PICKING)==0 &&
+                       (ob!=G.obedit)  
+         ) {
+               ParticleSystem *psys;
+               if(col || (ob->flag & SELECT)) cpack(0xFFFFFF); /* for visibility, also while wpaint */
+               glDepthMask(GL_FALSE);
+               
+               for(psys=ob->particlesystem.first; psys; psys=psys->next)
+                       draw_new_particle_system(C, v3d, base, psys, dt);
+               
+               if(G.f & G_PARTICLEEDIT && ob==OBACT) {
+                       psys= NULL; // XXX PE_get_current(ob);
+                       if(psys && !G.obedit && psys_in_edit_mode(psys))
+                               draw_particle_edit(C, scene, v3d, ob, psys, dt);
+               }
+               glDepthMask(GL_TRUE); 
+               if(col) cpack(col);
+       }
+
+       {
+               bConstraint *con;
+               for(con=ob->constraints.first; con; con= con->next) 
+               {
+                       if(con->type==CONSTRAINT_TYPE_RIGIDBODYJOINT) 
+                       {
+                               bRigidBodyJointConstraint *data = (bRigidBodyJointConstraint*)con->data;
+                               if(data->flag&CONSTRAINT_DRAW_PIVOT)
+                                       drawRBpivot(data);
+                       }
+               }
+       }
+
+       /* draw extra: after normal draw because of makeDispList */
+       if(dtx && !(G.f & (G_RENDER_OGL|G_RENDER_SHADOW))) {
+               if(dtx & OB_AXIS) {
+                       drawaxes(1.0f, flag, OB_ARROWS);
+               }
+               if(dtx & OB_BOUNDBOX) draw_bounding_volume(ob);
+               if(dtx & OB_TEXSPACE) drawtexspace(ob);
+               if(dtx & OB_DRAWNAME) {
+                       /* patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing */
+                       /* but, we also dont draw names for sets or duplicators */
+                       if(flag == 0) {
+                               if(v3d->zbuf) glDisable(GL_DEPTH_TEST);
+                               glRasterPos3f(0.0,  0.0,  0.0);
+
+                               BMF_DrawString(G.font, " ");
+                               BMF_DrawString(G.font, ob->id.name+2);
+                               if(v3d->zbuf) glEnable(GL_DEPTH_TEST);
+                       }
+               }
+               /*if(dtx & OB_DRAWIMAGE) drawDispListwire(&ob->disp);*/
+               if((dtx & OB_DRAWWIRE) && dt>=OB_SOLID) drawWireExtra(scene, v3d, ob);
+       }
+
+       if(dt<OB_SHADED) {
+               if((ob->gameflag & OB_DYNAMIC) || 
+                       ((ob->gameflag & OB_BOUNDS) && (ob->boundtype == OB_BOUND_SPHERE))) {
+                       float tmat[4][4], imat[4][4], vec[3];
+
+                       vec[0]= vec[1]= vec[2]= 0.0;
+                       wmGetMatrix(CTX_wm_window(C), tmat);
+                       Mat4Invert(imat, tmat);
+
+                       setlinestyle(2);
+                       drawcircball(GL_LINE_LOOP, vec, ob->inertia, imat);
+                       setlinestyle(0);
+               }
+       }
+
+       wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
+
+       if(zbufoff) glDisable(GL_DEPTH_TEST);
+
+       if(warning_recursive) return;
+       if(base->flag & (OB_FROMDUPLI|OB_RADIO)) return;
+       if(G.f & G_RENDER_SHADOW) return;
+
+       /* object centers, need to be drawn in viewmat space for speed, but OK for picking select */
+       if(ob!=OBACT || (G.f & (G_VERTEXPAINT|G_TEXTUREPAINT|G_WEIGHTPAINT))==0) {
+               int do_draw_center= -1; /* defines below are zero or positive... */
+
+               if((scene->basact)==base) 
+                       do_draw_center= ACTIVE;
+               else if(base->flag & SELECT) 
+                       do_draw_center= SELECT;
+               else if(empty_object || (v3d->flag & V3D_DRAW_CENTERS)) 
+                       do_draw_center= DESELECT;
+
+               if(do_draw_center != -1) {
+                       if(flag & DRAW_PICKING) {
+                               /* draw a single point for opengl selection */
+                               glBegin(GL_POINTS);
+                               glVertex3fv(ob->obmat[3]);
+                               glEnd();
+                       } 
+                       else if((flag & DRAW_CONSTCOLOR)==0) {
+                               /* we don't draw centers for duplicators and sets */
+                               drawcentercircle(v3d, ob->obmat[3], do_draw_center, ob->id.lib || ob->id.us>1);
+                       }
+               }
+       }
+
+       /* not for sets, duplicators or picking */
+       if(flag==0 && (!(v3d->flag & V3D_HIDE_HELPLINES))) {
+               ListBase *list;
+               
+               /* draw hook center and offset line */
+               if(ob!=G.obedit) draw_hooks(ob);
+               
+               /* help lines and so */
+               if(ob!=G.obedit && ob->parent && (ob->parent->lay & v3d->lay)) {
+                       setlinestyle(3);
+                       glBegin(GL_LINES);
+                       glVertex3fv(ob->obmat[3]);
+                       glVertex3fv(ob->orig);
+                       glEnd();
+                       setlinestyle(0);
+               }
+
+               /* Drawing the constraint lines */
+               list = &ob->constraints;
+               if (list) {
+                       bConstraint *curcon;
+                       bConstraintOb *cob;
+                       char col[4], col2[4];
+                       
+                       UI_GetThemeColor3ubv(TH_GRID, col);
+                       make_axis_color(col, col2, 'z');
+                       glColor3ubv((GLubyte *)col2);
+                       
+                       cob= constraints_make_evalob(ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
+                       
+                       for (curcon = list->first; curcon; curcon=curcon->next) {
+                               bConstraintTypeInfo *cti= constraint_get_typeinfo(curcon);
+                               ListBase targets = {NULL, NULL};
+                               bConstraintTarget *ct;
+                               
+                               if ((curcon->flag & CONSTRAINT_EXPAND) && (cti) && (cti->get_constraint_targets)) {
+                                       cti->get_constraint_targets(curcon, &targets);
+                                       
+                                       for (ct= targets.first; ct; ct= ct->next) {
+                                               /* calculate target's matrix */
+                                               if (cti->get_target_matrix) 
+                                                       cti->get_target_matrix(curcon, cob, ct, bsystem_time(ob, (float)(scene->r.cfra), give_timeoffset(ob)));
+                                               else
+                                                       Mat4One(ct->matrix);
+                                               
+                                               setlinestyle(3);
+                                               glBegin(GL_LINES);
+                                               glVertex3fv(ct->matrix[3]);
+                                               glVertex3fv(ob->obmat[3]);
+                                               glEnd();
+                                               setlinestyle(0);
+                                       }
+                                       
+                                       if (cti->flush_constraint_targets)
+                                               cti->flush_constraint_targets(curcon, &targets, 1);
+                               }
+                       }
+                       
+                       constraints_clear_evalob(cob);
+               }
+       }
+
+       free_old_images();
+}
+
+void draw_object_ext(const bContext *C, ARegion *ar, View3D *v3d, Scene *scene, Base *base)
+{
+       
+       if(v3d==NULL || base==NULL) return;
+       
+       if(v3d->drawtype > OB_WIRE) {
+               v3d->zbuf= 1;
+               glEnable(GL_DEPTH_TEST);
+       }
+       
+       G.f |= G_DRAW_EXT;
+
+       glDrawBuffer(GL_FRONT);
+// XXX persp(PERSP_VIEW);
+
+       if(v3d->flag & V3D_CLIPPING)
+               view3d_set_clipping(v3d);
+       
+       draw_object(C, scene, ar, v3d, base, 0);
+
+       if(v3d->flag & V3D_CLIPPING)
+               view3d_clr_clipping();
+       
+       G.f &= ~G_DRAW_EXT;
+
+       bglFlush();             /* reveil frontbuffer drawing */
+       glDrawBuffer(GL_BACK);
+       
+       if(v3d->zbuf) {
+               v3d->zbuf= 0;
+               glDisable(GL_DEPTH_TEST);
+       }
+// XXX ar->win_swap= WIN_FRONT_OK;
+}
+
+/* ***************** BACKBUF SEL (BBS) ********* */
+
+static void bbs_mesh_verts__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
+{
+       int offset = (intptr_t) userData;
+       EditVert *eve = EM_get_vert_for_index(index);
+
+       if (eve->h==0) {
+               WM_set_framebuffer_index_color(offset+index);
+               bglVertex3fv(co);
+       }
+}
+static int bbs_mesh_verts(DerivedMesh *dm, int offset)
+{
+       glPointSize( UI_GetThemeValuef(TH_VERTEX_SIZE) );
+       bglBegin(GL_POINTS);
+       dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, (void*)(intptr_t) offset);
+       bglEnd();
+       glPointSize(1.0);
+
+       return offset + G.totvert;
+}              
+
+static int bbs_mesh_wire__setDrawOptions(void *userData, int index)
+{
+       int offset = (intptr_t) userData;
+       EditEdge *eed = EM_get_edge_for_index(index);
+
+       if (eed->h==0) {
+               WM_set_framebuffer_index_color(offset+index);
+               return 1;
+       } else {
+               return 0;
+       }
+}
+static int bbs_mesh_wire(DerivedMesh *dm, int offset)
+{
+       dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, (void*)(intptr_t) offset);
+
+       return offset + G.totedge;
+}              
+
+static int bbs_mesh_solid__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
+{
+       if (EM_get_face_for_index(index)->h==0) {
+               if (userData) {
+                       WM_set_framebuffer_index_color(index+1);
+               }
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+static void bbs_mesh_solid__drawCenter(void *userData, int index, float *cent, float *no)
+{
+       EditFace *efa = EM_get_face_for_index(index);
+
+       if (efa->h==0 && efa->fgonf!=EM_FGON) {
+               WM_set_framebuffer_index_color(index+1);
+
+               bglVertex3fv(cent);
+       }
+}
+
+/* two options, facecolors or black */
+static int bbs_mesh_solid_EM(Scene *scene, View3D *v3d, DerivedMesh *dm, int facecol)
+{
+       cpack(0);
+
+       if (facecol) {
+               dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*)(intptr_t) 1, 0);
+
+               if( CHECK_OB_DRAWFACEDOT(scene, v3d, G.obedit->dt) ) {
+                       glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE));
+               
+                       bglBegin(GL_POINTS);
+                       dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, NULL);
+                       bglEnd();
+               }
+
+               return 1+G.totface;
+       } else {
+               dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*) 0, 0);
+               return 1;
+       }
+}
+
+static int bbs_mesh_solid__setDrawOpts(void *userData, int index, int *drawSmooth_r)
+{
+       Mesh *me = userData;
+
+       if (!(me->mface[index].flag&ME_HIDE)) {
+               WM_set_framebuffer_index_color(index+1);
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+/* TODO remove this - since face select mode now only works with painting */
+static void bbs_mesh_solid(Object *ob)
+{
+       DerivedMesh *dm = mesh_get_derived_final(ob, get_viewedit_datamask());
+       Mesh *me = (Mesh*)ob->data;
+       
+       glColor3ub(0, 0, 0);
+       dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, me, 0);
+
+       dm->release(dm);
+}
+
+void draw_object_backbufsel(const bContext *C, Scene *scene, View3D *v3d, Object *ob)
+{
+
+       wmMultMatrix(CTX_wm_window(C), ob->obmat);
+
+       glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT);
+       glEnable(GL_DEPTH_TEST);
+
+       switch( ob->type) {
+       case OB_MESH:
+               if(ob==G.obedit) {
+                       DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
+
+                       EM_init_index_arrays(1, 1, 1);
+
+                       em_solidoffs= bbs_mesh_solid_EM(scene, v3d, dm, scene->selectmode & SCE_SELECT_FACE);
+                       
+                       bglPolygonOffset(1.0);
+                       
+                       // we draw edges always, for loop (select) tools
+                       em_wireoffs= bbs_mesh_wire(dm, em_solidoffs);
+
+                       // we draw verts if vert select mode or if in transform (for snap).
+                       if(scene->selectmode & SCE_SELECT_VERTEX || G.moving & G_TRANSFORM_EDIT) 
+                               em_vertoffs= bbs_mesh_verts(dm, em_wireoffs);
+                       else em_vertoffs= em_wireoffs;
+                       
+                       bglPolygonOffset(0.0);
+
+                       dm->release(dm);
+
+                       EM_free_index_arrays();
+               }
+               else bbs_mesh_solid(ob);
+
+               break;
+       case OB_CURVE:
+       case OB_SURF:
+               break;
+       }
+
+       wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
+}
+
+
+/* ************* draw object instances for bones, for example ****************** */
+/*               assumes all matrices/etc set OK */
+
+/* helper function for drawing object instances - meshes */
+static void draw_object_mesh_instance(Scene *scene, View3D *v3d, Object *ob, int dt, int outline)
+{
+       DerivedMesh *dm=NULL, *edm=NULL;
+       int glsl;
+       
+       if(G.obedit && ob->data==G.obedit->data)
+               edm= editmesh_get_derived_base();
+       else 
+               dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
+
+       if(dt<=OB_WIRE) {
+               if(dm)
+                       dm->drawEdges(dm, 1);
+               else if(edm)
+                       edm->drawEdges(edm, 1); 
+       }
+       else {
+               if(outline)
+                       draw_mesh_object_outline(v3d, ob, dm?dm:edm);
+
+               if(dm) {
+                       glsl = draw_glsl_material(scene, ob, v3d, dt);
+                       GPU_set_object_materials(scene, ob, glsl, NULL);
+               }
+               else {
+                       glEnable(GL_COLOR_MATERIAL);
+                       UI_ThemeColor(TH_BONE_SOLID);
+                       glDisable(GL_COLOR_MATERIAL);
+               }
+               
+               glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
+               glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
+               glEnable(GL_LIGHTING);
+               
+               if(dm) {
+                       dm->drawFacesSolid(dm, GPU_enable_material);
+                       GPU_disable_material();
+               }
+               else if(edm)
+                       edm->drawMappedFaces(edm, NULL, NULL, 0);
+               
+               glDisable(GL_LIGHTING);
+       }
+
+       if(edm) edm->release(edm);
+       if(dm) dm->release(dm);
+}
+
+void draw_object_instance(Scene *scene, View3D *v3d, Object *ob, int dt, int outline)
+{
+       if (ob == NULL) 
+               return;
+               
+       switch (ob->type) {
+               case OB_MESH:
+                       draw_object_mesh_instance(scene, v3d, ob, dt, outline);
+                       break;
+               case OB_EMPTY:
+                       drawaxes(ob->empty_drawsize, 0, ob->empty_drawtype);
+                       break;
+       }
+}
index 712a69be77bb91a377ef311102f9dc300862a19a..d03681d6a590131e520b6787f4b5a97fef19e1c3 100644 (file)
@@ -33,6 +33,7 @@
 #include "DNA_action_types.h"
 #include "DNA_armature_types.h"
 #include "DNA_camera_types.h"
+#include "DNA_group_types.h"
 #include "DNA_key_types.h"
 #include "DNA_object_types.h"
 #include "DNA_space_types.h"
 
 #include "ED_screen.h"
 #include "ED_util.h"
+#include "ED_types.h"
 
 #include "UI_interface.h"
 #include "UI_interface_icons.h"
 #include "UI_resources.h"
 #include "UI_view2d.h"
 
+#include "GPU_draw.h"
+#include "GPU_material.h"
+
 #include "view3d_intern.h"     // own include
 
 
@@ -1145,6 +1150,178 @@ static void draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d)
        // XXX  areawinset(ar->win);    // restore viewport / scissor
 }
 
+/* ****************** View3d afterdraw *************** */
+
+typedef struct View3DAfter {
+       struct View3DAfter *next, *prev;
+       struct Base *base;
+       int type, flag;
+} View3DAfter;
+
+/* temp storage of Objects that need to be drawn as last */
+void add_view3d_after(View3D *v3d, Base *base, int type, int flag)
+{
+       View3DAfter *v3da= MEM_callocN(sizeof(View3DAfter), "View 3d after");
+       
+       BLI_addtail(&v3d->afterdraw, v3da);
+       v3da->base= base;
+       v3da->type= type;
+       v3da->flag= flag;
+}
+
+/* clears zbuffer and draws it over */
+static void view3d_draw_xray(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d, int clear)
+{
+       View3DAfter *v3da, *next;
+       int doit= 0;
+       
+       for(v3da= v3d->afterdraw.first; v3da; v3da= v3da->next)
+               if(v3da->type==V3D_XRAY) doit= 1;
+       
+       if(doit) {
+               if(clear && v3d->zbuf) glClear(GL_DEPTH_BUFFER_BIT);
+               v3d->xray= TRUE;
+               
+               for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
+                       next= v3da->next;
+                       if(v3da->type==V3D_XRAY) {
+                               draw_object(C, scene, ar, v3d, v3da->base, v3da->flag);
+                               BLI_remlink(&v3d->afterdraw, v3da);
+                               MEM_freeN(v3da);
+                       }
+               }
+               v3d->xray= FALSE;
+       }
+}
+
+/* disables write in zbuffer and draws it over */
+static void view3d_draw_transp(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d)
+{
+       View3DAfter *v3da, *next;
+       
+       glDepthMask(0);
+       v3d->transp= TRUE;
+       
+       for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
+               next= v3da->next;
+               if(v3da->type==V3D_TRANSP) {
+                       draw_object(C, scene, ar, v3d, v3da->base, v3da->flag);
+                       BLI_remlink(&v3d->afterdraw, v3da);
+                       MEM_freeN(v3da);
+               }
+       }
+       v3d->transp= FALSE;
+       
+       glDepthMask(1);
+       
+}
+
+/* *********************** */
+
+/*
+       In most cases call draw_dupli_objects,
+       draw_dupli_objects_color was added because when drawing set dupli's
+       we need to force the color
+ */
+static void draw_dupli_objects_color(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d, Base *base, int color)
+{      
+       ListBase *lb;
+       DupliObject *dob;
+       Base tbase;
+       BoundBox *bb= NULL;
+       GLuint displist=0;
+       short transflag, use_displist= -1;      /* -1 is initialize */
+       char dt, dtx;
+       
+       if (base->object->restrictflag & OB_RESTRICT_VIEW) return;
+       
+       tbase.flag= OB_FROMDUPLI|base->flag;
+       lb= object_duplilist(scene, base->object);
+       
+       for(dob= lb->first; dob; dob= dob->next) {
+               if(dob->no_draw);
+               else {
+                       tbase.object= dob->ob;
+                       
+                       /* extra service: draw the duplicator in drawtype of parent */
+                       /* MIN2 for the drawtype to allow bounding box objects in groups for lods */
+                       dt= tbase.object->dt;   tbase.object->dt= MIN2(tbase.object->dt, base->object->dt);
+                       dtx= tbase.object->dtx; tbase.object->dtx= base->object->dtx;
+                       
+                       /* negative scale flag has to propagate */
+                       transflag= tbase.object->transflag;
+                       if(base->object->transflag & OB_NEG_SCALE)
+                               tbase.object->transflag ^= OB_NEG_SCALE;
+                       
+                       UI_ThemeColorBlend(color, TH_BACK, 0.5);
+                       
+                       /* generate displist, test for new object */
+                       if(use_displist==1 && dob->prev && dob->prev->ob!=dob->ob) {
+                               use_displist= -1;
+                               glDeleteLists(displist, 1);
+                       }
+                       /* generate displist */
+                       if(use_displist == -1) {
+                               
+                               /* lamp drawing messes with matrices, could be handled smarter... but this works */
+                               if(dob->ob->type==OB_LAMP || dob->type==OB_DUPLIGROUP)
+                                       use_displist= 0;
+                               else {
+                                       /* disable boundbox check for list creation */
+                                       object_boundbox_flag(dob->ob, OB_BB_DISABLED, 1);
+                                       /* need this for next part of code */
+                                       bb= object_get_boundbox(dob->ob);
+                                       
+                                       Mat4One(dob->ob->obmat);        /* obmat gets restored */
+                                       
+                                       displist= glGenLists(1);
+                                       glNewList(displist, GL_COMPILE);
+                                       draw_object(C, scene, ar, v3d, &tbase, DRAW_CONSTCOLOR);
+                                       glEndList();
+                                       
+                                       use_displist= 1;
+                                       object_boundbox_flag(dob->ob, OB_BB_DISABLED, 0);
+                               }
+                       }
+                       if(use_displist) {
+                               wmMultMatrix(CTX_wm_window(C), dob->mat);
+                               if(boundbox_clip(v3d, dob->mat, bb))
+                                       glCallList(displist);
+                               wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
+                       }
+                       else {
+                               Mat4CpyMat4(dob->ob->obmat, dob->mat);
+                               draw_object(C, scene, ar, v3d, &tbase, DRAW_CONSTCOLOR);
+                       }
+                       
+                       tbase.object->dt= dt;
+                       tbase.object->dtx= dtx;
+                       tbase.object->transflag= transflag;
+               }
+       }
+       
+       /* Transp afterdraw disabled, afterdraw only stores base pointers, and duplis can be same obj */
+       
+       free_object_duplilist(lb);      /* does restore */
+       
+       if(use_displist)
+               glDeleteLists(displist, 1);
+}
+
+static void draw_dupli_objects(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d, Base *base)
+{
+       /* define the color here so draw_dupli_objects_color can be called
+       * from the set loop */
+       
+       int color= (base->flag & SELECT)?TH_SELECT:TH_WIRE;
+       /* debug */
+       if(base->object->dup_group && base->object->dup_group->id.us<1)
+               color= TH_REDALERT;
+       
+       draw_dupli_objects_color(C, scene, ar, v3d, base, color);
+}
+
+
 void view3d_update_depths(ARegion *ar, View3D *v3d)
 {
        /* Create storage for, and, if necessary, copy depth buffer */
@@ -1174,7 +1351,7 @@ void view3d_update_depths(ARegion *ar, View3D *v3d)
 }
 
 /* Enable sculpting in wireframe mode by drawing sculpt object only to the depth buffer */
-static void draw_sculpt_depths(Scene *scene, View3D *v3d)
+static void draw_sculpt_depths(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d)
 {
        Object *ob = OBACT;
        
@@ -1193,7 +1370,7 @@ static void draw_sculpt_depths(Scene *scene, View3D *v3d)
                
                glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
                glEnable(GL_DEPTH_TEST);
-// XXX         draw_object(BASACT, 0);
+               draw_object(C, scene, ar, v3d, BASACT, 0);
                glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
                if(!depth_on)
                        glDisable(GL_DEPTH_TEST);
@@ -1204,6 +1381,185 @@ static void draw_sculpt_depths(Scene *scene, View3D *v3d)
        }
 }
 
+void draw_depth(const bContext *C, Scene *scene, ARegion *ar, View3D *v3d, int (* func)(void *))
+{
+       Base *base;
+       Scene *sce;
+       short zbuf, flag;
+       float glalphaclip;
+       /* temp set drawtype to solid */
+       
+       /* Setting these temporarily is not nice */
+       zbuf = v3d->zbuf;
+       flag = v3d->flag;
+       glalphaclip = U.glalphaclip;
+       
+       U.glalphaclip = 0.5; /* not that nice but means we wont zoom into billboards */
+       v3d->flag &= ~V3D_SELECT_OUTLINE;
+       
+       setwinmatrixview3d(CTX_wm_window(C), v3d, ar->winx, ar->winy, NULL);    /* 0= no pick rect */
+       setviewmatrixview3d(v3d);       /* note: calls where_is_object for camera... */
+       
+       Mat4MulMat4(v3d->persmat, v3d->viewmat, v3d->winmat);
+       Mat4Invert(v3d->persinv, v3d->persmat);
+       Mat4Invert(v3d->viewinv, v3d->viewmat);
+       
+       glClear(GL_DEPTH_BUFFER_BIT);
+       
+       wmLoadMatrix(CTX_wm_window(C), v3d->viewmat);
+//     persp(PERSP_STORE);  // store correct view for persp(PERSP_VIEW) calls
+       
+       if(v3d->flag & V3D_CLIPPING) {
+               view3d_set_clipping(v3d);
+       }
+       
+       v3d->zbuf= TRUE;
+       glEnable(GL_DEPTH_TEST);
+       
+       /* draw set first */
+       if(scene->set) {
+               for(SETLOOPER(scene->set, base)) {
+                       if(v3d->lay & base->lay) {
+                               if (func == NULL || func(base)) {
+                                       draw_object(C, scene, ar, v3d, base, 0);
+                                       if(base->object->transflag & OB_DUPLI) {
+                                               draw_dupli_objects_color(C, scene, ar, v3d, base, TH_WIRE);
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       for(base= scene->base.first; base; base= base->next) {
+               if(v3d->lay & base->lay) {
+                       if (func == NULL || func(base)) {
+                               /* dupli drawing */
+                               if(base->object->transflag & OB_DUPLI) {
+                                       draw_dupli_objects(C, scene, ar, v3d, base);
+                               }
+                               draw_object(C, scene, ar, v3d, base, 0);
+                       }
+               }
+       }
+       
+       /* this isnt that nice, draw xray objects as if they are normal */
+       if (v3d->afterdraw.first) {
+               View3DAfter *v3da, *next;
+               int num = 0;
+               v3d->xray= TRUE;
+               
+               glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */
+               for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
+                       next= v3da->next;
+                       if(v3da->type==V3D_XRAY) {
+                               draw_object(C, scene, ar, v3d, v3da->base, 0);
+                               num++;
+                       }
+                       /* dont remove this time */
+               }
+               v3d->xray= FALSE;
+               
+               glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */
+               for(v3da= v3d->afterdraw.first; v3da; v3da= next) {
+                       next= v3da->next;
+                       if(v3da->type==V3D_XRAY) {
+                               v3d->xray= TRUE; v3d->transp= FALSE;  
+                       } else if (v3da->type==V3D_TRANSP) {
+                               v3d->xray= FALSE; v3d->transp= TRUE;
+                       }
+                       
+                       draw_object(C, scene, ar, v3d, v3da->base, 0); /* Draw Xray or Transp objects normally */
+                       BLI_remlink(&v3d->afterdraw, v3da);
+                       MEM_freeN(v3da);
+               }
+               v3d->xray= FALSE;
+               v3d->transp= FALSE;
+       }
+       
+       v3d->zbuf = zbuf;
+       U.glalphaclip = glalphaclip;
+       v3d->flag = flag;
+}
+
+typedef struct View3DShadow {
+       struct View3DShadow *next, *prev;
+       GPULamp *lamp;
+} View3DShadow;
+
+static void gpu_render_lamp_update(Scene *scene, View3D *v3d, Object *ob, Object *par, float obmat[][4], ListBase *shadows)
+{
+       GPULamp *lamp;
+       View3DShadow *shadow;
+       
+       lamp = GPU_lamp_from_blender(scene, ob, par);
+       
+       if(lamp) {
+               GPU_lamp_update(lamp, ob->lay, obmat);
+               
+               if((ob->lay & v3d->lay) && GPU_lamp_has_shadow_buffer(lamp)) {
+                       shadow= MEM_callocN(sizeof(View3DShadow), "View3DShadow");
+                       shadow->lamp = lamp;
+                       BLI_addtail(shadows, shadow);
+               }
+       }
+}
+
+static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
+{
+       ListBase shadows;
+       View3DShadow *shadow;
+       Scene *sce;
+       Base *base;
+       Object *ob;
+       
+       shadows.first= shadows.last= NULL;
+       
+       /* update lamp transform and gather shadow lamps */
+       for(SETLOOPER(scene, base)) {
+               ob= base->object;
+               
+               if(ob->type == OB_LAMP)
+                       gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, &shadows);
+               
+               if (ob->transflag & OB_DUPLI) {
+                       DupliObject *dob;
+                       ListBase *lb = object_duplilist(scene, ob);
+                       
+                       for(dob=lb->first; dob; dob=dob->next)
+                               if(dob->ob->type==OB_LAMP)
+                                       gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, &shadows);
+                       
+                       free_object_duplilist(lb);
+               }
+       }
+       
+       /* render shadows after updating all lamps, nested object_duplilist
+               * don't work correct since it's replacing object matrices */
+       for(shadow=shadows.first; shadow; shadow=shadow->next) {
+               /* this needs to be done better .. */
+               float viewmat[4][4], winmat[4][4];
+               int drawtype, lay, winsize, flag2;
+               
+               drawtype= v3d->drawtype;
+               lay= v3d->lay;
+               flag2= v3d->flag2 & V3D_SOLID_TEX;
+               
+               v3d->drawtype = OB_SOLID;
+               v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp);
+               v3d->flag2 &= ~V3D_SOLID_TEX;
+               
+               GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat);
+// XXX         drawview3d_render(v3d, viewmat, winsize, winsize, winmat, 1);
+               GPU_lamp_shadow_buffer_unbind(shadow->lamp);
+               
+               v3d->drawtype= drawtype;
+               v3d->lay= lay;
+               v3d->flag2 |= flag2;
+       }
+       
+       BLI_freelistN(&shadows);
+}
+
 
 void drawview3dspace(const bContext *C, ARegion *ar, View3D *v3d)
 {
@@ -1228,8 +1584,8 @@ void drawview3dspace(const bContext *C, ARegion *ar, View3D *v3d)
        }
        
        /* shadow buffers, before we setup matrices */
-//     if(draw_glsl_material(NULL, v3d->drawtype))
-//             gpu_update_lamps_shadows(scene, v3d);
+       if(draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
+               gpu_update_lamps_shadows(scene, v3d);
        
        setwinmatrixview3d(CTX_wm_window(C), v3d, ar->winx, ar->winy, NULL);    /* 0= no pick rect */
        setviewmatrixview3d(v3d);       /* note: calls where_is_object for camera... */
@@ -1319,10 +1675,10 @@ void drawview3dspace(const bContext *C, ARegion *ar, View3D *v3d)
                        if(v3d->lay & base->lay) {
                                
                                UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
-// XXX                         draw_object(base, DRAW_CONSTCOLOR|DRAW_SCENESET);
+                               draw_object(C, scene, ar, v3d, base, DRAW_CONSTCOLOR|DRAW_SCENESET);
                                
                                if(base->object->transflag & OB_DUPLI) {
-// XXX                                 draw_dupli_objects_color(v3d, base, TH_WIRE);
+                                       draw_dupli_objects_color(C, scene, ar, v3d, base, TH_WIRE);