From 07288789014de44a93392d441198b8d6d029e59a Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 21 Apr 2009 13:35:34 +0000 Subject: [PATCH 001/138] branch fron 2.5 for jaguarandi From a5ede4332043284255c2020d7b75c0c00f58db5d Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 10 May 2009 21:02:58 +0000 Subject: [PATCH 002/138] *new generic raytrace API *Adapted octree to a more generic raytrace API *ray shadow works (other untested stuff disabled atm) On the scene tested the user-cpu time got from 1:24 to 1:19/20 probably because of removed callbacks or sligtly diferente memory usage --- .../blender/editors/armature/meshlaplacian.c | 105 +-- .../render/extern/include/RE_raytrace.h | 126 ++- .../blender/render/intern/include/rayobject.h | 122 +++ .../render/intern/include/render_types.h | 7 +- .../blender/render/intern/source/rayobject.c | 276 +++++++ .../render/intern/source/rayobject_mesh.c | 128 +++ .../source/{raytrace.c => rayobject_octree.c} | 726 +++++------------- .../blender/render/intern/source/rayshade.c | 275 ++++--- .../blender/render/intern/source/rendercore.c | 33 +- 9 files changed, 973 insertions(+), 825 deletions(-) create mode 100644 source/blender/render/intern/include/rayobject.h create mode 100644 source/blender/render/intern/source/rayobject.c create mode 100644 source/blender/render/intern/source/rayobject_mesh.c rename source/blender/render/intern/source/{raytrace.c => rayobject_octree.c} (61%) diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 8807b21e653..c3ab60ffda6 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -30,6 +30,7 @@ #include #include +#include #include "MEM_guardedalloc.h" @@ -105,7 +106,7 @@ struct LaplacianSystem { float *p; /* values from all p vectors */ float *mindist; /* minimum distance to a bone for all vertices */ - RayTree *raytree; /* ray tracing acceleration structure */ + RayObject *raytree; /* ray tracing acceleration structure */ MFace **vface; /* a face that the vertex belongs to */ } heat; @@ -394,77 +395,31 @@ float laplacian_system_get_solution(int v) #define DISTANCE_EPSILON 1e-4f /* Raytracing for vertex to bone visibility */ - -static LaplacianSystem *HeatSys = NULL; - -static void heat_ray_coords_func(RayFace *face, float **v1, float **v2, float **v3, float **v4) -{ - MFace *mface= (MFace*)face; - float (*verts)[3]= HeatSys->heat.verts; - - *v1= verts[mface->v1]; - *v2= verts[mface->v2]; - *v3= verts[mface->v3]; - *v4= (mface->v4)? verts[mface->v4]: NULL; -} - -static int heat_ray_check_func(Isect *is, int ob, RayFace *face) -{ - float *v1, *v2, *v3, *v4, nor[3]; - - /* don't intersect if the ray faces along the face normal */ - heat_ray_coords_func(face, &v1, &v2, &v3, &v4); - - if(v4) CalcNormFloat4(v1, v2, v3, v4, nor); - else CalcNormFloat(v1, v2, v3, nor); - - return (INPR(nor, is->vec) < 0); -} - static void heat_ray_tree_create(LaplacianSystem *sys) { Mesh *me = sys->heat.mesh; - RayTree *tree; MFace *mface; - float min[3], max[3]; int a; - /* create a raytrace tree from the mesh */ - INIT_MINMAX(min, max); - - for(a=0; atotvert; a++) - DO_MINMAX(sys->heat.verts[a], min, max); - - tree= RE_ray_tree_create(64, me->totface, min, max, - heat_ray_coords_func, heat_ray_check_func, NULL, NULL); - - sys->heat.vface= MEM_callocN(sizeof(MFace*)*me->totvert, "HeatVFaces"); - - HeatSys= sys; + sys->heat.raytree = RayObject_mesh_create(me, me); + sys->heat.vface = MEM_callocN(sizeof(MFace*)*me->totvert, "HeatVFaces"); for(a=0, mface=me->mface; atotface; a++, mface++) { - RE_ray_tree_add_face(tree, 0, mface); - sys->heat.vface[mface->v1]= mface; sys->heat.vface[mface->v2]= mface; sys->heat.vface[mface->v3]= mface; if(mface->v4) sys->heat.vface[mface->v4]= mface; } - - HeatSys= NULL; - - RE_ray_tree_done(tree); - - sys->heat.raytree= tree; } static int heat_ray_bone_visible(LaplacianSystem *sys, int vertex, int bone) { Isect isec; MFace *mface; - float dir[3]; + float end[3]; int visible; + assert( 0 ); mface= sys->heat.vface[vertex]; if(!mface) return 1; @@ -473,22 +428,24 @@ static int heat_ray_bone_visible(LaplacianSystem *sys, int vertex, int bone) memset(&isec, 0, sizeof(isec)); isec.mode= RE_RAY_SHADOW; isec.lay= -1; - isec.face_last= NULL; - isec.faceorig= mface; + isec.orig.face = mface; + isec.skip = RE_SKIP_CULLFACE; VECCOPY(isec.start, sys->heat.verts[vertex]); - PclosestVL3Dfl(isec.end, isec.start, - sys->heat.root[bone], sys->heat.tip[bone]); + PclosestVL3Dfl(end, isec.start, sys->heat.root[bone], sys->heat.tip[bone]); + VECSUB(isec.vec, end, isec.start); + isec.labda = 1.0f; + +#if 0 + TODO /* add an extra offset to the start position to avoid self intersection */ - VECSUB(dir, isec.end, isec.start); + VECCOPY(dir, isec.vec); Normalize(dir); VecMulf(dir, 1e-5); VecAddf(isec.start, isec.start, dir); - - HeatSys= sys; - visible= !RE_ray_tree_intersect(sys->heat.raytree, &isec); - HeatSys= NULL; +#endif + visible= !RayObject_raycast(sys->heat.raytree, &isec); return visible; } @@ -752,7 +709,7 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numbones, /* free */ if(vertsflipped) MEM_freeN(vertsflipped); - RE_ray_tree_free(sys->heat.raytree); + RayObject_free(sys->heat.raytree); MEM_freeN(sys->heat.vface); MEM_freeN(sys->heat.mindist); @@ -1049,7 +1006,7 @@ typedef struct MeshDeformBind { int *varidx; /* raytrace */ - RayTree *raytree; + RayObject *raytree; } MeshDeformBind; /* ray intersection */ @@ -1173,7 +1130,7 @@ static void meshdeform_ray_tree_free(MeshDeformBind *mdb) static int meshdeform_intersect(MeshDeformBind *mdb, Isect *isec) { MFace *mface; - float face[4][3], co[3], uvw[3], len, nor[3]; + float face[4][3], co[3], uvw[3], len, nor[3], end[3]; int f, hit, is= 0, totface; isec->labda= 1e10; @@ -1181,6 +1138,8 @@ static int meshdeform_intersect(MeshDeformBind *mdb, Isect *isec) mface= mdb->cagedm->getFaceArray(mdb->cagedm); totface= mdb->cagedm->getNumFaces(mdb->cagedm); + VECADDFAC( end, isec->start, isec->vec, isec->labda ); + for(f=0; fcagecos[mface->v1]); VECCOPY(face[1], mdb->cagecos[mface->v2]); @@ -1188,26 +1147,26 @@ static int meshdeform_intersect(MeshDeformBind *mdb, Isect *isec) if(mface->v4) { VECCOPY(face[3], mdb->cagecos[mface->v4]); - hit= meshdeform_tri_intersect(isec->start, isec->end, face[0], face[1], face[2], co, uvw); + hit = meshdeform_tri_intersect(isec->start, end, face[0], face[1], face[2], co, uvw); if(hit) { CalcNormFloat(face[0], face[1], face[2], nor); } else { - hit= meshdeform_tri_intersect(isec->start, isec->end, face[0], face[2], face[3], co, uvw); + hit= meshdeform_tri_intersect(isec->start, end, face[0], face[2], face[3], co, uvw); CalcNormFloat(face[0], face[2], face[3], nor); } } else { - hit= meshdeform_tri_intersect(isec->start, isec->end, face[0], face[1], face[2], co, uvw); + hit= meshdeform_tri_intersect(isec->start, end, face[0], face[1], face[2], co, uvw); CalcNormFloat(face[0], face[1], face[2], nor); } if(hit) { - len= VecLenf(isec->start, co)/VecLenf(isec->start, isec->end); + len= VecLenf(isec->start, co)/VecLenf(isec->start, end); if(len < isec->labda) { isec->labda= len; - isec->face= mface; + isec->hit.face = mface; isec->isect= (INPR(isec->vec, nor) <= 0.0f); is= 1; } @@ -1223,20 +1182,18 @@ static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, float Isect isec; float (*cagecos)[3]; MFace *mface; - float vert[4][3], len; + float vert[4][3], len, end[3]; static float epsilon[3]= {0, 0, 0}; //1e-4, 1e-4, 1e-4}; /* setup isec */ memset(&isec, 0, sizeof(isec)); isec.mode= RE_RAY_MIRROR; /* we want the closest intersection */ isec.lay= -1; - isec.face_last= NULL; - isec.faceorig= NULL; isec.labda= 1e10f; VECADD(isec.start, co1, epsilon); - VECADD(isec.end, co2, epsilon); - VECSUB(isec.vec, isec.end, isec.start); + VECADD(end, co2, epsilon); + VECSUB(isec.vec, end, isec.start); #if 0 /*if(RE_ray_tree_intersect(mdb->raytree, &isec)) {*/ @@ -1244,7 +1201,7 @@ static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, float if(meshdeform_intersect(mdb, &isec)) { len= isec.labda; - mface= isec.face; + mface=(MFace*)isec.hit.face; /* create MDefBoundIsect */ isect= BLI_memarena_alloc(mdb->memarena, sizeof(*isect)); diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index 8f429f7dd90..b274fe681b3 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -22,7 +22,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): André Pinto. * * ***** END GPL LICENSE BLOCK ***** * RE_raytrace.h: ray tracing api, can be used independently from the renderer. @@ -31,84 +31,64 @@ #ifndef RE_RAYTRACE_H #define RE_RAYTRACE_H + +/* Internals about raycasting structures can be found on intern/raytree.h */ +typedef struct RayObject RayObject; +typedef struct Isect Isect; +struct DerivedMesh; +struct Mesh; + +int RayObject_raycast(RayObject *r, Isect *i); +void RayObject_add (RayObject *r, RayObject *); +void RayObject_done(RayObject *r); +void RayObject_free(RayObject *r); + +/* RayObject constructors */ +RayObject* RayObject_octree_create(int ocres, int size); + +//RayObject* RayObject_derivedmesh_create(struct DerivedMesh*, void *ob); +RayObject* RayObject_mesh_create(struct Mesh*, void *ob); + +/* Ray Intersection */ +struct Isect +{ + float start[3]; + float vec[3]; +/* float end[3]; - not used */ + + float labda, u, v; + + struct + { + void *ob; + void *face; +/* RayObject *obj; */ + } + hit, orig; + + RayObject *last_hit; /* last hit optimization */ + + short isect; /* which half of quad */ + short mode; /* RE_RAY_SHADOW, RE_RAY_MIRROR, RE_RAY_SHADOW_TRA */ + int lay; /* -1 default, set for layer lamps */ + + int skip; /* RE_SKIP_CULLFACE */ + + float col[4]; /* RGBA for shadow_tra */ + + void *userdata; +}; + /* ray types */ #define RE_RAY_SHADOW 0 #define RE_RAY_MIRROR 1 #define RE_RAY_SHADOW_TRA 2 -/* spatial tree for raytracing acceleration */ -typedef void RayTree; -/* abstraction of face type */ -typedef void RayFace; +/* skip options */ +#define RE_SKIP_CULLFACE 1 -/* object numbers above this are transformed */ -#define RE_RAY_TRANSFORM_OFFS 0x8000000 +/* TODO use: FLT_MAX? */ +#define RE_RAYTRACE_MAXDIST 1e33 -/* convert from pointer to index in array and back, with offset if the - * instance is transformed */ -#define RAY_OBJECT_SET(re, obi) \ - ((obi == NULL)? 0: \ - ((obi - (re)->objectinstance) + ((obi->flag & R_TRANSFORMED)? RE_RAY_TRANSFORM_OFFS: 0))) - -#define RAY_OBJECT_GET(re, i) \ - ((re)->objectinstance + ((i >= RE_RAY_TRANSFORM_OFFS)? i-RE_RAY_TRANSFORM_OFFS: i)) - - -/* struct for intersection data */ -typedef struct Isect { - float start[3]; /* start+vec = end, in ray_tree_intersect */ - float vec[3]; - float end[3]; - - float labda, u, v; /* distance to hitpoint, uv weights */ - - RayFace *face; /* face is where to intersect with */ - int ob; - RayFace *faceorig; /* start face */ - int oborig; - RayFace *face_last; /* for shadow optimize, last intersected face */ - int ob_last; - - short isect; /* which half of quad */ - short mode; /* RE_RAY_SHADOW, RE_RAY_MIRROR, RE_RAY_SHADOW_TRA */ - int lay; /* -1 default, set for layer lamps */ - - /* only used externally */ - float col[4]; /* RGBA for shadow_tra */ - - /* octree only */ - RayFace *facecontr; - int obcontr; - float ddalabda; - short faceisect; /* flag if facecontr was done or not */ - - /* custom pointer to be used in the RayCheckFunc */ - void *userdata; -} Isect; - -/* function callbacks for face type abstraction */ -typedef void (*RayCoordsFunc)(RayFace *face, - float **v1, float **v2, float **v3, float **v4); -typedef int (*RayCheckFunc)(Isect *is, int ob, RayFace *face); -typedef float *(*RayObjectTransformFunc)(void *userdata, int ob); - -/* tree building and freeing */ -RayTree *RE_ray_tree_create(int ocres, int totface, float *min, float *max, - RayCoordsFunc coordfunc, RayCheckFunc checkfunc, - RayObjectTransformFunc transformfunc, void *userdata); -void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face); -void RE_ray_tree_done(RayTree *tree); -void RE_ray_tree_free(RayTree *tree); - -/* intersection with full tree and single face */ -int RE_ray_tree_intersect(RayTree *tree, Isect *is); -int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc check); -int RE_ray_face_intersection(Isect *is, RayObjectTransformFunc transformfunc, - RayCoordsFunc coordsfunc); - -/* retrieve the diameter of the tree structure, for setting intersection - end distance */ -float RE_ray_tree_max_size(RayTree *tree); #endif /*__RE_RAYTRACE_H__*/ - diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h new file mode 100644 index 00000000000..a1b35ac0465 --- /dev/null +++ b/source/blender/render/intern/include/rayobject.h @@ -0,0 +1,122 @@ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef RE_RAYOBJECT_H +#define RE_RAYOBJECT_H + +#include "RE_raytrace.h" +#include + +/* RayObject + + A ray object is everything where we can cast rays like: + * a face/triangle + * an octree + * a bvh tree + * an octree of bvh's + * a bvh of bvh's + + + All types of RayObjects can be created by implementing the + callbacks of the RayObject. + + Due to high computing time evolved with casting on faces + there is a special type of RayObject (named RayFace) + which won't use callbacks like other generic nodes. + + In order to allow a mixture of RayFace+RayObjects, + all RayObjects must be 4byte aligned, allowing us to use the + 2 least significant bits (with the mask 0x02) to define the + type of RayObject. + + This leads to 4 possible types of RayObject, but at the moment + only 2 are used: + + addr&2 - type of object + 0 RayFace + 1 RayObject (generic with API callbacks) + 2 unused + 3 unused + + 0 was choosed to RayFace because thats the one where speed will be needed. + + You actually don't need to care about this if you are only using the API + described on RE_raytrace.h + */ + +typedef struct RayFace +{ + float *v1, *v2, *v3, *v4; + + void *ob; + void *face; + +} RayFace; + +struct RayObject +{ + struct RayObjectAPI *api; + +}; + +typedef int (*RayObject_raycast_callback)(RayObject *, Isect *); +typedef void (*RayObject_add_callback)(RayObject *, RayObject *); +typedef void (*RayObject_done_callback)(RayObject *); +typedef void (*RayObject_free_callback)(RayObject *); +typedef void (*RayObject_bb_callback)(RayObject *, float *min, float *max); + +typedef struct RayObjectAPI +{ + RayObject_raycast_callback raycast; + RayObject_add_callback add; + RayObject_done_callback done; + RayObject_free_callback free; + RayObject_bb_callback bb; + +} RayObjectAPI; + +//TODO use intptr_t +#define RayObject_align(o) ((RayObject*)(((int)o)&(~3))) +#define RayObject_unalign(o) ((RayObject*)(((int)o)|1)) +#define RayObject_isFace(o) ((((int)o)&3) == 0) + +/* + * Extend min/max coords so that the rayobject is inside them + */ +void RayObject_merge_bb(RayObject *ob, float *min, float *max); + +/* + * This function differs from RayObject_raycast + * RayObject_intersect does NOT perform last-hit optimization + * So this is probably a function to call inside raytrace structures + */ +int RayObject_intersect(RayObject *r, Isect *i); + +#define ISECT_EPSILON ((float)FLT_EPSILON) + +#endif diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index ab3758781ce..4846fe8d0e4 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -53,6 +53,7 @@ struct VlakTableNode; struct GHash; struct RenderBuckets; struct ObjectInstanceRen; +struct RayObject; #define TABLEINITSIZE 1024 #define LAMPINITSIZE 256 @@ -168,7 +169,8 @@ struct Render ListBase parts; /* octree tables and variables for raytrace */ - void *raytree; + struct RayObject *raytree; + struct RayObject *rayfaces; /* TODO Temporary */ /* occlusion tree */ void *occlusiontree; @@ -491,8 +493,7 @@ typedef struct LampRen { short YF_glowtype; /* ray optim */ - VlakRen *vlr_last[BLENDER_MAX_THREADS]; - ObjectInstanceRen *obi_last[BLENDER_MAX_THREADS]; + struct RayObject *last_hit[BLENDER_MAX_THREADS]; struct MTex *mtex[MAX_MTEX]; diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c new file mode 100644 index 00000000000..ee364d3586c --- /dev/null +++ b/source/blender/render/intern/source/rayobject.c @@ -0,0 +1,276 @@ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#include "assert.h" + +#include "BKE_utildefines.h" + +#include "RE_raytrace.h" +#include "rayobject.h" + +/* ray - triangle or quad intersection */ +static int intersect_rayface(RayFace *face, Isect *is) +{ + float co1[3],co2[3],co3[3],co4[3]; + float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22,r0,r1,r2; + float m0, m1, m2, divdet, det1; + short ok=0; + + if(is->orig.ob == face->ob && is->orig.face == face->face) + return 0; + + /* disabled until i got real & fast cylinder checking, this code doesnt work proper for faster strands */ + // if(is->mode==RE_RAY_SHADOW && is->vlr->flag & R_STRAND) + // return intersection_strand(is); + + + VECCOPY(co1, face->v1); + VECCOPY(co2, face->v2); + + //TODO if(v4) { SWAP(float*, v3, v4); } + if(face->v4) + { + VECCOPY(co3, face->v4); + VECCOPY(co4, face->v3); + } + else + { + VECCOPY(co3, face->v3); + } + + t00= co3[0]-co1[0]; + t01= co3[1]-co1[1]; + t02= co3[2]-co1[2]; + t10= co3[0]-co2[0]; + t11= co3[1]-co2[1]; + t12= co3[2]-co2[2]; + + r0= is->vec[0]; + r1= is->vec[1]; + r2= is->vec[2]; + + x0= t12*r1-t11*r2; + x1= t10*r2-t12*r0; + x2= t11*r0-t10*r1; + + divdet= t00*x0+t01*x1+t02*x2; + + m0= is->start[0]-co3[0]; + m1= is->start[1]-co3[1]; + m2= is->start[2]-co3[2]; + det1= m0*x0+m1*x1+m2*x2; + + if(divdet!=0.0f) { + float u; + + divdet= 1.0f/divdet; + u= det1*divdet; + if(u-(1.0f+ISECT_EPSILON)) { + float v, cros0, cros1, cros2; + + cros0= m1*t02-m2*t01; + cros1= m2*t00-m0*t02; + cros2= m0*t01-m1*t00; + v= divdet*(cros0*r0 + cros1*r1 + cros2*r2); + + if(v -(1.0f+ISECT_EPSILON)) { + float labda; + labda= divdet*(cros0*t10 + cros1*t11 + cros2*t12); + + if(labda>-ISECT_EPSILON && labda<1.0f+ISECT_EPSILON) { + is->labda= labda; + is->u= u; is->v= v; + ok= 1; + } + } + } + } + + if(ok==0 && face->v4) { + + t20= co3[0]-co4[0]; + t21= co3[1]-co4[1]; + t22= co3[2]-co4[2]; + + divdet= t20*x0+t21*x1+t22*x2; + if(divdet!=0.0f) { + float u; + divdet= 1.0f/divdet; + u = det1*divdet; + + if(u-(1.0f+ISECT_EPSILON)) { + float v, cros0, cros1, cros2; + cros0= m1*t22-m2*t21; + cros1= m2*t20-m0*t22; + cros2= m0*t21-m1*t20; + v= divdet*(cros0*r0 + cros1*r1 + cros2*r2); + + if(v-(1.0f+ISECT_EPSILON)) { + float labda; + labda= divdet*(cros0*t10 + cros1*t11 + cros2*t12); + + if(labda>-ISECT_EPSILON && labda<1.0f+ISECT_EPSILON) { + ok= 2; + is->labda= labda; + is->u= u; is->v= v; + } + } + } + } + } + + if(ok) { + is->isect= ok; // wich half of the quad + +/* + TODO + if(is->mode!=RE_RAY_SHADOW) { + / * for mirror & tra-shadow: large faces can be filled in too often, this prevents + a face being detected too soon... * / + if(is->labda > is->ddalabda) { + return 0; + } + } +*/ + +#if 0 + TODO + /* when a shadow ray leaves a face, it can be little outside the edges of it, causing + intersection to be detected in its neighbour face */ + if(is->facecontr && is->faceisect); // optimizing, the tests below are not needed + else if(is->labda< .1) { + RayFace *face= is->orig.face; + float *origv1, *origv2, *origv3, *origv4; + short de= 0; + + coordsfunc(face, &origv1, &origv2, &origv3, &origv4); + + if(ob == is->orig.ob) { + if(v1==origv1 || v2==origv1 || v3==origv1 || v4==origv1) de++; + if(v1==origv2 || v2==origv2 || v3==origv2 || v4==origv2) de++; + if(v1==origv3 || v2==origv3 || v3==origv3 || v4==origv3) de++; + if(origv4) { + if(v1==origv4 || v2==origv4 || v3==origv4 || v4==origv4) de++; + } + } + if(de) { + /* so there's a shared edge or vertex, let's intersect ray with face + itself, if that's true we can safely return 1, otherwise we assume + the intersection is invalid, 0 */ + + if(is->facecontr==NULL) { + is->obcontr= is->orig.ob; + is->facecontr= face; + is->faceisect= intersection2(face, is->orig.ob, transformfunc, coordsfunc, is->userdata, + -r0, -r1, -r2, + is->start[0], is->start[1], is->start[2]); + } + + if(is->faceisect) return 1; + return 0; + } + } +#endif + + is->hit.ob = face->ob; + is->hit.face = face->face; + return 1; + } + + return 0; +} + +int RayObject_raycast(RayObject *r, Isect *i) +{ + if(i->mode==RE_RAY_SHADOW && i->last_hit && RayObject_intersect(i->last_hit, i)) + return 1; + + return RayObject_intersect(r, i); +} + +int RayObject_intersect(RayObject *r, Isect *i) +{ + assert(i->mode==RE_RAY_SHADOW); + if(RayObject_isFace(r)) + { + return intersect_rayface( (RayFace*) r, i); + } + else + { + //TODO should be done somewhere else +// float len = Normalize( i->vec ); + int hit; + i->vec[0] *= i->labda; + i->vec[1] *= i->labda; + i->vec[2] *= i->labda; + i->labda = 1.0f; //RE_RAYTRACE_MAXDIST; //len; + + r = RayObject_align( r ); + + hit = r->api->raycast( r, i ); +// i->labda /= len; + + return hit; + } +} + +void RayObject_add(RayObject *r, RayObject *o) +{ + r = RayObject_align( r ); + return r->api->add( r, o ); +} + +void RayObject_done(RayObject *r) +{ + r = RayObject_align( r ); + r->api->done( r ); +} + +void RayObject_free(RayObject *r) +{ + r = RayObject_align( r ); + r->api->free( r ); +} + +void RayObject_merge_bb(RayObject *r, float *min, float *max) +{ + if(RayObject_isFace(r)) + { + RayFace *face = (RayFace*)r; + DO_MINMAX( face->v1, min, max ); + DO_MINMAX( face->v2, min, max ); + DO_MINMAX( face->v3, min, max ); + if(face->v4) DO_MINMAX( face->v4, min, max ); + } + else + { + r = RayObject_align( r ); + r->api->bb( r, min, max ); + } +} + diff --git a/source/blender/render/intern/source/rayobject_mesh.c b/source/blender/render/intern/source/rayobject_mesh.c new file mode 100644 index 00000000000..7b8bca38172 --- /dev/null +++ b/source/blender/render/intern/source/rayobject_mesh.c @@ -0,0 +1,128 @@ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#include "rayobject.h" + +#include "MEM_guardedalloc.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "BKE_utildefines.h" + +typedef struct RayMesh +{ + RayObject rayobj; + + Mesh *mesh; + void *ob; + + RayFace *faces; + int num_faces; + +} RayMesh; + +static int RayObject_mesh_intersect(RayObject *o, Isect *isec); +static void RayObject_mesh_add(RayObject *o, RayObject *ob); +static void RayObject_mesh_done(RayObject *o); +static void RayObject_mesh_free(RayObject *o); +static void RayObject_mesh_bb(RayObject *o, float *min, float *max); + +static RayObjectAPI mesh_api = +{ + RayObject_mesh_intersect, + RayObject_mesh_add, + RayObject_mesh_done, + RayObject_mesh_free, + RayObject_mesh_bb +}; + + +static int RayObject_mesh_intersect(RayObject *o, Isect *isec) +{ + RayMesh *rm= (RayMesh*)o; + int i, hit = 0; + for(i = 0; inum_faces; i++) + if(RayObject_raycast( (RayObject*)rm->faces+i, isec )) + { + hit = 1; + if(isec->mode == RE_RAY_SHADOW) + break; + } + + return hit; +} + +static void RayObject_mesh_add(RayObject *o, RayObject *ob) +{ +} + +static void RayObject_mesh_done(RayObject *o) +{ +} + +static void RayObject_mesh_free(RayObject *o) +{ + RayMesh *rm= (RayMesh*)o; + MEM_freeN( rm->faces ); + MEM_freeN( rm ); +} + +static void RayObject_mesh_bb(RayObject *o, float *min, float *max) +{ + RayMesh *rm= (RayMesh*)o; + int i; + for(i = 0; imesh->totvert; i++) + DO_MINMAX( rm->mesh->mvert[i].co, min, max); +} + +RayObject* RayObject_mesh_create(Mesh *mesh, void *ob) +{ + RayMesh *rm= MEM_callocN(sizeof(RayMesh), "Octree"); + int i; + RayFace *face; + MFace *mface; + + rm->rayobj.api = &mesh_api; + rm->mesh = mesh; + rm->faces = MEM_callocN(sizeof(RayFace)*mesh->totface, "octree rayobject nodes"); + rm->num_faces = mesh->totface; + + face = rm->faces; + mface = mesh->mface; + for(i=0; itotface; i++, face++, mface++) + { + face->v1 = mesh->mvert[mface->v1].co; + face->v2 = mesh->mvert[mface->v2].co; + face->v3 = mesh->mvert[mface->v3].co; + face->v4 = mface->v4 ? mesh->mvert[mface->v4].co : NULL; + + face->ob = ob; + face->face = (void*)i; + } + + return RayObject_unalign((RayObject*) rm); +} diff --git a/source/blender/render/intern/source/raytrace.c b/source/blender/render/intern/source/rayobject_octree.c similarity index 61% rename from source/blender/render/intern/source/raytrace.c rename to source/blender/render/intern/source/rayobject_octree.c index 09d3711885a..a738898871b 100644 --- a/source/blender/render/intern/source/raytrace.c +++ b/source/blender/render/intern/source/rayobject_octree.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "MEM_guardedalloc.h" @@ -41,10 +42,9 @@ #include "BLI_arithb.h" -#include "RE_raytrace.h" +#include "rayobject.h" /* ********** structs *************** */ - #define BRANCH_ARRAY 1024 #define NODE_ARRAY 4096 @@ -60,13 +60,14 @@ typedef struct OcVal typedef struct Node { - struct RayFace *v[8]; - int ob[8]; + struct RayObject *v[8]; struct OcVal ov[8]; struct Node *next; } Node; typedef struct Octree { + RayObject rayobj; + struct Branch **adrbranch; struct Node **adrnode; float ocsize; /* ocsize: mult factor, max size octree */ @@ -74,19 +75,29 @@ typedef struct Octree { float min[3], max[3]; int ocres; int branchcount, nodecount; - char *ocface; /* during building only */ - RayCoordsFunc coordsfunc; - RayCheckFunc checkfunc; - RayObjectTransformFunc transformfunc; - void *userdata; + + /* during building only */ + char *ocface; + + RayObject **ro_nodes; + int ro_nodes_size, ro_nodes_used; + } Octree; -/* ******** globals ***************** */ - -/* just for statistics */ -static int raycount; -static int accepted, rejected, coherent_ray; +static int RayObject_octree_intersect(RayObject *o, Isect *isec); +static void RayObject_octree_add(RayObject *o, RayObject *ob); +static void RayObject_octree_done(RayObject *o); +static void RayObject_octree_free(RayObject *o); +static void RayObject_octree_bb(RayObject *o, float *min, float *max); +static RayObjectAPI octree_api = +{ + RayObject_octree_intersect, + RayObject_octree_add, + RayObject_octree_done, + RayObject_octree_free, + RayObject_octree_bb +}; /* **************** ocval method ******************* */ /* within one octree node, a set of 3x15 bits defines a 'boundbox' to OR with */ @@ -233,7 +244,7 @@ static int face_in_node(RayFace *face, short x, short y, short z, float rtf[][3] return 0; } -static void ocwrite(Octree *oc, int ob, RayFace *face, int quad, short x, short y, short z, float rtf[][3]) +static void ocwrite(Octree *oc, RayFace *face, int quad, short x, short y, short z, float rtf[][3]) { Branch *br; Node *no; @@ -283,8 +294,7 @@ static void ocwrite(Octree *oc, int ob, RayFace *face, int quad, short x, short while(no->v[a]!=NULL) a++; } - no->v[a]= face; - no->ob[a]= ob; + no->v[a]= (RayObject*)face; if(quad) calc_ocval_face(rtf[0], rtf[1], rtf[2], rtf[3], x>>2, y>>1, z, &no->ov[a]); @@ -374,13 +384,10 @@ static void d2dda(Octree *oc, short b1, short b2, short c1, short c2, char *ocfa ocface[oc->ocres*ocx2+ocy2]=1; } -static void filltriangle(Octree *oc, short c1, short c2, char *ocface, short *ocmin) +static void filltriangle(Octree *oc, short c1, short c2, char *ocface, short *ocmin, short *ocmax) { - short *ocmax; int a, x, y, y1, y2; - ocmax=ocmin+3; - for(x=ocmin[c1];x<=ocmax[c1];x++) { a= oc->ocres*x; for(y=ocmin[c2];y<=ocmax[c2];y++) { @@ -399,7 +406,7 @@ static void filltriangle(Octree *oc, short c1, short c2, char *ocface, short *oc } } -void RE_ray_tree_free(RayTree *tree) +static void RayObject_octree_free(RayObject *tree) { Octree *oc= (Octree*)tree; @@ -439,65 +446,38 @@ void RE_ray_tree_free(RayTree *tree) MEM_freeN(oc); } -RayTree *RE_ray_tree_create(int ocres, int totface, float *min, float *max, RayCoordsFunc coordsfunc, RayCheckFunc checkfunc, RayObjectTransformFunc transformfunc, void *userdata) + +RayObject *RayObject_octree_create(int ocres, int size) { - Octree *oc; - float t00, t01, t02; - int c, ocres2; + Octree *oc= MEM_callocN(sizeof(Octree), "Octree"); - oc= MEM_callocN(sizeof(Octree), "Octree"); - oc->adrbranch= MEM_callocN(sizeof(void *)*BRANCH_ARRAY, "octree branches"); - oc->adrnode= MEM_callocN(sizeof(void *)*NODE_ARRAY, "octree nodes"); - - oc->coordsfunc= coordsfunc; - oc->checkfunc= checkfunc; - oc->transformfunc= transformfunc; - oc->userdata= userdata; - - /* only for debug info */ - raycount=0; - accepted= 0; - rejected= 0; - coherent_ray= 0; + oc->rayobj.api = &octree_api; - /* fill main octree struct */ - oc->ocres= ocres; - ocres2= oc->ocres*oc->ocres; + oc->ocres = ocres; - VECCOPY(oc->min, min); - VECCOPY(oc->max, max); + oc->ro_nodes = MEM_callocN(sizeof(RayObject*)*size, "octree rayobject nodes"); + oc->ro_nodes_size = size; + oc->ro_nodes_used = 0; - oc->adrbranch[0]=(Branch *)MEM_callocN(4096*sizeof(Branch), "makeoctree"); - /* the lookup table, per face, for which nodes to fill in */ - oc->ocface= MEM_callocN( 3*ocres2 + 8, "ocface"); - memset(oc->ocface, 0, 3*ocres2); - - for(c=0;c<3;c++) { /* octree enlarge, still needed? */ - oc->min[c]-= 0.01f; - oc->max[c]+= 0.01f; - } - - t00= oc->max[0]-oc->min[0]; - t01= oc->max[1]-oc->min[1]; - t02= oc->max[2]-oc->min[2]; - - /* this minus 0.1 is old safety... seems to be needed? */ - oc->ocfacx= (oc->ocres-0.1)/t00; - oc->ocfacy= (oc->ocres-0.1)/t01; - oc->ocfacz= (oc->ocres-0.1)/t02; - - oc->ocsize= sqrt(t00*t00+t01*t01+t02*t02); /* global, max size octree */ - - return (RayTree*)oc; + return RayObject_unalign((RayObject*) oc); } -void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) + +static void RayObject_octree_add(RayObject *tree, RayObject *node) { Octree *oc = (Octree*)tree; - float *v1, *v2, *v3, *v4, ocfac[3], rtf[4][3]; + + assert( oc->ro_nodes_used < oc->ro_nodes_size ); + oc->ro_nodes[ oc->ro_nodes_used++ ] = node; +} + +static void octree_fill_rayface(Octree *oc, RayFace *face) +{ + float ocfac[3], rtf[4][3]; float co1[3], co2[3], co3[3], co4[3]; - short rts[4][3], ocmin[6], *ocmax; + short rts[4][3]; + short ocmin[3], ocmax[3]; char *ocface= oc->ocface; // front, top, size view of face, to fill in int a, b, c, oc1, oc2, oc3, oc4, x, y, z, ocres2; @@ -507,28 +487,12 @@ void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) ocres2= oc->ocres*oc->ocres; - ocmax= ocmin+3; + VECCOPY(co1, face->v1); + VECCOPY(co2, face->v2); + VECCOPY(co3, face->v3); + if(face->v4) + VECCOPY(co4, face->v4); - oc->coordsfunc(face, &v1, &v2, &v3, &v4); - - VECCOPY(co1, v1); - VECCOPY(co2, v2); - VECCOPY(co3, v3); - if(v4) - VECCOPY(co4, v4); - - if(ob >= RE_RAY_TRANSFORM_OFFS) { - float (*mat)[4]= (float(*)[4])oc->transformfunc(oc->userdata, ob); - - if(mat) { - Mat4MulVecfl(mat, co1); - Mat4MulVecfl(mat, co2); - Mat4MulVecfl(mat, co3); - if(v4) - Mat4MulVecfl(mat, co4); - } - } - for(c=0;c<3;c++) { rtf[0][c]= (co1[c]-oc->min[c])*ocfac[c] ; rts[0][c]= (short)rtf[0][c]; @@ -536,7 +500,7 @@ void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) rts[1][c]= (short)rtf[1][c]; rtf[2][c]= (co3[c]-oc->min[c])*ocfac[c] ; rts[2][c]= (short)rtf[2][c]; - if(v4) { + if(face->v4) { rtf[3][c]= (co4[c]-oc->min[c])*ocfac[c] ; rts[3][c]= (short)rtf[3][c]; } @@ -546,7 +510,7 @@ void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) oc1= rts[0][c]; oc2= rts[1][c]; oc3= rts[2][c]; - if(v4==NULL) { + if(face->v4==NULL) { ocmin[c]= MIN3(oc1,oc2,oc3); ocmax[c]= MAX3(oc1,oc2,oc3); } @@ -560,7 +524,7 @@ void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) } if(ocmin[0]==ocmax[0] && ocmin[1]==ocmax[1] && ocmin[2]==ocmax[2]) { - ocwrite(oc, ob, face, (v4 != NULL), ocmin[0], ocmin[1], ocmin[2], rtf); + ocwrite(oc, face, (face->v4 != NULL), ocmin[0], ocmin[1], ocmin[2], rtf); } else { @@ -570,7 +534,7 @@ void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) d2dda(oc, 1,2,0,1,ocface+ocres2,rts,rtf); d2dda(oc, 1,2,0,2,ocface,rts,rtf); d2dda(oc, 1,2,1,2,ocface+2*ocres2,rts,rtf); - if(v4==NULL) { + if(face->v4==NULL) { d2dda(oc, 2,0,0,1,ocface+ocres2,rts,rtf); d2dda(oc, 2,0,0,2,ocface,rts,rtf); d2dda(oc, 2,0,1,2,ocface+2*ocres2,rts,rtf); @@ -584,9 +548,9 @@ void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) d2dda(oc, 3,0,1,2,ocface+2*ocres2,rts,rtf); } /* nothing todo with triangle..., just fills :) */ - filltriangle(oc, 0,1,ocface+ocres2,ocmin); - filltriangle(oc, 0,2,ocface,ocmin); - filltriangle(oc, 1,2,ocface+2*ocres2,ocmin); + filltriangle(oc, 0,1,ocface+ocres2,ocmin,ocmax); + filltriangle(oc, 0,2,ocface,ocmin,ocmax); + filltriangle(oc, 1,2,ocface+2*ocres2,ocmin,ocmax); /* init static vars here */ face_in_node(face, 0,0,0, rtf); @@ -599,7 +563,7 @@ void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) for(z=ocmin[2];z<=ocmax[2];z++) { if(ocface[b+z] && ocface[a+z]) { if(face_in_node(NULL, x, y, z, rtf)) - ocwrite(oc, ob, face, (v4 != NULL), x,y,z, rtf); + ocwrite(oc, face, (face->v4 != NULL), x,y,z, rtf); } } } @@ -625,433 +589,116 @@ void RE_ray_tree_add_face(RayTree *tree, int ob, RayFace *face) } } -void RE_ray_tree_done(RayTree *tree) +static void RayObject_octree_done(RayObject *tree) { - Octree *oc= (Octree*)tree; + Octree *oc = (Octree*)tree; + int c; + float t00, t01, t02; + int ocres2 = oc->ocres*oc->ocres; + + INIT_MINMAX(oc->min, oc->max); + + /* Calculate Bounding Box */ + for(c=0; cro_nodes_used; c++) + RayObject_merge_bb(oc->ro_nodes[c], oc->min, oc->max); + + /* Alloc memory */ + oc->adrbranch= MEM_callocN(sizeof(void *)*BRANCH_ARRAY, "octree branches"); + oc->adrnode= MEM_callocN(sizeof(void *)*NODE_ARRAY, "octree nodes"); + + oc->adrbranch[0]=(Branch *)MEM_callocN(4096*sizeof(Branch), "makeoctree"); + + /* the lookup table, per face, for which nodes to fill in */ + oc->ocface= MEM_callocN( 3*ocres2 + 8, "ocface"); + memset(oc->ocface, 0, 3*ocres2); + + for(c=0;c<3;c++) { /* octree enlarge, still needed? */ + oc->min[c]-= 0.01f; + oc->max[c]+= 0.01f; + } + + t00= oc->max[0]-oc->min[0]; + t01= oc->max[1]-oc->min[1]; + t02= oc->max[2]-oc->min[2]; + + /* this minus 0.1 is old safety... seems to be needed? */ + oc->ocfacx= (oc->ocres-0.1)/t00; + oc->ocfacy= (oc->ocres-0.1)/t01; + oc->ocfacz= (oc->ocres-0.1)/t02; + + oc->ocsize= sqrt(t00*t00+t01*t01+t02*t02); /* global, max size octree */ + + for(c=0; cro_nodes_used; c++) + { + assert( RayObject_isFace(oc->ro_nodes[c]) ); + octree_fill_rayface(oc, (RayFace*)oc->ro_nodes[c]); + } MEM_freeN(oc->ocface); - oc->ocface= NULL; + MEM_freeN(oc->ro_nodes); + + printf("%f %f - %f\n", oc->min[0], oc->max[0], oc->ocfacx ); + printf("%f %f - %f\n", oc->min[1], oc->max[1], oc->ocfacy ); + printf("%f %f - %f\n", oc->min[2], oc->max[2], oc->ocfacz ); } -/* ************ raytracer **************** */ - -#define ISECT_EPSILON ((float)FLT_EPSILON) - -/* only for self-intersecting test with current render face (where ray left) */ -static int intersection2(RayFace *face, int ob, RayObjectTransformFunc transformfunc, RayCoordsFunc coordsfunc, void *userdata, float r0, float r1, float r2, float rx1, float ry1, float rz1) +static void RayObject_octree_bb(RayObject *tree, float *min, float *max) { - float *v1, *v2, *v3, *v4, co1[3], co2[3], co3[3], co4[3]; - float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22; - float m0, m1, m2, divdet, det, det1; - float u1, v, u2; - - coordsfunc(face, &v1, &v2, &v3, &v4); - - /* happens for baking with non existing face */ - if(v1==NULL) - return 1; - - if(v4) { - SWAP(float*, v3, v4); - } - - VECCOPY(co1, v1); - VECCOPY(co2, v2); - VECCOPY(co3, v3); - if(v4) - VECCOPY(co4, v4); - - if(ob >= RE_RAY_TRANSFORM_OFFS) { - float (*mat)[4]= (float(*)[4])transformfunc(userdata, ob); - - if(mat) { - Mat4MulVecfl(mat, co1); - Mat4MulVecfl(mat, co2); - Mat4MulVecfl(mat, co3); - if(v4) - Mat4MulVecfl(mat, co4); - } - } - - t00= co3[0]-co1[0]; - t01= co3[1]-co1[1]; - t02= co3[2]-co1[2]; - t10= co3[0]-co2[0]; - t11= co3[1]-co2[1]; - t12= co3[2]-co2[2]; - - x0= t11*r2-t12*r1; - x1= t12*r0-t10*r2; - x2= t10*r1-t11*r0; - - divdet= t00*x0+t01*x1+t02*x2; - - m0= rx1-co3[0]; - m1= ry1-co3[1]; - m2= rz1-co3[2]; - det1= m0*x0+m1*x1+m2*x2; - - if(divdet!=0.0f) { - u1= det1/divdet; - - if(u1 -(1.0f+ISECT_EPSILON)) { - return 1; - } - } - } - - if(v4) { - - t20= co3[0]-co4[0]; - t21= co3[1]-co4[1]; - t22= co3[2]-co4[2]; - - divdet= t20*x0+t21*x1+t22*x2; - if(divdet!=0.0f) { - u2= det1/divdet; - - if(u2= -(1.0f+ISECT_EPSILON)) { - return 2; - } - } - } - } - return 0; -} - -#if 0 -/* ray - line intersection */ -/* disabled until i got real & fast cylinder checking, this code doesnt work proper -for faster strands */ - -static int intersection_strand(Isect *is) -{ - float v1[3], v2[3]; /* length of strand */ - float axis[3], rc[3], nor[3], radline, dist, len; - - /* radius strand */ - radline= 0.5f*VecLenf(is->vlr->v1->co, is->vlr->v2->co); - - VecMidf(v1, is->vlr->v1->co, is->vlr->v2->co); - VecMidf(v2, is->vlr->v3->co, is->vlr->v4->co); - - VECSUB(rc, v1, is->start); /* vector from base ray to base cylinder */ - VECSUB(axis, v2, v1); /* cylinder axis */ - - CROSS(nor, is->vec, axis); - len= VecLength(nor); - - if(len-radline) { - float dot1, dot2, dot3, rlen, alen, div; - float labda; - - /* calculating the intersection point of shortest distance */ - dot1 = INPR(rc, is->vec); - dot2 = INPR(is->vec, axis); - dot3 = INPR(rc, axis); - rlen = INPR(is->vec, is->vec); - alen = INPR(axis, axis); - - div = alen * rlen - dot2 * dot2; - if (ABS(div) < FLT_EPSILON) - return 0; - - labda = (dot1*dot2 - dot3*rlen)/div; - - radline/= sqrt(alen); - - /* labda: where on axis do we have closest intersection? */ - if(labda >= -radline && labda <= 1.0f+radline) { - VlakRen *vlr= is->faceorig; - VertRen *v1= is->vlr->v1, *v2= is->vlr->v2, *v3= is->vlr->v3, *v4= is->vlr->v4; - /* but we dont do shadows from faces sharing edge */ - - if(v1==vlr->v1 || v2==vlr->v1 || v3==vlr->v1 || v4==vlr->v1) return 0; - if(v1==vlr->v2 || v2==vlr->v2 || v3==vlr->v2 || v4==vlr->v2) return 0; - if(v1==vlr->v3 || v2==vlr->v3 || v3==vlr->v3 || v4==vlr->v3) return 0; - if(vlr->v4) { - if(v1==vlr->v4 || v2==vlr->v4 || v3==vlr->v4 || v4==vlr->v4) return 0; - } - return 1; - } - } - return 0; -} -#endif - -/* ray - triangle or quad intersection */ -int RE_ray_face_intersection(Isect *is, RayObjectTransformFunc transformfunc, RayCoordsFunc coordsfunc) -{ - RayFace *face= is->face; - int ob= is->ob; - float *v1,*v2,*v3,*v4,co1[3],co2[3],co3[3],co4[3]; - float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22,r0,r1,r2; - float m0, m1, m2, divdet, det1; - short ok=0; - - /* disabled until i got real & fast cylinder checking, this code doesnt work proper - for faster strands */ -// if(is->mode==RE_RAY_SHADOW && is->vlr->flag & R_STRAND) -// return intersection_strand(is); - - coordsfunc(face, &v1, &v2, &v3, &v4); - - if(v4) { - SWAP(float*, v3, v4); - } - - VECCOPY(co1, v1); - VECCOPY(co2, v2); - VECCOPY(co3, v3); - if(v4) - VECCOPY(co4, v4); - - if(ob) { - float (*mat)[4]= (float(*)[4])transformfunc(is->userdata, ob); - - if(mat) { - Mat4MulVecfl(mat, co1); - Mat4MulVecfl(mat, co2); - Mat4MulVecfl(mat, co3); - if(v4) - Mat4MulVecfl(mat, co4); - } - } - - t00= co3[0]-co1[0]; - t01= co3[1]-co1[1]; - t02= co3[2]-co1[2]; - t10= co3[0]-co2[0]; - t11= co3[1]-co2[1]; - t12= co3[2]-co2[2]; - - r0= is->vec[0]; - r1= is->vec[1]; - r2= is->vec[2]; - - x0= t12*r1-t11*r2; - x1= t10*r2-t12*r0; - x2= t11*r0-t10*r1; - - divdet= t00*x0+t01*x1+t02*x2; - - m0= is->start[0]-co3[0]; - m1= is->start[1]-co3[1]; - m2= is->start[2]-co3[2]; - det1= m0*x0+m1*x1+m2*x2; - - if(divdet!=0.0f) { - float u; - - divdet= 1.0f/divdet; - u= det1*divdet; - if(u-(1.0f+ISECT_EPSILON)) { - float v, cros0, cros1, cros2; - - cros0= m1*t02-m2*t01; - cros1= m2*t00-m0*t02; - cros2= m0*t01-m1*t00; - v= divdet*(cros0*r0 + cros1*r1 + cros2*r2); - - if(v -(1.0f+ISECT_EPSILON)) { - float labda; - labda= divdet*(cros0*t10 + cros1*t11 + cros2*t12); - - if(labda>-ISECT_EPSILON && labda<1.0f+ISECT_EPSILON) { - is->labda= labda; - is->u= u; is->v= v; - ok= 1; - } - } - } - } - - if(ok==0 && v4) { - - t20= co3[0]-co4[0]; - t21= co3[1]-co4[1]; - t22= co3[2]-co4[2]; - - divdet= t20*x0+t21*x1+t22*x2; - if(divdet!=0.0f) { - float u; - divdet= 1.0f/divdet; - u = det1*divdet; - - if(u-(1.0f+ISECT_EPSILON)) { - float v, cros0, cros1, cros2; - cros0= m1*t22-m2*t21; - cros1= m2*t20-m0*t22; - cros2= m0*t21-m1*t20; - v= divdet*(cros0*r0 + cros1*r1 + cros2*r2); - - if(v-(1.0f+ISECT_EPSILON)) { - float labda; - labda= divdet*(cros0*t10 + cros1*t11 + cros2*t12); - - if(labda>-ISECT_EPSILON && labda<1.0f+ISECT_EPSILON) { - ok= 2; - is->labda= labda; - is->u= u; is->v= v; - } - } - } - } - } - - if(ok) { - is->isect= ok; // wich half of the quad - - if(is->mode!=RE_RAY_SHADOW) { - /* for mirror & tra-shadow: large faces can be filled in too often, this prevents - a face being detected too soon... */ - if(is->labda > is->ddalabda) { - return 0; - } - } - - /* when a shadow ray leaves a face, it can be little outside the edges of it, causing - intersection to be detected in its neighbour face */ - - if(is->facecontr && is->faceisect); // optimizing, the tests below are not needed - else if(is->labda< .1) { - RayFace *face= is->faceorig; - float *origv1, *origv2, *origv3, *origv4; - short de= 0; - - coordsfunc(face, &origv1, &origv2, &origv3, &origv4); - - if(ob == is->oborig) { - if(v1==origv1 || v2==origv1 || v3==origv1 || v4==origv1) de++; - if(v1==origv2 || v2==origv2 || v3==origv2 || v4==origv2) de++; - if(v1==origv3 || v2==origv3 || v3==origv3 || v4==origv3) de++; - if(origv4) { - if(v1==origv4 || v2==origv4 || v3==origv4 || v4==origv4) de++; - } - } - if(de) { - /* so there's a shared edge or vertex, let's intersect ray with face - itself, if that's true we can safely return 1, otherwise we assume - the intersection is invalid, 0 */ - - if(is->facecontr==NULL) { - is->obcontr= is->oborig; - is->facecontr= face; - is->faceisect= intersection2(face, is->oborig, transformfunc, coordsfunc, is->userdata, -r0, -r1, -r2, is->start[0], is->start[1], is->start[2]); - } - - if(is->faceisect) return 1; - return 0; - } - } - - return 1; - } - - return 0; + Octree *oc = (Octree*)tree; + DO_MINMAX(oc->min, min, max); + DO_MINMAX(oc->max, min, max); } /* check all faces in this node */ -static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval, RayCheckFunc checkfunc) +static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval) { - RayFace *face; - int ob; short nr=0; - OcVal *ov; /* return on any first hit */ if(is->mode==RE_RAY_SHADOW) { - - face= no->v[0]; - ob= no->ob[0]; - while(face) { - - if(!(is->faceorig == face && is->oborig == ob)) { - - if(checkfunc(is, ob, face)) { - - ov= no->ov+nr; - if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { - //accepted++; - is->ob= ob; - is->face= face; - if(RE_ray_face_intersection(is, oc->transformfunc, oc->coordsfunc)) { - is->ob_last= ob; - is->face_last= face; - return 1; - } - } - //else rejected++; - } - } + for(; no; no = no->next) + for(nr=0; nr<8; nr++) + { + RayObject *face = no->v[nr]; + OcVal *ov = no->ov+nr; - nr++; - if(nr==8) { - no= no->next; - if(no==0) return 0; - nr=0; + if(!face) break; //TODO? return 0; + + if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) + { + if( RayObject_intersect(face,is) ) + return 1; } - face= no->v[nr]; - ob= no->ob[nr]; } } - else { /* else mirror or glass or shadowtra, return closest face */ + else + { /* else mirror or glass or shadowtra, return closest face */ Isect isect; int found= 0; - is->labda= 1.0f; /* needed? */ - isect= *is; /* copy for sorting */ + assert(0); - face= no->v[0]; - ob= no->ob[0]; - while(face) { - - if(!(is->faceorig == face && is->oborig == ob)) { - if(checkfunc(is, ob, face)) { - ov= no->ov+nr; - if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { - //accepted++; - - isect.ob= ob; - isect.face= face; - if(RE_ray_face_intersection(&isect, oc->transformfunc, oc->coordsfunc)) { - if(isect.labdalabda) { - *is= isect; - found= 1; - } - - } - } - //else rejected++; - } - } + is->labda= 1.0f; /* needed? */ + isect= *is; /* copy for sorting */ + + for(; no; no = no->next) + for(nr=0; nr<8; nr++) + { + RayObject *face = no->v[nr]; + OcVal *ov = no->ov+nr; - nr++; - if(nr==8) { - no= no->next; - if(no==NULL) break; - nr=0; + if(!face) return 0; + + if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) + { + + if( RayObject_raycast(face,is) ) + if(isect.labdalabda) { + *is= isect; + found= 1; + } } - face= no->v[nr]; - ob= no->ob[nr]; } return found; @@ -1175,21 +822,14 @@ static int do_coherence_test(int ocx1, int ocx2, int ocy1, int ocy2, int ocz1, i */ -int RE_ray_tree_intersect(RayTree *tree, Isect *is) -{ - Octree *oc= (Octree*)tree; - - return RE_ray_tree_intersect_check(tree, is, oc->checkfunc); -} - /* return 1: found valid intersection */ -/* starts with is->faceorig */ -int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc) +/* starts with is->orig.face */ +static int RayObject_octree_intersect(RayObject *tree, Isect *is) { Octree *oc= (Octree*)tree; Node *no; OcVal ocval; - float vec1[3], vec2[3]; + float vec1[3], vec2[3], end[3]; float u1,u2,ox1,ox2,oy1,oy2,oz1,oz2; float labdao,labdax,ldx,labday,ldy,labdaz,ldz, ddalabda; int dx,dy,dz; @@ -1200,45 +840,51 @@ int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc if(oc->branchcount==0) return 0; /* do this before intersect calls */ +#if 0 is->facecontr= NULL; /* to check shared edge */ is->obcontr= 0; is->faceisect= is->isect= 0; /* shared edge, quad half flag */ is->userdata= oc->userdata; +#endif +#if 0 /* only for shadow! */ if(is->mode==RE_RAY_SHADOW) { - /* check with last intersected shadow face */ - if(is->face_last!=NULL && !(is->face_last==is->faceorig && is->ob_last==is->oborig)) { - if(checkfunc(is, is->ob_last, is->face_last)) { - is->ob= is->ob_last; - is->face= is->face_last; + /* TODO check with last intersected shadow face */ + if(is->last.face!=NULL && !(is->last.face==is->orig.face && is->last.ob==is->orig.ob)) { + if(checkfunc(is, is->last.ob, is->last.face)) { + is->ob= is->last.ob; + is->face= is->last.face; VECSUB(is->vec, is->end, is->start); if(RE_ray_face_intersection(is, oc->transformfunc, oc->coordsfunc)) return 1; } } } +#endif - ldx= is->end[0] - is->start[0]; + VECADDFAC( end, is->start, is->vec, is->labda ); + ldx= end[0] - is->start[0]; u1= 0.0f; u2= 1.0f; - + /* clip with octree cube */ if(cliptest(-ldx, is->start[0]-oc->min[0], &u1,&u2)) { if(cliptest(ldx, oc->max[0]-is->start[0], &u1,&u2)) { - ldy= is->end[1] - is->start[1]; + ldy= end[1] - is->start[1]; if(cliptest(-ldy, is->start[1]-oc->min[1], &u1,&u2)) { if(cliptest(ldy, oc->max[1]-is->start[1], &u1,&u2)) { - ldz= is->end[2] - is->start[2]; + ldz = end[2] - is->start[2]; if(cliptest(-ldz, is->start[2]-oc->min[2], &u1,&u2)) { if(cliptest(ldz, oc->max[2]-is->start[2], &u1,&u2)) { c1=1; if(u2<1.0f) { - is->end[0]= is->start[0]+u2*ldx; - is->end[1]= is->start[1]+u2*ldy; - is->end[2]= is->start[2]+u2*ldz; + end[0]= is->start[0]+u2*ldx; + end[1]= is->start[1]+u2*ldy; + end[2]= is->start[2]+u2*ldz; } if(u1>0.0f) { + assert( 0 ); is->start[0]+=u1*ldx; is->start[1]+=u1*ldy; is->start[2]+=u1*ldz; @@ -1259,9 +905,9 @@ int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc ox1= (is->start[0]-oc->min[0])*oc->ocfacx; oy1= (is->start[1]-oc->min[1])*oc->ocfacy; oz1= (is->start[2]-oc->min[2])*oc->ocfacz; - ox2= (is->end[0]-oc->min[0])*oc->ocfacx; - oy2= (is->end[1]-oc->min[1])*oc->ocfacy; - oz2= (is->end[2]-oc->min[2])*oc->ocfacz; + ox2= (end[0]-oc->min[0])*oc->ocfacx; + oy2= (end[1]-oc->min[1])*oc->ocfacy; + oz2= (end[2]-oc->min[2])*oc->ocfacz; ocx1= (int)ox1; ocy1= (int)oy1; @@ -1269,9 +915,16 @@ int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc ocx2= (int)ox2; ocy2= (int)oy2; ocz2= (int)oz2; + +// for(ocx1=0; ocx1ocres; ocx1++) +// for(ocy1=0; ocy1ocres; ocy1++) +// for(ocz1=0; ocz1ocres; ocz1++) +// { +// no= ocread(oc, ocx1, ocy1, ocz1); +// if( testnode(oc, is, no, ocval) ) return 1; +// } - /* for intersection */ - VECSUB(is->vec, is->end, is->start); +// return 0; if(ocx1==ocx2 && ocy1==ocy2 && ocz1==ocz2) { no= ocread(oc, ocx1, ocy1, ocz1); @@ -1280,8 +933,8 @@ int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc vec1[0]= ox1; vec1[1]= oy1; vec1[2]= oz1; vec2[0]= ox2; vec2[1]= oy2; vec2[2]= oz2; calc_ocval_ray(&ocval, (float)ocx1, (float)ocy1, (float)ocz1, vec1, vec2); - is->ddalabda= 1.0f; - if( testnode(oc, is, no, ocval, checkfunc) ) return 1; +// is->ddalabda= 1.0f; + if( testnode(oc, is, no, ocval) ) return 1; } } else { @@ -1359,8 +1012,8 @@ int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc vec2[2]= oz1-ddalabda*doz; calc_ocval_ray(&ocval, (float)xo, (float)yo, (float)zo, vec1, vec2); - is->ddalabda= ddalabda; - if( testnode(oc, is, no, ocval, checkfunc) ) return 1; +// is->ddalabda= ddalabda; + if( testnode(oc, is, no, ocval) ) return 1; } labdao= ddalabda; @@ -1430,13 +1083,10 @@ int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc } /* reached end, no intersections found */ - is->ob_last= 0; - is->face_last= NULL; + is->hit.ob = 0; + is->hit.face = NULL; return 0; } -float RE_ray_tree_max_size(RayTree *tree) -{ - return ((Octree*)tree)->ocsize; -} + diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index e89cf20e4b1..83165bb6b52 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "MEM_guardedalloc.h" @@ -56,6 +57,7 @@ #include "texture.h" #include "RE_raytrace.h" +#include "rayobject.h" #define RAY_TRA 1 #define RAY_TRAFLIP 2 @@ -68,6 +70,7 @@ extern struct Render R; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +#if 0 static void vlr_face_coords(RayFace *face, float **v1, float **v2, float **v3, float **v4) { VlakRen *vlr= (VlakRen*)face; @@ -101,27 +104,28 @@ static float *vlr_get_transform(void *userdata, int i) return (obi->flag & R_TRANSFORMED)? (float*)obi->mat: NULL; } +#endif void freeraytree(Render *re) { if(re->raytree) { - RE_ray_tree_free(re->raytree); + RayObject_free(re->raytree); re->raytree= NULL; + MEM_freeN( re->rayfaces ); } } - void makeraytree(Render *re) { ObjectInstanceRen *obi; ObjectRen *obr; VlakRen *vlr= NULL; - float min[3], max[3], co1[3], co2[3], co3[3], co4[3]; double lasttime= PIL_check_seconds_timer(); int v, totv = 0, totface = 0; + RayFace *faces, *cur_face; - INIT_MINMAX(min, max); - - /* first min max raytree space */ + //TODO (for now octree only supports RayFaces so we need to create them) + // + //count faces for(obi=re->instancetable.first; obi; obi=obi->next) { obr= obi->obr; @@ -134,51 +138,31 @@ void makeraytree(Render *re) /* baking selected to active needs non-traceable too */ if((re->flag & R_BAKE_TRACE) || (vlr->mat->mode & MA_TRACEBLE)) { if((vlr->mat->mode & MA_WIRE)==0) { - VECCOPY(co1, vlr->v1->co); - VECCOPY(co2, vlr->v2->co); - VECCOPY(co3, vlr->v3->co); - - if(obi->flag & R_TRANSFORMED) { - Mat4MulVecfl(obi->mat, co1); - Mat4MulVecfl(obi->mat, co2); - Mat4MulVecfl(obi->mat, co3); - } - - DO_MINMAX(co1, min, max); - DO_MINMAX(co2, min, max); - DO_MINMAX(co3, min, max); - - if(vlr->v4) { - VECCOPY(co4, vlr->v4->co); - if(obi->flag & R_TRANSFORMED) - Mat4MulVecfl(obi->mat, co4); - DO_MINMAX(co4, min, max); - } - totface++; } } } } - - re->raytree= RE_ray_tree_create(re->r.ocres, totface, min, max, - vlr_face_coords, vlr_check_intersect, vlr_get_transform, re); - - if(min[0] > max[0]) { /* empty raytree */ - RE_ray_tree_done(re->raytree); - return; - } - + + re->raytree = RayObject_octree_create( re->r.ocres, totface ); + + //Fill rayfaces + re->rayfaces = (RayObject*)MEM_callocN(totface*sizeof(RayFace), "render faces"); + cur_face = faces = (RayFace*)re->rayfaces; + for(obi=re->instancetable.first; obi; obi=obi->next) { obr= obi->obr; if(re->excludeob && obr->ob == re->excludeob) continue; - for(v=0; vtotvlak; v++, totv++) { - if((v & 255)==0) { + for(v=0;vtotvlak;v++) { + if((v & 255)==0) + { double time= PIL_check_seconds_timer(); + vlr= obr->vlaknodes[v>>8].vlak; + vlr= obr->vlaknodes[v>>8].vlak; if(re->test_break(re->tbh)) break; @@ -192,23 +176,35 @@ void makeraytree(Render *re) } } else vlr++; - - if((re->flag & R_BAKE_TRACE) || (vlr->mat->mode & MA_TRACEBLE)) - if((vlr->mat->mode & MA_WIRE)==0) - RE_ray_tree_add_face(re->raytree, RAY_OBJECT_SET(re, obi), vlr); + /* baking selected to active needs non-traceable too */ + if((re->flag & R_BAKE_TRACE) || (vlr->mat->mode & MA_TRACEBLE)) { + if((vlr->mat->mode & MA_WIRE)==0) { + cur_face->v1 = vlr->v1->co; + cur_face->v2 = vlr->v2->co; + cur_face->v3 = vlr->v3->co; + cur_face->v4 = vlr->v4 ? vlr->v4->co : NULL; + + cur_face->ob = (void*)obi; + cur_face->face = vlr; + + RayObject_add( re->raytree, (RayObject*) cur_face ); + cur_face++; + } + } } } - RE_ray_tree_done(re->raytree); - + RayObject_done( re->raytree ); +//TODO vlr_face_coords, vlr_check_intersect, vlr_get_transform, re); + re->i.infostr= NULL; re->stats_draw(re->sdh, &re->i); } static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr) { - VlakRen *vlr= (VlakRen*)is->face; - ObjectInstanceRen *obi= RAY_OBJECT_GET(&R, is->ob); + ObjectInstanceRen *obi= (ObjectInstanceRen*)is->hit.ob; + VlakRen *vlr= (VlakRen*)is->hit.face; int osatex= 0; /* set up view vector */ @@ -420,29 +416,25 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo ShadeResult shr; Isect isec; float f, f1, fr, fg, fb; - float ref[3], maxsize=RE_ray_tree_max_size(R.raytree); + float ref[3]; float dist_mir = origshi->mat->dist_mir; + assert(0); + /* Warning, This is not that nice, and possibly a bit slow for every ray, however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */ memset(&shi, 0, sizeof(ShadeInput)); /* end warning! - Campbell */ VECCOPY(isec.start, start); - if (dist_mir > 0.0) { - isec.end[0]= start[0]+dist_mir*vec[0]; - isec.end[1]= start[1]+dist_mir*vec[1]; - isec.end[2]= start[2]+dist_mir*vec[2]; - } else { - isec.end[0]= start[0]+maxsize*vec[0]; - isec.end[1]= start[1]+maxsize*vec[1]; - isec.end[2]= start[2]+maxsize*vec[2]; - } + VECCOPY(isec.vec, vec ); + isec.labda = dist_mir > 0 ? dist_mir : RE_RAYTRACE_MAXDIST; isec.mode= RE_RAY_MIRROR; - isec.faceorig= (RayFace*)vlr; - isec.oborig= RAY_OBJECT_SET(&R, obi); - if(RE_ray_tree_intersect(R.raytree, &isec)) { + isec.orig.ob = obi; + isec.orig.face = vlr; + + if(RayObject_raycast(R.raytree, &isec)) { float d= 1.0f; shi.mask= origshi->mask; @@ -1279,8 +1271,10 @@ static void ray_trace_shadow_tra(Isect *is, int depth, int traflag) if it has col[3]>0.0f continue. so exit when alpha is full */ ShadeInput shi; ShadeResult shr; + + assert(0); - if(RE_ray_tree_intersect(R.raytree, is)) { + if(RayObject_raycast(R.raytree, is)) { float d= 1.0f; /* we got a face */ @@ -1312,8 +1306,9 @@ static void ray_trace_shadow_tra(Isect *is, int depth, int traflag) /* adapt isect struct */ VECCOPY(is->start, shi.co); - is->oborig= RAY_OBJECT_SET(&R, shi.obi); - is->faceorig= (RayFace*)shi.vlr; + + is->orig.ob = shi.obi; + is->orig.face = shi.vlr; ray_trace_shadow_tra(is, depth-1, traflag | RAY_TRA); } @@ -1329,9 +1324,11 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr) Isect isec; ShadeInput shi; ShadeResult shr_t; - float vec[3], accum[3], div= 0.0f, maxsize= RE_ray_tree_max_size(R.raytree); + float vec[3], accum[3], div= 0.0f; int a; + assert(0); + if(only_one) { return 0; } @@ -1339,8 +1336,8 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr) accum[0]= accum[1]= accum[2]= 0.0f; isec.mode= RE_RAY_MIRROR; - isec.faceorig= (RayFace*)ship->vlr; - isec.oborig= RAY_OBJECT_SET(&R, ship->obi); + isec.orig.ob = ship->obi; + isec.orig.face = ship->vlr; for(a=0; a<8*8; a++) { @@ -1352,12 +1349,12 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr) vec[1]-= vec[1]; vec[2]-= vec[2]; } + VECCOPY(isec.start, ship->co); - isec.end[0]= isec.start[0] + maxsize*vec[0]; - isec.end[1]= isec.start[1] + maxsize*vec[1]; - isec.end[2]= isec.start[2] + maxsize*vec[2]; - - if(RE_ray_tree_intersect(R.raytree, &isec)) { + VECCOPY(isec.vec, vec ); + isec.labda = RE_RAYTRACE_MAXDIST; + + if(RayObject_raycast(R.raytree, &isec)) { float fac; /* Warning, This is not that nice, and possibly a bit slow for every ray, @@ -1545,10 +1542,16 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) float dxyview[3], skyadded=0, div; int aocolor; - isec.faceorig= (RayFace*)shi->vlr; - isec.oborig= RAY_OBJECT_SET(&R, shi->obi); - isec.face_last= NULL; - isec.ob_last= 0; + assert(0); + + isec.orig.ob = shi->obi; + isec.orig.face = shi->vlr; + + isec.hit.ob = 0; + isec.hit.face = 0; + + isec.last_hit = NULL; + isec.mode= (R.wrld.aomode & WO_AODIST)?RE_RAY_SHADOW_TRA:RE_RAY_SHADOW; isec.lay= -1; @@ -1601,13 +1604,14 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) Normalize(dir); VECCOPY(isec.start, shi->co); - isec.end[0] = shi->co[0] - maxdist*dir[0]; - isec.end[1] = shi->co[1] - maxdist*dir[1]; - isec.end[2] = shi->co[2] - maxdist*dir[2]; + isec.vec[0] = -dir[0]; + isec.vec[1] = -dir[1]; + isec.vec[2] = -dir[2]; + isec.labda = maxdist; prev = fac; - if(RE_ray_tree_intersect(R.raytree, &isec)) { + if(RayObject_raycast(R.raytree, &isec)) { if (R.wrld.aomode & WO_AODIST) fac+= exp(-isec.labda*R.wrld.aodistfac); else fac+= 1.0f; } @@ -1672,10 +1676,16 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) float dxyview[3]; int j= -1, tot, actual=0, skyadded=0, aocolor, resol= R.wrld.aosamp; - isec.faceorig= (RayFace*)shi->vlr; - isec.oborig= RAY_OBJECT_SET(&R, shi->obi); - isec.face_last= NULL; - isec.ob_last= 0; + assert(0); + + isec.orig.ob = shi->obi; + isec.orig.face = shi->vlr; + + isec.hit.ob = 0; + isec.hit.face = 0; + + isec.last_hit = NULL; + isec.mode= (R.wrld.aomode & WO_AODIST)?RE_RAY_SHADOW_TRA:RE_RAY_SHADOW; isec.lay= -1; @@ -1725,14 +1735,15 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) actual++; - /* always set start/end, RE_ray_tree_intersect clips it */ + /* always set start/vec/labda */ VECCOPY(isec.start, shi->co); - isec.end[0] = shi->co[0] - maxdist*vec[0]; - isec.end[1] = shi->co[1] - maxdist*vec[1]; - isec.end[2] = shi->co[2] - maxdist*vec[2]; + isec.vec[0] = -vec[0]; + isec.vec[1] = -vec[1]; + isec.vec[2] = -vec[2]; + isec.labda = maxdist; /* do the trace */ - if(RE_ray_tree_intersect(R.raytree, &isec)) { + if(RayObject_raycast(R.raytree, &isec)) { if (R.wrld.aomode & WO_AODIST) sh+= exp(-isec.labda*R.wrld.aodistfac); else sh+= 1.0f; } @@ -1838,7 +1849,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * int samples=0; float samp3d[3]; - float fac=0.0f, vec[3]; + float fac=0.0f, vec[3], end[3]; float colsq[4]; float adapt_thresh = lar->adapt_thresh; int min_adapt_samples=4, max_samples = lar->ray_totsamp; @@ -1848,6 +1859,8 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * float jitco[RE_MAX_OSA][3]; int totjitco; +// assert(0); + colsq[0] = colsq[1] = colsq[2] = 0.0; if(isec->mode==RE_RAY_SHADOW_TRA) { shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 0.0f; @@ -1879,8 +1892,9 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * while (samples < max_samples) { - isec->faceorig= (RayFace*)shi->vlr; - isec->oborig= RAY_OBJECT_SET(&R, shi->obi); + + isec->orig.ob = shi->obi; + isec->orig.face = shi->vlr; /* manually jitter the start shading co-ord per sample * based on the pre-generated OSA texture sampling offsets, @@ -1916,11 +1930,11 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * /* align samples to lamp vector */ Mat3MulVecfl(lar->mat, samp3d); } - isec->end[0]= vec[0]+samp3d[0]; - isec->end[1]= vec[1]+samp3d[1]; - isec->end[2]= vec[2]+samp3d[2]; + end[0] = vec[0]+samp3d[0]; + end[1] = vec[1]+samp3d[1]; + end[2] = vec[2]+samp3d[2]; } else { - VECCOPY(isec->end, vec); + VECCOPY(end, vec); } if(shi->strand) { @@ -1928,7 +1942,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * float jitbias= 0.5f*(VecLength(shi->dxco) + VecLength(shi->dyco)); float v[3]; - VECSUB(v, co, isec->end); + VECSUB(v, co, end); Normalize(v); co[0] -= jitbias*v[0]; @@ -1937,6 +1951,11 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * } VECCOPY(isec->start, co); +// VECSUB(isec->vec, end, isec->start); + isec->vec[0] = end[0]-isec->start[0]; + isec->vec[1] = end[1]-isec->start[1]; + isec->vec[2] = end[2]-isec->start[2]; + isec->labda = 1.0f; // * Normalize(isec->vec); /* trace the ray */ if(isec->mode==RE_RAY_SHADOW_TRA) { @@ -1955,7 +1974,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * colsq[2] += isec->col[2]*isec->col[2]; } else { - if( RE_ray_tree_intersect(R.raytree, isec) ) fac+= 1.0f; + if( RayObject_raycast(R.raytree, isec) ) fac+= 1.0f; } samples++; @@ -1996,6 +2015,8 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa float fac=0.0f, div=0.0f, vec[3]; int a, j= -1, mask; + assert(0); + if(isec->mode==RE_RAY_SHADOW_TRA) { shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 0.0f; } @@ -2022,19 +2043,18 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa } } - isec->faceorig= (RayFace*)shi->vlr; - isec->oborig= RAY_OBJECT_SET(&R, shi->obi); + isec->orig.ob = shi->obi; + isec->orig.face = shi->vlr; vec[0]= jitlamp[0]; vec[1]= jitlamp[1]; vec[2]= 0.0f; Mat3MulVecfl(lar->mat, vec); - /* set start and end, RE_ray_tree_intersect clips it */ + /* set start and vec */ VECCOPY(isec->start, shi->co); - isec->end[0]= lampco[0]+vec[0]; - isec->end[1]= lampco[1]+vec[1]; - isec->end[2]= lampco[2]+vec[2]; + VECCOPY(isec->vec, vec); + isec->labda = 1.0f; if(isec->mode==RE_RAY_SHADOW_TRA) { /* isec.col is like shadfac, so defines amount of light (0.0 is full shadow) */ @@ -2047,7 +2067,7 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa shadfac[2] += isec->col[2]; shadfac[3] += isec->col[3]; } - else if( RE_ray_tree_intersect(R.raytree, isec) ) fac+= 1.0f; + else if( RayObject_raycast(R.raytree, isec) ) fac+= 1.0f; div+= 1.0f; jitlamp+= 2; @@ -2071,7 +2091,7 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) { Isect isec; - float lampco[3], maxsize; + float lampco[3]; /* setup isec */ if(shi->mat->mode & MA_SHADOW_TRA) isec.mode= RE_RAY_SHADOW_TRA; @@ -2084,19 +2104,16 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) /* only when not mir tracing, first hit optimm */ if(shi->depth==0) { - isec.face_last= (RayFace*)lar->vlr_last[shi->thread]; - isec.ob_last= RAY_OBJECT_SET(&R, lar->obi_last[shi->thread]); + isec.last_hit = lar->last_hit[shi->thread]; } else { - isec.face_last= NULL; - isec.ob_last= 0; + isec.last_hit = NULL; } if(lar->type==LA_SUN || lar->type==LA_HEMI) { - maxsize= RE_ray_tree_max_size(R.raytree); - lampco[0]= shi->co[0] - maxsize*lar->vec[0]; - lampco[1]= shi->co[1] - maxsize*lar->vec[1]; - lampco[2]= shi->co[2] - maxsize*lar->vec[2]; + lampco[0]= shi->co[0] - RE_RAYTRACE_MAXDIST*lar->vec[0]; + lampco[1]= shi->co[1] - RE_RAYTRACE_MAXDIST*lar->vec[1]; + lampco[2]= shi->co[2] - RE_RAYTRACE_MAXDIST*lar->vec[2]; } else { VECCOPY(lampco, lar->co); @@ -2109,13 +2126,15 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) } else { if(lar->ray_totsamp<2) { - isec.faceorig= (RayFace*)shi->vlr; - isec.oborig= RAY_OBJECT_SET(&R, shi->obi); + isec.orig.ob = shi->obi; + isec.orig.face = shi->vlr; + shadfac[3]= 1.0f; // 1.0=full light /* set up isec vec */ VECCOPY(isec.start, shi->co); - VECCOPY(isec.end, lampco); + VECSUB(isec.vec, lampco, isec.start); + isec.labda = 1.0f; if(isec.mode==RE_RAY_SHADOW_TRA) { /* isec.col is like shadfac, so defines amount of light (0.0 is full shadow) */ @@ -2125,7 +2144,11 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) ray_trace_shadow_tra(&isec, DEPTH_SHADOW_TRA, 0); QUATCOPY(shadfac, isec.col); } - else if(RE_ray_tree_intersect(R.raytree, &isec)) shadfac[3]= 0.0f; + else + { + assert(0); + if(RayObject_raycast(R.raytree, &isec)) shadfac[3]= 0.0f; + } } else { ray_shadow_jitter(shi, lar, lampco, shadfac, &isec); @@ -2134,8 +2157,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) /* for first hit optim, set last interesected shadow face */ if(shi->depth==0) { - lar->vlr_last[shi->thread]= (VlakRen*)isec.face_last; - lar->obi_last[shi->thread]= RAY_OBJECT_GET(&R, isec.ob_last); + lar->last_hit[shi->thread] = isec.last_hit; } } @@ -2145,7 +2167,9 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) static void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float *co) { Isect isec; - float lampco[3], maxsize; + float lampco[3]; + + assert(0); /* setup isec */ isec.mode= RE_RAY_SHADOW_TRA; @@ -2153,23 +2177,22 @@ static void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float if(lar->mode & LA_LAYER) isec.lay= lar->lay; else isec.lay= -1; if(lar->type==LA_SUN || lar->type==LA_HEMI) { - maxsize= RE_ray_tree_max_size(R.raytree); - lampco[0]= shi->co[0] - maxsize*lar->vec[0]; - lampco[1]= shi->co[1] - maxsize*lar->vec[1]; - lampco[2]= shi->co[2] - maxsize*lar->vec[2]; + lampco[0]= shi->co[0] - RE_RAYTRACE_MAXDIST*lar->vec[0]; + lampco[1]= shi->co[1] - RE_RAYTRACE_MAXDIST*lar->vec[1]; + lampco[2]= shi->co[2] - RE_RAYTRACE_MAXDIST*lar->vec[2]; } else { VECCOPY(lampco, lar->co); } - isec.faceorig= (RayFace*)shi->vlr; - isec.oborig= RAY_OBJECT_SET(&R, shi->obi); + isec.orig.ob = shi->obi; + isec.orig.face = shi->vlr; /* set up isec vec */ VECCOPY(isec.start, shi->co); VECCOPY(isec.end, lampco); - if(RE_ray_tree_intersect(R.raytree, &isec)) { + if(RayObject_raycast(R.raytree, &isec)) { /* we got a face */ /* render co */ diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index deb6f0db743..fe1ab21a4a4 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -31,6 +31,7 @@ #include #include #include +#include /* External modules: */ #include "MEM_guardedalloc.h" @@ -2234,6 +2235,7 @@ static void bake_displacement(void *handle, ShadeInput *shi, float dist, int x, } } +#if 0 static int bake_check_intersect(Isect *is, int ob, RayFace *face) { BakeShade *bs = (BakeShade*)is->userdata; @@ -2243,9 +2245,13 @@ static int bake_check_intersect(Isect *is, int ob, RayFace *face) return (R.objectinstance[ob].obr->ob != bs->actob); } +#endif -static int bake_intersect_tree(RayTree* raytree, Isect* isect, float *start, float *dir, float sign, float *hitco, float *dist) +static int bake_intersect_tree(RayObject* raytree, Isect* isect, float *start, float *dir, float sign, float *hitco, float *dist) { + //TODO + assert( 0 ); +#if 0 float maxdist; int hit; @@ -2253,15 +2259,17 @@ static int bake_intersect_tree(RayTree* raytree, Isect* isect, float *start, flo if(R.r.bake_maxdist > 0.0f) maxdist= R.r.bake_maxdist; else - maxdist= RE_ray_tree_max_size(R.raytree) + R.r.bake_biasdist; + maxdist= FLT_MAX + R.r.bake_biasdist; + //TODO normalized direction? VECADDFAC(isect->start, start, dir, -R.r.bake_biasdist); + isect->dir[0] = dir[0]*sign; + isect->dir[1] = dir[1]*sign; + isect->dir[2] = dir[2]*sign; + isect->labda = maxdist; - isect->end[0] = isect->start[0] + dir[0]*maxdist*sign; - isect->end[1] = isect->start[1] + dir[1]*maxdist*sign; - isect->end[2] = isect->start[2] + dir[2]*maxdist*sign; - - hit = RE_ray_tree_intersect_check(R.raytree, isect, bake_check_intersect); + hit = RayObject_raycast(raytree, isect); + //TODO bake_check_intersect if(hit) { hitco[0] = isect->start[0] + isect->labda*isect->vec[0]; hitco[1] = isect->start[1] + isect->labda*isect->vec[1]; @@ -2271,6 +2279,8 @@ static int bake_intersect_tree(RayTree* raytree, Isect* isect, float *start, flo } return hit; +#endif + return 0; } static void bake_set_vlr_dxyco(BakeShade *bs, float *uv1, float *uv2, float *uv3) @@ -2387,8 +2397,9 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) for(sign=-1; sign<=1; sign+=2) { memset(&isec, 0, sizeof(isec)); isec.mode= RE_RAY_MIRROR; - isec.faceorig= (RayFace*)vlr; - isec.oborig= RAY_OBJECT_SET(&R, obi); + + isec.orig.ob = obi; + isec.orig.face = vlr; isec.userdata= bs; if(bake_intersect_tree(R.raytree, &isec, shi->co, shi->vn, sign, co, &dist)) { @@ -2412,8 +2423,8 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) /* if hit, we shade from the new point, otherwise from point one starting face */ if(hit) { - vlr= (VlakRen*)minisec.face; - obi= RAY_OBJECT_GET(&R, minisec.ob); + obi= (ObjectInstanceRen*)minisec.hit.ob; + vlr= (VlakRen*)minisec.hit.face; quad= (minisec.isect == 2); VECCOPY(shi->co, minco); From f5566daa89a43a4b248f36b5335772ebd35960b8 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 11 May 2009 13:56:45 +0000 Subject: [PATCH 003/138] Added neighbour test on detected ray hit --- .../render/extern/include/RE_raytrace.h | 5 +- .../blender/render/intern/source/rayobject.c | 171 ++++++++++++------ .../blender/render/intern/source/rayshade.c | 1 + 3 files changed, 123 insertions(+), 54 deletions(-) diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index b274fe681b3..b5ff3d9cae0 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -85,7 +85,10 @@ struct Isect #define RE_RAY_SHADOW_TRA 2 /* skip options */ -#define RE_SKIP_CULLFACE 1 +#define RE_SKIP_CULLFACE (1 << 0) + +/* if using this flag then *face should be a pointer to a VlakRen */ +#define RE_SKIP_VLR_NEIGHBOUR (1 << 1) /* TODO use: FLT_MAX? */ #define RE_RAYTRACE_MAXDIST 1e33 diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index ee364d3586c..c816bcb2333 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -31,14 +31,96 @@ #include "BKE_utildefines.h" #include "RE_raytrace.h" +#include "render_types.h" #include "rayobject.h" +/* only for self-intersecting test with current render face (where ray left) */ +static int intersection2(VlakRen *face, float r0, float r1, float r2, float rx1, float ry1, float rz1) +{ + float co1[3], co2[3], co3[3], co4[3]; + float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22; + float m0, m1, m2, divdet, det, det1; + float u1, v, u2; + + VECCOPY(co1, face->v1->co); + VECCOPY(co2, face->v2->co); + if(face->v4) + { + VECCOPY(co3, face->v4->co); + VECCOPY(co4, face->v3->co); + } + else + { + VECCOPY(co3, face->v3->co); + } + + t00= co3[0]-co1[0]; + t01= co3[1]-co1[1]; + t02= co3[2]-co1[2]; + t10= co3[0]-co2[0]; + t11= co3[1]-co2[1]; + t12= co3[2]-co2[2]; + + x0= t11*r2-t12*r1; + x1= t12*r0-t10*r2; + x2= t10*r1-t11*r0; + + divdet= t00*x0+t01*x1+t02*x2; + + m0= rx1-co3[0]; + m1= ry1-co3[1]; + m2= rz1-co3[2]; + det1= m0*x0+m1*x1+m2*x2; + + if(divdet!=0.0f) { + u1= det1/divdet; + + if(u1 -(1.0f+ISECT_EPSILON)) { + return 1; + } + } + } + + if(face->v4) { + + t20= co3[0]-co4[0]; + t21= co3[1]-co4[1]; + t22= co3[2]-co4[2]; + + divdet= t20*x0+t21*x1+t22*x2; + if(divdet!=0.0f) { + u2= det1/divdet; + + if(u2= -(1.0f+ISECT_EPSILON)) { + return 2; + } + } + } + } + return 0; +} + + /* ray - triangle or quad intersection */ +/* this function shall only modify Isect if it detects an hit */ static int intersect_rayface(RayFace *face, Isect *is) { float co1[3],co2[3],co3[3],co4[3]; float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22,r0,r1,r2; float m0, m1, m2, divdet, det1; + float labda, u, v; short ok=0; if(is->orig.ob == face->ob && is->orig.face == face->face) @@ -51,8 +133,6 @@ static int intersect_rayface(RayFace *face, Isect *is) VECCOPY(co1, face->v1); VECCOPY(co2, face->v2); - - //TODO if(v4) { SWAP(float*, v3, v4); } if(face->v4) { VECCOPY(co3, face->v4); @@ -86,12 +166,11 @@ static int intersect_rayface(RayFace *face, Isect *is) det1= m0*x0+m1*x1+m2*x2; if(divdet!=0.0f) { - float u; divdet= 1.0f/divdet; u= det1*divdet; if(u-(1.0f+ISECT_EPSILON)) { - float v, cros0, cros1, cros2; + float cros0, cros1, cros2; cros0= m1*t02-m2*t01; cros1= m2*t00-m0*t02; @@ -99,12 +178,9 @@ static int intersect_rayface(RayFace *face, Isect *is) v= divdet*(cros0*r0 + cros1*r1 + cros2*r2); if(v -(1.0f+ISECT_EPSILON)) { - float labda; labda= divdet*(cros0*t10 + cros1*t11 + cros2*t12); if(labda>-ISECT_EPSILON && labda<1.0f+ISECT_EPSILON) { - is->labda= labda; - is->u= u; is->v= v; ok= 1; } } @@ -119,25 +195,21 @@ static int intersect_rayface(RayFace *face, Isect *is) divdet= t20*x0+t21*x1+t22*x2; if(divdet!=0.0f) { - float u; divdet= 1.0f/divdet; u = det1*divdet; if(u-(1.0f+ISECT_EPSILON)) { - float v, cros0, cros1, cros2; + float cros0, cros1, cros2; cros0= m1*t22-m2*t21; cros1= m2*t20-m0*t22; cros2= m0*t21-m1*t20; v= divdet*(cros0*r0 + cros1*r1 + cros2*r2); if(v-(1.0f+ISECT_EPSILON)) { - float labda; labda= divdet*(cros0*t10 + cros1*t11 + cros2*t12); if(labda>-ISECT_EPSILON && labda<1.0f+ISECT_EPSILON) { ok= 2; - is->labda= labda; - is->u= u; is->v= v; } } } @@ -145,8 +217,37 @@ static int intersect_rayface(RayFace *face, Isect *is) } if(ok) { - is->isect= ok; // wich half of the quad - + + /* when a shadow ray leaves a face, it can be little outside the edges of it, causing + intersection to be detected in its neighbour face */ + if(is->skip & RE_SKIP_VLR_NEIGHBOUR) + { + if(labda < 0.1f && is->orig.ob == face->ob) + { + VlakRen * a = is->orig.face; + VlakRen * b = face->face; + + /* so there's a shared edge or vertex, let's intersect ray with face + itself, if that's true we can safely return 1, otherwise we assume + the intersection is invalid, 0 */ + if(a->v1==b->v1 || a->v2==b->v1 || a->v3==b->v1 || a->v4==b->v1 + || a->v1==b->v2 || a->v2==b->v2 || a->v3==b->v2 || a->v4==b->v2 + || a->v1==b->v3 || a->v2==b->v3 || a->v3==b->v3 || a->v4==b->v3 + || a->v1==b->v4 || a->v2==b->v4 || a->v3==b->v4 || (a->v4 && a->v4==b->v4)) + if(!intersection2((VlakRen*)b, -r0, -r1, -r2, is->start[0], is->start[1], is->start[2])) + { + return 0; + } + } + } +#if 0 + else if(labda < ISECT_EPSILON) + { + /* too close to origin */ + return 0; + } +#endif + /* TODO if(is->mode!=RE_RAY_SHADOW) { @@ -157,46 +258,10 @@ static int intersect_rayface(RayFace *face, Isect *is) } } */ + is->isect= ok; // wich half of the quad + is->labda= labda; + is->u= u; is->v= v; -#if 0 - TODO - /* when a shadow ray leaves a face, it can be little outside the edges of it, causing - intersection to be detected in its neighbour face */ - if(is->facecontr && is->faceisect); // optimizing, the tests below are not needed - else if(is->labda< .1) { - RayFace *face= is->orig.face; - float *origv1, *origv2, *origv3, *origv4; - short de= 0; - - coordsfunc(face, &origv1, &origv2, &origv3, &origv4); - - if(ob == is->orig.ob) { - if(v1==origv1 || v2==origv1 || v3==origv1 || v4==origv1) de++; - if(v1==origv2 || v2==origv2 || v3==origv2 || v4==origv2) de++; - if(v1==origv3 || v2==origv3 || v3==origv3 || v4==origv3) de++; - if(origv4) { - if(v1==origv4 || v2==origv4 || v3==origv4 || v4==origv4) de++; - } - } - if(de) { - /* so there's a shared edge or vertex, let's intersect ray with face - itself, if that's true we can safely return 1, otherwise we assume - the intersection is invalid, 0 */ - - if(is->facecontr==NULL) { - is->obcontr= is->orig.ob; - is->facecontr= face; - is->faceisect= intersection2(face, is->orig.ob, transformfunc, coordsfunc, is->userdata, - -r0, -r1, -r2, - is->start[0], is->start[1], is->start[2]); - } - - if(is->faceisect) return 1; - return 0; - } - } -#endif - is->hit.ob = face->ob; is->hit.face = face->face; return 1; diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 83165bb6b52..2d617163e29 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -2055,6 +2055,7 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa VECCOPY(isec->start, shi->co); VECCOPY(isec->vec, vec); isec->labda = 1.0f; + isec->skip = RE_SKIP_VLR_NEIGHBOUR; if(isec->mode==RE_RAY_SHADOW_TRA) { /* isec.col is like shadfac, so defines amount of light (0.0 is full shadow) */ From da0c45e7eb5a25ee8ed01a3bd38168045fa3dc04 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 13 May 2009 01:56:03 +0000 Subject: [PATCH 004/138] Renamed exported functions from render to have the RE_ prefix RayObject_* => RE_rayobject_* --- .../blender/editors/armature/meshlaplacian.c | 6 ++-- .../render/extern/include/RE_raytrace.h | 12 ++++---- .../blender/render/intern/include/rayobject.h | 29 ++++++++++--------- .../blender/render/intern/source/rayobject.c | 18 ++++++------ .../render/intern/source/rayobject_mesh.c | 8 +++-- .../render/intern/source/rayobject_octree.c | 9 +++--- .../blender/render/intern/source/rayshade.c | 26 ++++++++--------- .../blender/render/intern/source/rendercore.c | 2 +- 8 files changed, 58 insertions(+), 52 deletions(-) diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index c3ab60ffda6..d74c8dbd0e1 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -401,7 +401,7 @@ static void heat_ray_tree_create(LaplacianSystem *sys) MFace *mface; int a; - sys->heat.raytree = RayObject_mesh_create(me, me); + sys->heat.raytree = RE_rayobject_mesh_create(me, me); sys->heat.vface = MEM_callocN(sizeof(MFace*)*me->totvert, "HeatVFaces"); for(a=0, mface=me->mface; atotface; a++, mface++) { @@ -445,7 +445,7 @@ static int heat_ray_bone_visible(LaplacianSystem *sys, int vertex, int bone) VecMulf(dir, 1e-5); VecAddf(isec.start, isec.start, dir); #endif - visible= !RayObject_raycast(sys->heat.raytree, &isec); + visible= !RE_rayobject_raycast(sys->heat.raytree, &isec); return visible; } @@ -709,7 +709,7 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numbones, /* free */ if(vertsflipped) MEM_freeN(vertsflipped); - RayObject_free(sys->heat.raytree); + RE_rayobject_free(sys->heat.raytree); MEM_freeN(sys->heat.vface); MEM_freeN(sys->heat.mindist); diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index b5ff3d9cae0..d661e355249 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -38,16 +38,16 @@ typedef struct Isect Isect; struct DerivedMesh; struct Mesh; -int RayObject_raycast(RayObject *r, Isect *i); -void RayObject_add (RayObject *r, RayObject *); -void RayObject_done(RayObject *r); -void RayObject_free(RayObject *r); +int RE_rayobject_raycast(RayObject *r, Isect *i); +void RE_rayobject_add (RayObject *r, RayObject *); +void RE_rayobject_done(RayObject *r); +void RE_rayobject_free(RayObject *r); /* RayObject constructors */ -RayObject* RayObject_octree_create(int ocres, int size); +RayObject* RE_rayobject_octree_create(int ocres, int size); //RayObject* RayObject_derivedmesh_create(struct DerivedMesh*, void *ob); -RayObject* RayObject_mesh_create(struct Mesh*, void *ob); +RayObject* RE_rayobject_mesh_create(struct Mesh*, void *ob); /* Ray Intersection */ struct Isect diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index a1b35ac0465..064341ae18b 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -84,19 +84,19 @@ struct RayObject }; -typedef int (*RayObject_raycast_callback)(RayObject *, Isect *); -typedef void (*RayObject_add_callback)(RayObject *, RayObject *); -typedef void (*RayObject_done_callback)(RayObject *); -typedef void (*RayObject_free_callback)(RayObject *); -typedef void (*RayObject_bb_callback)(RayObject *, float *min, float *max); +typedef int (*RE_rayobject_raycast_callback)(RayObject *, Isect *); +typedef void (*RE_rayobject_add_callback)(RayObject *, RayObject *); +typedef void (*RE_rayobject_done_callback)(RayObject *); +typedef void (*RE_rayobject_free_callback)(RayObject *); +typedef void (*RE_rayobject_merge_bb_callback)(RayObject *, float *min, float *max); typedef struct RayObjectAPI { - RayObject_raycast_callback raycast; - RayObject_add_callback add; - RayObject_done_callback done; - RayObject_free_callback free; - RayObject_bb_callback bb; + RE_rayobject_raycast_callback raycast; + RE_rayobject_add_callback add; + RE_rayobject_done_callback done; + RE_rayobject_free_callback free; + RE_rayobject_merge_bb_callback bb; } RayObjectAPI; @@ -104,18 +104,19 @@ typedef struct RayObjectAPI #define RayObject_align(o) ((RayObject*)(((int)o)&(~3))) #define RayObject_unalign(o) ((RayObject*)(((int)o)|1)) #define RayObject_isFace(o) ((((int)o)&3) == 0) +#define RayObject_isAligned(o) ((((int)o)&3) == 0) /* * Extend min/max coords so that the rayobject is inside them */ -void RayObject_merge_bb(RayObject *ob, float *min, float *max); +void RE_rayobject_merge_bb(RayObject *ob, float *min, float *max); /* - * This function differs from RayObject_raycast - * RayObject_intersect does NOT perform last-hit optimization + * This function differs from RE_rayobject_raycast + * RE_rayobject_intersect does NOT perform last-hit optimization * So this is probably a function to call inside raytrace structures */ -int RayObject_intersect(RayObject *r, Isect *i); +int RE_rayobject_intersect(RayObject *r, Isect *i); #define ISECT_EPSILON ((float)FLT_EPSILON) diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index c816bcb2333..9537a0e6424 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -26,7 +26,7 @@ * * ***** END GPL LICENSE BLOCK ***** */ -#include "assert.h" +#include #include "BKE_utildefines.h" @@ -270,15 +270,15 @@ static int intersect_rayface(RayFace *face, Isect *is) return 0; } -int RayObject_raycast(RayObject *r, Isect *i) +int RE_rayobject_raycast(RayObject *r, Isect *i) { - if(i->mode==RE_RAY_SHADOW && i->last_hit && RayObject_intersect(i->last_hit, i)) + if(i->mode==RE_RAY_SHADOW && i->last_hit && RE_rayobject_intersect(i->last_hit, i)) return 1; - return RayObject_intersect(r, i); + return RE_rayobject_intersect(r, i); } -int RayObject_intersect(RayObject *r, Isect *i) +int RE_rayobject_intersect(RayObject *r, Isect *i) { assert(i->mode==RE_RAY_SHADOW); if(RayObject_isFace(r)) @@ -304,25 +304,25 @@ int RayObject_intersect(RayObject *r, Isect *i) } } -void RayObject_add(RayObject *r, RayObject *o) +void RE_rayobject_add(RayObject *r, RayObject *o) { r = RayObject_align( r ); return r->api->add( r, o ); } -void RayObject_done(RayObject *r) +void RE_rayobject_done(RayObject *r) { r = RayObject_align( r ); r->api->done( r ); } -void RayObject_free(RayObject *r) +void RE_rayobject_free(RayObject *r) { r = RayObject_align( r ); r->api->free( r ); } -void RayObject_merge_bb(RayObject *r, float *min, float *max) +void RE_rayobject_merge_bb(RayObject *r, float *min, float *max) { if(RayObject_isFace(r)) { diff --git a/source/blender/render/intern/source/rayobject_mesh.c b/source/blender/render/intern/source/rayobject_mesh.c index 7b8bca38172..eee7231aef4 100644 --- a/source/blender/render/intern/source/rayobject_mesh.c +++ b/source/blender/render/intern/source/rayobject_mesh.c @@ -26,6 +26,8 @@ * * ***** END GPL LICENSE BLOCK ***** */ +#include + #include "rayobject.h" #include "MEM_guardedalloc.h" @@ -66,7 +68,7 @@ static int RayObject_mesh_intersect(RayObject *o, Isect *isec) RayMesh *rm= (RayMesh*)o; int i, hit = 0; for(i = 0; inum_faces; i++) - if(RayObject_raycast( (RayObject*)rm->faces+i, isec )) + if(RE_rayobject_raycast( (RayObject*)rm->faces+i, isec )) { hit = 1; if(isec->mode == RE_RAY_SHADOW) @@ -99,13 +101,15 @@ static void RayObject_mesh_bb(RayObject *o, float *min, float *max) DO_MINMAX( rm->mesh->mvert[i].co, min, max); } -RayObject* RayObject_mesh_create(Mesh *mesh, void *ob) +RayObject* RE_rayobject_mesh_create(Mesh *mesh, void *ob) { RayMesh *rm= MEM_callocN(sizeof(RayMesh), "Octree"); int i; RayFace *face; MFace *mface; + assert( RayObject_isAligned(rm) ); /* RayObject API assumes real data to be 4-byte aligned */ + rm->rayobj.api = &mesh_api; rm->mesh = mesh; rm->faces = MEM_callocN(sizeof(RayFace)*mesh->totface, "octree rayobject nodes"); diff --git a/source/blender/render/intern/source/rayobject_octree.c b/source/blender/render/intern/source/rayobject_octree.c index a738898871b..f9d621b8920 100644 --- a/source/blender/render/intern/source/rayobject_octree.c +++ b/source/blender/render/intern/source/rayobject_octree.c @@ -447,9 +447,10 @@ static void RayObject_octree_free(RayObject *tree) } -RayObject *RayObject_octree_create(int ocres, int size) +RayObject *RE_rayobject_octree_create(int ocres, int size) { Octree *oc= MEM_callocN(sizeof(Octree), "Octree"); + assert( RayObject_isAligned(oc) ); /* RayObject API assumes real data to be 4-byte aligned */ oc->rayobj.api = &octree_api; @@ -600,7 +601,7 @@ static void RayObject_octree_done(RayObject *tree) /* Calculate Bounding Box */ for(c=0; cro_nodes_used; c++) - RayObject_merge_bb(oc->ro_nodes[c], oc->min, oc->max); + RE_rayobject_merge_bb(oc->ro_nodes[c], oc->min, oc->max); /* Alloc memory */ oc->adrbranch= MEM_callocN(sizeof(void *)*BRANCH_ARRAY, "octree branches"); @@ -667,7 +668,7 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval) if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { - if( RayObject_intersect(face,is) ) + if( RE_rayobject_intersect(face,is) ) return 1; } } @@ -693,7 +694,7 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval) if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { - if( RayObject_raycast(face,is) ) + if( RE_rayobject_raycast(face,is) ) if(isect.labdalabda) { *is= isect; found= 1; diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 2d617163e29..7f9bdbc9f9d 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -109,7 +109,7 @@ static float *vlr_get_transform(void *userdata, int i) void freeraytree(Render *re) { if(re->raytree) { - RayObject_free(re->raytree); + RE_rayobject_free(re->raytree); re->raytree= NULL; MEM_freeN( re->rayfaces ); } @@ -144,7 +144,7 @@ void makeraytree(Render *re) } } - re->raytree = RayObject_octree_create( re->r.ocres, totface ); + re->raytree = RE_rayobject_octree_create( re->r.ocres, totface ); //Fill rayfaces re->rayfaces = (RayObject*)MEM_callocN(totface*sizeof(RayFace), "render faces"); @@ -187,14 +187,14 @@ void makeraytree(Render *re) cur_face->ob = (void*)obi; cur_face->face = vlr; - RayObject_add( re->raytree, (RayObject*) cur_face ); + RE_rayobject_add( re->raytree, (RayObject*) cur_face ); cur_face++; } } } } - RayObject_done( re->raytree ); + RE_rayobject_done( re->raytree ); //TODO vlr_face_coords, vlr_check_intersect, vlr_get_transform, re); re->i.infostr= NULL; @@ -434,7 +434,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo isec.orig.ob = obi; isec.orig.face = vlr; - if(RayObject_raycast(R.raytree, &isec)) { + if(RE_rayobject_raycast(R.raytree, &isec)) { float d= 1.0f; shi.mask= origshi->mask; @@ -1274,7 +1274,7 @@ static void ray_trace_shadow_tra(Isect *is, int depth, int traflag) assert(0); - if(RayObject_raycast(R.raytree, is)) { + if(RE_rayobject_raycast(R.raytree, is)) { float d= 1.0f; /* we got a face */ @@ -1354,7 +1354,7 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr) VECCOPY(isec.vec, vec ); isec.labda = RE_RAYTRACE_MAXDIST; - if(RayObject_raycast(R.raytree, &isec)) { + if(RE_rayobject_raycast(R.raytree, &isec)) { float fac; /* Warning, This is not that nice, and possibly a bit slow for every ray, @@ -1611,7 +1611,7 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) prev = fac; - if(RayObject_raycast(R.raytree, &isec)) { + if(RE_rayobject_raycast(R.raytree, &isec)) { if (R.wrld.aomode & WO_AODIST) fac+= exp(-isec.labda*R.wrld.aodistfac); else fac+= 1.0f; } @@ -1743,7 +1743,7 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) isec.labda = maxdist; /* do the trace */ - if(RayObject_raycast(R.raytree, &isec)) { + if(RE_rayobject_raycast(R.raytree, &isec)) { if (R.wrld.aomode & WO_AODIST) sh+= exp(-isec.labda*R.wrld.aodistfac); else sh+= 1.0f; } @@ -1974,7 +1974,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * colsq[2] += isec->col[2]*isec->col[2]; } else { - if( RayObject_raycast(R.raytree, isec) ) fac+= 1.0f; + if( RE_rayobject_raycast(R.raytree, isec) ) fac+= 1.0f; } samples++; @@ -2068,7 +2068,7 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa shadfac[2] += isec->col[2]; shadfac[3] += isec->col[3]; } - else if( RayObject_raycast(R.raytree, isec) ) fac+= 1.0f; + else if( RE_rayobject_raycast(R.raytree, isec) ) fac+= 1.0f; div+= 1.0f; jitlamp+= 2; @@ -2148,7 +2148,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) else { assert(0); - if(RayObject_raycast(R.raytree, &isec)) shadfac[3]= 0.0f; + if(RE_rayobject_raycast(R.raytree, &isec)) shadfac[3]= 0.0f; } } else { @@ -2193,7 +2193,7 @@ static void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float VECCOPY(isec.start, shi->co); VECCOPY(isec.end, lampco); - if(RayObject_raycast(R.raytree, &isec)) { + if(RE_rayobject_raycast(R.raytree, &isec)) { /* we got a face */ /* render co */ diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index fe1ab21a4a4..9fbb585fd02 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -2268,7 +2268,7 @@ static int bake_intersect_tree(RayObject* raytree, Isect* isect, float *start, f isect->dir[2] = dir[2]*sign; isect->labda = maxdist; - hit = RayObject_raycast(raytree, isect); + hit = RE_rayobject_raycast(raytree, isect); //TODO bake_check_intersect if(hit) { hitco[0] = isect->start[0] + isect->labda*isect->vec[0]; From 02ca0c6f7549b9405e2956598c100cfe09d95396 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 13 May 2009 02:01:04 +0000 Subject: [PATCH 005/138] I think this fix the black dots problem (ZanQdo machine is just faster than mine.. so he will test :) ) --- source/blender/render/intern/source/rayshade.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 7f9bdbc9f9d..55f54de8f15 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -1890,7 +1890,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * VECCOPY(vec, lampco); - + isec->skip = RE_SKIP_VLR_NEIGHBOUR; while (samples < max_samples) { isec->orig.ob = shi->obi; From aab6dfd724131fe58e492cc0cbac81e76c59a0dd Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 29 May 2009 21:32:52 +0000 Subject: [PATCH 006/138] Fixed black dot bug! (it does work for the test case I had) But I still wonder about its correction because it looks the oposite of whats documented and of what was used before :S I also took a long time to find it because I tought blender was feeding the raytrace structure with quads and triangles but it looks the quads get triangulated before reaching makeraytree (on rayshade.c). --- source/blender/render/intern/source/rayobject.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index 9537a0e6424..d7d02f07328 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -233,8 +233,8 @@ static int intersect_rayface(RayFace *face, Isect *is) if(a->v1==b->v1 || a->v2==b->v1 || a->v3==b->v1 || a->v4==b->v1 || a->v1==b->v2 || a->v2==b->v2 || a->v3==b->v2 || a->v4==b->v2 || a->v1==b->v3 || a->v2==b->v3 || a->v3==b->v3 || a->v4==b->v3 - || a->v1==b->v4 || a->v2==b->v4 || a->v3==b->v4 || (a->v4 && a->v4==b->v4)) - if(!intersection2((VlakRen*)b, -r0, -r1, -r2, is->start[0], is->start[1], is->start[2])) + || (b->v4 && (a->v1==b->v4 || a->v2==b->v4 || a->v3==b->v4 || a->v4==b->v4))) + if(intersection2((VlakRen*)b, -r0, -r1, -r2, is->start[0], is->start[1], is->start[2])) { return 0; } From 92811f0f6733eda0d5b8565cc6f7a0bad3259ef8 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 29 May 2009 22:55:06 +0000 Subject: [PATCH 007/138] Linked bvhkdop with raytrace api --- .../render/intern/source/rayobject_bvh.c | 124 ++++++++++++++++++ .../render/intern/source/rayobject_octree.c | 2 +- 2 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 source/blender/render/intern/source/rayobject_bvh.c diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c new file mode 100644 index 00000000000..972bbe81b73 --- /dev/null +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -0,0 +1,124 @@ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#include + +#include "MEM_guardedalloc.h" +#include "BKE_utildefines.h" +#include "BLI_kdopbvh.h" +#include "BLI_arithb.h" +#include "RE_raytrace.h" +#include "render_types.h" +#include "rayobject.h" + +static int RayObject_bvh_intersect(RayObject *o, Isect *isec); +static void RayObject_bvh_add(RayObject *o, RayObject *ob); +static void RayObject_bvh_done(RayObject *o); +static void RayObject_bvh_free(RayObject *o); +static void RayObject_bvh_bb(RayObject *o, float *min, float *max); + +static RayObjectAPI bvh_api = +{ + RayObject_bvh_intersect, + RayObject_bvh_add, + RayObject_bvh_done, + RayObject_bvh_free, + RayObject_bvh_bb +}; + +typedef struct BVHObject +{ + RayObject rayobj; + BVHTree *bvh; + +} BVHObject; + + +RayObject *RE_rayobject_bvh_create(int size) +{ + BVHObject *obj= (BVHObject*)MEM_callocN(sizeof(BVHObject), "BVHObject"); + assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ + + obj->rayobj.api = &bvh_api; + obj->bvh = BLI_bvhtree_new(size, 0.0, 4, 6); + + return RayObject_unalign((RayObject*) obj); +} + +static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) +{ + Isect *isect = (Isect*)userdata; + RayObject *face = (RayObject*)index; + + if(RE_rayobject_intersect(face,isect)) + { + hit->index = index; +// hit.distance = TODO + } +} + +static int RayObject_bvh_intersect(RayObject *o, Isect *isec) +{ + BVHObject *obj = (BVHObject*)o; + float dir[3]; + VECCOPY( dir, isec->vec ); + Normalize( dir ); + + //BLI_bvhtree_ray_cast returns -1 on non hit (in case we dont give a Hit structure + return BLI_bvhtree_ray_cast(obj->bvh, isec->start, dir, 0.0, NULL, bvh_callback, isec) != -1; +} + +static void RayObject_bvh_add(RayObject *o, RayObject *ob) +{ + BVHObject *obj = (BVHObject*)o; + float min_max[6]; + INIT_MINMAX(min_max, min_max+3); + RE_rayobject_merge_bb(ob, min_max, min_max+3); + BLI_bvhtree_insert(obj->bvh, (int)ob, min_max, 2 ); +} + +static void RayObject_bvh_done(RayObject *o) +{ + BVHObject *obj = (BVHObject*)o; + BLI_bvhtree_balance(obj->bvh); +} + +static void RayObject_bvh_free(RayObject *o) +{ + BVHObject *obj = (BVHObject*)o; + + if(obj->bvh) + BLI_bvhtree_free(obj->bvh); + + MEM_freeN(obj); +} + +static void RayObject_bvh_bb(RayObject *o, float *min, float *max) +{ + assert(0); +} diff --git a/source/blender/render/intern/source/rayobject_octree.c b/source/blender/render/intern/source/rayobject_octree.c index f9d621b8920..dc4669fa084 100644 --- a/source/blender/render/intern/source/rayobject_octree.c +++ b/source/blender/render/intern/source/rayobject_octree.c @@ -694,7 +694,7 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval) if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { - if( RE_rayobject_raycast(face,is) ) + if( RE_rayobject_intersect(face,is) ) if(isect.labdalabda) { *is= isect; found= 1; From 4b5059094578021c6350529b98ee194501cc4188 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 31 May 2009 02:35:58 +0000 Subject: [PATCH 008/138] *Some debug *Some more integration with bli bvh (just testing stuff) --- .../render/extern/include/RE_raytrace.h | 6 +++- .../blender/render/intern/source/rayobject.c | 31 ++++++++++--------- .../render/intern/source/rayobject_bvh.c | 18 ++++++----- .../blender/render/intern/source/rayshade.c | 9 ++++-- 4 files changed, 40 insertions(+), 24 deletions(-) diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index d661e355249..07c1cc045fe 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -45,6 +45,7 @@ void RE_rayobject_free(RayObject *r); /* RayObject constructors */ RayObject* RE_rayobject_octree_create(int ocres, int size); +RayObject* RE_rayobject_bvh_create(int size); //RayObject* RayObject_derivedmesh_create(struct DerivedMesh*, void *ob); RayObject* RE_rayobject_mesh_create(struct Mesh*, void *ob); @@ -54,9 +55,12 @@ struct Isect { float start[3]; float vec[3]; + float labda; + + float dist; /* length of vec, configured by RE_rayobject_raycast */ /* float end[3]; - not used */ - float labda, u, v; + float u, v; struct { diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index d7d02f07328..be247d0d86b 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -27,8 +27,10 @@ * ***** END GPL LICENSE BLOCK ***** */ #include +#include #include "BKE_utildefines.h" +#include "BLI_arithb.h" #include "RE_raytrace.h" #include "render_types.h" @@ -264,6 +266,7 @@ static int intersect_rayface(RayFace *face, Isect *is) is->hit.ob = face->ob; is->hit.face = face->face; + is->last_hit = (RayObject*)face; return 1; } @@ -272,6 +275,19 @@ static int intersect_rayface(RayFace *face, Isect *is) int RE_rayobject_raycast(RayObject *r, Isect *i) { + static int casted_rays = 0; + + if(casted_rays++ % (1<<20) == 0) + printf("Casting %d rays\n", casted_rays); + + i->vec[0] *= i->labda; + i->vec[1] *= i->labda; + i->vec[2] *= i->labda; + i->labda = 1.0f; //RE_RAYTRACE_MAXDIST; //len; + i->dist = VecLength(i->vec); + + + assert(i->mode==RE_RAY_SHADOW); if(i->mode==RE_RAY_SHADOW && i->last_hit && RE_rayobject_intersect(i->last_hit, i)) return 1; @@ -280,27 +296,14 @@ int RE_rayobject_raycast(RayObject *r, Isect *i) int RE_rayobject_intersect(RayObject *r, Isect *i) { - assert(i->mode==RE_RAY_SHADOW); if(RayObject_isFace(r)) { return intersect_rayface( (RayFace*) r, i); } else { - //TODO should be done somewhere else -// float len = Normalize( i->vec ); - int hit; - i->vec[0] *= i->labda; - i->vec[1] *= i->labda; - i->vec[2] *= i->labda; - i->labda = 1.0f; //RE_RAYTRACE_MAXDIST; //len; - r = RayObject_align( r ); - - hit = r->api->raycast( r, i ); -// i->labda /= len; - - return hit; + return r->api->raycast( r, i ); } } diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index 972bbe81b73..aa36bc44010 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -65,7 +65,7 @@ RayObject *RE_rayobject_bvh_create(int size) assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ obj->rayobj.api = &bvh_api; - obj->bvh = BLI_bvhtree_new(size, 0.0, 4, 6); + obj->bvh = BLI_bvhtree_new(size, 0.0, 2, 6); return RayObject_unalign((RayObject*) obj); } @@ -78,19 +78,23 @@ static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTr if(RE_rayobject_intersect(face,isect)) { hit->index = index; -// hit.distance = TODO + + if(isect->mode == RE_RAY_SHADOW) + hit->dist = 0; } } static int RayObject_bvh_intersect(RayObject *o, Isect *isec) { BVHObject *obj = (BVHObject*)o; - float dir[3]; - VECCOPY( dir, isec->vec ); - Normalize( dir ); +// float dir[3]; +// VECCOPY( dir, isec->vec ); +// Normalize( dir ); + BVHTreeRayHit hit; + hit.index = 0; + hit.dist = isec->labda*isec->dist; - //BLI_bvhtree_ray_cast returns -1 on non hit (in case we dont give a Hit structure - return BLI_bvhtree_ray_cast(obj->bvh, isec->start, dir, 0.0, NULL, bvh_callback, isec) != -1; + return BLI_bvhtree_ray_cast(obj->bvh, isec->start, isec->vec, 0.0, &hit, bvh_callback, isec) != 0; } static void RayObject_bvh_add(RayObject *o, RayObject *ob) diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 55f54de8f15..9bc1d5e75ce 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -122,6 +122,7 @@ void makeraytree(Render *re) double lasttime= PIL_check_seconds_timer(); int v, totv = 0, totface = 0; RayFace *faces, *cur_face; + int tot_quads = 0; //TODO (for now octree only supports RayFaces so we need to create them) // @@ -144,7 +145,9 @@ void makeraytree(Render *re) } } - re->raytree = RE_rayobject_octree_create( re->r.ocres, totface ); + printf("RE_rayobject_*_create( %d )\n", totface); +// re->raytree = RE_rayobject_octree_create( re->r.ocres, totface ); + re->raytree = RE_rayobject_bvh_create( totface ); //Fill rayfaces re->rayfaces = (RayObject*)MEM_callocN(totface*sizeof(RayFace), "render faces"); @@ -182,7 +185,7 @@ void makeraytree(Render *re) cur_face->v1 = vlr->v1->co; cur_face->v2 = vlr->v2->co; cur_face->v3 = vlr->v3->co; - cur_face->v4 = vlr->v4 ? vlr->v4->co : NULL; + cur_face->v4 = vlr->v4 ? tot_quads++, vlr->v4->co : NULL; cur_face->ob = (void*)obi; cur_face->face = vlr; @@ -194,7 +197,9 @@ void makeraytree(Render *re) } } + printf("call RE_rayobject_done( %dtri, %dquads )\n", totface-tot_quads, tot_quads); RE_rayobject_done( re->raytree ); + printf("return RE_rayobject_done( )\n"); //TODO vlr_face_coords, vlr_check_intersect, vlr_get_transform, re); re->i.infostr= NULL; From 2e8979643871ed66ba3accddc7ec61465b6052b7 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 3 Jun 2009 14:42:28 +0000 Subject: [PATCH 009/138] RayObject to support instances.. its not still plugged in the renderer, as so, it hasn't been tested yet --- .../render/extern/include/RE_raytrace.h | 1 + .../render/intern/source/rayobject_instance.c | 139 ++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 source/blender/render/intern/source/rayobject_instance.c diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index 07c1cc045fe..b0e26940ffc 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -46,6 +46,7 @@ void RE_rayobject_free(RayObject *r); /* RayObject constructors */ RayObject* RE_rayobject_octree_create(int ocres, int size); RayObject* RE_rayobject_bvh_create(int size); +RayObject *RE_rayobject_instance_create(RayObject *target, float transform[][4]); //RayObject* RayObject_derivedmesh_create(struct DerivedMesh*, void *ob); RayObject* RE_rayobject_mesh_create(struct Mesh*, void *ob); diff --git a/source/blender/render/intern/source/rayobject_instance.c b/source/blender/render/intern/source/rayobject_instance.c new file mode 100644 index 00000000000..ba675dcb1e7 --- /dev/null +++ b/source/blender/render/intern/source/rayobject_instance.c @@ -0,0 +1,139 @@ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#include + +#include "MEM_guardedalloc.h" +#include "BKE_utildefines.h" +#include "BLI_arithb.h" +#include "RE_raytrace.h" +#include "rayobject.h" + +static int RayObject_instance_intersect(RayObject *o, Isect *isec); +static void RayObject_instance_free(RayObject *o); +static void RayObject_instance_bb(RayObject *o, float *min, float *max); + +static RayObjectAPI instance_api = +{ + RayObject_instance_intersect, + NULL, //static void RayObject_instance_add(RayObject *o, RayObject *ob); + NULL, //static void RayObject_instance_done(RayObject *o); + RayObject_instance_free, + RayObject_instance_bb +}; + +typedef struct InstanceRayObject +{ + RayObject rayobj; + RayObject *target; + float global2target[4][4]; + float target2global[4][4]; + +} InstanceRayObject; + + +RayObject *RE_rayobject_instance_create(RayObject *target, float transform[][4]) +{ + InstanceRayObject *obj= (InstanceRayObject*)MEM_callocN(sizeof(InstanceRayObject), "InstanceRayObject"); + assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ + + obj->rayobj.api = &instance_api; + obj->target = target; + + Mat4CpyMat4(obj->global2target, transform); + Mat4Invert(obj->target2global, obj->global2target); + + return RayObject_unalign((RayObject*) obj); +} + +static int RayObject_instance_intersect(RayObject *o, Isect *isec) +{ + //TODO + // *there is probably a faster way to convert between coordinates + + InstanceRayObject *obj = (InstanceRayObject*)o; + int res; + float start[3], vec[3], labda_point[3], labda; + + + VECCOPY( start, isec->start ); + VECCOPY( vec , isec->vec ); + labda = isec->labda; + VECADDFAC( labda_point, start, vec, labda ); + + + //Transform to target coordinates system + VECADD( isec->vec, isec->vec, isec->start ); + VecMat4MulVecfl(isec->start, obj->target2global, isec->start); + VecMat4MulVecfl(isec->vec , obj->target2global, isec->vec); + VecMat4MulVecfl(labda_point, obj->target2global, labda_point); + isec->labda = VecLenf( isec->start, labda_point ); + VECSUB( isec->vec, isec->vec, isec->start ); + + //Raycast + res = RE_rayobject_intersect(obj->target, isec); + + //Restore coordinate space coords + if(res == 0) + isec->labda = labda; + else + { + VECADDFAC( labda_point, isec->start, isec->vec, isec->labda ); + VecMat4MulVecfl(labda_point, obj->global2target, labda_point); + isec->labda = VecLenf( start, labda_point ); + + } + VECCOPY( isec->start, start ); + VECCOPY( isec->vec, vec ); + + return res; +} + +static void RayObject_instance_free(RayObject *o) +{ + InstanceRayObject *obj = (InstanceRayObject*)o; + MEM_freeN(obj); +} + +static void RayObject_instance_bb(RayObject *o, float *min, float *max) +{ + //TODO: + // *better bb.. calculated witouth rotations of bb + // *maybe cache that better fitted BB at the InstanceRayObject + InstanceRayObject *obj = (InstanceRayObject*)o; + + float m[3], M[3]; + INIT_MINMAX(m, M); + RE_rayobject_merge_bb(obj->target, m, M); + + VecMat4MulVecfl(m, obj->target2global, m); + VecMat4MulVecfl(M, obj->target2global, M); + + DO_MINMAX(m, min, max); + DO_MINMAX(M, min, max); +} From 2fad9229242d3af5f7c2ff8c385c41b353ffd017 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 3 Jun 2009 23:56:04 +0000 Subject: [PATCH 010/138] *enabled mirror rays again *octree is fine *bvh tree gives bad results --- .../blender/render/intern/source/rayobject.c | 22 +++----- .../render/intern/source/rayobject_octree.c | 52 ++++--------------- .../blender/render/intern/source/rayshade.c | 6 +-- 3 files changed, 19 insertions(+), 61 deletions(-) diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index be247d0d86b..ecc74f9c11c 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -250,16 +250,9 @@ static int intersect_rayface(RayFace *face, Isect *is) } #endif -/* - TODO - if(is->mode!=RE_RAY_SHADOW) { - / * for mirror & tra-shadow: large faces can be filled in too often, this prevents - a face being detected too soon... * / - if(is->labda > is->ddalabda) { - return 0; - } - } -*/ + if(is->mode!=RE_RAY_SHADOW && labda > is->labda) + return 0; + is->isect= ok; // wich half of the quad is->labda= labda; is->u= u; is->v= v; @@ -280,14 +273,13 @@ int RE_rayobject_raycast(RayObject *r, Isect *i) if(casted_rays++ % (1<<20) == 0) printf("Casting %d rays\n", casted_rays); - i->vec[0] *= i->labda; +/* i->vec[0] *= i->labda; i->vec[1] *= i->labda; i->vec[2] *= i->labda; - i->labda = 1.0f; //RE_RAYTRACE_MAXDIST; //len; - i->dist = VecLength(i->vec); + i->labda = 1.0f; +*/ +// i->dist = VecLength(i->vec); - - assert(i->mode==RE_RAY_SHADOW); if(i->mode==RE_RAY_SHADOW && i->last_hit && RE_rayobject_intersect(i->last_hit, i)) return 1; diff --git a/source/blender/render/intern/source/rayobject_octree.c b/source/blender/render/intern/source/rayobject_octree.c index dc4669fa084..018c7735284 100644 --- a/source/blender/render/intern/source/rayobject_octree.c +++ b/source/blender/render/intern/source/rayobject_octree.c @@ -664,7 +664,7 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval) RayObject *face = no->v[nr]; OcVal *ov = no->ov+nr; - if(!face) break; //TODO? return 0; + if(!face) break; if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { @@ -675,30 +675,20 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval) } else { /* else mirror or glass or shadowtra, return closest face */ - Isect isect; int found= 0; - assert(0); - - is->labda= 1.0f; /* needed? */ - isect= *is; /* copy for sorting */ - for(; no; no = no->next) for(nr=0; nr<8; nr++) { RayObject *face = no->v[nr]; OcVal *ov = no->ov+nr; - if(!face) return 0; + if(!face) break; if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { - if( RE_rayobject_intersect(face,is) ) - if(isect.labdalabda) { - *is= isect; - found= 1; - } + found= 1; } } @@ -848,22 +838,6 @@ static int RayObject_octree_intersect(RayObject *tree, Isect *is) is->userdata= oc->userdata; #endif -#if 0 - /* only for shadow! */ - if(is->mode==RE_RAY_SHADOW) { - - /* TODO check with last intersected shadow face */ - if(is->last.face!=NULL && !(is->last.face==is->orig.face && is->last.ob==is->orig.ob)) { - if(checkfunc(is, is->last.ob, is->last.face)) { - is->ob= is->last.ob; - is->face= is->last.face; - VECSUB(is->vec, is->end, is->start); - if(RE_ray_face_intersection(is, oc->transformfunc, oc->coordsfunc)) return 1; - } - } - } -#endif - VECADDFAC( end, is->start, is->vec, is->labda ); ldx= end[0] - is->start[0]; u1= 0.0f; @@ -880,6 +854,10 @@ static int RayObject_octree_intersect(RayObject *tree, Isect *is) if(cliptest(ldz, oc->max[2]-is->start[2], &u1,&u2)) { c1=1; if(u2<1.0f) { + is->vec[0] = u2*ldx; + is->vec[1] = u2*ldy; + is->vec[2] = u2*ldz; + end[0]= is->start[0]+u2*ldx; end[1]= is->start[1]+u2*ldy; end[2]= is->start[2]+u2*ldz; @@ -917,16 +895,6 @@ static int RayObject_octree_intersect(RayObject *tree, Isect *is) ocy2= (int)oy2; ocz2= (int)oz2; -// for(ocx1=0; ocx1ocres; ocx1++) -// for(ocy1=0; ocy1ocres; ocy1++) -// for(ocz1=0; ocz1ocres; ocz1++) -// { -// no= ocread(oc, ocx1, ocy1, ocz1); -// if( testnode(oc, is, no, ocval) ) return 1; -// } - -// return 0; - if(ocx1==ocx2 && ocy1==ocy2 && ocz1==ocz2) { no= ocread(oc, ocx1, ocy1, ocz1); if(no) { @@ -934,7 +902,7 @@ static int RayObject_octree_intersect(RayObject *tree, Isect *is) vec1[0]= ox1; vec1[1]= oy1; vec1[2]= oz1; vec2[0]= ox2; vec2[1]= oy2; vec2[2]= oz2; calc_ocval_ray(&ocval, (float)ocx1, (float)ocy1, (float)ocz1, vec1, vec2); -// is->ddalabda= 1.0f; + is->labda = 1.0f; if( testnode(oc, is, no, ocval) ) return 1; } } @@ -1012,8 +980,8 @@ static int RayObject_octree_intersect(RayObject *tree, Isect *is) vec2[1]= oy1-ddalabda*doy; vec2[2]= oz1-ddalabda*doz; calc_ocval_ray(&ocval, (float)xo, (float)yo, (float)zo, vec1, vec2); - -// is->ddalabda= ddalabda; + + is->labda= ddalabda; if( testnode(oc, is, no, ocval) ) return 1; } diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 9bc1d5e75ce..b0515e17424 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -146,8 +146,8 @@ void makeraytree(Render *re) } printf("RE_rayobject_*_create( %d )\n", totface); -// re->raytree = RE_rayobject_octree_create( re->r.ocres, totface ); - re->raytree = RE_rayobject_bvh_create( totface ); + re->raytree = RE_rayobject_octree_create( re->r.ocres, totface ); +// re->raytree = RE_rayobject_bvh_create( totface ); //Fill rayfaces re->rayfaces = (RayObject*)MEM_callocN(totface*sizeof(RayFace), "render faces"); @@ -424,8 +424,6 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo float ref[3]; float dist_mir = origshi->mat->dist_mir; - assert(0); - /* Warning, This is not that nice, and possibly a bit slow for every ray, however some variables were not initialized properly in, unless using shade_input_initialize(...), we need to do a memset */ memset(&shi, 0, sizeof(ShadeInput)); From 1dcab2c87560272112c39b48f28ef1d884ba563a Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 5 Jun 2009 14:44:54 +0000 Subject: [PATCH 011/138] Fixed reflections on bvh tree (its kinda of a hackish-fix.. must be improved later) --- .../blender/render/intern/source/rayobject.c | 6 +-- .../render/intern/source/rayobject_bvh.c | 37 +++++++++++++------ .../blender/render/intern/source/rayshade.c | 5 ++- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index ecc74f9c11c..e622dd971ee 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -273,12 +273,12 @@ int RE_rayobject_raycast(RayObject *r, Isect *i) if(casted_rays++ % (1<<20) == 0) printf("Casting %d rays\n", casted_rays); -/* i->vec[0] *= i->labda; + i->labda = 10000.0; + i->vec[0] *= i->labda; i->vec[1] *= i->labda; i->vec[2] *= i->labda; i->labda = 1.0f; -*/ -// i->dist = VecLength(i->vec); + i->dist = VecLength(i->vec); if(i->mode==RE_RAY_SHADOW && i->last_hit && RE_rayobject_intersect(i->last_hit, i)) return 1; diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index aa36bc44010..232b221fbdb 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -55,6 +55,7 @@ typedef struct BVHObject { RayObject rayobj; BVHTree *bvh; + float bb[2][3]; } BVHObject; @@ -65,36 +66,42 @@ RayObject *RE_rayobject_bvh_create(int size) assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ obj->rayobj.api = &bvh_api; - obj->bvh = BLI_bvhtree_new(size, 0.0, 2, 6); + obj->bvh = BLI_bvhtree_new(size, FLT_EPSILON, 2, 6); + INIT_MINMAX(obj->bb[0], obj->bb[1]); return RayObject_unalign((RayObject*) obj); } static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) { - Isect *isect = (Isect*)userdata; + Isect *isec = (Isect*)userdata; RayObject *face = (RayObject*)index; - if(RE_rayobject_intersect(face,isect)) + if(RE_rayobject_intersect(face,isec)) { hit->index = index; - if(isect->mode == RE_RAY_SHADOW) + if(isec->mode == RE_RAY_SHADOW) hit->dist = 0; +// TODO +// else +// hit->dist = isec->labda; } } static int RayObject_bvh_intersect(RayObject *o, Isect *isec) { BVHObject *obj = (BVHObject*)o; -// float dir[3]; -// VECCOPY( dir, isec->vec ); -// Normalize( dir ); BVHTreeRayHit hit; + float dir[3]; + + VECCOPY(dir, isec->vec); + Normalize(dir); + hit.index = 0; - hit.dist = isec->labda*isec->dist; + hit.dist = FLT_MAX; //TODO isec->labda; - return BLI_bvhtree_ray_cast(obj->bvh, isec->start, isec->vec, 0.0, &hit, bvh_callback, isec) != 0; + return BLI_bvhtree_ray_cast(obj->bvh, isec->start, dir, 0.0, &hit, bvh_callback, isec); } static void RayObject_bvh_add(RayObject *o, RayObject *ob) @@ -102,8 +109,12 @@ static void RayObject_bvh_add(RayObject *o, RayObject *ob) BVHObject *obj = (BVHObject*)o; float min_max[6]; INIT_MINMAX(min_max, min_max+3); - RE_rayobject_merge_bb(ob, min_max, min_max+3); - BLI_bvhtree_insert(obj->bvh, (int)ob, min_max, 2 ); + RE_rayobject_merge_bb(ob, min_max, min_max+3); + + DO_MINMAX(min_max , obj->bb[0], obj->bb[1]); + DO_MINMAX(min_max+3, obj->bb[0], obj->bb[1]); + + BLI_bvhtree_insert(obj->bvh, (int)ob, min_max, 2 ); } static void RayObject_bvh_done(RayObject *o) @@ -124,5 +135,7 @@ static void RayObject_bvh_free(RayObject *o) static void RayObject_bvh_bb(RayObject *o, float *min, float *max) { - assert(0); + BVHObject *obj = (BVHObject*)o; + DO_MINMAX( obj->bb[0], min, max ); + DO_MINMAX( obj->bb[1], min, max ); } diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index b0515e17424..2eb545f7364 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -146,8 +146,8 @@ void makeraytree(Render *re) } printf("RE_rayobject_*_create( %d )\n", totface); - re->raytree = RE_rayobject_octree_create( re->r.ocres, totface ); -// re->raytree = RE_rayobject_bvh_create( totface ); +// re->raytree = RE_rayobject_octree_create( re->r.ocres, totface ); + re->raytree = RE_rayobject_bvh_create( totface ); //Fill rayfaces re->rayfaces = (RayObject*)MEM_callocN(totface*sizeof(RayFace), "render faces"); @@ -433,6 +433,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo VECCOPY(isec.vec, vec ); isec.labda = dist_mir > 0 ? dist_mir : RE_RAYTRACE_MAXDIST; isec.mode= RE_RAY_MIRROR; + isec.skip = RE_SKIP_VLR_NEIGHBOUR; isec.orig.ob = obi; isec.orig.face = vlr; From 49479ef91044965077cb0053623e51967dd662c6 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Thu, 11 Jun 2009 16:44:01 +0000 Subject: [PATCH 012/138] *Instance support at dupliverts/faces *Octree works nicely on hierarchic trees *the old code was quite destructive at the Isect variable changing isec->start, end, vec..now it only changes isec->labda (and hit results) Currently rendering a BVH of all objects, where each object has it own octree. --- .../render/extern/include/RE_raytrace.h | 2 +- .../render/intern/include/render_types.h | 13 +- .../blender/render/intern/source/rayobject.c | 13 +- .../render/intern/source/rayobject_bvh.c | 9 +- .../render/intern/source/rayobject_instance.c | 74 +++-- .../render/intern/source/rayobject_octree.c | 62 ++-- .../blender/render/intern/source/rayshade.c | 304 ++++++++++++------ .../render/intern/source/renderdatabase.c | 17 + 8 files changed, 329 insertions(+), 165 deletions(-) diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index b0e26940ffc..db3dc50c843 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -46,7 +46,7 @@ void RE_rayobject_free(RayObject *r); /* RayObject constructors */ RayObject* RE_rayobject_octree_create(int ocres, int size); RayObject* RE_rayobject_bvh_create(int size); -RayObject *RE_rayobject_instance_create(RayObject *target, float transform[][4]); +RayObject* RE_rayobject_instance_create(RayObject *target, float transform[][4], void *ob, void *target_ob); //RayObject* RayObject_derivedmesh_create(struct DerivedMesh*, void *ob); RayObject* RE_rayobject_mesh_create(struct Mesh*, void *ob); diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 4846fe8d0e4..88bf30bd9ef 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -54,6 +54,7 @@ struct GHash; struct RenderBuckets; struct ObjectInstanceRen; struct RayObject; +struct RayFace; #define TABLEINITSIZE 1024 #define LAMPINITSIZE 256 @@ -170,7 +171,7 @@ struct Render /* octree tables and variables for raytrace */ struct RayObject *raytree; - struct RayObject *rayfaces; /* TODO Temporary */ + struct RayFace *rayfaces; /* occlusion tree */ void *occlusiontree; @@ -280,6 +281,12 @@ typedef struct ObjectRen { int actmtface, actmcol, bakemtface; float obmat[4][4]; /* only used in convertblender.c, for instancing */ + + /* used on makeraytree */ + struct RayObject *raytree; + struct RayFace *rayfaces; + struct ObjectInstanceRen *rayobi; + } ObjectRen; typedef struct ObjectInstanceRen { @@ -297,6 +304,10 @@ typedef struct ObjectInstanceRen { float *vectors; int totvector; + + /* used on makeraytree */ + struct RayObject *raytree; + } ObjectInstanceRen; /* ------------------------------------------------------------------------- */ diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index e622dd971ee..5fc70deaee7 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -128,10 +128,6 @@ static int intersect_rayface(RayFace *face, Isect *is) if(is->orig.ob == face->ob && is->orig.face == face->face) return 0; - /* disabled until i got real & fast cylinder checking, this code doesnt work proper for faster strands */ - // if(is->mode==RE_RAY_SHADOW && is->vlr->flag & R_STRAND) - // return intersection_strand(is); - VECCOPY(co1, face->v1); VECCOPY(co2, face->v2); @@ -182,7 +178,7 @@ static int intersect_rayface(RayFace *face, Isect *is) if(v -(1.0f+ISECT_EPSILON)) { labda= divdet*(cros0*t10 + cros1*t11 + cros2*t12); - if(labda>-ISECT_EPSILON && labda<1.0f+ISECT_EPSILON) { + if(labda>-ISECT_EPSILON && labdalabda) { ok= 1; } } @@ -210,7 +206,7 @@ static int intersect_rayface(RayFace *face, Isect *is) if(v-(1.0f+ISECT_EPSILON)) { labda= divdet*(cros0*t10 + cros1*t11 + cros2*t12); - if(labda>-ISECT_EPSILON && labda<1.0f+ISECT_EPSILON) { + if(labda>-ISECT_EPSILON && labdalabda) { ok= 2; } } @@ -250,9 +246,6 @@ static int intersect_rayface(RayFace *face, Isect *is) } #endif - if(is->mode!=RE_RAY_SHADOW && labda > is->labda) - return 0; - is->isect= ok; // wich half of the quad is->labda= labda; is->u= u; is->v= v; @@ -274,10 +267,12 @@ int RE_rayobject_raycast(RayObject *r, Isect *i) printf("Casting %d rays\n", casted_rays); i->labda = 10000.0; +/* i->vec[0] *= i->labda; i->vec[1] *= i->labda; i->vec[2] *= i->labda; i->labda = 1.0f; +*/ i->dist = VecLength(i->vec); if(i->mode==RE_RAY_SHADOW && i->last_hit && RE_rayobject_intersect(i->last_hit, i)) diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index 232b221fbdb..c5e0cca808c 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -66,7 +66,7 @@ RayObject *RE_rayobject_bvh_create(int size) assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ obj->rayobj.api = &bvh_api; - obj->bvh = BLI_bvhtree_new(size, FLT_EPSILON, 2, 6); + obj->bvh = BLI_bvhtree_new(size, FLT_EPSILON, 4, 6); INIT_MINMAX(obj->bb[0], obj->bb[1]); return RayObject_unalign((RayObject*) obj); @@ -83,9 +83,8 @@ static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTr if(isec->mode == RE_RAY_SHADOW) hit->dist = 0; -// TODO -// else -// hit->dist = isec->labda; + else + hit->dist = isec->labda*isec->dist; } } @@ -99,7 +98,7 @@ static int RayObject_bvh_intersect(RayObject *o, Isect *isec) Normalize(dir); hit.index = 0; - hit.dist = FLT_MAX; //TODO isec->labda; + hit.dist = isec->labda*isec->dist; return BLI_bvhtree_ray_cast(obj->bvh, isec->start, dir, 0.0, &hit, bvh_callback, isec); } diff --git a/source/blender/render/intern/source/rayobject_instance.c b/source/blender/render/intern/source/rayobject_instance.c index ba675dcb1e7..a5024e97450 100644 --- a/source/blender/render/intern/source/rayobject_instance.c +++ b/source/blender/render/intern/source/rayobject_instance.c @@ -51,22 +51,28 @@ typedef struct InstanceRayObject { RayObject rayobj; RayObject *target; + + void *ob; //Object represented by this instance + void *target_ob; //Object represented by the inner RayObject, needed to handle self-intersection + float global2target[4][4]; float target2global[4][4]; } InstanceRayObject; -RayObject *RE_rayobject_instance_create(RayObject *target, float transform[][4]) +RayObject *RE_rayobject_instance_create(RayObject *target, float transform[][4], void *ob, void *target_ob) { InstanceRayObject *obj= (InstanceRayObject*)MEM_callocN(sizeof(InstanceRayObject), "InstanceRayObject"); assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ obj->rayobj.api = &instance_api; obj->target = target; + obj->ob = ob; + obj->target_ob = target_ob; - Mat4CpyMat4(obj->global2target, transform); - Mat4Invert(obj->target2global, obj->global2target); + Mat4CpyMat4(obj->target2global, transform); + Mat4Invert(obj->global2target, obj->target2global); return RayObject_unalign((RayObject*) obj); } @@ -78,39 +84,54 @@ static int RayObject_instance_intersect(RayObject *o, Isect *isec) InstanceRayObject *obj = (InstanceRayObject*)o; int res; - float start[3], vec[3], labda_point[3], labda; + float start[3], vec[3], labda, dist; + int changed = 0; + + //TODO - this is disabling self intersection on instances + if(isec->orig.ob == obj->ob && obj->ob) + { + changed = 1; + isec->orig.ob = obj->target_ob; + } VECCOPY( start, isec->start ); VECCOPY( vec , isec->vec ); labda = isec->labda; - VECADDFAC( labda_point, start, vec, labda ); - - + dist = isec->dist; + //Transform to target coordinates system VECADD( isec->vec, isec->vec, isec->start ); - VecMat4MulVecfl(isec->start, obj->target2global, isec->start); - VecMat4MulVecfl(isec->vec , obj->target2global, isec->vec); - VecMat4MulVecfl(labda_point, obj->target2global, labda_point); - isec->labda = VecLenf( isec->start, labda_point ); + + Mat4MulVecfl(obj->global2target, isec->start); + Mat4MulVecfl(obj->global2target, isec->vec ); + + isec->dist = VecLenf( isec->start, isec->vec ); VECSUB( isec->vec, isec->vec, isec->start ); + isec->labda *= isec->dist / dist; + //Raycast res = RE_rayobject_intersect(obj->target, isec); //Restore coordinate space coords if(res == 0) - isec->labda = labda; - else { - VECADDFAC( labda_point, isec->start, isec->vec, isec->labda ); - VecMat4MulVecfl(labda_point, obj->global2target, labda_point); - isec->labda = VecLenf( start, labda_point ); + isec->labda = labda; } + else + { + isec->labda *= dist / isec->dist; + isec->hit.ob = obj->ob; + } + isec->dist = dist; VECCOPY( isec->start, start ); - VECCOPY( isec->vec, vec ); + VECCOPY( isec->vec, vec ); + if(changed) + isec->orig.ob = obj->ob; + return res; } @@ -123,17 +144,20 @@ static void RayObject_instance_free(RayObject *o) static void RayObject_instance_bb(RayObject *o, float *min, float *max) { //TODO: - // *better bb.. calculated witouth rotations of bb - // *maybe cache that better fitted BB at the InstanceRayObject + // *better bb.. calculated without rotations of bb + // *maybe cache that better-fitted-BB at the InstanceRayObject InstanceRayObject *obj = (InstanceRayObject*)o; - float m[3], M[3]; + float m[3], M[3], t[3]; + int i, j; INIT_MINMAX(m, M); RE_rayobject_merge_bb(obj->target, m, M); - VecMat4MulVecfl(m, obj->target2global, m); - VecMat4MulVecfl(M, obj->target2global, M); - - DO_MINMAX(m, min, max); - DO_MINMAX(M, min, max); + //There must be a faster way than rotating all the 8 vertexs of the BB + for(i=0; i<8; i++) + { + for(j=0; j<3; j++) t[j] = i&(1<target2global, t); + DO_MINMAX(t, min, max); + } } diff --git a/source/blender/render/intern/source/rayobject_octree.c b/source/blender/render/intern/source/rayobject_octree.c index 018c7735284..b715695dc10 100644 --- a/source/blender/render/intern/source/rayobject_octree.c +++ b/source/blender/render/intern/source/rayobject_octree.c @@ -636,7 +636,9 @@ static void RayObject_octree_done(RayObject *tree) } MEM_freeN(oc->ocface); + oc->ocface = NULL; MEM_freeN(oc->ro_nodes); + oc->ro_nodes = NULL; printf("%f %f - %f\n", oc->min[0], oc->max[0], oc->ocfacx ); printf("%f %f - %f\n", oc->min[1], oc->max[1], oc->ocfacy ); @@ -820,9 +822,10 @@ static int RayObject_octree_intersect(RayObject *tree, Isect *is) Octree *oc= (Octree*)tree; Node *no; OcVal ocval; - float vec1[3], vec2[3], end[3]; + float vec1[3], vec2[3], start[3], end[3]; float u1,u2,ox1,ox2,oy1,oy2,oz1,oz2; float labdao,labdax,ldx,labday,ldy,labdaz,ldz, ddalabda; + float olabda = 0; int dx,dy,dz; int xo,yo,zo,c1=0; int ocx1,ocx2,ocy1, ocy2,ocz1,ocz2; @@ -838,35 +841,33 @@ static int RayObject_octree_intersect(RayObject *tree, Isect *is) is->userdata= oc->userdata; #endif + VECCOPY( start, is->start ); VECADDFAC( end, is->start, is->vec, is->labda ); - ldx= end[0] - is->start[0]; + ldx= is->vec[0]*is->labda; + olabda = is->labda; u1= 0.0f; u2= 1.0f; /* clip with octree cube */ - if(cliptest(-ldx, is->start[0]-oc->min[0], &u1,&u2)) { - if(cliptest(ldx, oc->max[0]-is->start[0], &u1,&u2)) { - ldy= end[1] - is->start[1]; - if(cliptest(-ldy, is->start[1]-oc->min[1], &u1,&u2)) { - if(cliptest(ldy, oc->max[1]-is->start[1], &u1,&u2)) { - ldz = end[2] - is->start[2]; - if(cliptest(-ldz, is->start[2]-oc->min[2], &u1,&u2)) { - if(cliptest(ldz, oc->max[2]-is->start[2], &u1,&u2)) { + if(cliptest(-ldx, start[0]-oc->min[0], &u1,&u2)) { + if(cliptest(ldx, oc->max[0]-start[0], &u1,&u2)) { + ldy= is->vec[1]*is->labda; + if(cliptest(-ldy, start[1]-oc->min[1], &u1,&u2)) { + if(cliptest(ldy, oc->max[1]-start[1], &u1,&u2)) { + ldz = is->vec[2]*is->labda; + if(cliptest(-ldz, start[2]-oc->min[2], &u1,&u2)) { + if(cliptest(ldz, oc->max[2]-start[2], &u1,&u2)) { c1=1; if(u2<1.0f) { - is->vec[0] = u2*ldx; - is->vec[1] = u2*ldy; - is->vec[2] = u2*ldz; - - end[0]= is->start[0]+u2*ldx; - end[1]= is->start[1]+u2*ldy; - end[2]= is->start[2]+u2*ldz; + end[0] = start[0]+u2*ldx; + end[1] = start[1]+u2*ldy; + end[2] = start[2]+u2*ldz; } + if(u1>0.0f) { - assert( 0 ); - is->start[0]+=u1*ldx; - is->start[1]+=u1*ldy; - is->start[2]+=u1*ldz; + start[0] += u1*ldx; + start[1] += u1*ldy; + start[2] += u1*ldz; } } } @@ -881,9 +882,9 @@ static int RayObject_octree_intersect(RayObject *tree, Isect *is) //ocread(oc, oc->ocres, 0, 0); /* setup 3dda to traverse octree */ - ox1= (is->start[0]-oc->min[0])*oc->ocfacx; - oy1= (is->start[1]-oc->min[1])*oc->ocfacy; - oz1= (is->start[2]-oc->min[2])*oc->ocfacz; + ox1= (start[0]-oc->min[0])*oc->ocfacx; + oy1= (start[1]-oc->min[1])*oc->ocfacy; + oz1= (start[2]-oc->min[2])*oc->ocfacz; ox2= (end[0]-oc->min[0])*oc->ocfacx; oy2= (end[1]-oc->min[1])*oc->ocfacy; oz2= (end[2]-oc->min[2])*oc->ocfacz; @@ -902,11 +903,11 @@ static int RayObject_octree_intersect(RayObject *tree, Isect *is) vec1[0]= ox1; vec1[1]= oy1; vec1[2]= oz1; vec2[0]= ox2; vec2[1]= oy2; vec2[2]= oz2; calc_ocval_ray(&ocval, (float)ocx1, (float)ocy1, (float)ocz1, vec1, vec2); - is->labda = 1.0f; if( testnode(oc, is, no, ocval) ) return 1; } } else { + int found = 0; //static int coh_ocx1,coh_ocx2,coh_ocy1, coh_ocy2,coh_ocz1,coh_ocz2; float dox, doy, doz; int eqval; @@ -981,10 +982,15 @@ static int RayObject_octree_intersect(RayObject *tree, Isect *is) vec2[2]= oz1-ddalabda*doz; calc_ocval_ray(&ocval, (float)xo, (float)yo, (float)zo, vec1, vec2); - is->labda= ddalabda; - if( testnode(oc, is, no, ocval) ) return 1; + //is->labda = (u1+ddalabda*(u2-u1))*olabda; + if( testnode(oc, is, no, ocval) ) + found = 1; + + if(is->labda < (u1+ddalabda*(u2-u1))*olabda) + return found; } + labdao= ddalabda; /* traversing ocree nodes need careful detection of smallest values, with proper @@ -1052,8 +1058,6 @@ static int RayObject_octree_intersect(RayObject *tree, Isect *is) } /* reached end, no intersections found */ - is->hit.ob = 0; - is->hit.face = NULL; return 0; } diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 2eb545f7364..707af95aaef 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -71,16 +71,6 @@ extern struct Render R; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ #if 0 -static void vlr_face_coords(RayFace *face, float **v1, float **v2, float **v3, float **v4) -{ - VlakRen *vlr= (VlakRen*)face; - - *v1 = (vlr->v1)? vlr->v1->co: NULL; - *v2 = (vlr->v2)? vlr->v2->co: NULL; - *v3 = (vlr->v3)? vlr->v3->co: NULL; - *v4 = (vlr->v4)? vlr->v4->co: NULL; -} - static int vlr_check_intersect(Isect *is, int ob, RayFace *face) { ObjectInstanceRen *obi= RAY_OBJECT_GET((Render*)is->userdata, ob); @@ -97,115 +87,239 @@ static int vlr_check_intersect(Isect *is, int ob, RayFace *face) else return (is->lay & obi->lay); } - -static float *vlr_get_transform(void *userdata, int i) -{ - ObjectInstanceRen *obi= RAY_OBJECT_GET((Render*)userdata, i); - - return (obi->flag & R_TRANSFORMED)? (float*)obi->mat: NULL; -} #endif void freeraytree(Render *re) { - if(re->raytree) { + ObjectInstanceRen *obi; + + if(re->raytree) + { RE_rayobject_free(re->raytree); - re->raytree= NULL; - MEM_freeN( re->rayfaces ); + re->raytree = NULL; + } + if(re->rayfaces) + { + MEM_freeN(re->rayfaces); + re->rayfaces = NULL; + } + + for(obi=re->instancetable.first; obi; obi=obi->next) + { + ObjectRen *obr = obi->obr; + if(obr->raytree) + { + RE_rayobject_free(obr->raytree); + obr->raytree = NULL; + } + if(obr->rayfaces) + { + MEM_freeN(obr->rayfaces); + obr->rayfaces = NULL; + } + if(obi->raytree) + { + RE_rayobject_free(obi->raytree); + obi->raytree = NULL; + } } } -void makeraytree(Render *re) + +static int is_raytraceable_vlr(Render *re, VlakRen *vlr) { - ObjectInstanceRen *obi; - ObjectRen *obr; - VlakRen *vlr= NULL; - double lasttime= PIL_check_seconds_timer(); - int v, totv = 0, totface = 0; - RayFace *faces, *cur_face; - int tot_quads = 0; + if((re->flag & R_BAKE_TRACE) || (vlr->mat->mode & MA_TRACEBLE)) + if((vlr->mat->mode & MA_WIRE)==0) + return 1; + return 0; +} - //TODO (for now octree only supports RayFaces so we need to create them) - // - //count faces - for(obi=re->instancetable.first; obi; obi=obi->next) { - obr= obi->obr; +static int is_raytraceable(Render *re, ObjectInstanceRen *obi) +{ + int v; + ObjectRen *obr = obi->obr; - if(re->excludeob && obr->ob == re->excludeob) - continue; + if(re->excludeob && obr->ob == re->excludeob) + return 0; - for(v=0;vtotvlak;v++) { - if((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak; - else vlr++; - /* baking selected to active needs non-traceable too */ - if((re->flag & R_BAKE_TRACE) || (vlr->mat->mode & MA_TRACEBLE)) { - if((vlr->mat->mode & MA_WIRE)==0) { - totface++; - } - } - } + for(v=0;vtotvlak;v++) + { + VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); + if(is_raytraceable_vlr(re, vlr)) + return 1; } - - printf("RE_rayobject_*_create( %d )\n", totface); -// re->raytree = RE_rayobject_octree_create( re->r.ocres, totface ); - re->raytree = RE_rayobject_bvh_create( totface ); - - //Fill rayfaces - re->rayfaces = (RayObject*)MEM_callocN(totface*sizeof(RayFace), "render faces"); - cur_face = faces = (RayFace*)re->rayfaces; - - for(obi=re->instancetable.first; obi; obi=obi->next) { - obr= obi->obr; + return 0; +} - if(re->excludeob && obr->ob == re->excludeob) - continue; +RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) +{ + //TODO + // out-of-memory safeproof + // break render + // update render stats + ObjectRen *obr = obi->obr; + + if(obr->raytree == NULL) + { + RayObject *raytree; + RayFace *face; + int v; + + //Count faces + int faces = 0; + for(v=0;vtotvlak;v++) + { + VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); + if(is_raytraceable_vlr(re, vlr)) + faces++; + } + assert( faces > 0 ); - for(v=0;vtotvlak;v++) { - if((v & 255)==0) + //Create Ray cast accelaration structure + + //TODO dynamic ocres + raytree = obr->raytree = RE_rayobject_octree_create( re->r.ocres, faces ); +// raytree = obr->raytree = RE_rayobject_bvh_create( faces ); + face = obr->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "ObjectRen faces"); + obr->rayobi = obi; + + for(v=0;vtotvlak;v++) + { + VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); + if(is_raytraceable_vlr(re, vlr)) { - double time= PIL_check_seconds_timer(); - - vlr= obr->vlaknodes[v>>8].vlak; - - vlr= obr->vlaknodes[v>>8].vlak; - if(re->test_break(re->tbh)) - break; - if(time-lasttime>1.0f) { - char str[32]; - sprintf(str, "Filling Octree: %d", totv); - re->i.infostr= str; - re->stats_draw(re->sdh, &re->i); - re->i.infostr= NULL; - lasttime= time; - } - } - else vlr++; - /* baking selected to active needs non-traceable too */ - if((re->flag & R_BAKE_TRACE) || (vlr->mat->mode & MA_TRACEBLE)) { - if((vlr->mat->mode & MA_WIRE)==0) { - cur_face->v1 = vlr->v1->co; - cur_face->v2 = vlr->v2->co; - cur_face->v3 = vlr->v3->co; - cur_face->v4 = vlr->v4 ? tot_quads++, vlr->v4->co : NULL; - - cur_face->ob = (void*)obi; - cur_face->face = vlr; - - RE_rayobject_add( re->raytree, (RayObject*) cur_face ); - cur_face++; - } + face->v1 = vlr->v1->co; + face->v2 = vlr->v2->co; + face->v3 = vlr->v3->co; + face->v4 = vlr->v4 ? vlr->v4->co : NULL; + + face->ob = obi; + face->face = vlr; + + RE_rayobject_add( raytree, (RayObject*)face++ ); } } + RE_rayobject_done( raytree ); } - printf("call RE_rayobject_done( %dtri, %dquads )\n", totface-tot_quads, tot_quads); - RE_rayobject_done( re->raytree ); - printf("return RE_rayobject_done( )\n"); -//TODO vlr_face_coords, vlr_check_intersect, vlr_get_transform, re); + + if(obi->flag & R_TRANSFORMED) + { + obi->raytree = RE_rayobject_instance_create( obr->raytree, obi->mat, obi, obi->obr->rayobi ); + } + + if(obi->raytree) return obi->raytree; + return obi->obr->raytree; +} + +/* + * create an hierarchic raytrace structure with all objects + * + * R_TRANSFORMED objects instances reuse the same tree by using the rayobject_instance + */ +static void makeraytree_hier(Render *re) +{ + //TODO + // out-of-memory safeproof + // break render + // update render stats + + ObjectInstanceRen *obi; + int num_objects = 0; + + re->i.infostr="Creating raytrace structure"; + re->stats_draw(re->sdh, &re->i); + + //Count number of objects + for(obi=re->instancetable.first; obi; obi=obi->next) + if(is_raytraceable(re, obi)) + num_objects++; + + //Create raytree + re->raytree = RE_rayobject_bvh_create( num_objects ); + + for(obi=re->instancetable.first; obi; obi=obi->next) + if(is_raytraceable(re, obi)) + { + RayObject *obj = makeraytree_object(re, obi); + RE_rayobject_add( re->raytree, obj ); + + if(re->test_break(re->tbh)) + break; + } + + if(!re->test_break(re->tbh)) + { + RE_rayobject_done( re->raytree ); + } re->i.infostr= NULL; re->stats_draw(re->sdh, &re->i); } +/* + * create a single raytrace structure with all faces + */ +static void makeraytree_single(Render *re) +{ + ObjectInstanceRen *obi; + RayObject *raytree; + RayFace *face; + int faces = 0, obs = 0; + + for(obi=re->instancetable.first; obi; obi=obi->next) + if(is_raytraceable(re, obi)) + { + int v; + ObjectRen *obr = obi->obr; + obs++; + + assert((obi->flag & R_TRANSFORMED) == 0); //Not suported + + for(v=0;vtotvlak;v++) + { + VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); + if(is_raytraceable_vlr(re, vlr)) + faces++; + } + } + + //Create raytree + raytree = re->raytree = RE_rayobject_octree_create(re->r.ocres, faces); + face = re->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces"); + + for(obi=re->instancetable.first; obi; obi=obi->next) + if(is_raytraceable(re, obi)) + { + int v; + ObjectRen *obr = obi->obr; + + for(v=0;vtotvlak;v++) + { + VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); + face->v1 = vlr->v1->co; + face->v2 = vlr->v2->co; + face->v3 = vlr->v3->co; + face->v4 = vlr->v4 ? vlr->v4->co : NULL; + + face->ob = obi; + face->face = vlr; + + RE_rayobject_add( raytree, (RayObject*)face++ ); + } + } + RE_rayobject_done( raytree ); +} + +void makeraytree(Render *re) +{ + if(1) + makeraytree_hier(re); + else + makeraytree_single(re); +} + + + static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr) { ObjectInstanceRen *obi= (ObjectInstanceRen*)is->hit.ob; diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 621831fb341..5f21a0e2e1a 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -75,6 +75,7 @@ #include "BKE_DerivedMesh.h" #include "RE_render_ext.h" /* externtex */ +#include "RE_raytrace.h" #include "renderpipeline.h" #include "render_types.h" @@ -872,13 +873,29 @@ void free_renderdata_tables(Render *re) MEM_freeN(obr->mtface); if(obr->mcol) MEM_freeN(obr->mcol); + + if(obr->rayfaces) + { + MEM_freeN(obr->rayfaces); + obr->rayfaces = NULL; + } + if(obr->raytree) + { + RE_rayobject_free(obr->raytree); + obr->raytree = NULL; + } } if(re->objectinstance) { for(obi=re->instancetable.first; obi; obi=obi->next) + { if(obi->vectors) MEM_freeN(obi->vectors); + if(obi->raytree) + RE_rayobject_free(obi->raytree); + } + MEM_freeN(re->objectinstance); re->objectinstance= NULL; re->totinstance= 0; From d198480db81f7efea85ee67c9ecedff9aaf5e2f5 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Thu, 11 Jun 2009 18:25:29 +0000 Subject: [PATCH 013/138] *ray<->bb hit optimization... just to make it "slightly" faster :P Based on Tactical Optimization of Ray/Box Intersection, by Graham Fyffe [http://tog.acm.org/resources/RTNews/html/rtnv21n1.html#art9] *for now it breaks shrinkwrap or other stuff that relies on sphere-raycast of BLI_kdopbvh. --- source/blender/blenlib/intern/BLI_kdopbvh.c | 39 ++++++++++++++++++- .../blender/render/intern/source/rayshade.c | 7 ++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 0f8194362c9..51b51e5ecca 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -101,6 +101,8 @@ typedef struct BVHRayCastData BVHTreeRay ray; float ray_dot_axis[13]; + float idot_axis[13]; + int index[6]; BVHTreeRayHit hit; } BVHRayCastData; @@ -1404,6 +1406,7 @@ int BLI_bvhtree_find_nearest(BVHTree *tree, const float *co, BVHTreeNearest *nea * raycast is done by performing a DFS on the BVHTree and saving the closest hit */ + //Determines the distance that the ray must travel to hit the bounding volume of the given node static float ray_nearest_hit(BVHRayCastData *data, BVHNode *node) { @@ -1443,13 +1446,40 @@ static float ray_nearest_hit(BVHRayCastData *data, BVHNode *node) return low; } +//Determines the distance that the ray must travel to hit the bounding volume of the given node +//Based on Tactical Optimization of Ray/Box Intersection, by Graham Fyffe +//[http://tog.acm.org/resources/RTNews/html/rtnv21n1.html#art9] +// +//TODO this doens't has data->ray.radius in consideration +static float fast_ray_nearest_hit(const BVHRayCastData *data, const BVHNode *node) +{ + const float *bv = node->bv; + float dist; + + float t1x = (bv[data->index[0]] - data->ray.origin[0]) * data->idot_axis[0]; + float t2x = (bv[data->index[1]] - data->ray.origin[0]) * data->idot_axis[0]; + float t1y = (bv[data->index[2]] - data->ray.origin[1]) * data->idot_axis[1]; + float t2y = (bv[data->index[3]] - data->ray.origin[1]) * data->idot_axis[1]; + float t1z = (bv[data->index[4]] - data->ray.origin[2]) * data->idot_axis[2]; + float t2z = (bv[data->index[5]] - data->ray.origin[2]) * data->idot_axis[2]; + + if(t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) return FLT_MAX; + if(t2x < 0.0 || t2y < 0.0 || t2z < 0.0) return FLT_MAX; + if(t1x > data->hit.dist || t1y > data->hit.dist || t1z > data->hit.dist) return FLT_MAX; + + dist = t1x; + if (t1y > dist) dist = t1y; + if (t1z > dist) dist = t1z; + return dist; +} + static void dfs_raycast(BVHRayCastData *data, BVHNode *node) { int i; //ray-bv is really fast.. and simple tests revealed its worth to test it //before calling the ray-primitive functions - float dist = ray_nearest_hit(data, node); + float dist = fast_ray_nearest_hit(data, node); if(dist >= data->hit.dist) return; if(node->totnode == 0) @@ -1503,9 +1533,16 @@ int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float for(i=0; i<3; i++) { data.ray_dot_axis[i] = INPR( data.ray.direction, KDOP_AXES[i]); + data.idot_axis[i] = 1.0f / data.ray_dot_axis[i]; if(fabs(data.ray_dot_axis[i]) < FLT_EPSILON) + { data.ray_dot_axis[i] = 0.0; + } + data.index[2*i] = data.idot_axis[i] < 0.0 ? 1 : 0; + data.index[2*i+1] = 1 - data.index[2*i]; + data.index[2*i] += 2*i; + data.index[2*i+1] += 2*i; } diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 707af95aaef..8a5a0dbf06d 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -177,8 +177,8 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) //Create Ray cast accelaration structure //TODO dynamic ocres - raytree = obr->raytree = RE_rayobject_octree_create( re->r.ocres, faces ); -// raytree = obr->raytree = RE_rayobject_bvh_create( faces ); +// raytree = obr->raytree = RE_rayobject_octree_create( re->r.ocres, faces ); + raytree = obr->raytree = RE_rayobject_bvh_create( faces ); face = obr->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "ObjectRen faces"); obr->rayobi = obi; @@ -284,7 +284,8 @@ static void makeraytree_single(Render *re) } //Create raytree - raytree = re->raytree = RE_rayobject_octree_create(re->r.ocres, faces); +// raytree = re->raytree = RE_rayobject_octree_create(re->r.ocres, faces); + raytree = re->raytree = RE_rayobject_bvh_create(faces); face = re->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces"); for(obi=re->instancetable.first; obi; obi=obi->next) From 590f3a43bf2e5e4826e943aa6b5cdf0ebc76aa6d Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 14 Jun 2009 10:56:29 +0000 Subject: [PATCH 014/138] Enabled the missing features (not tested) bug-reports are welcome --- .../blender/render/intern/source/rayobject.c | 2 +- source/blender/render/intern/source/rayshade.c | 18 ++---------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index 5fc70deaee7..4d0606e2067 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -266,8 +266,8 @@ int RE_rayobject_raycast(RayObject *r, Isect *i) if(casted_rays++ % (1<<20) == 0) printf("Casting %d rays\n", casted_rays); - i->labda = 10000.0; /* + i->labda = 10000.0; i->vec[0] *= i->labda; i->vec[1] *= i->labda; i->vec[2] *= i->labda; diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index d9ba89d15e8..10115dc97e9 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -1393,8 +1393,6 @@ static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int ShadeInput shi; ShadeResult shr; - assert(0); - if(RE_rayobject_raycast(R.raytree, is)) { float d= 1.0f; /* we got a face */ @@ -1662,8 +1660,6 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) float dxyview[3], skyadded=0, div; int aocolor; - assert(0); - isec.orig.ob = shi->obi; isec.orig.face = shi->vlr; @@ -1796,8 +1792,6 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) float dxyview[3]; int j= -1, tot, actual=0, skyadded=0, aocolor, resol= R.wrld.aosamp; - assert(0); - isec.orig.ob = shi->obi; isec.orig.face = shi->vlr; @@ -1979,8 +1973,6 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * float jitco[RE_MAX_OSA][3]; int totjitco; -// assert(0); - colsq[0] = colsq[1] = colsq[2] = 0.0; if(isec->mode==RE_RAY_SHADOW_TRA) { shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 0.0f; @@ -2071,7 +2063,6 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * } VECCOPY(isec->start, co); -// VECSUB(isec->vec, end, isec->start); isec->vec[0] = end[0]-isec->start[0]; isec->vec[1] = end[1]-isec->start[1]; isec->vec[2] = end[2]-isec->start[2]; @@ -2135,8 +2126,6 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa float fac=0.0f, div=0.0f, vec[3]; int a, j= -1, mask; - assert(0); - if(isec->mode==RE_RAY_SHADOW_TRA) { shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 0.0f; } @@ -2265,11 +2254,8 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) ray_trace_shadow_tra(&isec, shi, DEPTH_SHADOW_TRA, 0); QUATCOPY(shadfac, isec.col); } - else - { - assert(0); - if(RE_rayobject_raycast(R.raytree, &isec)) shadfac[3]= 0.0f; - } + else if(RE_rayobject_raycast(R.raytree, &isec)) + shadfac[3]= 0.0f; } else { ray_shadow_jitter(shi, lar, lampco, shadfac, &isec); From 419dde702146fa9d49b309e746b03782baae8baf Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 17 Jun 2009 00:01:27 +0000 Subject: [PATCH 015/138] Non recursive tree transverse on raycast *for now proximity-heuristic on tree transverse is disabled --- source/blender/blenlib/intern/BLI_kdopbvh.c | 53 +++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 51b51e5ecca..3a5da8dd8aa 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -52,6 +52,7 @@ typedef struct BVHNode { struct BVHNode **children; struct BVHNode *parent; // some user defined traversed need that + struct BVHNode *skip[2]; float *bv; // Bounding volume of all nodes, max 13 axis int index; // face, edge, vertex index char totnode; // how many nodes are used, used for speedup @@ -355,6 +356,23 @@ int partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis){ } ////////////////////////////////////////////////////////////////////////////////////////////////////// +static void build_skip_links(BVHTree *tree, BVHNode *node, BVHNode *left, BVHNode *right) +{ + int i; + + node->skip[0] = left; + node->skip[1] = right; + + for (i = 0; i < node->totnode; i++) + { + if(i+1 < node->totnode) + build_skip_links(tree, node->children[i], left, node->children[i+1] ); + else + build_skip_links(tree, node->children[i], left, right ); + + left = node->children[i]; + } +} /* * BVHTree bounding volumes functions @@ -941,6 +959,7 @@ void BLI_bvhtree_balance(BVHTree *tree) for(i = 0; i < tree->totbranch; i++) tree->nodes[tree->totleaf + i] = branches_array + i; + build_skip_links(tree, tree->nodes[tree->totleaf], NULL, NULL); //bvhtree_info(tree); } @@ -1513,6 +1532,37 @@ static void dfs_raycast(BVHRayCastData *data, BVHNode *node) } } +static void iterative_raycast(BVHRayCastData *data, BVHNode *node) +{ + while(node) + { + float dist = fast_ray_nearest_hit(data, node); + if(dist >= data->hit.dist) + { + node = node->skip[1]; + continue; + } + + if(node->totnode == 0) + { + if(data->callback) + data->callback(data->userdata, node->index, &data->ray, &data->hit); + else + { + data->hit.index = node->index; + data->hit.dist = dist; + VECADDFAC(data->hit.co, data->ray.origin, data->ray.direction, dist); + } + + node = node->skip[1]; + } + else + { + node = node->children[0]; + } + } +} + int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) { int i; @@ -1555,7 +1605,10 @@ int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float } if(root) + { dfs_raycast(&data, root); +// iterative_raycast(&data, root); + } if(hit) From 10a4338936db1a196703ad0ad8f983c3ba503ac8 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 21 Jun 2009 11:08:30 +0000 Subject: [PATCH 016/138] *fixs ray_shadow_jitter (area soft shadow) (detected with test249/render/arealight.blend) --- source/blender/render/intern/source/rayshade.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 10115dc97e9..4c72f80224a 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -2162,7 +2162,9 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa /* set start and vec */ VECCOPY(isec->start, shi->co); - VECCOPY(isec->vec, vec); + isec->vec[0] = vec[0]+lampco[0]-shi->co[0]; + isec->vec[1] = vec[1]+lampco[1]-shi->co[1]; + isec->vec[2] = vec[2]+lampco[2]-shi->co[2]; isec->labda = 1.0f; isec->skip = RE_SKIP_VLR_NEIGHBOUR; From edfb507088165db835c184f55829832af0776f33 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 24 Jun 2009 19:29:48 +0000 Subject: [PATCH 017/138] *Fixed handling of HEMI and SUN lights shadows --- .../blender/render/intern/source/rayshade.c | 68 ++++++++++++++----- 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 4c72f80224a..be7b2665bdb 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -1957,7 +1957,7 @@ static void ray_shadow_jittered_coords(ShadeInput *shi, int max, float jitco[RE_ } } -static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *shadfac, Isect *isec) +static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, int lampvec, float *shadfac, Isect *isec) { QMCSampler *qsa=NULL; int samples=0; @@ -2018,6 +2018,8 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * if (lar->type == LA_LOCAL) { float ru[3], rv[3], v[3], s[3]; + assert(lampvec == 0); + /* calc tangent plane vectors */ v[0] = co[0] - lampco[0]; v[1] = co[1] - lampco[1]; @@ -2036,6 +2038,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * VECCOPY(samp3d, s); } else { + assert(lampvec); /* sampling, returns quasi-random vector in [sizex,sizey]^2 plane */ QMC_sampleRect(samp3d, qsa, shi->thread, samples, lar->area_size, lar->area_sizey); @@ -2063,10 +2066,20 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * } VECCOPY(isec->start, co); - isec->vec[0] = end[0]-isec->start[0]; - isec->vec[1] = end[1]-isec->start[1]; - isec->vec[2] = end[2]-isec->start[2]; - isec->labda = 1.0f; // * Normalize(isec->vec); + if(lampvec) + { + isec->vec[0] = end[0]; + isec->vec[1] = end[1]; + isec->vec[2] = end[2]; + isec->labda = RE_RAYTRACE_MAXDIST; + } + else + { + isec->vec[0] = end[0]-isec->start[0]; + isec->vec[1] = end[1]-isec->start[1]; + isec->vec[2] = end[2]-isec->start[2]; + isec->labda = 1.0f; // * Normalize(isec->vec); + } /* trace the ray */ if(isec->mode==RE_RAY_SHADOW_TRA) { @@ -2119,7 +2132,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * release_thread_qmcsampler(&R, shi->thread, qsa); } -static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, float *shadfac, Isect *isec) +static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, int lampvec, float *shadfac, Isect *isec) { /* area soft shadow */ float *jitlamp; @@ -2162,10 +2175,20 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa /* set start and vec */ VECCOPY(isec->start, shi->co); - isec->vec[0] = vec[0]+lampco[0]-shi->co[0]; - isec->vec[1] = vec[1]+lampco[1]-shi->co[1]; - isec->vec[2] = vec[2]+lampco[2]-shi->co[2]; - isec->labda = 1.0f; + if(lampvec) + { + isec->vec[0] = vec[0]+lampco[0]; + isec->vec[1] = vec[1]+lampco[1]; + isec->vec[2] = vec[2]+lampco[2]; + isec->labda = RE_RAYTRACE_MAXDIST; + } + else + { + isec->vec[0] = vec[0]+lampco[0]-shi->co[0]; + isec->vec[1] = vec[1]+lampco[1]-shi->co[1]; + isec->vec[2] = vec[2]+lampco[2]-shi->co[2]; + isec->labda = 1.0f; + } isec->skip = RE_SKIP_VLR_NEIGHBOUR; if(isec->mode==RE_RAY_SHADOW_TRA) { @@ -2204,6 +2227,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) { Isect isec; float lampco[3]; + int lampvec; /* indicates if lampco is a vector lamp */ /* setup isec */ if(shi->mat->mode & MA_SHADOW_TRA) isec.mode= RE_RAY_SHADOW_TRA; @@ -2223,17 +2247,19 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) } if(lar->type==LA_SUN || lar->type==LA_HEMI) { - lampco[0]= shi->co[0] - RE_RAYTRACE_MAXDIST*lar->vec[0]; - lampco[1]= shi->co[1] - RE_RAYTRACE_MAXDIST*lar->vec[1]; - lampco[2]= shi->co[2] - RE_RAYTRACE_MAXDIST*lar->vec[2]; + lampco[0]= -lar->vec[0]; + lampco[1]= -lar->vec[1]; + lampco[2]= -lar->vec[2]; + lampvec = 1; } else { VECCOPY(lampco, lar->co); + lampvec = 0; } if (ELEM(lar->ray_samp_method, LA_SAMP_HALTON, LA_SAMP_HAMMERSLEY)) { - ray_shadow_qmc(shi, lar, lampco, shadfac, &isec); + ray_shadow_qmc(shi, lar, lampco, lampvec, shadfac, &isec); } else { if(lar->ray_totsamp<2) { @@ -2245,8 +2271,16 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) /* set up isec vec */ VECCOPY(isec.start, shi->co); - VECSUB(isec.vec, lampco, isec.start); - isec.labda = 1.0f; + if(lampvec) + { + VECCOPY(isec.vec, lampco); + isec.labda = RE_RAYTRACE_MAXDIST; + } + else + { + VECSUB(isec.vec, lampco, isec.start); + isec.labda = 1.0f; + } if(isec.mode==RE_RAY_SHADOW_TRA) { /* isec.col is like shadfac, so defines amount of light (0.0 is full shadow) */ @@ -2260,7 +2294,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) shadfac[3]= 0.0f; } else { - ray_shadow_jitter(shi, lar, lampco, shadfac, &isec); + ray_shadow_jitter(shi, lar, lampco, lampvec, shadfac, &isec); } } From 165593931ff325fa1fbdbad61537b42b5532b3cd Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 26 Jun 2009 02:11:08 +0000 Subject: [PATCH 018/138] *another blackdots fixed - had forgoted to enable skip-neighbour faces on ao. --- source/blender/render/intern/source/rayshade.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index be7b2665bdb..320b4cb601b 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -1662,6 +1662,7 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) isec.orig.ob = shi->obi; isec.orig.face = shi->vlr; + isec.skip = RE_SKIP_VLR_NEIGHBOUR; isec.hit.ob = 0; isec.hit.face = 0; @@ -1794,6 +1795,7 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) isec.orig.ob = shi->obi; isec.orig.face = shi->vlr; + isec.skip = RE_SKIP_VLR_NEIGHBOUR; isec.hit.ob = 0; isec.hit.face = 0; @@ -2018,8 +2020,6 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, int lam if (lar->type == LA_LOCAL) { float ru[3], rv[3], v[3], s[3]; - assert(lampvec == 0); - /* calc tangent plane vectors */ v[0] = co[0] - lampco[0]; v[1] = co[1] - lampco[1]; @@ -2038,7 +2038,6 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, int lam VECCOPY(samp3d, s); } else { - assert(lampvec); /* sampling, returns quasi-random vector in [sizex,sizey]^2 plane */ QMC_sampleRect(samp3d, qsa, shi->thread, samples, lar->area_size, lar->area_sizey); From f5f6850f23d594582c6438d04296ab84ef973521 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 29 Jun 2009 19:48:11 +0000 Subject: [PATCH 019/138] *make type of acceleration structure changeable at runtime *added some counter code (test/hits) for primitives and raycasts --- release/ui/buttons_scene.py | 1 + source/blender/makesrna/intern/rna_scene.c | 13 ++++++ .../render/extern/include/RE_raytrace.h | 36 +++++++++++++++- .../blender/render/intern/source/rayobject.c | 42 ++++++++++++++----- .../blender/render/intern/source/rayshade.c | 22 ++++++---- 5 files changed, 94 insertions(+), 20 deletions(-) diff --git a/release/ui/buttons_scene.py b/release/ui/buttons_scene.py index df172ea8298..25ff12de306 100644 --- a/release/ui/buttons_scene.py +++ b/release/ui/buttons_scene.py @@ -25,6 +25,7 @@ class RENDER_PT_shading(RenderButtonsPanel): col.itemR(rd, "render_raytracing", text="Ray Tracing") colsub = col.column() colsub.active = rd.render_raytracing + colsub.itemR(rd, "raytrace_structure", text="Structure") colsub.itemR(rd, "octree_resolution", text="Octree") col.itemR(rd, "dither_intensity", text="Dither", slider=True) diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 1365ab75fc7..662327439b9 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -199,6 +199,13 @@ void rna_def_scene_render_data(BlenderRNA *brna) {256, "OCTREE_RES_256", 0, "256", ""}, {512, "OCTREE_RES_512", 0, "512", ""}, {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem raytrace_structure_items[] = { + {R_RAYSTRUCTURE_HIER_BVH_BVH, "{R_RAYSTRUCTURE_HIER_BVH_BVH", 0, "BVH of BVH's", "Create a BVH of objects (each object has it own BVH)"}, + {R_RAYSTRUCTURE_HIER_BVH_OCTREE, "{R_RAYSTRUCTURE_HIER_BVH_OCTREE", 0, "BVH of octree", "Create a BVH of objects (each object has it own octree)"}, + {R_RAYSTRUCTURE_SINGLE_BVH, "{R_RAYSTRUCTURE_SINGLE_BVH", 0, "Single BVH", "BVH of all primitives (no instance support)"}, + {R_RAYSTRUCTURE_SINGLE_OCTREE, "{R_RAYSTRUCTURE_SINGLE_OCTREE", 0, "Octree", "Octree of all primitives (no instance support)"}, + {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem fixed_oversample_items[] = { {5, "OVERSAMPLE_5", 0, "5", ""}, @@ -594,6 +601,12 @@ void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_enum_items(prop, octree_resolution_items); RNA_def_property_ui_text(prop, "Octree Resolution", "Resolution of raytrace accelerator. Use higher resolutions for larger scenes."); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + + prop= RNA_def_property(srna, "raytrace_structure", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "raystructure"); + RNA_def_property_enum_items(prop, raytrace_structure_items); + RNA_def_property_ui_text(prop, "Raytrace Acceleration Structure", "Type of raytrace accelerator structure."); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); prop= RNA_def_property(srna, "antialiasing", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_OSA); diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index db3dc50c843..b1d8abef766 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -31,10 +31,12 @@ #ifndef RE_RAYTRACE_H #define RE_RAYTRACE_H +#define RE_RAY_COUNTER /* Internals about raycasting structures can be found on intern/raytree.h */ typedef struct RayObject RayObject; typedef struct Isect Isect; +typedef struct RayCounter RayCounter; struct DerivedMesh; struct Mesh; @@ -80,10 +82,42 @@ struct Isect int skip; /* RE_SKIP_CULLFACE */ float col[4]; /* RGBA for shadow_tra */ - + void *userdata; + +#ifdef RE_RAY_COUNTER + RayCounter *count; +#endif + }; +#ifdef RE_RAYCOUNTER + +struct RayCounter +{ + + struct + { + unsigned long long test, hit; + + } intersect_rayface, raycast; + + unsigned long long rayshadow_last_hit_optimization; +}; + +void RE_RC_INIT (RayCounter *rc); +void RE_RC_MERGE(RayCounter *rc, RayCounter *tmp); +#define RE_RC_COUNT(var) (var)++ + +#else + +#define RE_RC_INIT(rc) +#define RE_RC_MERGE(dest,src) +#define RE_RC_COUNT(var) + +#endif + + /* ray types */ #define RE_RAY_SHADOW 0 #define RE_RAY_MIRROR 1 diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index 4d0606e2067..ef224dc7d21 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -128,6 +128,7 @@ static int intersect_rayface(RayFace *face, Isect *is) if(is->orig.ob == face->ob && is->orig.face == face->face) return 0; + RE_RC_COUNT(is->count->intersect_rayface.test); VECCOPY(co1, face->v1); VECCOPY(co2, face->v2); @@ -246,6 +247,8 @@ static int intersect_rayface(RayFace *face, Isect *is) } #endif + RE_RC_COUNT(is->count->intersect_rayface.hit); + is->isect= ok; // wich half of the quad is->labda= labda; is->u= u; is->v= v; @@ -261,24 +264,27 @@ static int intersect_rayface(RayFace *face, Isect *is) int RE_rayobject_raycast(RayObject *r, Isect *i) { - static int casted_rays = 0; - - if(casted_rays++ % (1<<20) == 0) - printf("Casting %d rays\n", casted_rays); + RE_RC_COUNT(i->count->raycast.test); -/* - i->labda = 10000.0; - i->vec[0] *= i->labda; - i->vec[1] *= i->labda; - i->vec[2] *= i->labda; - i->labda = 1.0f; -*/ i->dist = VecLength(i->vec); if(i->mode==RE_RAY_SHADOW && i->last_hit && RE_rayobject_intersect(i->last_hit, i)) + { + RE_RC_COUNT(i->count->raycast.hit); + RE_RC_COUNT(i->count->rayshadow_last_hit_optimization ); return 1; + } +#ifdef RE_RAYCOUNTER + if(RE_rayobject_intersect(r, i)) + { + RE_RC_COUNT(i->count->raycast.hit); + return 1; + } + return 0; +#else return RE_rayobject_intersect(r, i); +#endif } int RE_rayobject_intersect(RayObject *r, Isect *i) @@ -329,3 +335,17 @@ void RE_rayobject_merge_bb(RayObject *r, float *min, float *max) } } +#ifdef RE_RAYCOUNTER +void RE_merge_raycounter(RayCounter *dest, RayCounter *tmp) +{ + int i; + for(i=0; i<3; i++) dest->casted[i] += tmp->casted[i]; + for(i=0; i<3; i++) dest->hit [i] += tmp->hit [i]; + + dest->test_primitives += tmp->test_primitives; + dest->hit_primitives += tmp->hit_primitives; + + dest->test_bb += tmp->test_bb; + dest->hit_bb += tmp->hit_bb; +} +#endif \ No newline at end of file diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 320b4cb601b..66afb7510a4 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -175,10 +175,13 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) assert( faces > 0 ); //Create Ray cast accelaration structure - + //TODO dynamic ocres -// raytree = obr->raytree = RE_rayobject_octree_create( re->r.ocres, faces ); - raytree = obr->raytree = RE_rayobject_bvh_create( faces ); + if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_OCTREE) + raytree = obr->raytree = RE_rayobject_octree_create( re->r.ocres, faces ); + else //if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_BVH) + raytree = obr->raytree = RE_rayobject_bvh_create( faces ); + face = obr->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "ObjectRen faces"); obr->rayobi = obi; @@ -284,8 +287,11 @@ static void makeraytree_single(Render *re) } //Create raytree -// raytree = re->raytree = RE_rayobject_octree_create(re->r.ocres, faces); - raytree = re->raytree = RE_rayobject_bvh_create(faces); + if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_OCTREE) + raytree = re->raytree = RE_rayobject_octree_create( re->r.ocres, faces ); + else //if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_BVH) + raytree = re->raytree = RE_rayobject_bvh_create( faces ); + face = re->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces"); for(obi=re->instancetable.first; obi; obi=obi->next) @@ -313,10 +319,10 @@ static void makeraytree_single(Render *re) void makeraytree(Render *re) { - if(1) - makeraytree_hier(re); - else + if(ELEM(re->r.raystructure, R_RAYSTRUCTURE_SINGLE_BVH, R_RAYSTRUCTURE_SINGLE_OCTREE)) makeraytree_single(re); + else + makeraytree_hier(re); } From 1136656bbadc92936fa497e2ddd99bae1b982982 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 29 Jun 2009 20:15:59 +0000 Subject: [PATCH 020/138] *forgot this file --- source/blender/makesdna/DNA_scene_types.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 7391201776e..e8279604100 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -232,6 +232,8 @@ typedef struct RenderData { /* render engine, octree resolution */ short renderer, ocres; + short raystructure; + short pad4[3]; /** * What to do with the sky/background. Picks sky/premul/key @@ -660,6 +662,12 @@ typedef struct Scene { #define R_INTERN 0 #define R_YAFRAY 1 +/* raytrace structure */ +#define R_RAYSTRUCTURE_HIER_BVH_BVH 0 +#define R_RAYSTRUCTURE_HIER_BVH_OCTREE 1 +#define R_RAYSTRUCTURE_SINGLE_OCTREE 2 +#define R_RAYSTRUCTURE_SINGLE_BVH 3 + /* scemode (int now) */ #define R_DOSEQ 0x0001 #define R_BG_RENDER 0x0002 From e0cfafa6292cbcec5d49817583204a418308aac7 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 30 Jun 2009 01:17:50 +0000 Subject: [PATCH 021/138] Measure build time... *as expected it's a lot faster on BVH --- .../blender/render/intern/include/rayobject.h | 27 +++++++++++++++++++ .../blender/render/intern/source/rayshade.c | 4 +-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index 064341ae18b..53d96d6331f 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -120,4 +120,31 @@ int RE_rayobject_intersect(RayObject *r, Isect *i); #define ISECT_EPSILON ((float)FLT_EPSILON) + + +#if !defined(_WIN32) + +#include +#include +#include + +#define BENCH(a,name) \ + do { \ + double _t1, _t2; \ + struct timeval _tstart, _tend; \ + clock_t _clock_init = clock(); \ + gettimeofday ( &_tstart, NULL); \ + (a); \ + gettimeofday ( &_tend, NULL); \ + _t1 = ( double ) _tstart.tv_sec + ( double ) _tstart.tv_usec/ ( 1000*1000 ); \ + _t2 = ( double ) _tend.tv_sec + ( double ) _tend.tv_usec/ ( 1000*1000 ); \ + printf("BENCH:%s: %fs (real) %fs (cpu)\n", #name, _t2-_t1, (float)(clock()-_clock_init)/CLOCKS_PER_SEC);\ + } while(0) +#else + +#define BENCH(a) (a) + +#endif + + #endif diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 66afb7510a4..3fe3ac8690b 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -320,9 +320,9 @@ static void makeraytree_single(Render *re) void makeraytree(Render *re) { if(ELEM(re->r.raystructure, R_RAYSTRUCTURE_SINGLE_BVH, R_RAYSTRUCTURE_SINGLE_OCTREE)) - makeraytree_single(re); + BENCH(makeraytree_single(re), tree_build); else - makeraytree_hier(re); + BENCH(makeraytree_hier(re), tree_build); } From 021e0cc53f5169a92e06eafa321bc53b305f002f Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 30 Jun 2009 14:05:33 +0000 Subject: [PATCH 022/138] *reserved RayObject align offset 0 for private usage inside each structure point is that other structures like trees can then distiguish between other nodes or rayobject primitives withouth needing any other variable. (Note yet used but will reduce memory by a nice factor (linear to the number of primitives)) --- .../blender/render/intern/include/rayobject.h | 21 ++++++++++++------- .../blender/render/intern/source/rayobject.c | 16 +++++++------- .../render/intern/source/rayobject_bvh.c | 2 +- .../render/intern/source/rayobject_instance.c | 2 +- .../render/intern/source/rayobject_mesh.c | 2 +- .../render/intern/source/rayobject_octree.c | 4 ++-- .../blender/render/intern/source/rayshade.c | 7 +++++-- 7 files changed, 32 insertions(+), 22 deletions(-) diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index 53d96d6331f..d516c122bcc 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -58,13 +58,15 @@ only 2 are used: addr&2 - type of object - 0 RayFace - 1 RayObject (generic with API callbacks) - 2 unused + 0 Self (reserved for each structure) + 1 RayFace + 2 RayObject (generic with API callbacks) 3 unused - 0 was choosed to RayFace because thats the one where speed will be needed. - + 0 means it's reserved and has it own meaning inside each ray acceleration structure + (this way each structure can use the allign offset to determine if a node represents a + RayObject primitive, which can be used to save memory) + You actually don't need to care about this if you are only using the API described on RE_raytrace.h */ @@ -101,10 +103,13 @@ typedef struct RayObjectAPI } RayObjectAPI; //TODO use intptr_t -#define RayObject_align(o) ((RayObject*)(((int)o)&(~3))) -#define RayObject_unalign(o) ((RayObject*)(((int)o)|1)) -#define RayObject_isFace(o) ((((int)o)&3) == 0) +#define RayObject_align(o) ((RayObject*)(((int)o)&(~3))) +#define RayObject_unalignRayFace(o) ((RayObject*)(((int)o)|1)) +#define RayObject_unalignRayAPI(o) ((RayObject*)(((int)o)|2)) + #define RayObject_isAligned(o) ((((int)o)&3) == 0) +#define RayObject_isRayFace(o) ((((int)o)&3) == 1) +#define RayObject_isRayAPI(o) ((((int)o)&3) == 2) /* * Extend min/max coords so that the rayobject is inside them diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index ef224dc7d21..3af2969b67e 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -255,7 +255,7 @@ static int intersect_rayface(RayFace *face, Isect *is) is->hit.ob = face->ob; is->hit.face = face->face; - is->last_hit = (RayObject*)face; + is->last_hit = (RayObject*) RayObject_unalignRayFace(face); return 1; } @@ -289,15 +289,16 @@ int RE_rayobject_raycast(RayObject *r, Isect *i) int RE_rayobject_intersect(RayObject *r, Isect *i) { - if(RayObject_isFace(r)) + if(RayObject_isRayFace(r)) { - return intersect_rayface( (RayFace*) r, i); + return intersect_rayface( (RayFace*) RayObject_align(r), i); } - else + else if(RayObject_isRayAPI(r)) { r = RayObject_align( r ); return r->api->raycast( r, i ); } + else assert(0); } void RE_rayobject_add(RayObject *r, RayObject *o) @@ -320,19 +321,20 @@ void RE_rayobject_free(RayObject *r) void RE_rayobject_merge_bb(RayObject *r, float *min, float *max) { - if(RayObject_isFace(r)) + if(RayObject_isRayFace(r)) { - RayFace *face = (RayFace*)r; + RayFace *face = (RayFace*) RayObject_align(r); DO_MINMAX( face->v1, min, max ); DO_MINMAX( face->v2, min, max ); DO_MINMAX( face->v3, min, max ); if(face->v4) DO_MINMAX( face->v4, min, max ); } - else + else if(RayObject_isRayAPI(r)) { r = RayObject_align( r ); r->api->bb( r, min, max ); } + else assert(0); } #ifdef RE_RAYCOUNTER diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index c5e0cca808c..54fbc5ba0be 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -69,7 +69,7 @@ RayObject *RE_rayobject_bvh_create(int size) obj->bvh = BLI_bvhtree_new(size, FLT_EPSILON, 4, 6); INIT_MINMAX(obj->bb[0], obj->bb[1]); - return RayObject_unalign((RayObject*) obj); + return RayObject_unalignRayAPI((RayObject*) obj); } static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) diff --git a/source/blender/render/intern/source/rayobject_instance.c b/source/blender/render/intern/source/rayobject_instance.c index a5024e97450..4a67e8108cb 100644 --- a/source/blender/render/intern/source/rayobject_instance.c +++ b/source/blender/render/intern/source/rayobject_instance.c @@ -74,7 +74,7 @@ RayObject *RE_rayobject_instance_create(RayObject *target, float transform[][4], Mat4CpyMat4(obj->target2global, transform); Mat4Invert(obj->global2target, obj->target2global); - return RayObject_unalign((RayObject*) obj); + return RayObject_unalignRayAPI((RayObject*) obj); } static int RayObject_instance_intersect(RayObject *o, Isect *isec) diff --git a/source/blender/render/intern/source/rayobject_mesh.c b/source/blender/render/intern/source/rayobject_mesh.c index eee7231aef4..538c245988d 100644 --- a/source/blender/render/intern/source/rayobject_mesh.c +++ b/source/blender/render/intern/source/rayobject_mesh.c @@ -128,5 +128,5 @@ RayObject* RE_rayobject_mesh_create(Mesh *mesh, void *ob) face->face = (void*)i; } - return RayObject_unalign((RayObject*) rm); + return RayObject_unalignRayAPI((RayObject*) rm); } diff --git a/source/blender/render/intern/source/rayobject_octree.c b/source/blender/render/intern/source/rayobject_octree.c index b715695dc10..b7850c05104 100644 --- a/source/blender/render/intern/source/rayobject_octree.c +++ b/source/blender/render/intern/source/rayobject_octree.c @@ -461,7 +461,7 @@ RayObject *RE_rayobject_octree_create(int ocres, int size) oc->ro_nodes_used = 0; - return RayObject_unalign((RayObject*) oc); + return RayObject_unalignRayAPI((RayObject*) oc); } @@ -631,7 +631,7 @@ static void RayObject_octree_done(RayObject *tree) for(c=0; cro_nodes_used; c++) { - assert( RayObject_isFace(oc->ro_nodes[c]) ); + assert( RayObject_isRayFace(oc->ro_nodes[c]) ); octree_fill_rayface(oc, (RayFace*)oc->ro_nodes[c]); } diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 3fe3ac8690b..975de3a5da3 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -198,7 +198,9 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) face->ob = obi; face->face = vlr; - RE_rayobject_add( raytree, (RayObject*)face++ ); + RE_rayobject_add( raytree, RayObject_unalignRayFace(face) ); + + face++; } } RE_rayobject_done( raytree ); @@ -311,7 +313,8 @@ static void makeraytree_single(Render *re) face->ob = obi; face->face = vlr; - RE_rayobject_add( raytree, (RayObject*)face++ ); + RE_rayobject_add( raytree, RayObject_unalignRayFace(face) ); + face++; } } RE_rayobject_done( raytree ); From 1deba75110aebda447beb79a8f07dae35f5bcc65 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 30 Jun 2009 22:07:42 +0000 Subject: [PATCH 023/138] *Added initial code of rayobject_rtbuild An helper class to build trees --- .../render/extern/include/RE_raytrace.h | 9 +- .../render/intern/include/rayobject_rtbuild.h | 84 +++++++ .../{rayobject_bvh.c => rayobject_blibvh.c} | 32 +-- .../render/intern/source/rayobject_rtbuild.c | 222 ++++++++++++++++++ .../blender/render/intern/source/rayshade.c | 6 +- 5 files changed, 332 insertions(+), 21 deletions(-) create mode 100644 source/blender/render/intern/include/rayobject_rtbuild.h rename source/blender/render/intern/source/{rayobject_bvh.c => rayobject_blibvh.c} (78%) create mode 100644 source/blender/render/intern/source/rayobject_rtbuild.c diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index b1d8abef766..0f92f54b396 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -47,7 +47,7 @@ void RE_rayobject_free(RayObject *r); /* RayObject constructors */ RayObject* RE_rayobject_octree_create(int ocres, int size); -RayObject* RE_rayobject_bvh_create(int size); +RayObject* RE_rayobject_blibvh_create(int size); RayObject* RE_rayobject_instance_create(RayObject *target, float transform[][4], void *ob, void *target_ob); //RayObject* RayObject_derivedmesh_create(struct DerivedMesh*, void *ob); @@ -59,8 +59,13 @@ struct Isect float start[3]; float vec[3]; float labda; + + /* length of vec, configured by RE_rayobject_raycast */ + int bv_index[6]; + float idot_axis[3]; + float dist; - float dist; /* length of vec, configured by RE_rayobject_raycast */ + /* float end[3]; - not used */ float u, v; diff --git a/source/blender/render/intern/include/rayobject_rtbuild.h b/source/blender/render/intern/include/rayobject_rtbuild.h new file mode 100644 index 00000000000..b1458a571dd --- /dev/null +++ b/source/blender/render/intern/include/rayobject_rtbuild.h @@ -0,0 +1,84 @@ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef RE_RAYOBJECT_RTBUILD_H +#define RE_RAYOBJECT_RTBUILD_H + +#include "rayobject.h" + +/* + * Ray Tree Builder + * this structs helps building any type of tree + * it contains several methods to organiza/split nodes + * allowing to create a given tree on the fly. + * + * Idea is that other trees BVH, BIH can use this code to + * generate with simple calls, and then convert to the theirs + * specific structure on the fly. + */ +#define MAX_CHILDS 32 +typedef struct RTBuilder +{ + /* list to all primitives in this tree */ + RayObject **begin, **end; + + /* axis used (if any) on the split method */ + int split_axis; + + /* links to child partitions calculated during splitting */ + RayObject **child[MAX_CHILDS+1]; + +} RTBuilder; + +/* used during creation */ +RTBuilder* rtbuild_create(int size); +void rtbuild_free(RTBuilder *b); +void rtbuild_add(RTBuilder *b, RayObject *o); +int rtbuild_size(RTBuilder *b); + +/* used during tree reorganization */ +RTBuilder* rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp); +void rtbuild_mean_split(RTBuilder *b, int nchilds, int axis); +void rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds); + +/* +static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *b) +{ + int i; + int nc = rtbuild_mean_split_largest_axis(b, BVH_NCHILDS); + RTBuilder tmp; + + BVHNode *bvh = tree->next_node++; + + bvh->split_axis = tmp->split_axis; + for(i=0; ichild[i] = bvh_rearrange( rtbuild_get_child(b, i, &tmp) ); +} + */ + +#endif diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_blibvh.c similarity index 78% rename from source/blender/render/intern/source/rayobject_bvh.c rename to source/blender/render/intern/source/rayobject_blibvh.c index 54fbc5ba0be..41da4679b6a 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_blibvh.c @@ -36,19 +36,19 @@ #include "render_types.h" #include "rayobject.h" -static int RayObject_bvh_intersect(RayObject *o, Isect *isec); -static void RayObject_bvh_add(RayObject *o, RayObject *ob); -static void RayObject_bvh_done(RayObject *o); -static void RayObject_bvh_free(RayObject *o); -static void RayObject_bvh_bb(RayObject *o, float *min, float *max); +static int RayObject_blibvh_intersect(RayObject *o, Isect *isec); +static void RayObject_blibvh_add(RayObject *o, RayObject *ob); +static void RayObject_blibvh_done(RayObject *o); +static void RayObject_blibvh_free(RayObject *o); +static void RayObject_blibvh_bb(RayObject *o, float *min, float *max); static RayObjectAPI bvh_api = { - RayObject_bvh_intersect, - RayObject_bvh_add, - RayObject_bvh_done, - RayObject_bvh_free, - RayObject_bvh_bb + RayObject_blibvh_intersect, + RayObject_blibvh_add, + RayObject_blibvh_done, + RayObject_blibvh_free, + RayObject_blibvh_bb }; typedef struct BVHObject @@ -60,7 +60,7 @@ typedef struct BVHObject } BVHObject; -RayObject *RE_rayobject_bvh_create(int size) +RayObject *RE_rayobject_blibvh_create(int size) { BVHObject *obj= (BVHObject*)MEM_callocN(sizeof(BVHObject), "BVHObject"); assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ @@ -88,7 +88,7 @@ static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTr } } -static int RayObject_bvh_intersect(RayObject *o, Isect *isec) +static int RayObject_blibvh_intersect(RayObject *o, Isect *isec) { BVHObject *obj = (BVHObject*)o; BVHTreeRayHit hit; @@ -103,7 +103,7 @@ static int RayObject_bvh_intersect(RayObject *o, Isect *isec) return BLI_bvhtree_ray_cast(obj->bvh, isec->start, dir, 0.0, &hit, bvh_callback, isec); } -static void RayObject_bvh_add(RayObject *o, RayObject *ob) +static void RayObject_blibvh_add(RayObject *o, RayObject *ob) { BVHObject *obj = (BVHObject*)o; float min_max[6]; @@ -116,13 +116,13 @@ static void RayObject_bvh_add(RayObject *o, RayObject *ob) BLI_bvhtree_insert(obj->bvh, (int)ob, min_max, 2 ); } -static void RayObject_bvh_done(RayObject *o) +static void RayObject_blibvh_done(RayObject *o) { BVHObject *obj = (BVHObject*)o; BLI_bvhtree_balance(obj->bvh); } -static void RayObject_bvh_free(RayObject *o) +static void RayObject_blibvh_free(RayObject *o) { BVHObject *obj = (BVHObject*)o; @@ -132,7 +132,7 @@ static void RayObject_bvh_free(RayObject *o) MEM_freeN(obj); } -static void RayObject_bvh_bb(RayObject *o, float *min, float *max) +static void RayObject_blibvh_bb(RayObject *o, float *min, float *max) { BVHObject *obj = (BVHObject*)o; DO_MINMAX( obj->bb[0], min, max ); diff --git a/source/blender/render/intern/source/rayobject_rtbuild.c b/source/blender/render/intern/source/rayobject_rtbuild.c new file mode 100644 index 00000000000..b89729e2b45 --- /dev/null +++ b/source/blender/render/intern/source/rayobject_rtbuild.c @@ -0,0 +1,222 @@ +#include "rayobject_rtbuild.h" +#include "MEM_guardedalloc.h" +#include "BLI_arithb.h" +#include "BKE_utildefines.h" + +static int partition_nth_element(RTBuilder *b, int _begin, int _end, int n); +static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis); + + +static void RayObject_rtbuild_init(RTBuilder *b, RayObject **begin, RayObject **end) +{ + int i; + + b->begin = begin; + b->end = end; + b->split_axis = 0; + + for(i=0; ichild[i] = 0; +} + +RTBuilder* RayObject_rtbuild_create(int size) +{ + RTBuilder *builder = (RTBuilder*) MEM_mallocN( sizeof(RTBuilder), "RTBuilder" ); + RayObject **memblock= (RayObject**)MEM_mallocN( sizeof(RayObject*),"RTBuilder.objects"); + RayObject_rtbuild_init(builder, memblock, memblock); + return builder; +} + +void RayObject_rtbuild_free(RTBuilder *b) +{ + MEM_freeN(b->begin); + MEM_freeN(b); +} + +void RayObject_rtbuild_add(RTBuilder *b, RayObject *o) +{ + *(b->end++) = o; +} + +RTBuilder* rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp) +{ + RayObject_rtbuild_init( tmp, b->child[child], b->child[child+1] ); + return tmp; +} + +int RayObject_rtbuild_size(RTBuilder *b) +{ + return b->end - b->begin; +} + +/* Split methods */ +static void merge_bb(RTBuilder *b, float *min, float *max) +{ + RayObject **index = b->begin; + + for(; index != b->end; index++) + RE_rayobject_merge_bb(*index, min, max); +} + +static int calc_largest_axis(RTBuilder *b) +{ + float min[3], max[3], sub[3]; + + INIT_MINMAX(min, max); + merge_bb( b, min, max); + + VECSUB(sub, max, min); + if(sub[0] > sub[1]) + { + if(sub[0] > sub[2]) + return 0; + else + return 2; + } + else + { + if(sub[1] > sub[2]) + return 1; + else + return 2; + } +} + + +//Unballanced mean +//TODO better balance nodes +//TODO suport for variable number of partitions (its hardcoded in 2) +void rtbuild_mean_split(RTBuilder *b, int nchilds, int axis) +{ + int nth[3] = {0, (b->end - b->begin)/2, b->end-b->begin}; + split_leafs(b, nth, 2, axis); +} + + +void rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds) +{ + int axis = calc_largest_axis(b); + rtbuild_mean_split(b, nchilds, axis); +} + + +/* + * Helper code + * PARTITION code / used on mean-split + * basicly this a std::nth_element (like on C++ STL algorithm) + */ +static void sort_swap(RTBuilder *b, int i, int j) +{ + SWAP(RayObject*, b->begin[i], b->begin[j]); +} + +static int sort_get_value(RTBuilder *b, int i) +{ + float min[3], max[3]; + RE_rayobject_merge_bb(b->begin[i], min, max); + return max[i]; +} + +static int medianof3(RTBuilder *d, int a, int b, int c) +{ + float fa = sort_get_value( d, a ); + float fb = sort_get_value( d, b ); + float fc = sort_get_value( d, c ); + + if(fb < fa) + { + if(fc < fb) + return b; + else + { + if(fc < fa) + return c; + else + return a; + } + } + else + { + if(fc > fb) + return b; + else + { + if(fc > fa) + return c; + else + return a; + } + } +} + +static void insertionsort(RTBuilder *b, int lo, int hi) +{ + int i; + for(i=lo; ibegin[i]; + float tv= sort_get_value(b, i); + int j=i; + + while( j != lo && tv < sort_get_value(b, j-1)) + { + b->begin[j] = b->begin[j-1]; + j--; + } + b->begin[j] = t; + } +} + +static int partition(RTBuilder *b, int lo, int mid, int hi) +{ + float x = sort_get_value( b, mid ); + + int i=lo, j=hi; + while (1) + { + while (sort_get_value(b,i) < x) i++; + j--; + while (x < sort_get_value(b,j)) j--; + if(!(i < j)) + return i; + + sort_swap(b, i, j); + i++; + } +} + +// +// PARTITION code / used on mean-split +// basicly this is an adapted std::nth_element (C++ STL ) +// +// after a call to this function you can expect one of: +// every node to left of a[n] are smaller or equal to it +// every node to the right of a[n] are greater or equal to it +static int partition_nth_element(RTBuilder *b, int _begin, int _end, int n) +{ + int begin = _begin, end = _end, cut; + while(end-begin > 3) + { + cut = partition(b, begin, medianof3(b, begin, begin+(end-begin)/2, end-1), end); + if(cut <= n) + begin = cut; + else + end = cut; + } + insertionsort(b, begin, end); + + return n; +} + +static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis) +{ + int i; + b->split_axis = split_axis; + for(i=0; i < partitions-1; i++) + { + if(nth[i] >= nth[partitions]) + break; + + partition_nth_element(b, nth[i], nth[i+1], nth[partitions] ); + } +} diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 975de3a5da3..75c93fc1c80 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -180,7 +180,7 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_OCTREE) raytree = obr->raytree = RE_rayobject_octree_create( re->r.ocres, faces ); else //if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_BVH) - raytree = obr->raytree = RE_rayobject_bvh_create( faces ); + raytree = obr->raytree = RE_rayobject_blibvh_create( faces ); face = obr->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "ObjectRen faces"); obr->rayobi = obi; @@ -240,7 +240,7 @@ static void makeraytree_hier(Render *re) num_objects++; //Create raytree - re->raytree = RE_rayobject_bvh_create( num_objects ); + re->raytree = RE_rayobject_blibvh_create( num_objects ); for(obi=re->instancetable.first; obi; obi=obi->next) if(is_raytraceable(re, obi)) @@ -292,7 +292,7 @@ static void makeraytree_single(Render *re) if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_OCTREE) raytree = re->raytree = RE_rayobject_octree_create( re->r.ocres, faces ); else //if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_BVH) - raytree = re->raytree = RE_rayobject_bvh_create( faces ); + raytree = re->raytree = RE_rayobject_blibvh_create( faces ); face = re->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces"); From 91226e6807435c6e0163865fea4cb45e22b14e16 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 1 Jul 2009 11:27:43 +0000 Subject: [PATCH 024/138] *Added rayobject_bvh A bvh structure to use on the raytracer --- .../render/extern/include/RE_raytrace.h | 8 +- .../blender/render/intern/include/rayobject.h | 6 + .../render/intern/include/rayobject_rtbuild.h | 23 +- .../blender/render/intern/source/rayobject.c | 61 +++++- .../render/intern/source/rayobject_bvh.c | 200 ++++++++++++++++++ .../render/intern/source/rayobject_rtbuild.c | 49 +++-- .../blender/render/intern/source/rayshade.c | 6 +- 7 files changed, 302 insertions(+), 51 deletions(-) create mode 100644 source/blender/render/intern/source/rayobject_bvh.c diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index 0f92f54b396..e1d03c996a4 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -46,12 +46,14 @@ void RE_rayobject_done(RayObject *r); void RE_rayobject_free(RayObject *r); /* RayObject constructors */ + RayObject* RE_rayobject_octree_create(int ocres, int size); -RayObject* RE_rayobject_blibvh_create(int size); RayObject* RE_rayobject_instance_create(RayObject *target, float transform[][4], void *ob, void *target_ob); -//RayObject* RayObject_derivedmesh_create(struct DerivedMesh*, void *ob); -RayObject* RE_rayobject_mesh_create(struct Mesh*, void *ob); +#define RE_rayobject_tree_create RE_rayobject_bvh_create +RayObject* RE_rayobject_blibvh_create(int size); /* BLI_kdopbvh.c */ +RayObject* RE_rayobject_bvh_create(int size); /* rayobject_bvh.c */ + /* Ray Intersection */ struct Isect diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index d516c122bcc..3b77341f229 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -123,6 +123,12 @@ void RE_rayobject_merge_bb(RayObject *ob, float *min, float *max); */ int RE_rayobject_intersect(RayObject *r, Isect *i); +/* + * Returns distance ray must travel to hit the given bounding box + * BB should be in format [2][3] + */ +float RE_rayobject_bb_intersect(const Isect *i, const float *bb); + #define ISECT_EPSILON ((float)FLT_EPSILON) diff --git a/source/blender/render/intern/include/rayobject_rtbuild.h b/source/blender/render/intern/include/rayobject_rtbuild.h index b1458a571dd..fbe3930149c 100644 --- a/source/blender/render/intern/include/rayobject_rtbuild.h +++ b/source/blender/render/intern/include/rayobject_rtbuild.h @@ -50,8 +50,8 @@ typedef struct RTBuilder /* axis used (if any) on the split method */ int split_axis; - /* links to child partitions calculated during splitting */ - RayObject **child[MAX_CHILDS+1]; + /* child partitions calculated during splitting */ + int child_offset[MAX_CHILDS+1]; } RTBuilder; @@ -63,22 +63,9 @@ int rtbuild_size(RTBuilder *b); /* used during tree reorganization */ RTBuilder* rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp); -void rtbuild_mean_split(RTBuilder *b, int nchilds, int axis); -void rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds); -/* -static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *b) -{ - int i; - int nc = rtbuild_mean_split_largest_axis(b, BVH_NCHILDS); - RTBuilder tmp; - - BVHNode *bvh = tree->next_node++; - - bvh->split_axis = tmp->split_axis; - for(i=0; ichild[i] = bvh_rearrange( rtbuild_get_child(b, i, &tmp) ); -} - */ +/* Calculates child partitions and returns number of efectively needed partitions */ +int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis); +int rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds); #endif diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index 3af2969b67e..7779c2aee82 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -36,6 +36,34 @@ #include "render_types.h" #include "rayobject.h" + +/* + * Determines the distance that the ray must travel to hit the bounding volume of the given node + * Based on Tactical Optimization of Ray/Box Intersection, by Graham Fyffe + * [http://tog.acm.org/resources/RTNews/html/rtnv21n1.html#art9] + */ +float RE_rayobject_bb_intersect(const Isect *isec, const float *bb) +{ + float dist; + + float t1x = (bb[isec->bv_index[0]] - isec->start[0]) * isec->idot_axis[0]; + float t2x = (bb[isec->bv_index[1]] - isec->start[0]) * isec->idot_axis[0]; + float t1y = (bb[isec->bv_index[2]] - isec->start[1]) * isec->idot_axis[1]; + float t2y = (bb[isec->bv_index[3]] - isec->start[1]) * isec->idot_axis[1]; + float t1z = (bb[isec->bv_index[4]] - isec->start[2]) * isec->idot_axis[2]; + float t2z = (bb[isec->bv_index[5]] - isec->start[2]) * isec->idot_axis[2]; + + if(t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) return FLT_MAX; + if(t2x < 0.0 || t2y < 0.0 || t2z < 0.0) return FLT_MAX; + if(t1x > isec->labda || t1y > isec->labda || t1z > isec->labda) return FLT_MAX; + + dist = t1x; + if (t1y > dist) dist = t1y; + if (t1z > dist) dist = t1z; + return dist; +} + + /* only for self-intersecting test with current render face (where ray left) */ static int intersection2(VlakRen *face, float r0, float r1, float r2, float rx1, float ry1, float rz1) { @@ -262,28 +290,43 @@ static int intersect_rayface(RayFace *face, Isect *is) return 0; } -int RE_rayobject_raycast(RayObject *r, Isect *i) +int RE_rayobject_raycast(RayObject *r, Isect *isec) { - RE_RC_COUNT(i->count->raycast.test); + int i; + RE_RC_COUNT(isec->count->raycast.test); - i->dist = VecLength(i->vec); + /* Setup vars used on raycast */ + isec->dist = VecLength(isec->vec); - if(i->mode==RE_RAY_SHADOW && i->last_hit && RE_rayobject_intersect(i->last_hit, i)) + for(i=0; i<3; i++) { - RE_RC_COUNT(i->count->raycast.hit); - RE_RC_COUNT(i->count->rayshadow_last_hit_optimization ); + isec->idot_axis[i] = 1.0f / isec->vec[i]; + + isec->bv_index[2*i] = isec->idot_axis[i] < 0.0 ? 1 : 0; + isec->bv_index[2*i+1] = 1 - isec->bv_index[2*i]; + + isec->bv_index[2*i] = i+3*isec->bv_index[2*i]; + isec->bv_index[2*i+1] = i+3*isec->bv_index[2*i+1]; + } + + + /* Last hit heuristic */ + if(isec->mode==RE_RAY_SHADOW && isec->last_hit && RE_rayobject_intersect(isec->last_hit, isec)) + { + RE_RC_COUNT(isec->count->raycast.hit); + RE_RC_COUNT(isec->count->rayshadow_last_hit_optimization ); return 1; } #ifdef RE_RAYCOUNTER - if(RE_rayobject_intersect(r, i)) + if(RE_rayobject_intersect(r, isec)) { - RE_RC_COUNT(i->count->raycast.hit); + RE_RC_COUNT(isec->count->raycast.hit); return 1; } return 0; #else - return RE_rayobject_intersect(r, i); + return RE_rayobject_intersect(r, isec); #endif } diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c new file mode 100644 index 00000000000..ea590ef83fd --- /dev/null +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -0,0 +1,200 @@ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#include + +#include "MEM_guardedalloc.h" +#include "BKE_utildefines.h" +#include "BLI_arithb.h" +#include "RE_raytrace.h" +#include "rayobject_rtbuild.h" +#include "rayobject.h" + +#define BVH_NCHILDS 2 +typedef struct BVHTree BVHTree; + +static int bvh_intersect(BVHTree *obj, Isect *isec); +static void bvh_add(BVHTree *o, RayObject *ob); +static void bvh_done(BVHTree *o); +static void bvh_free(BVHTree *o); +static void bvh_bb(BVHTree *o, float *min, float *max); + +static RayObjectAPI bvh_api = +{ + (RE_rayobject_raycast_callback) bvh_intersect, + (RE_rayobject_add_callback) bvh_add, + (RE_rayobject_done_callback) bvh_done, + (RE_rayobject_free_callback) bvh_free, + (RE_rayobject_merge_bb_callback)bvh_bb +}; + +typedef struct BVHNode BVHNode; +struct BVHNode +{ + BVHNode *child[BVH_NCHILDS]; + float bb[2][3]; +}; + +struct BVHTree +{ + RayObject rayobj; + + BVHNode *alloc, *next_node, *root; + RTBuilder *builder; + +}; + + +RayObject *RE_rayobject_bvh_create(int size) +{ + BVHTree *obj= (BVHTree*)MEM_callocN(sizeof(BVHTree), "BVHTree"); + assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ + + obj->rayobj.api = &bvh_api; + obj->builder = rtbuild_create( size ); + obj->root = NULL; + + return RayObject_unalignRayAPI((RayObject*) obj); +} + +static void bvh_free(BVHTree *obj) +{ + if(obj->builder) + rtbuild_free(obj->builder); + + if(obj->alloc) + MEM_freeN(obj->alloc); + + MEM_freeN(obj); +} + + +static void bvh_merge_bb(BVHNode *node, float *min, float *max) +{ + if(RayObject_isAligned(node)) + { + //TODO only half operations needed + DO_MINMAX(node->bb[0], min, max); + DO_MINMAX(node->bb[1], min, max); + } + else + { + RE_rayobject_merge_bb( (RayObject*)node, min, max); + } +} + +static void bvh_bb(BVHTree *obj, float *min, float *max) +{ + bvh_merge_bb(obj->root, min, max); +} + +/* + * Tree transverse + */ +static int dfs_raycast(BVHNode *node, Isect *isec) +{ + int hit = 0; + if(RE_rayobject_bb_intersect(isec, (const float*)node->bb) != FLT_MAX) + { + int i; + for(i=0; ichild[i])) + { + hit = dfs_raycast(node->child[i], isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + else + { + hit = RE_rayobject_intersect( (RayObject*)node->child[i], isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + } + return hit; +} + +static int bvh_intersect(BVHTree *obj, Isect *isec) +{ + if(RayObject_isAligned(obj->root)) + return dfs_raycast(obj->root, isec); + else + return RE_rayobject_intersect( (RayObject*)obj->root, isec); +} + + +/* + * Builds a BVH tree from builder object + */ +static void bvh_add(BVHTree *obj, RayObject *ob) +{ + rtbuild_add( obj->builder, ob ); +} + +static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder) +{ + if(rtbuild_size(builder) == 1) + { + return (BVHNode*)builder->begin[0]; + } + else + { + int i; + int nc = rtbuild_mean_split_largest_axis(builder, BVH_NCHILDS); + RTBuilder tmp; + + BVHNode *parent = tree->next_node++; + + INIT_MINMAX(parent->bb[0], parent->bb[1]); +// bvh->split_axis = tmp->split_axis; + for(i=0; ichild[i] = bvh_rearrange( tree, rtbuild_get_child(builder, i, &tmp) ); + bvh_merge_bb(parent->child[i], parent->bb[0], parent->bb[1]); + } + + return parent; + } +} + +static void bvh_done(BVHTree *obj) +{ + int needed_nodes; + assert(obj->root == NULL && obj->next_node == NULL && obj->builder); + + needed_nodes = (rtbuild_size(obj->builder)+1)*2; + assert(needed_nodes > 0); + obj->alloc = (BVHNode*)MEM_mallocN( sizeof(BVHNode)*needed_nodes, "BVHTree.Nodes"); + obj->next_node = obj->alloc; + obj->root = bvh_rearrange( obj, obj->builder ); + + assert(obj->alloc+needed_nodes >= obj->next_node); + + + rtbuild_free( obj->builder ); + obj->builder = NULL; +} + diff --git a/source/blender/render/intern/source/rayobject_rtbuild.c b/source/blender/render/intern/source/rayobject_rtbuild.c index b89729e2b45..46833b8c15d 100644 --- a/source/blender/render/intern/source/rayobject_rtbuild.c +++ b/source/blender/render/intern/source/rayobject_rtbuild.c @@ -2,12 +2,13 @@ #include "MEM_guardedalloc.h" #include "BLI_arithb.h" #include "BKE_utildefines.h" +#include static int partition_nth_element(RTBuilder *b, int _begin, int _end, int n); static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis); -static void RayObject_rtbuild_init(RTBuilder *b, RayObject **begin, RayObject **end) +static void rtbuild_init(RTBuilder *b, RayObject **begin, RayObject **end) { int i; @@ -16,35 +17,35 @@ static void RayObject_rtbuild_init(RTBuilder *b, RayObject **begin, RayObject ** b->split_axis = 0; for(i=0; ichild[i] = 0; + b->child_offset[i] = 0; } -RTBuilder* RayObject_rtbuild_create(int size) +RTBuilder* rtbuild_create(int size) { RTBuilder *builder = (RTBuilder*) MEM_mallocN( sizeof(RTBuilder), "RTBuilder" ); - RayObject **memblock= (RayObject**)MEM_mallocN( sizeof(RayObject*),"RTBuilder.objects"); - RayObject_rtbuild_init(builder, memblock, memblock); + RayObject **memblock= (RayObject**)MEM_mallocN( sizeof(RayObject*)*size,"RTBuilder.objects"); + rtbuild_init(builder, memblock, memblock); return builder; } -void RayObject_rtbuild_free(RTBuilder *b) +void rtbuild_free(RTBuilder *b) { MEM_freeN(b->begin); MEM_freeN(b); } -void RayObject_rtbuild_add(RTBuilder *b, RayObject *o) +void rtbuild_add(RTBuilder *b, RayObject *o) { *(b->end++) = o; } RTBuilder* rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp) { - RayObject_rtbuild_init( tmp, b->child[child], b->child[child+1] ); + rtbuild_init( tmp, b->begin + b->child_offset[child], b->begin + b->child_offset[child+1] ); return tmp; } -int RayObject_rtbuild_size(RTBuilder *b) +int rtbuild_size(RTBuilder *b) { return b->end - b->begin; } @@ -86,17 +87,23 @@ static int calc_largest_axis(RTBuilder *b) //Unballanced mean //TODO better balance nodes //TODO suport for variable number of partitions (its hardcoded in 2) -void rtbuild_mean_split(RTBuilder *b, int nchilds, int axis) +int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis) { - int nth[3] = {0, (b->end - b->begin)/2, b->end-b->begin}; - split_leafs(b, nth, 2, axis); + b->child_offset[0] = 0; + b->child_offset[1] = (b->end - b->begin) / 2; + b->child_offset[2] = (b->end - b->begin); + + assert( b->child_offset[0] != b->child_offset[1] && b->child_offset[1] != b->child_offset[2]); + + split_leafs(b, b->child_offset, 2, axis); + return 2; } -void rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds) +int rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds) { int axis = calc_largest_axis(b); - rtbuild_mean_split(b, nchilds, axis); + return rtbuild_mean_split(b, nchilds, axis); } @@ -110,11 +117,12 @@ static void sort_swap(RTBuilder *b, int i, int j) SWAP(RayObject*, b->begin[i], b->begin[j]); } -static int sort_get_value(RTBuilder *b, int i) +static float sort_get_value(RTBuilder *b, int i) { float min[3], max[3]; + INIT_MINMAX(min, max); RE_rayobject_merge_bb(b->begin[i], min, max); - return max[i]; + return max[b->split_axis]; } static int medianof3(RTBuilder *d, int a, int b, int c) @@ -174,9 +182,14 @@ static int partition(RTBuilder *b, int lo, int mid, int hi) int i=lo, j=hi; while (1) { - while (sort_get_value(b,i) < x) i++; + while(sort_get_value(b,i) < x) + i++; + j--; - while (x < sort_get_value(b,j)) j--; + + while(x < sort_get_value(b,j)) + j--; + if(!(i < j)) return i; diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 75c93fc1c80..4c16ac05ec2 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -180,7 +180,7 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_OCTREE) raytree = obr->raytree = RE_rayobject_octree_create( re->r.ocres, faces ); else //if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_BVH) - raytree = obr->raytree = RE_rayobject_blibvh_create( faces ); + raytree = obr->raytree = RE_rayobject_tree_create( faces ); face = obr->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "ObjectRen faces"); obr->rayobi = obi; @@ -240,7 +240,7 @@ static void makeraytree_hier(Render *re) num_objects++; //Create raytree - re->raytree = RE_rayobject_blibvh_create( num_objects ); + re->raytree = RE_rayobject_tree_create( num_objects ); for(obi=re->instancetable.first; obi; obi=obi->next) if(is_raytraceable(re, obi)) @@ -292,7 +292,7 @@ static void makeraytree_single(Render *re) if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_OCTREE) raytree = re->raytree = RE_rayobject_octree_create( re->r.ocres, faces ); else //if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_BVH) - raytree = re->raytree = RE_rayobject_blibvh_create( faces ); + raytree = re->raytree = RE_rayobject_tree_create( faces ); face = re->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces"); From 1b557a61a53235f978262c52ac79fa16464bdd91 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 1 Jul 2009 12:36:05 +0000 Subject: [PATCH 025/138] fixed ray mirror/trans shadow on rayobject_bvh --- source/blender/render/intern/source/rayobject_bvh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index ea590ef83fd..4be57543a77 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -125,12 +125,12 @@ static int dfs_raycast(BVHNode *node, Isect *isec) for(i=0; ichild[i])) { - hit = dfs_raycast(node->child[i], isec); + hit |= dfs_raycast(node->child[i], isec); if(hit && isec->mode == RE_RAY_SHADOW) return hit; } else { - hit = RE_rayobject_intersect( (RayObject*)node->child[i], isec); + hit |= RE_rayobject_intersect( (RayObject*)node->child[i], isec); if(hit && isec->mode == RE_RAY_SHADOW) return hit; } } From b14298f959180762c3bbf31d42a747e55ca48494 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Thu, 2 Jul 2009 11:28:42 +0000 Subject: [PATCH 026/138] svn merge -r 21041:21301 https://svn.blender.org/svnroot/bf-blender/branches/blender2.5/blender --- CMake/macros.cmake | 2 +- CMakeLists.txt | 51 +- SConstruct | 2 - config/darwin-config.py | 9 - config/irix6-config.py | 9 - config/linux2-config.py | 9 - config/linuxcross-config.py | 9 - config/openbsd3-config.py | 9 - config/sunos5-config.py | 9 - config/win32-mingw-config.py | 9 - config/win32-vc-config.py | 9 - config/win64-vc-config.py | 9 - extern/CMakeLists.txt | 5 - extern/Makefile | 2 +- extern/SConscript | 4 - extern/qhull/CMakeLists.txt | 45 - extern/qhull/COPYING.txt | 37 - extern/qhull/README.txt | 318 -- extern/qhull/REGISTER.txt | 37 - extern/qhull/SConscript | 35 - extern/qhull/VisualC6/qhull.dsw | 29 - extern/qhull/VisualC6/qhull/qhull.dsp | 192 - extern/qhull/include/qhull/geom.h | 177 - extern/qhull/include/qhull/io.h | 149 - extern/qhull/include/qhull/mem.h | 174 - extern/qhull/include/qhull/merge.h | 171 - extern/qhull/include/qhull/poly.h | 290 -- extern/qhull/include/qhull/qhull.h | 1048 ----- extern/qhull/include/qhull/qhull_a.h | 127 - extern/qhull/include/qhull/qset.h | 468 -- extern/qhull/include/qhull/stat.h | 520 --- extern/qhull/include/qhull/user.h | 762 --- extern/qhull/make/msvc_7_0/qhull.vcproj | 677 --- extern/qhull/make/msvc_9_0/qhull.vcproj | 877 ---- extern/qhull/src/Make-config.sh | 285 -- extern/qhull/src/Makefile | 55 - extern/qhull/src/Makefile.txt | 190 - extern/qhull/src/geom.c | 1230 ----- extern/qhull/src/geom.h | 177 - extern/qhull/src/geom2.c | 2160 --------- extern/qhull/src/global.c | 2018 -------- extern/qhull/src/io.c | 4089 ----------------- extern/qhull/src/io.h | 149 - extern/qhull/src/mem.c | 447 -- extern/qhull/src/mem.h | 174 - extern/qhull/src/merge.c | 3626 --------------- extern/qhull/src/merge.h | 171 - extern/qhull/src/poly.c | 1180 ----- extern/qhull/src/poly.h | 290 -- extern/qhull/src/poly2.c | 3070 ------------- extern/qhull/src/qconvex.c | 334 -- extern/qhull/src/qdelaun.c | 323 -- extern/qhull/src/qhalf.c | 324 -- extern/qhull/src/qhull.c | 1395 ------ extern/qhull/src/qhull.h | 1048 ----- extern/qhull/src/qhull_a.h | 127 - extern/qhull/src/qhull_interface.cpp | 96 - extern/qhull/src/qset.c | 1301 ------ extern/qhull/src/qset.h | 468 -- extern/qhull/src/qvoronoi.c | 318 -- extern/qhull/src/rbox.c | 788 ---- extern/qhull/src/stat.c | 700 --- extern/qhull/src/stat.h | 520 --- extern/qhull/src/unix.c | 376 -- extern/qhull/src/user.c | 324 -- extern/qhull/src/user.h | 762 --- extern/qhull/src/user_eg.c | 310 -- extern/qhull/src/user_eg2.c | 532 --- extern/solid/CMakeLists.txt | 34 - extern/solid/LICENSE_GPL.txt | 349 -- extern/solid/LICENSE_QPL.txt | 110 - extern/solid/Makefile | 56 - extern/solid/README.txt | 55 - extern/solid/SConscript | 34 - extern/solid/SOLID/SOLID.h | 279 -- extern/solid/SOLID/SOLID_broad.h | 75 - extern/solid/SOLID/SOLID_types.h | 53 - extern/solid/VisualC6/broad/broad.dsp | 132 - extern/solid/VisualC6/complex/complex.dsp | 116 - extern/solid/VisualC6/convex/convex.dsp | 232 - extern/solid/VisualC6/dynamics/dynamics.dsp | 120 - extern/solid/VisualC6/gldemo/gldemo.dsp | 102 - extern/solid/VisualC6/mnm/mnm.dsp | 100 - extern/solid/VisualC6/physics/physics.dsp | 100 - extern/solid/VisualC6/sample/sample.dsp | 102 - extern/solid/VisualC6/solid.dsw | 89 - extern/solid/VisualC6/solid/solid.dsp | 148 - extern/solid/VisualC6/solid_dll/solid_dll.dsp | 147 - extern/solid/include/GEN_MinMax.h | 76 - extern/solid/include/GEN_random.h | 49 - extern/solid/include/MT/Interval.h | 180 - extern/solid/include/MT/Matrix3x3.h | 380 -- extern/solid/include/MT/Quaternion.h | 316 -- extern/solid/include/MT/Transform.h | 189 - extern/solid/include/MT/Tuple3.h | 120 - extern/solid/include/MT/Tuple4.h | 112 - extern/solid/include/MT/Vector3.h | 283 -- extern/solid/include/MT_BBox.h | 119 - extern/solid/include/MT_Interval.h | 33 - extern/solid/include/MT_Matrix3x3.h | 34 - extern/solid/include/MT_Point3.h | 31 - extern/solid/include/MT_Quaternion.h | 35 - extern/solid/include/MT_Scalar.h | 158 - extern/solid/include/MT_Transform.h | 38 - extern/solid/include/MT_Vector3.h | 50 - extern/solid/include/SOLID.h | 279 -- extern/solid/include/SOLID_broad.h | 75 - extern/solid/include/SOLID_types.h | 53 - extern/solid/make/msvc_7_0/broad/broad.vcproj | 262 -- .../make/msvc_7_0/complex/complex.vcproj | 252 - .../solid/make/msvc_7_0/convex/convex.vcproj | 337 -- extern/solid/make/msvc_7_0/solid.vcproj | 462 -- extern/solid/make/msvc_9_0/broad/broad.vcproj | 369 -- .../make/msvc_9_0/complex/complex.vcproj | 355 -- .../solid/make/msvc_9_0/convex/convex.vcproj | 469 -- extern/solid/make/msvc_9_0/solid.vcproj | 595 --- extern/solid/src/DT_AlgoTable.h | 47 - extern/solid/src/DT_C-api.cpp | 581 --- extern/solid/src/DT_Encounter.cpp | 111 - extern/solid/src/DT_Encounter.h | 84 - extern/solid/src/DT_Object.cpp | 276 -- extern/solid/src/DT_Object.h | 157 - extern/solid/src/DT_RespTable.cpp | 184 - extern/solid/src/DT_RespTable.h | 139 - extern/solid/src/DT_Response.h | 63 - extern/solid/src/DT_Scene.cpp | 183 - extern/solid/src/DT_Scene.h | 57 - extern/solid/src/Makefile | 45 - extern/solid/src/broad/BP_C-api.cpp | 77 - extern/solid/src/broad/BP_Endpoint.h | 108 - extern/solid/src/broad/BP_EndpointList.cpp | 237 - extern/solid/src/broad/BP_EndpointList.h | 109 - extern/solid/src/broad/BP_Proxy.cpp | 120 - extern/solid/src/broad/BP_Proxy.h | 78 - extern/solid/src/broad/BP_ProxyList.h | 69 - extern/solid/src/broad/BP_Scene.cpp | 151 - extern/solid/src/broad/BP_Scene.h | 79 - extern/solid/src/broad/Makefile | 41 - extern/solid/src/complex/DT_BBoxTree.cpp | 90 - extern/solid/src/complex/DT_BBoxTree.h | 540 --- extern/solid/src/complex/DT_CBox.h | 134 - extern/solid/src/complex/DT_Complex.cpp | 327 -- extern/solid/src/complex/DT_Complex.h | 94 - extern/solid/src/complex/Makefile | 42 - extern/solid/src/convex/DT_Accuracy.cpp | 30 - extern/solid/src/convex/DT_Accuracy.h | 47 - extern/solid/src/convex/DT_Array.h | 75 - extern/solid/src/convex/DT_Box.cpp | 112 - extern/solid/src/convex/DT_Box.h | 62 - extern/solid/src/convex/DT_Cone.cpp | 48 - extern/solid/src/convex/DT_Cone.h | 45 - extern/solid/src/convex/DT_Convex.cpp | 426 -- extern/solid/src/convex/DT_Convex.h | 64 - extern/solid/src/convex/DT_Cylinder.cpp | 39 - extern/solid/src/convex/DT_Cylinder.h | 42 - extern/solid/src/convex/DT_Facet.cpp | 80 - extern/solid/src/convex/DT_Facet.h | 134 - extern/solid/src/convex/DT_GJK.h | 438 -- extern/solid/src/convex/DT_Hull.h | 53 - extern/solid/src/convex/DT_IndexArray.h | 33 - extern/solid/src/convex/DT_LineSegment.cpp | 36 - extern/solid/src/convex/DT_LineSegment.h | 52 - extern/solid/src/convex/DT_Minkowski.h | 51 - extern/solid/src/convex/DT_PenDepth.cpp | 376 -- extern/solid/src/convex/DT_PenDepth.h | 36 - extern/solid/src/convex/DT_Point.cpp | 36 - extern/solid/src/convex/DT_Point.h | 46 - extern/solid/src/convex/DT_Polyhedron.cpp | 415 -- extern/solid/src/convex/DT_Polyhedron.h | 76 - extern/solid/src/convex/DT_Polytope.cpp | 69 - extern/solid/src/convex/DT_Polytope.h | 51 - extern/solid/src/convex/DT_Shape.h | 72 - extern/solid/src/convex/DT_Sphere.cpp | 90 - extern/solid/src/convex/DT_Sphere.h | 43 - extern/solid/src/convex/DT_Transform.h | 53 - extern/solid/src/convex/DT_Triangle.cpp | 96 - extern/solid/src/convex/DT_Triangle.h | 63 - extern/solid/src/convex/DT_VertexBase.h | 84 - extern/solid/src/convex/Makefile | 41 - intern/bsp/test/Makefile | 2 +- intern/guardedalloc/intern/mallocn.c | 12 +- intern/iksolver/test/Makefile | 2 +- intern/moto/include/MT_Matrix3x3.h | 24 + intern/string/intern/STR_String.cpp | 6 +- .../blender/BPY_python/BPY_python.vcproj | 44 +- projectfiles_vc9/blender/blender.sln | 146 - projectfiles_vc9/blender/blender.vcproj | 12 +- .../blender/blenkernel/BKE_blenkernel.vcproj | 12 +- .../blender/blenlib/BLI_blenlib.vcproj | 2 +- .../blender/editors/ED_editors.vcproj | 44 +- .../blender/makesrna/RNA_makesrna.vcproj | 30 +- .../blender/makesrna/RNA_rna.vcproj | 10 +- projectfiles_vc9/blender/nodes/nodes.vcproj | 8 +- .../blenderhook/KX_blenderhook.vcproj | 4 +- .../gameengine/converter/KX_converter.vcproj | 12 +- .../expression/EXP_expressions.vcproj | 12 +- .../gameengine/gamelogic/SCA_GameLogic.vcproj | 12 +- .../gameplayer/axctl/GP_axctl.vcproj | 4 +- .../gameplayer/common/GP_common.vcproj | 8 +- .../gameplayer/ghost/GP_ghost.vcproj | 4 +- .../gameengine/ketsji/KX_ketsji.vcproj | 20 +- .../ketsji/network/KX_network.vcproj | 12 +- .../PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj | 12 +- .../rasterizer/RAS_rasterizer.vcproj | 12 +- .../gameengine/videotexture/TEX_Video.vcproj | 4 +- .../kernel/system/SYS_system.vcproj | 4 +- release/ui/buttons_data_armature.py | 4 +- release/ui/buttons_data_camera.py | 4 +- release/ui/buttons_data_curve.py | 4 +- release/ui/buttons_data_lamp.py | 4 +- release/ui/buttons_data_lattice.py | 4 +- release/ui/buttons_data_mesh.py | 143 +- release/ui/buttons_data_modifier.py | 167 +- release/ui/buttons_data_text.py | 4 +- release/ui/buttons_material.py | 4 +- release/ui/buttons_object_constraint.py | 27 +- release/ui/buttons_particle.py | 182 +- release/ui/buttons_physic_cloth.py | 48 + release/ui/buttons_texture.py | 4 +- release/ui/buttons_world.py | 4 +- release/ui/space_buttons.py | 36 + release/ui/space_filebrowser.py | 65 + release/ui/space_image.py | 645 +-- release/ui/space_info.py | 119 + release/ui/space_logic.py | 8 + release/ui/space_outliner.py | 4 +- release/ui/space_sequencer.py | 14 +- release/ui/space_text.py | 22 +- source/Makefile | 11 - source/blender/CMakeLists.txt | 1 - source/blender/Makefile | 2 +- source/blender/SConscript | 1 - source/blender/blenfont/BLF_api.h | 17 + source/blender/blenfont/intern/blf.c | 25 + source/blender/blenfont/intern/blf_dir.c | 2 +- source/blender/blenfont/intern/blf_font.c | 36 +- source/blender/blenfont/intern/blf_glyph.c | 33 + source/blender/blenfont/intern/blf_internal.h | 2 +- .../blenfont/intern/blf_internal_types.h | 12 +- source/blender/blenfont/intern/blf_lang.c | 2 +- source/blender/blenkernel/BKE_cloth.h | 5 +- source/blender/blenkernel/BKE_context.h | 3 +- source/blender/blenkernel/BKE_exotic.h | 1 - source/blender/blenkernel/BKE_gpencil.h | 2 +- source/blender/blenkernel/BKE_material.h | 15 +- source/blender/blenkernel/BKE_packedFile.h | 52 +- source/blender/blenkernel/BKE_particle.h | 7 + source/blender/blenkernel/BKE_pointcache.h | 57 +- source/blender/blenkernel/BKE_report.h | 7 +- source/blender/blenkernel/BKE_sequence.h | 2 +- source/blender/blenkernel/BKE_utildefines.h | 8 +- source/blender/blenkernel/intern/anim_sys.c | 4 + source/blender/blenkernel/intern/blender.c | 1 - .../blender/blenkernel/intern/cdderivedmesh.c | 2 +- source/blender/blenkernel/intern/cloth.c | 168 +- source/blender/blenkernel/intern/constraint.c | 8 +- source/blender/blenkernel/intern/context.c | 24 +- source/blender/blenkernel/intern/depsgraph.c | 20 +- source/blender/blenkernel/intern/displist.c | 36 +- source/blender/blenkernel/intern/effect.c | 2 + source/blender/blenkernel/intern/exotic.c | 594 +-- source/blender/blenkernel/intern/fluidsim.c | 2 + source/blender/blenkernel/intern/font.c | 8 +- source/blender/blenkernel/intern/gpencil.c | 2 +- source/blender/blenkernel/intern/idprop.c | 8 +- source/blender/blenkernel/intern/image.c | 6 +- source/blender/blenkernel/intern/implicit.c | 10 +- source/blender/blenkernel/intern/material.c | 4 +- source/blender/blenkernel/intern/modifier.c | 29 +- source/blender/blenkernel/intern/multires.c | 6 +- source/blender/blenkernel/intern/packedFile.c | 227 +- source/blender/blenkernel/intern/particle.c | 99 +- .../blenkernel/intern/particle_system.c | 208 +- source/blender/blenkernel/intern/pointcache.c | 892 +++- source/blender/blenkernel/intern/report.c | 6 +- source/blender/blenkernel/intern/scene.c | 9 +- source/blender/blenkernel/intern/sequence.c | 2 +- source/blender/blenlib/BLI_listbase.h | 4 +- source/blender/blenlib/BLI_noise.h | 2 +- source/blender/blenlib/BLI_rect.h | 2 +- source/blender/blenlib/BLI_storage.h | 7 +- source/blender/blenlib/BLI_string.h | 4 +- source/blender/blenlib/BLI_util.h | 1 + source/blender/blenlib/intern/dynamiclist.c | 2 +- source/blender/blenlib/intern/dynamiclist.h | 2 +- source/blender/blenlib/intern/listbase.c | 2 +- source/blender/blenlib/intern/psfont.c | 4 +- source/blender/blenlib/intern/storage.c | 54 +- source/blender/blenlib/intern/string.c | 2 +- source/blender/blenlib/intern/util.c | 24 +- .../blender/blenloader/intern/readblenentry.c | 2 + source/blender/blenloader/intern/readfile.c | 148 +- source/blender/blenloader/intern/writefile.c | 28 +- source/blender/blenpluginapi/intern/Makefile | 4 - source/blender/editors/animation/Makefile | 2 +- .../blender/editors/animation/anim_channels.c | 2 +- .../editors/animation/keyframes_draw.c | 2 +- .../blender/editors/armature/BIF_generate.h | 2 +- .../blender/editors/armature/BIF_retarget.h | 2 +- source/blender/editors/armature/Makefile | 2 +- .../editors/armature/editarmature_generate.c | 2 +- .../editors/armature/editarmature_sketch.c | 107 +- .../blender/editors/armature/meshlaplacian.c | 2 +- .../blender/editors/armature/meshlaplacian.h | 2 +- source/blender/editors/curve/Makefile | 2 +- source/blender/editors/curve/curve_intern.h | 1 - source/blender/editors/curve/curve_ops.c | 1 - source/blender/editors/curve/editcurve.c | 2 +- source/blender/editors/curve/editfont.c | 44 - source/blender/editors/datafiles/Bfont.c | 2 +- source/blender/editors/datafiles/Makefile | 2 +- source/blender/editors/gpencil/Makefile | 2 +- source/blender/editors/gpencil/gpencil_edit.c | 2 +- source/blender/editors/include/BIF_gl.h | 2 +- source/blender/editors/include/ED_curve.h | 3 + source/blender/editors/include/ED_datafiles.h | 2 +- .../blender/editors/include/ED_fileselect.h | 32 +- source/blender/editors/include/ED_fluidsim.h | 2 +- .../editors/include/ED_keyframes_draw.h | 2 +- .../blender/editors/include/ED_keyframing.h | 6 +- source/blender/editors/include/ED_mesh.h | 7 +- source/blender/editors/include/ED_object.h | 1 + source/blender/editors/include/ED_particle.h | 2 +- .../include/ED_pointcache.h} | 42 +- .../editors/include/ED_previewrender.h | 6 +- source/blender/editors/include/ED_view3d.h | 2 + source/blender/editors/include/UI_icons.h | 4 +- source/blender/editors/include/UI_interface.h | 17 +- source/blender/editors/include/UI_resources.h | 2 +- source/blender/editors/interface/Makefile | 2 +- source/blender/editors/interface/interface.c | 137 +- .../editors/interface/interface_draw.c | 2 +- .../editors/interface/interface_handlers.c | 141 +- .../editors/interface/interface_icons.c | 101 +- .../editors/interface/interface_intern.h | 25 +- .../editors/interface/interface_layout.c | 180 +- .../editors/interface/interface_panel.c | 9 +- .../editors/interface/interface_regions.c | 215 +- .../editors/interface/interface_style.c | 38 +- .../editors/interface/interface_templates.c | 541 ++- .../editors/interface/interface_utils.c | 88 +- .../editors/interface/interface_widgets.c | 136 +- source/blender/editors/interface/resources.c | 2 +- source/blender/editors/interface/view2d.c | 8 +- source/blender/editors/mesh/Makefile | 2 +- source/blender/editors/mesh/editmesh.c | 4 +- source/blender/editors/mesh/editmesh_add.c | 4 +- source/blender/editors/mesh/editmesh_mods.c | 8 +- source/blender/editors/mesh/editmesh_tools.c | 6 +- source/blender/editors/mesh/mesh_intern.h | 9 + source/blender/editors/mesh/mesh_layers.c | 424 ++ source/blender/editors/mesh/mesh_ops.c | 6 + source/blender/editors/object/Makefile | 2 +- source/blender/editors/object/editkey.c | 144 +- source/blender/editors/object/object_edit.c | 27 +- source/blender/editors/object/object_intern.h | 14 + .../blender/editors/object/object_modifier.c | 2 +- source/blender/editors/object/object_ops.c | 12 + .../editdeform.c => object/object_vgroup.c} | 274 +- source/blender/editors/physics/Makefile | 2 +- .../blender/editors/physics/ed_pointcache.c | 382 ++ source/blender/editors/physics/editparticle.c | 34 +- .../blender/editors/physics/physics_intern.h | 2 +- source/blender/editors/preview/Makefile | 2 +- .../blender/editors/preview/previewrender.c | 256 +- source/blender/editors/screen/Makefile | 2 +- source/blender/editors/screen/area.c | 16 +- source/blender/editors/screen/glutil.c | 2 +- source/blender/editors/screen/screen_ops.c | 5 +- source/blender/editors/sculpt_paint/Makefile | 2 +- source/blender/editors/sculpt_paint/sculpt.c | 897 +--- .../editors/sculpt_paint/sculpt_intern.h | 2 +- .../editors/sculpt_paint/sculpt_stroke.c | 2 +- source/blender/editors/space_action/Makefile | 2 +- .../editors/space_action/action_draw.c | 2 +- .../editors/space_action/action_edit.c | 2 +- .../editors/space_action/action_select.c | 2 +- source/blender/editors/space_api/Makefile | 2 +- source/blender/editors/space_api/spacetypes.c | 2 + source/blender/editors/space_buttons/Makefile | 2 +- .../blender/editors/space_buttons/SConscript | 3 - .../editors/space_buttons/buttons_context.c | 9 +- .../editors/space_buttons/buttons_header.c | 6 +- .../editors/space_buttons/buttons_intern.h | 11 + .../editors/space_buttons/buttons_ops.c | 368 +- .../editors/space_buttons/space_buttons.c | 30 +- source/blender/editors/space_file/Makefile | 2 +- source/blender/editors/space_file/file_draw.c | 77 - .../blender/editors/space_file/file_header.c | 2 +- .../blender/editors/space_file/file_intern.h | 12 +- source/blender/editors/space_file/file_ops.c | 222 +- .../blender/editors/space_file/file_panels.c | 165 + source/blender/editors/space_file/filelist.c | 8 +- source/blender/editors/space_file/filelist.h | 1 - source/blender/editors/space_file/filesel.c | 4 +- source/blender/editors/space_file/fsmenu.c | 39 +- source/blender/editors/space_file/fsmenu.h | 13 +- .../blender/editors/space_file/space_file.c | 126 +- source/blender/editors/space_graph/Makefile | 2 +- .../blender/editors/space_graph/graph_draw.c | 2 +- .../blender/editors/space_graph/graph_edit.c | 2 +- .../editors/space_graph/graph_select.c | 2 +- source/blender/editors/space_image/Makefile | 2 +- .../editors/space_image/image_buttons.c | 48 +- .../blender/editors/space_image/image_draw.c | 28 +- .../editors/space_image/image_header.c | 14 +- .../blender/editors/space_image/image_ops.c | 150 +- .../blender/editors/space_image/space_image.c | 8 +- source/blender/editors/space_info/Makefile | 2 +- source/blender/editors/space_info/SConscript | 3 - .../blender/editors/space_info/info_header.c | 507 -- .../blender/editors/space_info/info_intern.h | 7 + source/blender/editors/space_info/info_ops.c | 397 ++ .../blender/editors/space_info/space_info.c | 28 +- source/blender/editors/space_logic/Makefile | 2 +- source/blender/editors/space_logic/SConscript | 3 - .../editors/space_logic/logic_buttons.c | 2 +- .../editors/space_logic/logic_header.c | 2 +- .../editors/space_logic/logic_window.c | 102 +- source/blender/editors/space_nla/Makefile | 2 +- source/blender/editors/space_nla/nla_header.c | 2 +- source/blender/editors/space_node/Makefile | 2 +- source/blender/editors/space_node/node_draw.c | 2 +- .../blender/editors/space_node/node_header.c | 2 +- .../blender/editors/space_outliner/Makefile | 2 +- .../blender/editors/space_outliner/outliner.c | 19 +- .../editors/space_outliner/outliner_header.c | 2 +- .../editors/space_outliner/space_outliner.c | 2 +- source/blender/editors/space_script/Makefile | 2 +- .../editors/space_script/script_header.c | 2 +- .../blender/editors/space_sequencer/Makefile | 2 +- .../space_sequencer/sequencer_buttons.c | 2 +- source/blender/editors/space_sound/Makefile | 2 +- .../editors/space_sound/sound_header.c | 2 +- source/blender/editors/space_text/Makefile | 2 +- .../blender/editors/space_text/text_header.c | 4 +- .../blender/editors/space_text/text_python.c | 2 +- source/blender/editors/space_time/Makefile | 2 +- .../blender/editors/space_time/space_time.c | 2 +- .../blender/editors/space_time/time_header.c | 6 +- source/blender/editors/space_view3d/Makefile | 2 +- .../blender/editors/space_view3d/drawobject.c | 58 +- .../editors/space_view3d/space_view3d.c | 18 + .../editors/space_view3d/view3d_buttons.c | 4 +- .../editors/space_view3d/view3d_header.c | 127 +- .../editors/space_view3d/view3d_select.c | 21 +- .../editors/space_view3d/view3d_toolbar.c | 125 +- .../editors/space_view3d/view3d_view.c | 6 +- source/blender/editors/transform/Makefile | 2 +- source/blender/editors/transform/transform.c | 14 +- source/blender/editors/transform/transform.h | 1 + .../editors/transform/transform_conversions.c | 18 +- .../editors/transform/transform_generics.c | 15 +- .../editors/transform/transform_input.c | 3 +- .../editors/transform/transform_ndofinput.c | 1 + .../editors/transform/transform_numinput.c | 1 + .../blender/editors/transform/transform_ops.c | 2 +- .../editors/transform/transform_snap.c | 19 +- source/blender/editors/util/Makefile | 2 +- source/blender/editors/util/undo.c | 2 + source/blender/editors/uvedit/Makefile | 2 +- source/blender/editors/uvedit/uvedit_draw.c | 22 +- source/blender/editors/uvedit/uvedit_ops.c | 112 +- source/blender/gpu/intern/Makefile | 2 +- source/blender/imbuf/intern/imbuf.h | 2 +- source/blender/imbuf/intern/readimage.c | 21 - source/blender/makesdna/DNA_brush_types.h | 1 + source/blender/makesdna/DNA_object_force.h | 22 + source/blender/makesdna/DNA_particle_types.h | 6 +- source/blender/makesdna/DNA_scene_types.h | 69 +- source/blender/makesdna/DNA_screen_types.h | 4 + source/blender/makesdna/DNA_space_types.h | 50 +- source/blender/makesdna/DNA_userdef_types.h | 10 +- .../makesdna/DNA_windowmanager_types.h | 34 +- source/blender/makesdna/intern/makesdna.c | 2 - source/blender/makesrna/Makefile | 2 +- source/blender/makesrna/RNA_access.h | 40 +- source/blender/makesrna/RNA_define.h | 4 +- source/blender/makesrna/RNA_enum_types.h | 5 +- source/blender/makesrna/RNA_types.h | 21 +- source/blender/makesrna/intern/Makefile | 2 +- source/blender/makesrna/intern/makesrna.c | 105 +- source/blender/makesrna/intern/rna_ID.c | 2 +- source/blender/makesrna/intern/rna_access.c | 500 +- source/blender/makesrna/intern/rna_action.c | 2 +- source/blender/makesrna/intern/rna_actuator.c | 2 +- .../blender/makesrna/intern/rna_animation.c | 2 +- source/blender/makesrna/intern/rna_armature.c | 27 +- source/blender/makesrna/intern/rna_brush.c | 6 +- source/blender/makesrna/intern/rna_camera.c | 2 +- source/blender/makesrna/intern/rna_cloth.c | 45 +- source/blender/makesrna/intern/rna_color.c | 2 +- .../blender/makesrna/intern/rna_constraint.c | 15 +- source/blender/makesrna/intern/rna_context.c | 22 +- .../blender/makesrna/intern/rna_controller.c | 2 +- source/blender/makesrna/intern/rna_curve.c | 2 +- source/blender/makesrna/intern/rna_define.c | 17 +- source/blender/makesrna/intern/rna_fcurve.c | 2 +- source/blender/makesrna/intern/rna_fluidsim.c | 2 +- source/blender/makesrna/intern/rna_group.c | 2 +- source/blender/makesrna/intern/rna_image.c | 47 +- source/blender/makesrna/intern/rna_internal.h | 4 +- .../makesrna/intern/rna_internal_types.h | 6 +- source/blender/makesrna/intern/rna_key.c | 2 +- source/blender/makesrna/intern/rna_lamp.c | 12 +- source/blender/makesrna/intern/rna_lattice.c | 2 +- source/blender/makesrna/intern/rna_main.c | 4 +- source/blender/makesrna/intern/rna_main_api.c | 2 +- source/blender/makesrna/intern/rna_material.c | 2 +- source/blender/makesrna/intern/rna_mesh.c | 265 +- source/blender/makesrna/intern/rna_mesh_api.c | 223 +- source/blender/makesrna/intern/rna_meta.c | 2 +- source/blender/makesrna/intern/rna_modifier.c | 60 +- source/blender/makesrna/intern/rna_nodetree.c | 2 +- .../makesrna/intern/rna_nodetree_types.h | 2 +- source/blender/makesrna/intern/rna_object.c | 125 +- .../blender/makesrna/intern/rna_object_api.c | 2 +- .../makesrna/intern/rna_object_force.c | 450 +- .../blender/makesrna/intern/rna_packedfile.c | 2 +- source/blender/makesrna/intern/rna_particle.c | 132 +- source/blender/makesrna/intern/rna_pose.c | 2 +- source/blender/makesrna/intern/rna_property.c | 2 +- source/blender/makesrna/intern/rna_radio.c | 140 - source/blender/makesrna/intern/rna_rna.c | 18 +- source/blender/makesrna/intern/rna_scene.c | 109 +- source/blender/makesrna/intern/rna_screen.c | 30 +- .../blender/makesrna/intern/rna_scriptlink.c | 2 +- source/blender/makesrna/intern/rna_sensor.c | 2 +- source/blender/makesrna/intern/rna_sequence.c | 2 +- source/blender/makesrna/intern/rna_sound.c | 2 +- source/blender/makesrna/intern/rna_space.c | 203 +- source/blender/makesrna/intern/rna_text.c | 2 +- source/blender/makesrna/intern/rna_texture.c | 2 +- source/blender/makesrna/intern/rna_timeline.c | 2 +- source/blender/makesrna/intern/rna_ui.c | 18 +- source/blender/makesrna/intern/rna_ui_api.c | 42 +- source/blender/makesrna/intern/rna_userdef.c | 24 +- source/blender/makesrna/intern/rna_vfont.c | 2 +- source/blender/makesrna/intern/rna_vpaint.c | 2 +- source/blender/makesrna/intern/rna_wm.c | 250 +- source/blender/makesrna/intern/rna_wm_api.c | 2 +- source/blender/makesrna/intern/rna_world.c | 4 +- source/blender/python/BPY_extern.h | 4 +- source/blender/python/BPY_menus.c | 1118 ----- source/blender/python/BPY_menus.h | 128 - source/blender/python/Makefile | 2 +- source/blender/python/generic/BGL.c | 13 +- source/blender/python/generic/BGL.h | 2 +- source/blender/python/generic/Geometry.c | 36 +- source/blender/python/generic/Geometry.h | 2 +- source/blender/python/generic/Makefile | 2 +- source/blender/python/generic/Mathutils.c | 279 +- source/blender/python/generic/Mathutils.h | 51 +- .../python/generic/bpy_internal_import.c | 2 +- .../python/generic/bpy_internal_import.h | 2 +- source/blender/python/generic/euler.c | 296 +- source/blender/python/generic/euler.h | 21 +- source/blender/python/generic/matrix.c | 494 +- source/blender/python/generic/matrix.h | 35 +- source/blender/python/generic/quat.c | 466 +- source/blender/python/generic/quat.h | 23 +- source/blender/python/generic/vector.c | 1236 +++-- source/blender/python/generic/vector.h | 21 +- source/blender/python/intern/Makefile | 2 +- source/blender/python/intern/bpy_compat.h | 2 +- source/blender/python/intern/bpy_interface.c | 13 +- source/blender/python/intern/bpy_operator.c | 2 +- source/blender/python/intern/bpy_operator.h | 2 +- .../blender/python/intern/bpy_operator_wrap.c | 113 +- .../blender/python/intern/bpy_operator_wrap.h | 2 +- source/blender/python/intern/bpy_rna.c | 892 +++- source/blender/python/intern/bpy_rna.h | 2 +- source/blender/python/intern/bpy_ui.c | 2 +- source/blender/python/intern/bpy_ui.h | 2 +- source/blender/python/intern/bpy_util.c | 4 +- source/blender/python/intern/bpy_util.h | 2 +- source/blender/radiosity/CMakeLists.txt | 36 - source/blender/radiosity/Makefile | 34 - source/blender/radiosity/SConscript | 12 - .../blender/radiosity/extern/include/radio.h | 173 - .../radiosity/extern/include/radio_types.h | 168 - source/blender/radiosity/intern/Makefile | 34 - .../blender/radiosity/intern/source/Makefile | 55 - .../radiosity/intern/source/raddisplay.c | 477 -- .../radiosity/intern/source/radfactors.c | 939 ---- .../blender/radiosity/intern/source/radio.c | 390 -- .../blender/radiosity/intern/source/radnode.c | 1103 ----- .../radiosity/intern/source/radpostprocess.c | 824 ---- .../radiosity/intern/source/radpreprocess.c | 828 ---- .../radiosity/intern/source/radrender.c | 530 --- .../render/extern/include/RE_render_ext.h | 3 +- .../render/intern/source/convertblender.c | 10 +- .../blender/render/intern/source/pipeline.c | 20 +- source/blender/render/intern/source/zbuf.c | 108 +- source/blender/windowmanager/WM_api.h | 8 +- source/blender/windowmanager/WM_types.h | 36 +- source/blender/windowmanager/intern/Makefile | 2 +- source/blender/windowmanager/intern/wm.c | 12 + .../windowmanager/intern/wm_event_system.c | 17 +- .../blender/windowmanager/intern/wm_files.c | 4 +- .../windowmanager/intern/wm_init_exit.c | 5 - .../blender/windowmanager/intern/wm_keymap.c | 313 +- .../windowmanager/intern/wm_operators.c | 21 +- .../windowmanager/intern/wm_subwindow.c | 2 +- source/blender/windowmanager/wm_cursors.h | 2 +- source/blender/windowmanager/wm_subwindow.h | 2 +- source/creator/CMakeLists.txt | 12 +- .../BlenderRoutines/BL_KetsjiEmbedStart.cpp | 41 +- .../gameengine/BlenderRoutines/CMakeLists.txt | 3 +- .../BlenderRoutines/KX_BlenderCanvas.cpp | 2 + source/gameengine/BlenderRoutines/Makefile | 4 +- source/gameengine/BlenderRoutines/SConscript | 8 +- source/gameengine/CMakeLists.txt | 1 - .../Converter/BL_ActionActuator.cpp | 49 +- .../gameengine/Converter/BL_ActionActuator.h | 9 +- .../Converter/BL_BlenderDataConversion.cpp | 13 - .../Converter/BL_ShapeActionActuator.cpp | 40 +- .../Converter/BL_ShapeActionActuator.h | 9 +- .../Converter/KX_BlenderSceneConverter.cpp | 28 +- source/gameengine/Converter/Makefile | 3 +- source/gameengine/Converter/SConscript | 5 - source/gameengine/Expressions/BoolValue.cpp | 3 +- source/gameengine/Expressions/CMakeLists.txt | 1 + source/gameengine/Expressions/IntValue.cpp | 2 +- source/gameengine/Expressions/KX_Python.h | 2 + source/gameengine/Expressions/ListValue.cpp | 59 +- source/gameengine/Expressions/ListValue.h | 4 +- source/gameengine/Expressions/Makefile | 1 + .../gameengine/Expressions/PyObjectPlus.cpp | 376 +- source/gameengine/Expressions/PyObjectPlus.h | 99 +- source/gameengine/Expressions/StringValue.h | 2 +- source/gameengine/Expressions/Value.cpp | 124 +- source/gameengine/Expressions/Value.h | 16 +- .../GameLogic/SCA_2DFilterActuator.cpp | 42 +- .../GameLogic/SCA_2DFilterActuator.h | 13 +- .../GameLogic/SCA_ANDController.cpp | 31 +- .../gameengine/GameLogic/SCA_ANDController.h | 10 +- .../GameLogic/SCA_ActuatorSensor.cpp | 37 +- .../gameengine/GameLogic/SCA_ActuatorSensor.h | 7 +- .../gameengine/GameLogic/SCA_AlwaysSensor.cpp | 31 +- .../gameengine/GameLogic/SCA_AlwaysSensor.h | 12 +- .../gameengine/GameLogic/SCA_DelaySensor.cpp | 40 +- source/gameengine/GameLogic/SCA_DelaySensor.h | 7 +- .../GameLogic/SCA_ExpressionController.cpp | 5 +- .../GameLogic/SCA_ExpressionController.h | 11 +- source/gameengine/GameLogic/SCA_IActuator.cpp | 5 +- source/gameengine/GameLogic/SCA_IActuator.h | 3 +- .../gameengine/GameLogic/SCA_IController.cpp | 47 +- source/gameengine/GameLogic/SCA_IController.h | 6 +- .../gameengine/GameLogic/SCA_ILogicBrick.cpp | 44 +- source/gameengine/GameLogic/SCA_ILogicBrick.h | 6 +- source/gameengine/GameLogic/SCA_IObject.cpp | 81 +- source/gameengine/GameLogic/SCA_IObject.h | 7 +- source/gameengine/GameLogic/SCA_ISensor.cpp | 46 +- source/gameengine/GameLogic/SCA_ISensor.h | 7 +- .../GameLogic/SCA_JoystickSensor.cpp | 73 +- .../gameengine/GameLogic/SCA_JoystickSensor.h | 7 +- .../GameLogic/SCA_KeyboardSensor.cpp | 61 +- .../gameengine/GameLogic/SCA_KeyboardSensor.h | 7 +- .../gameengine/GameLogic/SCA_LogicManager.cpp | 1 + .../gameengine/GameLogic/SCA_MouseSensor.cpp | 47 +- source/gameengine/GameLogic/SCA_MouseSensor.h | 7 +- .../GameLogic/SCA_NANDController.cpp | 31 +- .../gameengine/GameLogic/SCA_NANDController.h | 6 +- .../GameLogic/SCA_NORController.cpp | 31 +- .../gameengine/GameLogic/SCA_NORController.h | 10 +- .../gameengine/GameLogic/SCA_ORController.cpp | 32 +- .../gameengine/GameLogic/SCA_ORController.h | 9 +- .../GameLogic/SCA_PropertyActuator.cpp | 38 +- .../GameLogic/SCA_PropertyActuator.h | 8 +- .../GameLogic/SCA_PropertySensor.cpp | 42 +- .../gameengine/GameLogic/SCA_PropertySensor.h | 7 +- .../GameLogic/SCA_PythonController.cpp | 63 +- .../GameLogic/SCA_PythonController.h | 6 +- .../GameLogic/SCA_RandomActuator.cpp | 48 +- .../gameengine/GameLogic/SCA_RandomActuator.h | 7 +- .../gameengine/GameLogic/SCA_RandomSensor.cpp | 46 +- .../gameengine/GameLogic/SCA_RandomSensor.h | 7 +- .../GameLogic/SCA_XNORController.cpp | 31 +- .../gameengine/GameLogic/SCA_XNORController.h | 5 +- .../GameLogic/SCA_XORController.cpp | 31 +- .../gameengine/GameLogic/SCA_XORController.h | 10 +- source/gameengine/GamePlayer/common/Makefile | 3 - .../gameengine/GamePlayer/common/SConscript | 5 - .../GamePlayer/common/unix/GPU_Engine.cpp | 3 - .../GamePlayer/common/unix/Makefile | 2 - source/gameengine/GamePlayer/ghost/SConscript | 4 - source/gameengine/Ketsji/BL_Shader.cpp | 43 +- source/gameengine/Ketsji/BL_Shader.h | 6 +- .../KXNetwork/KX_NetworkMessageActuator.cpp | 37 +- .../KXNetwork/KX_NetworkMessageActuator.h | 7 +- .../KXNetwork/KX_NetworkMessageSensor.cpp | 43 +- .../KXNetwork/KX_NetworkMessageSensor.h | 7 +- .../gameengine/Ketsji/KX_BlenderMaterial.cpp | 43 +- source/gameengine/Ketsji/KX_BlenderMaterial.h | 9 +- source/gameengine/Ketsji/KX_CDActuator.cpp | 47 +- source/gameengine/Ketsji/KX_CDActuator.h | 7 +- source/gameengine/Ketsji/KX_Camera.cpp | 65 +- source/gameengine/Ketsji/KX_Camera.h | 7 +- .../gameengine/Ketsji/KX_CameraActuator.cpp | 39 +- source/gameengine/Ketsji/KX_CameraActuator.h | 8 +- .../gameengine/Ketsji/KX_ClientObjectInfo.h | 12 - .../Ketsji/KX_ConstraintActuator.cpp | 50 +- .../gameengine/Ketsji/KX_ConstraintActuator.h | 7 +- .../Ketsji/KX_ConstraintWrapper.cpp | 42 +- .../gameengine/Ketsji/KX_ConstraintWrapper.h | 5 +- .../Ketsji/KX_ConvertPhysicsObject.h | 30 - .../Ketsji/KX_ConvertPhysicsObjects.cpp | 592 --- source/gameengine/Ketsji/KX_GameActuator.cpp | 45 +- source/gameengine/Ketsji/KX_GameActuator.h | 7 +- source/gameengine/Ketsji/KX_GameObject.cpp | 445 +- source/gameengine/Ketsji/KX_GameObject.h | 42 +- source/gameengine/Ketsji/KX_IpoActuator.cpp | 37 +- source/gameengine/Ketsji/KX_IpoActuator.h | 7 +- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 10 +- source/gameengine/Ketsji/KX_Light.cpp | 56 +- source/gameengine/Ketsji/KX_Light.h | 6 +- source/gameengine/Ketsji/KX_MeshProxy.cpp | 55 +- source/gameengine/Ketsji/KX_MeshProxy.h | 3 - .../gameengine/Ketsji/KX_MouseFocusSensor.cpp | 33 +- .../gameengine/Ketsji/KX_MouseFocusSensor.h | 5 +- source/gameengine/Ketsji/KX_NearSensor.cpp | 46 +- source/gameengine/Ketsji/KX_NearSensor.h | 9 +- .../gameengine/Ketsji/KX_ObjectActuator.cpp | 173 +- source/gameengine/Ketsji/KX_ObjectActuator.h | 18 +- .../Ketsji/KX_OdePhysicsController.cpp | 257 -- .../Ketsji/KX_OdePhysicsController.h | 109 - .../gameengine/Ketsji/KX_ParentActuator.cpp | 37 +- source/gameengine/Ketsji/KX_ParentActuator.h | 7 +- .../Ketsji/KX_PhysicsObjectWrapper.cpp | 49 +- .../Ketsji/KX_PhysicsObjectWrapper.h | 6 +- source/gameengine/Ketsji/KX_PolyProxy.cpp | 61 +- source/gameengine/Ketsji/KX_PolyProxy.h | 2 - .../gameengine/Ketsji/KX_PolygonMaterial.cpp | 44 +- source/gameengine/Ketsji/KX_PolygonMaterial.h | 7 +- .../Ketsji/KX_PyConstraintBinding.cpp | 2 +- source/gameengine/Ketsji/KX_PyMath.cpp | 92 +- source/gameengine/Ketsji/KX_PyMath.h | 57 +- source/gameengine/Ketsji/KX_PythonInit.cpp | 38 +- .../gameengine/Ketsji/KX_PythonInitTypes.cpp | 233 +- source/gameengine/Ketsji/KX_PythonSeq.cpp | 12 +- source/gameengine/Ketsji/KX_RadarSensor.cpp | 40 +- source/gameengine/Ketsji/KX_RadarSensor.h | 7 +- source/gameengine/Ketsji/KX_RaySensor.cpp | 39 +- source/gameengine/Ketsji/KX_RaySensor.h | 8 +- .../Ketsji/KX_SCA_AddObjectActuator.cpp | 45 +- .../Ketsji/KX_SCA_AddObjectActuator.h | 7 +- .../Ketsji/KX_SCA_DynamicActuator.cpp | 45 +- .../Ketsji/KX_SCA_DynamicActuator.h | 8 +- .../Ketsji/KX_SCA_EndObjectActuator.cpp | 35 +- .../Ketsji/KX_SCA_EndObjectActuator.h | 6 +- .../Ketsji/KX_SCA_ReplaceMeshActuator.cpp | 45 +- .../Ketsji/KX_SCA_ReplaceMeshActuator.h | 9 +- source/gameengine/Ketsji/KX_Scene.cpp | 88 +- source/gameengine/Ketsji/KX_Scene.h | 10 +- source/gameengine/Ketsji/KX_SceneActuator.cpp | 50 +- source/gameengine/Ketsji/KX_SceneActuator.h | 7 +- source/gameengine/Ketsji/KX_SoundActuator.cpp | 53 +- source/gameengine/Ketsji/KX_SoundActuator.h | 7 +- source/gameengine/Ketsji/KX_StateActuator.cpp | 41 +- source/gameengine/Ketsji/KX_StateActuator.h | 9 +- .../Ketsji/KX_SumoPhysicsController.cpp | 244 - .../Ketsji/KX_SumoPhysicsController.h | 122 - source/gameengine/Ketsji/KX_TouchSensor.cpp | 44 +- source/gameengine/Ketsji/KX_TouchSensor.h | 7 +- .../gameengine/Ketsji/KX_TrackToActuator.cpp | 51 +- source/gameengine/Ketsji/KX_TrackToActuator.h | 5 +- .../gameengine/Ketsji/KX_VehicleWrapper.cpp | 44 +- source/gameengine/Ketsji/KX_VehicleWrapper.h | 5 +- source/gameengine/Ketsji/KX_VertexProxy.cpp | 96 +- source/gameengine/Ketsji/KX_VertexProxy.h | 3 - .../Ketsji/KX_VisibilityActuator.cpp | 43 +- .../gameengine/Ketsji/KX_VisibilityActuator.h | 8 +- source/gameengine/Ketsji/Makefile | 5 +- source/gameengine/Ketsji/SConscript | 9 +- source/gameengine/Physics/BlOde/Makefile | 48 - .../Physics/BlOde/OdePhysicsController.cpp | 625 --- .../Physics/BlOde/OdePhysicsController.h | 164 - .../Physics/BlOde/OdePhysicsEnvironment.cpp | 277 -- .../Physics/BlOde/OdePhysicsEnvironment.h | 94 - source/gameengine/Physics/BlOde/SConscript | 15 - source/gameengine/Physics/Dummy/Makefile | 2 +- source/gameengine/Physics/Makefile | 3 +- source/gameengine/Physics/Sumo/CMakeLists.txt | 46 - .../gameengine/Physics/Sumo/Fuzzics/Makefile | 34 - .../Sumo/Fuzzics/include/SM_Callback.h | 11 - .../Fuzzics/include/SM_ClientObjectInfo.h | 16 - .../Physics/Sumo/Fuzzics/include/SM_Debug.h | 26 - .../Sumo/Fuzzics/include/SM_FhObject.h | 56 - .../Sumo/Fuzzics/include/SM_MotionState.h | 77 - .../Physics/Sumo/Fuzzics/include/SM_Object.h | 393 -- .../Physics/Sumo/Fuzzics/include/SM_Props.h | 58 - .../Physics/Sumo/Fuzzics/include/SM_Scene.h | 172 - .../Physics/Sumo/Fuzzics/sample/Makefile | 25 - .../Physics/Sumo/Fuzzics/sample/particle.cpp | 709 --- .../Physics/Sumo/Fuzzics/sample/particle0.cpp | 695 --- .../Physics/Sumo/Fuzzics/src/Makefile | 14 - .../Physics/Sumo/Fuzzics/src/SM_FhObject.cpp | 180 - .../Sumo/Fuzzics/src/SM_MotionState.cpp | 100 - .../Physics/Sumo/Fuzzics/src/SM_Object.cpp | 1298 ------ .../Physics/Sumo/Fuzzics/src/SM_Scene.cpp | 378 -- source/gameengine/Physics/Sumo/Makefile | 50 - source/gameengine/Physics/Sumo/SConscript | 25 - .../Physics/Sumo/SumoPHYCallbackBridge.cpp | 66 - .../Physics/Sumo/SumoPHYCallbackBridge.h | 28 - .../Physics/Sumo/SumoPhysicsController.cpp | 495 -- .../Physics/Sumo/SumoPhysicsController.h | 192 - .../Physics/Sumo/SumoPhysicsEnvironment.cpp | 264 -- .../Physics/Sumo/SumoPhysicsEnvironment.h | 110 - source/gameengine/Physics/Sumo/convert.txt | 35 - .../Physics/Sumo/include/interpolator.h | 27 - source/gameengine/Physics/common/Makefile | 2 +- source/gameengine/SConscript | 8 - .../VideoTexture/FilterBlueScreen.cpp | 20 +- .../gameengine/VideoTexture/FilterColor.cpp | 8 +- .../gameengine/VideoTexture/FilterNormal.cpp | 4 +- .../gameengine/VideoTexture/ImageRender.cpp | 16 +- .../gameengine/VideoTexture/ImageViewport.cpp | 16 +- source/gameengine/VideoTexture/VideoBase.cpp | 4 +- .../gameengine/VideoTexture/VideoFFmpeg.cpp | 4 +- .../gameengine/VideoTexture/blendVideoTex.cpp | 2 +- source/nan_compile.mk | 15 - source/nan_definitions.mk | 41 - source/nan_link.mk | 4 - tools/btools.py | 13 +- 825 files changed, 14547 insertions(+), 77617 deletions(-) delete mode 100644 extern/qhull/CMakeLists.txt delete mode 100644 extern/qhull/COPYING.txt delete mode 100644 extern/qhull/README.txt delete mode 100644 extern/qhull/REGISTER.txt delete mode 100644 extern/qhull/SConscript delete mode 100644 extern/qhull/VisualC6/qhull.dsw delete mode 100644 extern/qhull/VisualC6/qhull/qhull.dsp delete mode 100644 extern/qhull/include/qhull/geom.h delete mode 100644 extern/qhull/include/qhull/io.h delete mode 100644 extern/qhull/include/qhull/mem.h delete mode 100644 extern/qhull/include/qhull/merge.h delete mode 100644 extern/qhull/include/qhull/poly.h delete mode 100644 extern/qhull/include/qhull/qhull.h delete mode 100644 extern/qhull/include/qhull/qhull_a.h delete mode 100644 extern/qhull/include/qhull/qset.h delete mode 100644 extern/qhull/include/qhull/stat.h delete mode 100644 extern/qhull/include/qhull/user.h delete mode 100644 extern/qhull/make/msvc_7_0/qhull.vcproj delete mode 100644 extern/qhull/make/msvc_9_0/qhull.vcproj delete mode 100755 extern/qhull/src/Make-config.sh delete mode 100644 extern/qhull/src/Makefile delete mode 100644 extern/qhull/src/Makefile.txt delete mode 100644 extern/qhull/src/geom.c delete mode 100644 extern/qhull/src/geom.h delete mode 100644 extern/qhull/src/geom2.c delete mode 100644 extern/qhull/src/global.c delete mode 100644 extern/qhull/src/io.c delete mode 100644 extern/qhull/src/io.h delete mode 100644 extern/qhull/src/mem.c delete mode 100644 extern/qhull/src/mem.h delete mode 100644 extern/qhull/src/merge.c delete mode 100644 extern/qhull/src/merge.h delete mode 100644 extern/qhull/src/poly.c delete mode 100644 extern/qhull/src/poly.h delete mode 100644 extern/qhull/src/poly2.c delete mode 100644 extern/qhull/src/qconvex.c delete mode 100644 extern/qhull/src/qdelaun.c delete mode 100644 extern/qhull/src/qhalf.c delete mode 100644 extern/qhull/src/qhull.c delete mode 100644 extern/qhull/src/qhull.h delete mode 100644 extern/qhull/src/qhull_a.h delete mode 100644 extern/qhull/src/qhull_interface.cpp delete mode 100644 extern/qhull/src/qset.c delete mode 100644 extern/qhull/src/qset.h delete mode 100644 extern/qhull/src/qvoronoi.c delete mode 100644 extern/qhull/src/rbox.c delete mode 100644 extern/qhull/src/stat.c delete mode 100644 extern/qhull/src/stat.h delete mode 100644 extern/qhull/src/unix.c delete mode 100644 extern/qhull/src/user.c delete mode 100644 extern/qhull/src/user.h delete mode 100644 extern/qhull/src/user_eg.c delete mode 100644 extern/qhull/src/user_eg2.c delete mode 100644 extern/solid/CMakeLists.txt delete mode 100644 extern/solid/LICENSE_GPL.txt delete mode 100644 extern/solid/LICENSE_QPL.txt delete mode 100644 extern/solid/Makefile delete mode 100644 extern/solid/README.txt delete mode 100644 extern/solid/SConscript delete mode 100644 extern/solid/SOLID/SOLID.h delete mode 100644 extern/solid/SOLID/SOLID_broad.h delete mode 100644 extern/solid/SOLID/SOLID_types.h delete mode 100644 extern/solid/VisualC6/broad/broad.dsp delete mode 100644 extern/solid/VisualC6/complex/complex.dsp delete mode 100644 extern/solid/VisualC6/convex/convex.dsp delete mode 100644 extern/solid/VisualC6/dynamics/dynamics.dsp delete mode 100644 extern/solid/VisualC6/gldemo/gldemo.dsp delete mode 100644 extern/solid/VisualC6/mnm/mnm.dsp delete mode 100644 extern/solid/VisualC6/physics/physics.dsp delete mode 100644 extern/solid/VisualC6/sample/sample.dsp delete mode 100644 extern/solid/VisualC6/solid.dsw delete mode 100644 extern/solid/VisualC6/solid/solid.dsp delete mode 100644 extern/solid/VisualC6/solid_dll/solid_dll.dsp delete mode 100644 extern/solid/include/GEN_MinMax.h delete mode 100644 extern/solid/include/GEN_random.h delete mode 100644 extern/solid/include/MT/Interval.h delete mode 100644 extern/solid/include/MT/Matrix3x3.h delete mode 100644 extern/solid/include/MT/Quaternion.h delete mode 100644 extern/solid/include/MT/Transform.h delete mode 100644 extern/solid/include/MT/Tuple3.h delete mode 100644 extern/solid/include/MT/Tuple4.h delete mode 100644 extern/solid/include/MT/Vector3.h delete mode 100644 extern/solid/include/MT_BBox.h delete mode 100644 extern/solid/include/MT_Interval.h delete mode 100644 extern/solid/include/MT_Matrix3x3.h delete mode 100644 extern/solid/include/MT_Point3.h delete mode 100644 extern/solid/include/MT_Quaternion.h delete mode 100644 extern/solid/include/MT_Scalar.h delete mode 100644 extern/solid/include/MT_Transform.h delete mode 100644 extern/solid/include/MT_Vector3.h delete mode 100644 extern/solid/include/SOLID.h delete mode 100644 extern/solid/include/SOLID_broad.h delete mode 100644 extern/solid/include/SOLID_types.h delete mode 100644 extern/solid/make/msvc_7_0/broad/broad.vcproj delete mode 100644 extern/solid/make/msvc_7_0/complex/complex.vcproj delete mode 100644 extern/solid/make/msvc_7_0/convex/convex.vcproj delete mode 100644 extern/solid/make/msvc_7_0/solid.vcproj delete mode 100644 extern/solid/make/msvc_9_0/broad/broad.vcproj delete mode 100644 extern/solid/make/msvc_9_0/complex/complex.vcproj delete mode 100644 extern/solid/make/msvc_9_0/convex/convex.vcproj delete mode 100644 extern/solid/make/msvc_9_0/solid.vcproj delete mode 100644 extern/solid/src/DT_AlgoTable.h delete mode 100644 extern/solid/src/DT_C-api.cpp delete mode 100644 extern/solid/src/DT_Encounter.cpp delete mode 100644 extern/solid/src/DT_Encounter.h delete mode 100644 extern/solid/src/DT_Object.cpp delete mode 100644 extern/solid/src/DT_Object.h delete mode 100644 extern/solid/src/DT_RespTable.cpp delete mode 100644 extern/solid/src/DT_RespTable.h delete mode 100644 extern/solid/src/DT_Response.h delete mode 100644 extern/solid/src/DT_Scene.cpp delete mode 100644 extern/solid/src/DT_Scene.h delete mode 100644 extern/solid/src/Makefile delete mode 100644 extern/solid/src/broad/BP_C-api.cpp delete mode 100644 extern/solid/src/broad/BP_Endpoint.h delete mode 100644 extern/solid/src/broad/BP_EndpointList.cpp delete mode 100644 extern/solid/src/broad/BP_EndpointList.h delete mode 100644 extern/solid/src/broad/BP_Proxy.cpp delete mode 100644 extern/solid/src/broad/BP_Proxy.h delete mode 100644 extern/solid/src/broad/BP_ProxyList.h delete mode 100644 extern/solid/src/broad/BP_Scene.cpp delete mode 100644 extern/solid/src/broad/BP_Scene.h delete mode 100644 extern/solid/src/broad/Makefile delete mode 100644 extern/solid/src/complex/DT_BBoxTree.cpp delete mode 100644 extern/solid/src/complex/DT_BBoxTree.h delete mode 100644 extern/solid/src/complex/DT_CBox.h delete mode 100644 extern/solid/src/complex/DT_Complex.cpp delete mode 100644 extern/solid/src/complex/DT_Complex.h delete mode 100644 extern/solid/src/complex/Makefile delete mode 100644 extern/solid/src/convex/DT_Accuracy.cpp delete mode 100644 extern/solid/src/convex/DT_Accuracy.h delete mode 100644 extern/solid/src/convex/DT_Array.h delete mode 100644 extern/solid/src/convex/DT_Box.cpp delete mode 100644 extern/solid/src/convex/DT_Box.h delete mode 100644 extern/solid/src/convex/DT_Cone.cpp delete mode 100644 extern/solid/src/convex/DT_Cone.h delete mode 100644 extern/solid/src/convex/DT_Convex.cpp delete mode 100644 extern/solid/src/convex/DT_Convex.h delete mode 100644 extern/solid/src/convex/DT_Cylinder.cpp delete mode 100644 extern/solid/src/convex/DT_Cylinder.h delete mode 100644 extern/solid/src/convex/DT_Facet.cpp delete mode 100644 extern/solid/src/convex/DT_Facet.h delete mode 100644 extern/solid/src/convex/DT_GJK.h delete mode 100644 extern/solid/src/convex/DT_Hull.h delete mode 100644 extern/solid/src/convex/DT_IndexArray.h delete mode 100644 extern/solid/src/convex/DT_LineSegment.cpp delete mode 100644 extern/solid/src/convex/DT_LineSegment.h delete mode 100644 extern/solid/src/convex/DT_Minkowski.h delete mode 100644 extern/solid/src/convex/DT_PenDepth.cpp delete mode 100644 extern/solid/src/convex/DT_PenDepth.h delete mode 100644 extern/solid/src/convex/DT_Point.cpp delete mode 100644 extern/solid/src/convex/DT_Point.h delete mode 100644 extern/solid/src/convex/DT_Polyhedron.cpp delete mode 100644 extern/solid/src/convex/DT_Polyhedron.h delete mode 100644 extern/solid/src/convex/DT_Polytope.cpp delete mode 100644 extern/solid/src/convex/DT_Polytope.h delete mode 100644 extern/solid/src/convex/DT_Shape.h delete mode 100644 extern/solid/src/convex/DT_Sphere.cpp delete mode 100644 extern/solid/src/convex/DT_Sphere.h delete mode 100644 extern/solid/src/convex/DT_Transform.h delete mode 100644 extern/solid/src/convex/DT_Triangle.cpp delete mode 100644 extern/solid/src/convex/DT_Triangle.h delete mode 100644 extern/solid/src/convex/DT_VertexBase.h delete mode 100644 extern/solid/src/convex/Makefile create mode 100644 release/ui/space_buttons.py create mode 100644 release/ui/space_filebrowser.py create mode 100644 release/ui/space_info.py rename source/blender/{makesdna/DNA_radio_types.h => editors/include/ED_pointcache.h} (55%) create mode 100644 source/blender/editors/mesh/mesh_layers.c rename source/blender/editors/{mesh/editdeform.c => object/object_vgroup.c} (80%) create mode 100644 source/blender/editors/physics/ed_pointcache.c create mode 100644 source/blender/editors/space_file/file_panels.c delete mode 100644 source/blender/editors/space_info/info_header.c create mode 100644 source/blender/editors/space_info/info_ops.c delete mode 100644 source/blender/makesrna/intern/rna_radio.c delete mode 100644 source/blender/python/BPY_menus.c delete mode 100644 source/blender/python/BPY_menus.h delete mode 100644 source/blender/radiosity/CMakeLists.txt delete mode 100644 source/blender/radiosity/Makefile delete mode 100644 source/blender/radiosity/SConscript delete mode 100644 source/blender/radiosity/extern/include/radio.h delete mode 100644 source/blender/radiosity/extern/include/radio_types.h delete mode 100644 source/blender/radiosity/intern/Makefile delete mode 100644 source/blender/radiosity/intern/source/Makefile delete mode 100644 source/blender/radiosity/intern/source/raddisplay.c delete mode 100644 source/blender/radiosity/intern/source/radfactors.c delete mode 100644 source/blender/radiosity/intern/source/radio.c delete mode 100644 source/blender/radiosity/intern/source/radnode.c delete mode 100644 source/blender/radiosity/intern/source/radpostprocess.c delete mode 100644 source/blender/radiosity/intern/source/radpreprocess.c delete mode 100644 source/blender/radiosity/intern/source/radrender.c delete mode 100644 source/gameengine/Ketsji/KX_OdePhysicsController.cpp delete mode 100644 source/gameengine/Ketsji/KX_OdePhysicsController.h delete mode 100644 source/gameengine/Ketsji/KX_SumoPhysicsController.cpp delete mode 100644 source/gameengine/Ketsji/KX_SumoPhysicsController.h delete mode 100644 source/gameengine/Physics/BlOde/Makefile delete mode 100644 source/gameengine/Physics/BlOde/OdePhysicsController.cpp delete mode 100644 source/gameengine/Physics/BlOde/OdePhysicsController.h delete mode 100644 source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp delete mode 100644 source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h delete mode 100644 source/gameengine/Physics/BlOde/SConscript delete mode 100644 source/gameengine/Physics/Sumo/CMakeLists.txt delete mode 100644 source/gameengine/Physics/Sumo/Fuzzics/Makefile delete mode 100644 source/gameengine/Physics/Sumo/Fuzzics/include/SM_Callback.h delete mode 100644 source/gameengine/Physics/Sumo/Fuzzics/include/SM_ClientObjectInfo.h delete mode 100644 source/gameengine/Physics/Sumo/Fuzzics/include/SM_Debug.h delete mode 100644 source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h delete mode 100644 source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h delete mode 100644 source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h delete mode 100644 source/gameengine/Physics/Sumo/Fuzzics/include/SM_Props.h delete mode 100644 source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h delete mode 100644 source/gameengine/Physics/Sumo/Fuzzics/sample/Makefile delete mode 100644 source/gameengine/Physics/Sumo/Fuzzics/sample/particle.cpp delete mode 100644 source/gameengine/Physics/Sumo/Fuzzics/sample/particle0.cpp delete mode 100644 source/gameengine/Physics/Sumo/Fuzzics/src/Makefile delete mode 100644 source/gameengine/Physics/Sumo/Fuzzics/src/SM_FhObject.cpp delete mode 100644 source/gameengine/Physics/Sumo/Fuzzics/src/SM_MotionState.cpp delete mode 100644 source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp delete mode 100644 source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp delete mode 100644 source/gameengine/Physics/Sumo/Makefile delete mode 100644 source/gameengine/Physics/Sumo/SConscript delete mode 100644 source/gameengine/Physics/Sumo/SumoPHYCallbackBridge.cpp delete mode 100644 source/gameengine/Physics/Sumo/SumoPHYCallbackBridge.h delete mode 100644 source/gameengine/Physics/Sumo/SumoPhysicsController.cpp delete mode 100644 source/gameengine/Physics/Sumo/SumoPhysicsController.h delete mode 100644 source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp delete mode 100644 source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h delete mode 100644 source/gameengine/Physics/Sumo/convert.txt delete mode 100644 source/gameengine/Physics/Sumo/include/interpolator.h diff --git a/CMake/macros.cmake b/CMake/macros.cmake index bc8892e4b99..44fc2903875 100644 --- a/CMake/macros.cmake +++ b/CMake/macros.cmake @@ -61,7 +61,7 @@ MACRO(SETUP_LIBLINKS SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PLATFORM_LINKFLAGS} ") #TARGET_LINK_LIBRARIES(${target} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ${PYTHON_LIB} ${PYTHON_LINKFLAGS} ${JPEG_LIB} ${PNG_LIB} ${ZLIB_LIB} ${SDL_LIB} ${LLIBS}) - TARGET_LINK_LIBRARIES(${target} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ${PYTHON_LINKFLAGS} ${JPEG_LIB} ${PNG_LIB} ${ZLIB_LIB} ${SDL_LIB} ${LLIBS}) + TARGET_LINK_LIBRARIES(${target} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ${PYTHON_LINKFLAGS} ${JPEG_LIBRARY} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ${SDL_LIB} ${LLIBS}) # since we are using the local libs for python when compiling msvc projects, we need to add _d when compiling debug versions diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c7ee34cc14..714ec4095af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,7 +89,7 @@ INCLUDE(CMake/macros.cmake) IF(UNIX) IF(WITH_OPENAL) - INCLUDE(${CMAKE_ROOT}/Modules/FindOpenAL.cmake) + FIND_PACKAGE(OpenAL) IF(OPENAL_FOUND) SET(WITH_OPENAL ON) SET(OPENAL_LIB ${OPENAL_LIBRARY}) @@ -102,22 +102,12 @@ IF(UNIX) FIND_LIBRARY(INTL_LIBRARY NAMES intl PATHS - /usr/local/lib - /usr/lib /sw/lib - /opt/local/lib - /opt/csw/lib - /opt/lib ) FIND_LIBRARY(ICONV_LIBRARY NAMES iconv PATHS - /usr/local/lib - /usr/lib /sw/lib - /opt/local/lib - /opt/csw/lib - /opt/lib ) IF(INTL_LIBRARY AND ICONV_LIBRARY) SET(GETTEXT_LIB ${INTL_LIBRARY} ${ICONV_LIBRARY}) @@ -136,14 +126,14 @@ IF(UNIX) ) SET(FREETYPE_LIB freetype) - INCLUDE(${CMAKE_ROOT}/Modules/FindPythonLibs.cmake) + FIND_PACKAGE(PythonLibs) SET(PYTHON_INC "${PYTHON_INCLUDE_PATH}" CACHE STRING "") SET(PYTHON_LIB "${PYTHON_LIBRARIES}" CACHE STRING "") - INCLUDE(${CMAKE_ROOT}/Modules/FindPythonInterp.cmake) + FIND_PACKAGE(PythonInterp) SET(PYTHON_BINARY ${PYTHON_EXECUTABLE} CACHE STRING "") SET(PYTHON_LINKFLAGS "-Xlinker -export-dynamic") - INCLUDE(${CMAKE_ROOT}/Modules/FindSDL.cmake) + FIND_PACKAGE(SDL) SET(SDL_INC ${SDL_INCLUDE_DIR}) SET(SDL_LIB ${SDL_LIBRARY}) @@ -164,11 +154,11 @@ IF(UNIX) SET(FFMPEG_LIB avformat avcodec avutil avdevice swscale) SET(FFMPEG_LIBPATH ${FFMPEG}/lib) - SET(JPEG_LIB jpeg) + FIND_PACKAGE(JPEG REQUIRED) - SET(PNG_LIB png) + FIND_PACKAGE(PNG REQUIRED) - SET(ZLIB_LIB z) + FIND_PACKAGE(ZLIB REQUIRED) SET(LLIBS "-lXi -lutil -lc -lm -lpthread -lstdc++ -lX11 -ldl") @@ -186,12 +176,13 @@ IF(UNIX) # Better warnings SET(C_WARNINGS "-Wall -Wno-char-subscripts -Wpointer-arith -Wcast-align -Wnested-externs -Wdeclaration-after-statement") - INCLUDE_DIRECTORIES(/usr/include /usr/local/include) + INCLUDE_DIRECTORIES(${JPEG_INCLUDE_DIR} ${PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ) ENDIF(UNIX) IF(WIN32) - INCLUDE(${CMAKE_ROOT}/Modules/Platform/Windows-cl.cmake) + # this file is included anyway when building under Windows with cl.exe + # INCLUDE(${CMAKE_ROOT}/Modules/Platform/Windows-cl.cmake) SET(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/windows) @@ -202,10 +193,10 @@ IF(WIN32) ENDIF(CMAKE_CL_64) SET(PYTHON ${LIBDIR}/python) - SET(PYTHON_VERSION 2.5) + SET(PYTHON_VERSION 2.6) SET(PYTHON_INC "${PYTHON}/include/python${PYTHON_VERSION}") SET(PYTHON_BINARY python) - SET(PYTHON_LIB python25) + SET(PYTHON_LIB python26) SET(PYTHON_LIBPATH ${PYTHON}/lib) IF(CMAKE_CL_64) @@ -219,15 +210,15 @@ IF(WIN32) ENDIF(CMAKE_CL_64) IF(CMAKE_CL_64) - SET(PNG_LIB libpng) + SET(PNG_LIBRARIES libpng) ELSE(CMAKE_CL_64) - SET(PNG_LIB libpng_st) + SET(PNG_LIBRARIES libpng_st) ENDIF(CMAKE_CL_64) - SET(JPEG_LIB libjpeg) + SET(JPEG_LIBRARY libjpeg) SET(ZLIB ${LIBDIR}/zlib) SET(ZLIB_INC ${ZLIB}/include) - SET(ZLIB_LIB libz) + SET(ZLIB_LIBRARIES zlib) SET(ZLIB_LIBPATH ${ZLIB}/lib) SET(PTHREADS ${LIBDIR}/pthreads) @@ -335,7 +326,7 @@ IF(APPLE) ENDIF(CMAKE_OSX_ARCHITECTURES MATCHES i386) IF(WITH_OPENAL) - INCLUDE(${CMAKE_ROOT}/Modules/FindOpenAL.cmake) + FIND_PACKAGE(OpenAL) IF(OPENAL_FOUND) SET(WITH_OPENAL ON) SET(OPENAL_LIB ${OPENAL_LIBRARY}) @@ -362,12 +353,12 @@ IF(APPLE) SET(GETTEXT_LIB intl iconv) SET(GETTEXT_LIBPATH ${GETTEXT}/lib) - SET(PNG_LIB png) - SET(JPEG_LIB jpeg) + SET(PNG_LIBRARIES png) + SET(JPEG_LIBRARY jpeg) SET(ZLIB /usr) SET(ZLIB_INC "${ZLIB}/include") - SET(ZLIB_LIB z) + SET(ZLIB_LIBRARIES z) SET(FREETYPE ${LIBDIR}/freetype) SET(FREETYPE_INC ${FREETYPE}/include ${FREETYPE}/include/freetype2) @@ -438,7 +429,7 @@ ENDIF(WITH_WEBPLUGIN) #----------------------------------------------------------------------------- # Configure OpenGL. -INCLUDE(${CMAKE_ROOT}/Modules/FindOpenGL.cmake) +FIND_PACKAGE(OpenGL) INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR}) #----------------------------------------------------------------------------- # Extra compile flags diff --git a/SConstruct b/SConstruct index 808fa09bea0..b85bc799ea5 100644 --- a/SConstruct +++ b/SConstruct @@ -285,9 +285,7 @@ if 'blenderlite' in B.targets: target_env_defs['WITH_BF_SDL'] = False target_env_defs['WITH_BF_JPEG'] = False target_env_defs['WITH_BF_PNG'] = False - target_env_defs['WITH_BF_ODE'] = False target_env_defs['WITH_BF_BULLET'] = False - target_env_defs['WITH_BF_SOLID'] = False target_env_defs['WITH_BF_BINRELOC'] = False target_env_defs['BF_BUILDINFO'] = False target_env_defs['BF_NO_ELBEEM'] = True diff --git a/config/darwin-config.py b/config/darwin-config.py index 080820f885a..785f1cb42a2 100644 --- a/config/darwin-config.py +++ b/config/darwin-config.py @@ -141,20 +141,11 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' WITH_BF_GAMEENGINE=True WITH_BF_PLAYER=True -WITH_BF_ODE = False -BF_ODE = LIBDIR + '/ode' -BF_ODE_INC = '${BF_ODE}/include' -BF_ODE_LIB = '${BF_ODE}/lib/libode.a' - WITH_BF_BULLET = True BF_BULLET = '#extern/bullet2/src' BF_BULLET_INC = '${BF_BULLET}' BF_BULLET_LIB = 'extern_bullet' -BF_SOLID = '#extern/solid' -BF_SOLID_INC = '${BF_SOLID}' -BF_SOLID_LIB = 'extern_solid' - #WITH_BF_NSPR = True #BF_NSPR = $(LIBDIR)/nspr #BF_NSPR_INC = -I$(BF_NSPR)/include -I$(BF_NSPR)/include/nspr diff --git a/config/irix6-config.py b/config/irix6-config.py index 3c8fd0dece4..87af6b29eb1 100644 --- a/config/irix6-config.py +++ b/config/irix6-config.py @@ -74,20 +74,11 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' WITH_BF_GAMEENGINE='false' -WITH_BF_ODE = 'false' -BF_ODE = LIBDIR + '/ode' -BF_ODE_INC = BF_ODE + '/include' -BF_ODE_LIB = BF_ODE + '/lib/libode.a' - WITH_BF_BULLET = 'true' BF_BULLET = '#extern/bullet2/src' BF_BULLET_INC = '${BF_BULLET}' BF_BULLET_LIB = 'extern_bullet' -BF_SOLID = '#extern/solid' -BF_SOLID_INC = '${BF_SOLID}' -BF_SOLID_LIB = 'extern_solid' - #WITH_BF_NSPR = 'true' #BF_NSPR = $(LIBDIR)/nspr #BF_NSPR_INC = -I$(BF_NSPR)/include -I$(BF_NSPR)/include/nspr diff --git a/config/linux2-config.py b/config/linux2-config.py index 4cea4bb8e05..86de10c8fb3 100644 --- a/config/linux2-config.py +++ b/config/linux2-config.py @@ -77,20 +77,11 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = True -WITH_BF_ODE = False -BF_ODE = LIBDIR + '/ode' -BF_ODE_INC = BF_ODE + '/include' -BF_ODE_LIB = BF_ODE + '/lib/libode.a' - WITH_BF_BULLET = True BF_BULLET = '#extern/bullet2/src' BF_BULLET_INC = '${BF_BULLET}' BF_BULLET_LIB = 'extern_bullet' -BF_SOLID = '#extern/solid' -BF_SOLID_INC = '${BF_SOLID}' -BF_SOLID_LIB = 'extern_solid' - #WITH_BF_NSPR = True #BF_NSPR = $(LIBDIR)/nspr #BF_NSPR_INC = -I$(BF_NSPR)/include -I$(BF_NSPR)/include/nspr diff --git a/config/linuxcross-config.py b/config/linuxcross-config.py index 2f15ef67e6c..5e5c44ecd69 100644 --- a/config/linuxcross-config.py +++ b/config/linuxcross-config.py @@ -74,20 +74,11 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' WITH_BF_GAMEENGINE = False -WITH_BF_ODE = True -BF_ODE = LIBDIR + '/ode' -BF_ODE_INC = BF_ODE + '/include' -BF_ODE_LIB = BF_ODE + '/lib/libode.a' - WITH_BF_BULLET = True BF_BULLET = '#extern/bullet2/src' BF_BULLET_INC = '${BF_BULLET}' BF_BULLET_LIB = 'extern_bullet' -BF_SOLID = '#extern/solid' -BF_SOLID_INC = '${BF_SOLID}' -BF_SOLID_LIB = 'extern_solid' - BF_WINTAB = LIBDIR + '/wintab' BF_WINTAB_INC = '${BF_WINTAB}/INCLUDE' diff --git a/config/openbsd3-config.py b/config/openbsd3-config.py index f27066b43f7..2b0621e2ed3 100644 --- a/config/openbsd3-config.py +++ b/config/openbsd3-config.py @@ -61,20 +61,11 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' WITH_BF_GAMEENGINE=False -WITH_BF_ODE = False -BF_ODE = LIBDIR + '/ode' -BF_ODE_INC = '${BF_ODE}/include' -BF_ODE_LIB = '${BF_ODE}/lib/libode.a' - WITH_BF_BULLET = True BF_BULLET = '#extern/bullet2/src' BF_BULLET_INC = '${BF_BULLET}' BF_BULLET_LIB = 'extern_bullet' -BF_SOLID = '#extern/solid' -BF_SOLID_INC = '${BF_SOLID}' -BF_SOLID_LIB = 'extern_solid' - #WITH_BF_NSPR = True #BF_NSPR = $(LIBDIR)/nspr #BF_NSPR_INC = -I$(BF_NSPR)/include -I$(BF_NSPR)/include/nspr diff --git a/config/sunos5-config.py b/config/sunos5-config.py index e050a5950aa..dc067b6f568 100644 --- a/config/sunos5-config.py +++ b/config/sunos5-config.py @@ -69,20 +69,11 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' WITH_BF_GAMEENGINE=False -WITH_BF_ODE = False -BF_ODE = LIBDIR + '/ode' -BF_ODE_INC = BF_ODE + '/include' -BF_ODE_LIB = BF_ODE + '/lib/libode.a' - WITH_BF_BULLET = True BF_BULLET = '#extern/bullet2/src' BF_BULLET_INC = '${BF_BULLET}' BF_BULLET_LIB = 'extern_bullet' -BF_SOLID = '#extern/solid' -BF_SOLID_INC = '${BF_SOLID}' -BF_SOLID_LIB = 'extern_solid' - #WITH_BF_NSPR = True #BF_NSPR = $(LIBDIR)/nspr #BF_NSPR_INC = -I$(BF_NSPR)/include -I$(BF_NSPR)/include/nspr diff --git a/config/win32-mingw-config.py b/config/win32-mingw-config.py index 5b9b2f9b9dc..42e56417f54 100644 --- a/config/win32-mingw-config.py +++ b/config/win32-mingw-config.py @@ -77,20 +77,11 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' WITH_BF_GAMEENGINE = False -WITH_BF_ODE = True -BF_ODE = LIBDIR + '/ode' -BF_ODE_INC = BF_ODE + '/include' -BF_ODE_LIB = BF_ODE + '/lib/libode.a' - WITH_BF_BULLET = True BF_BULLET = '#extern/bullet2/src' BF_BULLET_INC = '${BF_BULLET}' BF_BULLET_LIB = 'extern_bullet' -BF_SOLID = '#extern/solid' -BF_SOLID_INC = '${BF_SOLID}' -BF_SOLID_LIB = 'extern_solid' - BF_WINTAB = LIBDIR + '/wintab' BF_WINTAB_INC = '${BF_WINTAB}/INCLUDE' diff --git a/config/win32-vc-config.py b/config/win32-vc-config.py index 04e87a23ed1..82babeb1a3a 100644 --- a/config/win32-vc-config.py +++ b/config/win32-vc-config.py @@ -90,20 +90,11 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = True -WITH_BF_ODE = True -BF_ODE = LIBDIR + '/ode' -BF_ODE_INC = BF_ODE + '/include' -BF_ODE_LIB = BF_ODE + '/lib/libode.a' - WITH_BF_BULLET = True BF_BULLET = '#extern/bullet2/src' BF_BULLET_INC = '${BF_BULLET}' BF_BULLET_LIB = 'extern_bullet' -BF_SOLID = '#extern/solid' -BF_SOLID_INC = '${BF_SOLID}' -BF_SOLID_LIB = 'extern_solid' - BF_WINTAB = LIBDIR + '/wintab' BF_WINTAB_INC = '${BF_WINTAB}/INCLUDE' diff --git a/config/win64-vc-config.py b/config/win64-vc-config.py index fcc6f1ab846..83e27a85574 100644 --- a/config/win64-vc-config.py +++ b/config/win64-vc-config.py @@ -93,20 +93,11 @@ BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = False -WITH_BF_ODE = True -BF_ODE = LIBDIR + '/ode' -BF_ODE_INC = BF_ODE + '/include' -BF_ODE_LIB = BF_ODE + '/lib/libode.a' - WITH_BF_BULLET = True BF_BULLET = '#extern/bullet2/src' BF_BULLET_INC = '${BF_BULLET}' BF_BULLET_LIB = 'extern_bullet' -BF_SOLID = '#extern/solid' -BF_SOLID_INC = '${BF_SOLID}' -BF_SOLID_LIB = 'extern_solid' - BF_WINTAB = LIBDIR + '/wintab' BF_WINTAB_INC = '${BF_WINTAB}/INCLUDE' diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt index 8dcace11e7d..b6cfe3b113e 100644 --- a/extern/CMakeLists.txt +++ b/extern/CMakeLists.txt @@ -24,11 +24,6 @@ # # ***** END GPL LICENSE BLOCK ***** -IF(WITH_GAMEENGINE) - ADD_SUBDIRECTORY(qhull) - ADD_SUBDIRECTORY(solid) -ENDIF(WITH_GAMEENGINE) - IF(WITH_BULLET) ADD_SUBDIRECTORY(bullet2) ENDIF(WITH_BULLET) diff --git a/extern/Makefile b/extern/Makefile index 8311006444f..61499da8743 100644 --- a/extern/Makefile +++ b/extern/Makefile @@ -30,7 +30,7 @@ include nan_definitions.mk SOURCEDIR = extern DIR = $(OCGDIR)/extern -DIRS = qhull/src solid glew/src +DIRS = glew/src ifeq ($(WITH_FFMPEG), true) ifeq ($(NAN_FFMPEG), $(LCGDIR)/ffmpeg) diff --git a/extern/SConscript b/extern/SConscript index 126f40b00b3..175613c3d2b 100644 --- a/extern/SConscript +++ b/extern/SConscript @@ -4,10 +4,6 @@ Import('env') SConscript(['glew/SConscript']) -if env['WITH_BF_GAMEENGINE']: - if env['WITH_BF_SOLID']: - SConscript(['qhull/SConscript', 'solid/SConscript']) - if env['WITH_BF_BULLET']: SConscript(['bullet2/src/SConscript']) diff --git a/extern/qhull/CMakeLists.txt b/extern/qhull/CMakeLists.txt deleted file mode 100644 index f2ac24afff3..00000000000 --- a/extern/qhull/CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -# $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, Blender Foundation -# All rights reserved. -# -# The Original Code is: all of this file. -# -# Contributor(s): Jacques Beaurain. -# -# ***** END GPL LICENSE BLOCK ***** - -SET(INC include src) - -SET(SRC - src/geom.c - src/geom2.c - src/global.c - src/io.c - src/mem.c - src/merge.c - src/poly.c - src/poly2.c - src/qhull.c - src/qset.c - src/stat.c - src/user.c -) - -BLENDERLIB(extern_qhull "${SRC}" "${INC}") -#, libtype=['game2','player'], priority=[50, 85] diff --git a/extern/qhull/COPYING.txt b/extern/qhull/COPYING.txt deleted file mode 100644 index 1334eba6d0b..00000000000 --- a/extern/qhull/COPYING.txt +++ /dev/null @@ -1,37 +0,0 @@ - Qhull, Copyright (c) 1993-2002 - - The National Science and Technology Research Center for - Computation and Visualization of Geometric Structures - (The Geometry Center) - University of Minnesota - 400 Lind Hall - 207 Church Street S.E. - Minneapolis, MN 55455 USA - - email: qhull@geom.umn.edu - -This software includes Qhull from The Geometry Center. Qhull is -copyrighted as noted above. Qhull is free software and may be obtained -via http from www.geom.umn.edu. It may be freely copied, modified, -and redistributed under the following conditions: - -1. All copyright notices must remain intact in all files. - -2. A copy of this text file must be distributed along with any copies - of Qhull that you redistribute; this includes copies that you have - modified, or copies of programs or other software products that - include Qhull. - -3. If you modify Qhull, you must include a notice giving the - name of the person performing the modification, the date of - modification, and the reason for such modification. - -4. When distributing modified versions of Qhull, or other software - products that include Qhull, you must provide notice that the original - source code may be obtained as noted above. - -5. There is no warranty or other guarantee of fitness for Qhull, it is - provided solely "as is". Bug reports or fixes may be sent to - qhull_bug@geom.umn.edu; the authors may or may not act on them as - they desire. - diff --git a/extern/qhull/README.txt b/extern/qhull/README.txt deleted file mode 100644 index 9ef958a1f47..00000000000 --- a/extern/qhull/README.txt +++ /dev/null @@ -1,318 +0,0 @@ -Name - - qhull, rbox 2002.1 August 20, 2002 - -Convex hull, Delaunay triangulation, Voronoi diagrams, Halfspace intersection - - Documentation: - html/index.htm - - Available from: - - - - - Version 1 (simplicial only): - - - - News and a paper: - - - -Purpose - - Qhull is a general dimension convex hull program that reads a set - of points from stdin, and outputs the smallest convex set that contains - the points to stdout. It also generates Delaunay triangulations, Voronoi - diagrams, furthest-site Voronoi diagrams, and halfspace intersections - about a point. - - Rbox is a useful tool in generating input for Qhull; it generates - hypercubes, diamonds, cones, circles, simplices, spirals, - lattices, and random points. - - Qhull produces graphical output for Geomview. This helps with - understanding the output. - - -Environment requirements - - Qhull and rbox should run on all 32-bit and 64-bit computers. Use - an ANSI C or C++ compiler to compile the program. The software is - self-contained. - - Qhull is copyrighted software. Please read COPYING.txt and REGISTER.txt - before using or distributing Qhull. - -To contribute to Qhull - - Qhull is on Savannah, http://savannah.gnu.org/projects/qhull/ - -Qhull on Windows 95, 98, ME, NT, 2000, XP - - The zip file contains rbox.exe, qhull.exe, qconvex.exe, qdelaunay.exe, - qhalf.exe, qvoronoi.exe, documentation files, and source files. - - To install Qhull: - - Unzip the files into a directory. You may use WinZip32 - - Open a DOS window for the directory. - - In Windows 95, the DOS window needs improvement. - - Double-click on qhull\eg\qhull-go.bat to call doskey (arrow keys). - - Increase the size of the screen font to 8x12. - - If the text is too dim, fix the screen colors with shareware (e.g., crt.exe) - - If you use qhull a lot, consider using the Cygwin Unix shell, - Cygwin tools (http://sources.redhat.com/cygwin/) - - Execute 'qconvex' for a synopsis and examples. - - Execute 'rbox 10 | qconvex' to compute the convex hull of 10 random points. - - Execute 'rbox 10 | qconvex i TO file' to write results to 'file'. - - If an error occurs, Windows 95 sends the error to stdout instead of stderr - - use 'TO xxx' to send normal output to xxx and error output to stdout - - Browse the documentation: qhull\html\index.htm - -Compiling for Unix - - The gzip file, qhull.tgz, contains documentation and source files for - qhull and rbox. - - To unpack the gzip file - - tar zxf qhull.tgz - - cd qhull - - Compiling with the Debian Make:[R. Laboissiere] - - cd src - - ./Make-config.sh - - cd .. - - configure - - make - - Compiling with Makefile (i.e., Makefile.txt) - - cd src - - in Makefile, check the CC, CCOPTS1, PRINTMAN, and PRINTC defines - - the defaults are gcc and enscript - - CCOPTS1 should include the ANSI flag. It defines __STDC__ - - in user.h, check the definitions of qh_SECticks and qh_CPUclock. - - use '#define qh_CLOCKtype 2' for timing runs longer than 1 hour - - type: make - - this builds: qhull qconvex qdelaunay qhalf qvoronoi rbox libqhull.a - - type: make doc - - this prints the man page - - See also qhull/html/index.htm - - if your compiler reports many errors, it is probably not a ANSI C compiler - - you will need to set the -ansi switch or find another compiler - - if your compiler warns about missing prototypes for fprintf() etc. - - this is ok, your compiler should have these in stdio.h - - if your compiler warns about missing prototypes for memset() etc. - - include memory.h in qhull_a.h - - if your compiler is gcc-2.95.1, you need to set flag -fno-strict-aliasing. - - This flag is set by default for other versions [Karas, Krishnaswami] - - if your compiler reports "global.c: storage size of 'qh_qh' isn't known" - - delete the initializer "={0}" in global.c, stat.c and mem.c - - if your compiler warns about "stat.c: improper initializer" - - this is ok, the initializer is not used - - if you have trouble building libqhull.a with 'ar' - - try 'make -f Makefile.txt qhullx' - - if the code compiles, the qhull test case will automatically execute - - if an error occurs, there's an incompatibility between machines - - For gcc-2.95.1, you need to set flag -fno-strict-aliasing. - It is set by default for other versions of gcc [Karas, Krishnaswami] - - If you can, try a different compiler - - You can turn off the Qhull memory manager with qh_NOmem in mem.h - - You can turn off compiler optimization (-O2 in Makefile) - - If you find the source of the problem, please let us know - - if you have Geomview (www.geomview.org) - - try 'rbox 100 | qconvex G >a' and load 'a' into Geomview - - run 'q_eg' for Geomview examples of Qhull output (see qh-eg.htm) - - to install the programs and their man pages: - - define MANDIR and BINDIR - - type 'make install' - -Compiling for Windows NT, 2000, XP with cygwin (www.cygwin.com) - - - install cygwin with gcc, make, ar, and ln - - cd qhull/src - - make -f Makefile.txt - -Compiling for Windows 95, 98, NT, 2000, XP - - Qhull compiles as a console application in Visual C++ 5.0 at warning - level 3. - - Visual C++ quickstart for qhull.exe: - - create a "Win32 console application" called "qhull" - - add the following files: - geom.c geom2.c global.c io.c mem.c merge.c poly.c poly2.c qhull.c - qset.c stat.c unix.c user.c - - create a "Win32 console application" called "rbox" - - add rbox.c - - Visual C++ quickstart for qhull library, qconvex.exe, etc. - - To simplify setting up lots of projects, - - create a temporary "Win32 console application" called "source" - - add all .c files from .../src/... - - In Tools::Options::Tab - Set tab size to 8 and indent size to 2 - - - create a "Win32 console application" called "rbox" - - move rbox.c from "qhull source" - - for Project:Settings..., Link - you only need the default libraries - - build the project - - - create a "Win32 static library" called "library" - - move these files from "qhull source" - geom.c geom2.c global.c io.c mem.c merge.c poly.c poly2.c qhull.c - qset.c stat.c user.c - - set the library file (use the same for debug and release) - - build the project - - - create a "Win32 console application" called "qhull" - - move unix.c from "qhull source" - - Set the library file in Project:Settings..., Link - - Qhull does not use other libraries - - - create a "Win32 console application" called "qconvex" - - move qconvex.c from "qhull source" - - Set the library file in Project:Settings..., Link - - - do the same for qdelaun.c, qhalf, qvoronoi.c, user_eg.c, user_eg2.c - - delete "qhull sources" since it is no longer needed - - Set the library file in Project:Settings..., Link - - use Project:Settings to make any changes - - use batch build to rebuild everything - - Qhull compiles with Borland C++ 5.0 bcc32. A Makefile is included. - Execute 'make -f MBorland'. If you use the Borland IDE, set the ANSI - option in Options:Project:Compiler:Source:Language-compliance. - - Qhull compiles with Borland C++ 4.02 for Win32 and DOS Power Pack. - Use 'make -f MBorland -D_DPMI'. Qhull 1.0 compiles with Borland - C++ 4.02. For rbox 1.0, use "bcc32 -WX -w- -O2-e -erbox -lc rbox.c". - Use the same options for Qhull 1.0. [D. Zwick] - - Qhull compiles with Metrowerks C++ 1.7 with the ANSI option. - - If you turn on full warnings, the compiler will report a number of - unused variables, variables set but not used, and dead code. These are - intentional. For example, variables may be initialized (unnecessarily) - to prevent warnings about possible use of uninitialized variables. - -Compiling for the Power Macintosh - - Qhull compiles for the Power Macintosh with Metrowerk's C compiler. - It uses the SIOUX interface to read point coordinates and return output. - There is no graphical output. For project files, see 'Compiling for - Windows 95'. Instead of using SIOUX, Qhull may be embedded within an - application. - - Version 1 is available for Macintosh computers by download of qhull.sit.hqx - It reads point coordinates from a standard file and returns output - to a standard file. There is no graphical output. - - -Compiling for other machines - - Some users have reported problems with compiling Qhull under Irix 5.1. It - compiles under other versions of Irix. - - If you have troubles with the memory manager, you can turn it off by - defining qh_NOmem in mem.h. - - You may compile Qhull with a C++ compiler. - - -Distributed files - - README.txt // instructions for installing Qhull - REGISTER.txt // Qhull registration - COPYING.txt // copyright notice - Announce.txt // announcement - Changes.txt // change history for Qhull and rbox - qh-faq.htm // Frequently asked questions - qh-home.htm // Home page - qh-get.htm // Download page - html/index.htm // Manual - Makefile.txt // Makefile for Unix or cygwin 'make' - MBorland // Makefile for Borland C++/Win32 - Make-config.sh // Create Debian configure and automake - -src/ - rbox consists of: - rbox.exe // Win32 executable (.zip only) - rbox.htm // html manual - rbox.man // Unix man page - rbox.txt - rbox.c // source program - - qhull consists of: - qhull.exe // Win32 executables (.zip only) - qconvex.exe - qdelaunay.exe - qhalf.exe - qvoronoi.exe - qhull-go.bat // DOS window - qconvex.htm // html manuals - qdelaun.htm - qdelau_f.htm - qhalf.htm - qvoronoi.htm - qvoron_f.htm - qh-eg.htm - qh-impre.htm - qh-in.htm - index.htm - qh-opt*.htm - qh-quick.htm - qh--4d.gif,etc. // images for manual - qhull.man // Unix man page - qhull.txt - q_eg // shell script for Geomview examples - q_egtest // shell script for Geomview test examples - q_test // shell script to test qhull - - top-level source files: - src/index.htm // index to source files - qh-...htm // specific files - user.h // header file of user definable constants - qhull.h // header file for qhull - unix.c // Unix front end to qhull - qhull.c // Quickhull algorithm with partitioning - user.c // user re-definable functions - user_eg.c // example of incorporating qhull into a user program - user_eg2.c // more complex example - qhull_interface.cpp // call Qhull from C++ - - other source files: - qhull_a.h // include file for *.c - geom.c // geometric routines - geom2.c - geom.h - global.c // global variables - io.c // input-output routines - io.h - mem.c // memory routines, this is stand-alone code - mem.h - merge.c // merging of non-convex facets - merge.h - poly.c // polyhedron routines - poly2.c - poly.h - qset.c // set routines, this only depends on mem.c - qset.h - stat.c // statistics - stat.h - -Authors: - - C. Bradford Barber Hannu Huhdanpaa - bradb@geom.umn.edu hannu@geom.umn.edu - - c/o The Geometry Center - University of Minnesota - 400 Lind Hall - 207 Church Street S.E. - Minneapolis, MN 55455 - - This software was developed under NSF grants NSF/DMS-8920161 and - NSF-CCR-91-15793 750-7504 at the Geometry Center and Harvard - University. If you find Qhull useful, please let us know. diff --git a/extern/qhull/REGISTER.txt b/extern/qhull/REGISTER.txt deleted file mode 100644 index 767eb1c0cda..00000000000 --- a/extern/qhull/REGISTER.txt +++ /dev/null @@ -1,37 +0,0 @@ -Dear User of Geometry Center Software: - -We would like to find out how you are using our software. Think of -Geometry Center software as a new kind of shareware: you share your -science and successes with us, and we share our software and support -with you. - -If you use Geometry Center software, please send us a note telling -us what you are doing with it. - -We need to know: - - (1) What you are working on - an abstract of your work would be - fine. - - (2) What Geometry Center software you use. - - (3) How that software has helped you, for example, by increasing - your productivity or allowing you to do things you could not do - before. In particular, if you feel that Geometry Center - software has had a direct bearing on your work, please tell us - about this. - -We encourage you to cite the use of any Geometry Center software you -have used in your publications. - -To cite Qhull, use - - Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T., "The Quickhull - algorithm for convex hulls," ACM Trans. on Mathematical Software, - Dec 1996. http://www.geom.umn.edu/software/qhull - -Please send e-mail to - - qhull@geom.umn.edu - -Thank you! diff --git a/extern/qhull/SConscript b/extern/qhull/SConscript deleted file mode 100644 index d3db67cddc0..00000000000 --- a/extern/qhull/SConscript +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/python -import sys -import os - -Import('env') -defs = '' -cflags = [] -if sys.platform=='linux2' or sys.platform=='linux-i386': - cflags += ['-O2','-ansi'] -elif env['OURPLATFORM']=='win32-vc': - cflags += ['/O2'] -elif env['OURPLATFORM']=='win32-mingw': - cflags += ['-O2'] -elif sys.platform=='sunos5': - cflags += ['-O2', '-ansi'] -elif sys.platform=='darwin': - cflags += ['-O2', '-pipe', '-fPIC', '-funsigned-char', '-ffast-math'] - -sources = ['src/geom.c', - 'src/geom2.c', - 'src/global.c', - 'src/io.c', - 'src/mem.c', - 'src/merge.c', - 'src/poly.c', - 'src/poly2.c', - 'src/qhull.c', - 'src/qset.c', - 'src/stat.c', - 'src/user.c'] - - -incs = 'include src' - -env.BlenderLib ( 'extern_qhull', sources, Split(incs), Split(defs), libtype=['extern'], priority=[50], compileflags = cflags) diff --git a/extern/qhull/VisualC6/qhull.dsw b/extern/qhull/VisualC6/qhull.dsw deleted file mode 100644 index 96c68d8e34c..00000000000 --- a/extern/qhull/VisualC6/qhull.dsw +++ /dev/null @@ -1,29 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "qhull"=".\qhull\qhull.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/extern/qhull/VisualC6/qhull/qhull.dsp b/extern/qhull/VisualC6/qhull/qhull.dsp deleted file mode 100644 index 6e059b0994c..00000000000 --- a/extern/qhull/VisualC6/qhull/qhull.dsp +++ /dev/null @@ -1,192 +0,0 @@ -# Microsoft Developer Studio Project File - Name="qhull" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -CFG=qhull - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "qhull.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "qhull.mak" CFG="qhull - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "qhull - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "qhull - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "qhull - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -LINK32=cwlink.exe -MTL=midl.exe -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo -# Begin Special Build Tool -SOURCE="$(InputPath)" -PostBuild_Cmds=XCOPY /Y ..\..\include\qhull\*.h ..\..\..\..\..\lib\windows\qhull\include\qhull\ XCOPY /Y Release\*.lib ..\..\..\..\..\lib\windows\qhull\lib\ -# End Special Build Tool - -!ELSEIF "$(CFG)" == "qhull - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Target_Dir "" -LINK32=cwlink.exe -MTL=midl.exe -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /MT /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo -# Begin Special Build Tool -SOURCE="$(InputPath)" -PostBuild_Cmds=XCOPY /Y ..\..\include\qhull\*.h ..\..\..\..\..\lib\windows\qhull\include\qhull\ XCOPY /Y Debug\*.lib ..\..\..\..\..\lib\windows\qhull\lib\Debug\ -# End Special Build Tool - -!ENDIF - -# Begin Target - -# Name "qhull - Win32 Release" -# Name "qhull - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\..\src\geom.c -# End Source File -# Begin Source File - -SOURCE=..\..\src\geom2.c -# End Source File -# Begin Source File - -SOURCE=..\..\src\global.c -# End Source File -# Begin Source File - -SOURCE=..\..\src\io.c -# End Source File -# Begin Source File - -SOURCE=..\..\src\mem.c -# End Source File -# Begin Source File - -SOURCE=..\..\src\merge.c -# End Source File -# Begin Source File - -SOURCE=..\..\src\poly.c -# End Source File -# Begin Source File - -SOURCE=..\..\src\poly2.c -# End Source File -# Begin Source File - -SOURCE=..\..\src\qhull.c -# End Source File -# Begin Source File - -SOURCE=..\..\src\qset.c -# End Source File -# Begin Source File - -SOURCE=..\..\src\stat.c -# End Source File -# Begin Source File - -SOURCE=..\..\src\user.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=..\..\src\geom.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\io.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\mem.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\merge.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\poly.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\qhull.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\qhull_a.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\qset.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\stat.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\user.h -# End Source File -# End Group -# End Target -# End Project diff --git a/extern/qhull/include/qhull/geom.h b/extern/qhull/include/qhull/geom.h deleted file mode 100644 index 32440cff56f..00000000000 --- a/extern/qhull/include/qhull/geom.h +++ /dev/null @@ -1,177 +0,0 @@ -/*
  ---------------------------------
-
-  geom.h 
-    header file for geometric routines
-
-   see qh-geom.htm and geom.c
-
-   copyright (c) 1993-2002 The Geometry Center        
-*/
-
-#ifndef qhDEFgeom
-#define qhDEFgeom 1
-
-/* ============ -macros- ======================== */
-
-/*----------------------------------
-   
-  fabs_(a)
-    returns the absolute value of a
-*/
-#define fabs_( a ) ((( a ) < 0 ) ? -( a ):( a ))
-               
-/*----------------------------------
-  
-  fmax_(a,b)
-    returns the maximum value of a and b
-*/
-#define fmax_( a,b )  ( ( a ) < ( b ) ? ( b ) : ( a ) )
-
-/*----------------------------------
-
-  fmin_(a,b)
-    returns the minimum value of a and b
-*/
-#define fmin_( a,b )  ( ( a ) > ( b ) ? ( b ) : ( a ) )
-
-/*----------------------------------
-
-  maximize_(maxval, val)
-    set maxval to val if val is greater than maxval
-*/
-#define maximize_( maxval, val ) {if (( maxval ) < ( val )) ( maxval )= ( val );}
-
-/*----------------------------------
-
-  minimize_(minval, val)
-    set minval to val if val is less than minval
-*/
-#define minimize_( minval, val ) {if (( minval ) > ( val )) ( minval )= ( val );}
-
-/*----------------------------------
-
-  det2_(a1, a2,     
-        b1, b2)
-  
-    compute a 2-d determinate
-*/
-#define det2_( a1,a2,b1,b2 ) (( a1 )*( b2 ) - ( a2 )*( b1 ))
-
-/*----------------------------------
-  
-  det3_(a1, a2, a3,    
-       b1, b2, b3,
-       c1, c2, c3)
-  
-    compute a 3-d determinate
-*/
-#define det3_( a1,a2,a3,b1,b2,b3,c1,c2,c3 ) ( ( a1 )*det2_( b2,b3,c2,c3 ) \
-                - ( b1 )*det2_( a2,a3,c2,c3 ) + ( c1 )*det2_( a2,a3,b2,b3 ) )
-
-/*----------------------------------
-  
-  dX( p1, p2 )
-  dY( p1, p2 )
-  dZ( p1, p2 )
-  
-    given two indices into rows[],
-
-    compute the difference between X, Y, or Z coordinates
-*/
-#define dX( p1,p2 )  ( *( rows[p1] ) - *( rows[p2] ))
-#define dY( p1,p2 )  ( *( rows[p1]+1 ) - *( rows[p2]+1 ))
-#define dZ( p1,p2 )  ( *( rows[p1]+2 ) - *( rows[p2]+2 ))
-#define dW( p1,p2 )  ( *( rows[p1]+3 ) - *( rows[p2]+3 ))
-
-/*============= prototypes in alphabetical order, infrequent at end ======= */
-
-void    qh_backnormal (realT **rows, int numrow, int numcol, boolT sign, coordT *normal, boolT *nearzero);
-void	qh_distplane (pointT *point, facetT *facet, realT *dist);
-facetT *qh_findbest (pointT *point, facetT *startfacet,
-		     boolT bestoutside, boolT isnewfacets, boolT noupper,
-		     realT *dist, boolT *isoutside, int *numpart);
-facetT *qh_findbesthorizon (boolT ischeckmax, pointT *point, 
-	             facetT *startfacet, boolT noupper, realT *bestdist, int *numpart);
-facetT *qh_findbestnew (pointT *point, facetT *startfacet, realT *dist, 
-		     boolT bestoutside, boolT *isoutside, int *numpart);
-void 	qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero);
-realT   qh_getangle(pointT *vect1, pointT *vect2);
-pointT *qh_getcenter(setT *vertices);
-pointT *qh_getcentrum(facetT *facet);
-realT   qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist);
-void    qh_normalize (coordT *normal, int dim, boolT toporient);
-void    qh_normalize2 (coordT *normal, int dim, boolT toporient, 
-            realT *minnorm, boolT *ismin);
-pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist);
-
-void    qh_setfacetplane(facetT *newfacets);
-void 	qh_sethyperplane_det (int dim, coordT **rows, coordT *point0, 
-              boolT toporient, coordT *normal, realT *offset, boolT *nearzero);
-void 	qh_sethyperplane_gauss (int dim, coordT **rows, pointT *point0, 
-	     boolT toporient, coordT *normal, coordT *offset, boolT *nearzero);
-boolT   qh_sharpnewfacets (void);
-
-/*========= infrequently used code in geom2.c =============*/
-
-
-coordT *qh_copypoints (coordT *points, int numpoints, int dimension);
-void    qh_crossproduct (int dim, realT vecA[3], realT vecB[3], realT vecC[3]);
-realT 	qh_determinant (realT **rows, int dim, boolT *nearzero);
-realT   qh_detjoggle (pointT *points, int numpoints, int dimension);
-void    qh_detroundoff (void);
-realT   qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero);
-realT   qh_distnorm (int dim, pointT *point, pointT *normal, realT *offsetp);
-realT   qh_distround (int dimension, realT maxabs, realT maxsumabs);
-realT   qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv);
-realT   qh_facetarea (facetT *facet);
-realT   qh_facetarea_simplex (int dim, coordT *apex, setT *vertices, 
-          vertexT *notvertex,  boolT toporient, coordT *normal, realT *offset);
-pointT *qh_facetcenter (setT *vertices);
-facetT *qh_findgooddist (pointT *point, facetT *facetA, realT *distp, facetT **facetlist);
-void    qh_getarea (facetT *facetlist);
-boolT   qh_gram_schmidt(int dim, realT **rows);
-boolT   qh_inthresholds (coordT *normal, realT *angle);
-void    qh_joggleinput (void);
-realT  *qh_maxabsval (realT *normal, int dim);
-setT   *qh_maxmin(pointT *points, int numpoints, int dimension);
-realT   qh_maxouter (void);
-void    qh_maxsimplex (int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex);
-realT   qh_minabsval (realT *normal, int dim);
-int     qh_mindiff (realT *vecA, realT *vecB, int dim);
-boolT   qh_orientoutside (facetT *facet);
-void    qh_outerinner (facetT *facet, realT *outerplane, realT *innerplane);
-coordT  qh_pointdist(pointT *point1, pointT *point2, int dim);
-void    qh_printmatrix (FILE *fp, char *string, realT **rows, int numrow, int numcol);
-void    qh_printpoints (FILE *fp, char *string, setT *points);
-void    qh_projectinput (void);
-void 	qh_projectpoints (signed char *project, int n, realT *points, 
-             int numpoints, int dim, realT *newpoints, int newdim);
-int     qh_rand( void);
-void    qh_srand( int seed);
-realT   qh_randomfactor (void);
-void    qh_randommatrix (realT *buffer, int dim, realT **row);
-void    qh_rotateinput (realT **rows);
-void    qh_rotatepoints (realT *points, int numpoints, int dim, realT **rows);
-void    qh_scaleinput (void);
-void    qh_scalelast (coordT *points, int numpoints, int dim, coordT low,
-		   coordT high, coordT newhigh);
-void 	qh_scalepoints (pointT *points, int numpoints, int dim,
-  		realT *newlows, realT *newhighs);
-boolT   qh_sethalfspace (int dim, coordT *coords, coordT **nextp, 
-              coordT *normal, coordT *offset, coordT *feasible);
-coordT *qh_sethalfspace_all (int dim, int count, coordT *halfspaces, pointT *feasible);
-pointT *qh_voronoi_center (int dim, setT *points);
-
-#endif /* qhDEFgeom */
-
-
-
diff --git a/extern/qhull/include/qhull/io.h b/extern/qhull/include/qhull/io.h
deleted file mode 100644
index 351d56b3708..00000000000
--- a/extern/qhull/include/qhull/io.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
  ---------------------------------
-
-   io.h 
-   declarations of Input/Output functions
-
-   see README, qhull.h and io.c
-
-   copyright (c) 1993-2002, The Geometry Center
-*/
-
-#ifndef qhDEFio
-#define qhDEFio 1
-
-/*============ constants and flags ==================*/
-
-/*----------------------------------
-  
-  qh_MAXfirst
-    maximum length of first two lines of stdin
-*/
-#define qh_MAXfirst  200
-
-/*----------------------------------
-  
-  qh_MINradius
-    min radius for Gp and Gv, fraction of maxcoord
-*/
-#define qh_MINradius 0.02
-
-/*----------------------------------
-  
-  qh_GEOMepsilon
-    adjust outer planes for 'lines closer' and geomview roundoff.  
-    This prevents bleed through.
-*/
-#define qh_GEOMepsilon 2e-3
-
-/*----------------------------------
-  
-  qh_WHITESPACE
-    possible values of white space
-*/
-#define qh_WHITESPACE " \n\t\v\r\f"
-
-
-/*----------------------------------
-  
-  qh_RIDGE
-    to select which ridges to print in qh_eachvoronoi
-*/
-typedef enum
-{
-    qh_RIDGEall = 0, qh_RIDGEinner, qh_RIDGEouter
-}
-qh_RIDGE;
-
-/*----------------------------------
-  
-  printvridgeT
-    prints results of qh_printvdiagram
-
-  see:
-    qh_printvridge for an example
-*/
-typedef void (*printvridgeT)(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
-
-/*============== -prototypes in alphabetical order =========*/
-
-void    dfacet( unsigned id);
-void    dvertex( unsigned id);
-void    qh_countfacets (facetT *facetlist, setT *facets, boolT printall, 
-              int *numfacetsp, int *numsimplicialp, int *totneighborsp, 
-              int *numridgesp, int *numcoplanarsp, int *numnumtricoplanarsp);
-pointT *qh_detvnorm (vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp);
-setT   *qh_detvridge (vertexT *vertex);
-setT   *qh_detvridge3 (vertexT *atvertex, vertexT *vertex);
-int     qh_eachvoronoi (FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder);
-int     qh_eachvoronoi_all (FILE *fp, printvridgeT printvridge, boolT isupper, qh_RIDGE innerouter, boolT inorder);
-void	qh_facet2point(facetT *facet, pointT **point0, pointT **point1, realT *mindist);
-setT   *qh_facetvertices (facetT *facetlist, setT *facets, boolT allfacets);
-void    qh_geomplanes (facetT *facet, realT *outerplane, realT *innerplane);
-void    qh_markkeep (facetT *facetlist);
-setT   *qh_markvoronoi (facetT *facetlist, setT *facets, boolT printall, boolT *islowerp, int *numcentersp);
-void    qh_order_vertexneighbors(vertexT *vertex);
-void	qh_printafacet(FILE *fp, int format, facetT *facet, boolT printall);
-void    qh_printbegin (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
-void 	qh_printcenter (FILE *fp, int format, char *string, facetT *facet);
-void    qh_printcentrum (FILE *fp, facetT *facet, realT radius);
-void    qh_printend (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
-void    qh_printend4geom (FILE *fp, facetT *facet, int *num, boolT printall);
-void    qh_printextremes (FILE *fp, facetT *facetlist, setT *facets, int printall);
-void    qh_printextremes_2d (FILE *fp, facetT *facetlist, setT *facets, int printall);
-void    qh_printextremes_d (FILE *fp, facetT *facetlist, setT *facets, int printall);
-void	qh_printfacet(FILE *fp, facetT *facet);
-void	qh_printfacet2math(FILE *fp, facetT *facet, int notfirst);
-void	qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]);
-void    qh_printfacet2geom_points(FILE *fp, pointT *point1, pointT *point2,
-			       facetT *facet, realT offset, realT color[3]);
-void	qh_printfacet3math (FILE *fp, facetT *facet, int notfirst);
-void	qh_printfacet3geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]);
-void	qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]);
-void	qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]);
-void	qh_printfacet3vertex(FILE *fp, facetT *facet, int format);
-void	qh_printfacet4geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]);
-void	qh_printfacet4geom_simplicial(FILE *fp, facetT *facet, realT color[3]);
-void	qh_printfacetNvertex_nonsimplicial(FILE *fp, facetT *facet, int id, int format);
-void	qh_printfacetNvertex_simplicial(FILE *fp, facetT *facet, int format);
-void    qh_printfacetheader(FILE *fp, facetT *facet);
-void    qh_printfacetridges(FILE *fp, facetT *facet);
-void	qh_printfacets(FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
-void	qh_printhelp_degenerate(FILE *fp);
-void	qh_printhelp_singular(FILE *fp);
-void	qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2,
-  		   setT *vertices, realT color[3]);
-void	qh_printneighborhood (FILE *fp, int format, facetT *facetA, facetT *facetB, boolT printall);
-void    qh_printline3geom (FILE *fp, pointT *pointA, pointT *pointB, realT color[3]);
-void	qh_printpoint(FILE *fp, char *string, pointT *point);
-void	qh_printpointid(FILE *fp, char *string, int dim, pointT *point, int id);
-void    qh_printpoint3 (FILE *fp, pointT *point);
-void    qh_printpoints_out (FILE *fp, facetT *facetlist, setT *facets, int printall);
-void    qh_printpointvect (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]);
-void    qh_printpointvect2 (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius);
-void	qh_printridge(FILE *fp, ridgeT *ridge);
-void    qh_printspheres(FILE *fp, setT *vertices, realT radius);
-void    qh_printvdiagram (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
-int     qh_printvdiagram2 (FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder);
-void	qh_printvertex(FILE *fp, vertexT *vertex);
-void	qh_printvertexlist (FILE *fp, char* string, facetT *facetlist,
-                         setT *facets, boolT printall);
-void	qh_printvertices (FILE *fp, char* string, setT *vertices);
-void    qh_printvneighbors (FILE *fp, facetT* facetlist, setT *facets, boolT printall);
-void    qh_printvoronoi (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
-void    qh_printvnorm (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
-void    qh_printvridge (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
-void	qh_produce_output(void);
-void    qh_projectdim3 (pointT *source, pointT *destination);
-int     qh_readfeasible (int dim, char *remainder);
-coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
-void    qh_setfeasible (int dim);
-boolT	qh_skipfacet(facetT *facet);
-
-#endif /* qhDEFio */
diff --git a/extern/qhull/include/qhull/mem.h b/extern/qhull/include/qhull/mem.h
deleted file mode 100644
index e9ebd1bb9bc..00000000000
--- a/extern/qhull/include/qhull/mem.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
  ---------------------------------
-
-   mem.h 
-     prototypes for memory management functions
-
-   see qh-mem.htm, mem.c and qset.h
-
-   for error handling, writes message and calls
-     qh_errexit (qhmem_ERRmem, NULL, NULL) if insufficient memory
-       and
-     qh_errexit (qhmem_ERRqhull, NULL, NULL) otherwise
-
-   copyright (c) 1993-2002, The Geometry Center
-*/
-
-#ifndef qhDEFmem
-#define qhDEFmem
-
-/*---------------------------------
-  
-  qh_NOmem
-    turn off quick-fit memory allocation
-
-  notes:
-    mem.c implements Quickfit memory allocation for about 20% time
-    savings.  If it fails on your machine, try to locate the
-    problem, and send the answer to qhull@geom.umn.edu.  If this can
-    not be done, define qh_NOmem to use malloc/free instead.
-
-   #define qh_NOmem
-*/
-
-/*-------------------------------------------
-    to avoid bus errors, memory allocation must consider alignment requirements.
-    malloc() automatically takes care of alignment.   Since mem.c manages
-    its own memory, we need to explicitly specify alignment in
-    qh_meminitbuffers().
-
-    A safe choice is sizeof(double).  sizeof(float) may be used if doubles 
-    do not occur in data structures and pointers are the same size.  Be careful
-    of machines (e.g., DEC Alpha) with large pointers.  If gcc is available, 
-    use __alignof__(double) or fmax_(__alignof__(float), __alignof__(void *)).
-
-   see qh_MEMalign in user.h for qhull's alignment
-*/
-
-#define qhmem_ERRmem 4    /* matches qh_ERRmem in qhull.h */
-#define qhmem_ERRqhull 5  /* matches qh_ERRqhull in qhull.h */
-
-/*----------------------------------
-  
-  ptr_intT
-    for casting a void* to an integer-type
-  
-  notes:
-    On 64-bit machines, a pointer may be larger than an 'int'.  
-    qh_meminit() checks that 'long' holds a 'void*'
-*/
-typedef unsigned long ptr_intT;
-
-/*----------------------------------
- 
-  qhmemT
-    global memory structure for mem.c
- 
- notes:
-   users should ignore qhmem except for writing extensions
-   qhmem is allocated in mem.c 
-   
-   qhmem could be swapable like qh and qhstat, but then
-   multiple qh's and qhmem's would need to keep in synch.  
-   A swapable qhmem would also waste memory buffers.  As long
-   as memory operations are atomic, there is no problem with
-   multiple qh structures being active at the same time.
-   If you need separate address spaces, you can swap the
-   contents of qhmem.
-*/
-typedef struct qhmemT qhmemT;
-extern qhmemT qhmem; 
-
-struct qhmemT {               /* global memory management variables */
-  int      BUFsize;	      /* size of memory allocation buffer */
-  int      BUFinit;	      /* initial size of memory allocation buffer */
-  int      TABLEsize;         /* actual number of sizes in free list table */
-  int      NUMsizes;          /* maximum number of sizes in free list table */
-  int      LASTsize;          /* last size in free list table */
-  int      ALIGNmask;         /* worst-case alignment, must be 2^n-1 */
-  void	 **freelists;          /* free list table, linked by offset 0 */
-  int     *sizetable;         /* size of each freelist */
-  int     *indextable;        /* size->index table */
-  void    *curbuffer;         /* current buffer, linked by offset 0 */
-  void    *freemem;           /*   free memory in curbuffer */
-  int 	   freesize;          /*   size of free memory in bytes */
-  void 	  *tempstack;         /* stack of temporary memory, managed by users */
-  FILE    *ferr;              /* file for reporting errors */
-  int      IStracing;         /* =5 if tracing memory allocations */
-  int      cntquick;          /* count of quick allocations */
-                              /* remove statistics doesn't effect speed */
-  int      cntshort;          /* count of short allocations */
-  int      cntlong;           /* count of long allocations */
-  int      curlong;           /* current count of inuse, long allocations */
-  int      freeshort;	      /* count of short memfrees */
-  int      freelong;	      /* count of long memfrees */
-  int      totshort;          /* total size of short allocations */
-  int      totlong;           /* total size of long allocations */
-  int      maxlong;           /* maximum totlong */
-  int      cntlarger;         /* count of setlarger's */
-  int      totlarger;         /* total copied by setlarger */
-};
-
-
-/*==================== -macros ====================*/
-
-/*----------------------------------
-   
-  qh_memalloc_(size, object, type)  
-    returns object of size bytes 
-	assumes size<=qhmem.LASTsize and void **freelistp is a temp
-*/
-
-#ifdef qh_NOmem
-#define qh_memalloc_(size, freelistp, object, type) {\
-  object= (type*)qh_memalloc (size); }
-#else /* !qh_NOmem */
-
-#define qh_memalloc_(size, freelistp, object, type) {\
-  freelistp= qhmem.freelists + qhmem.indextable[size];\
-  if ((object= (type*)*freelistp)) {\
-    qhmem.cntquick++;  \
-    *freelistp= *((void **)*freelistp);\
-  }else object= (type*)qh_memalloc (size);}
-#endif
-
-/*----------------------------------
-   
-  qh_memfree_(object, size) 
-    free up an object
-
-  notes:
-    object may be NULL
-    assumes size<=qhmem.LASTsize and void **freelistp is a temp
-*/
-#ifdef qh_NOmem
-#define qh_memfree_(object, size, freelistp) {\
-  qh_memfree (object, size); }
-#else /* !qh_NOmem */
-
-#define qh_memfree_(object, size, freelistp) {\
-  if (object) { \
-    qhmem .freeshort++;\
-    freelistp= qhmem.freelists + qhmem.indextable[size];\
-    *((void **)object)= *freelistp;\
-    *freelistp= object;}}
-#endif
-
-/*=============== prototypes in alphabetical order ============*/
-
-void *qh_memalloc(int insize);
-void qh_memfree (void *object, int size);
-void qh_memfreeshort (int *curlong, int *totlong);
-void qh_meminit (FILE *ferr);
-void qh_meminitbuffers (int tracelevel, int alignment, int numsizes,
-			int bufsize, int bufinit);
-void qh_memsetup (void);
-void qh_memsize(int size);
-void qh_memstatistics (FILE *fp);
-
-#endif /* qhDEFmem */
diff --git a/extern/qhull/include/qhull/merge.h b/extern/qhull/include/qhull/merge.h
deleted file mode 100644
index 7fc2afa5967..00000000000
--- a/extern/qhull/include/qhull/merge.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
  ---------------------------------
-
-   merge.h 
-   header file for merge.c
-
-   see qh-merge.htm and merge.c
-
-   copyright (c) 1993-2002, The Geometry Center
-*/
-
-#ifndef qhDEFmerge
-#define qhDEFmerge 1
-
-
-/*============ -constants- ==============*/
-
-/*----------------------------------
-
-  qh_ANGLEredundant
-    indicates redundant merge in mergeT->angle
-*/
-#define qh_ANGLEredundant 6.0
-
-/*----------------------------------
-  
-  qh_ANGLEdegen
-    indicates degenerate facet in mergeT->angle
-*/
-#define qh_ANGLEdegen     5.0
-
-/*----------------------------------
-  
-  qh_ANGLEconcave
-    offset to indicate concave facets in mergeT->angle
-  
-  notes:
-    concave facets are assigned the range of [2,4] in mergeT->angle
-    roundoff error may make the angle less than 2
-*/
-#define qh_ANGLEconcave  1.5
-
-/*----------------------------------
-  
-  MRG... (mergeType)
-    indicates the type of a merge (mergeT->type)
-*/
-typedef enum {	/* in sort order for facet_mergeset */
-  MRGnone= 0,
-  MRGcoplanar,		/* centrum coplanar */
-  MRGanglecoplanar,	/* angle coplanar */
-  			/* could detect half concave ridges */
-  MRGconcave,		/* concave ridge */
-  MRGflip,		/* flipped facet. facet1 == facet2 */
-  MRGridge,		/* duplicate ridge (qh_MERGEridge) */
-                        /* degen and redundant go onto degen_mergeset */
-  MRGdegen,		/* degenerate facet (not enough neighbors) facet1 == facet2 */
-  MRGredundant,		/* redundant facet (vertex subset) */
-  			/* merge_degenredundant assumes degen < redundant */
-  MRGmirror,	        /* mirror facet from qh_triangulate */
-  ENDmrg
-} mergeType;
-
-/*----------------------------------
-  
-  qh_MERGEapex
-    flag for qh_mergefacet() to indicate an apex merge  
-*/
-#define qh_MERGEapex     True
-
-/*============ -structures- ====================*/
-
-/*----------------------------------
-     
-  mergeT
-    structure used to merge facets
-*/
-
-typedef struct mergeT mergeT;
-struct mergeT {		/* initialize in qh_appendmergeset */
-  realT   angle;        /* angle between normals of facet1 and facet2 */
-  facetT *facet1; 	/* will merge facet1 into facet2 */
-  facetT *facet2;
-  mergeType type;
-};
-
-
-/*=========== -macros- =========================*/
-
-/*----------------------------------
-     
-  FOREACHmerge_( merges ) {...}
-    assign 'merge' to each merge in merges
-       
-  notes:
-    uses 'mergeT *merge, **mergep;'
-    if qh_mergefacet(),
-      restart since qh.facet_mergeset may change
-    see FOREACHsetelement_
-*/
-#define FOREACHmerge_( merges ) FOREACHsetelement_(mergeT, merges, merge)
-
-/*============ prototypes in alphabetical order after pre/postmerge =======*/
-
-void    qh_premerge (vertexT *apex, realT maxcentrum, realT maxangle);
-void    qh_postmerge (char *reason, realT maxcentrum, realT maxangle, 
-             boolT vneighbors);
-void    qh_all_merges (boolT othermerge, boolT vneighbors);
-void    qh_appendmergeset(facetT *facet, facetT *neighbor, mergeType mergetype, realT *angle);
-setT   *qh_basevertices( facetT *samecycle);
-void    qh_checkconnect (void /* qh new_facets */);
-boolT   qh_checkzero (boolT testall);
-void    qh_copynonconvex (ridgeT *atridge);
-void    qh_degen_redundant_facet (facetT *facet);
-void   	qh_degen_redundant_neighbors (facetT *facet, facetT *delfacet);
-vertexT *qh_find_newvertex (vertexT *oldvertex, setT *vertices, setT *ridges);
-void    qh_findbest_test (boolT testcentrum, facetT *facet, facetT *neighbor,
-           facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp);
-facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp);
-void 	qh_flippedmerges(facetT *facetlist, boolT *wasmerge);
-void 	qh_forcedmerges( boolT *wasmerge);
-void	qh_getmergeset(facetT *facetlist);
-void 	qh_getmergeset_initial (facetT *facetlist);
-void    qh_hashridge (setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex);
-ridgeT *qh_hashridge_find (setT *hashtable, int hashsize, ridgeT *ridge, 
-              vertexT *vertex, vertexT *oldvertex, int *hashslot);
-void 	qh_makeridges(facetT *facet);
-void    qh_mark_dupridges(facetT *facetlist);
-void    qh_maydropneighbor (facetT *facet);
-int     qh_merge_degenredundant (void);
-void    qh_merge_nonconvex( facetT *facet1, facetT *facet2, mergeType mergetype);
-void    qh_mergecycle (facetT *samecycle, facetT *newfacet);
-void    qh_mergecycle_all (facetT *facetlist, boolT *wasmerge);
-void    qh_mergecycle_facets( facetT *samecycle, facetT *newfacet);
-void    qh_mergecycle_neighbors(facetT *samecycle, facetT *newfacet);
-void    qh_mergecycle_ridges(facetT *samecycle, facetT *newfacet);
-void    qh_mergecycle_vneighbors( facetT *samecycle, facetT *newfacet);
-void 	qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, boolT mergeapex);
-void    qh_mergefacet2d (facetT *facet1, facetT *facet2);
-void 	qh_mergeneighbors(facetT *facet1, facetT *facet2);
-void 	qh_mergeridges(facetT *facet1, facetT *facet2);
-void    qh_mergesimplex(facetT *facet1, facetT *facet2, boolT mergeapex);
-void    qh_mergevertex_del (vertexT *vertex, facetT *facet1, facetT *facet2);
-void    qh_mergevertex_neighbors(facetT *facet1, facetT *facet2);
-void	qh_mergevertices(setT *vertices1, setT **vertices);
-setT   *qh_neighbor_intersections (vertexT *vertex);
-void    qh_newvertices (setT *vertices);
-boolT   qh_reducevertices (void);
-vertexT *qh_redundant_vertex (vertexT *vertex);
-boolT   qh_remove_extravertices (facetT *facet);
-vertexT *qh_rename_sharedvertex (vertexT *vertex, facetT *facet);
-void	qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex);
-void    qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges,
-			facetT *oldfacet, facetT *neighborA);
-boolT 	qh_test_appendmerge (facetT *facet, facetT *neighbor);
-boolT   qh_test_vneighbors (void /* qh newfacet_list */);
-void    qh_tracemerge (facetT *facet1, facetT *facet2);
-void    qh_tracemerging (void);
-void    qh_updatetested( facetT *facet1, facetT *facet2);
-setT   *qh_vertexridges (vertexT *vertex);
-void    qh_vertexridges_facet (vertexT *vertex, facetT *facet, setT **ridges);
-void    qh_willdelete (facetT *facet, facetT *replace);
-
-#endif /* qhDEFmerge */
diff --git a/extern/qhull/include/qhull/poly.h b/extern/qhull/include/qhull/poly.h
deleted file mode 100644
index 294ec9527fc..00000000000
--- a/extern/qhull/include/qhull/poly.h
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
  ---------------------------------
-
-   poly.h 
-   header file for poly.c and poly2.c
-
-   see qh-poly.htm, qhull.h and poly.c
-
-   copyright (c) 1993-2002, The Geometry Center
-*/
-
-#ifndef qhDEFpoly
-#define qhDEFpoly 1
-
-/*===============   constants ========================== */
-
-/*----------------------------------
-  
-  ALGORITHMfault   
-    use as argument to checkconvex() to report errors during buildhull
-*/
-#define qh_ALGORITHMfault 0
-
-/*----------------------------------
-  
-  DATAfault        
-    use as argument to checkconvex() to report errors during initialhull
-*/
-#define qh_DATAfault 1
-
-/*----------------------------------
-  
-  DUPLICATEridge
-    special value for facet->neighbor to indicate a duplicate ridge
-  
-  notes:
-    set by matchneighbor, used by matchmatch and mark_dupridge
-*/
-#define qh_DUPLICATEridge ( facetT * ) 1L
-
-/*----------------------------------
-  
-  MERGEridge       flag in facet
-    special value for facet->neighbor to indicate a merged ridge
-  
-  notes:
-    set by matchneighbor, used by matchmatch and mark_dupridge
-*/
-#define qh_MERGEridge ( facetT * ) 2L
-
-
-/*============ -structures- ====================*/
-
-/*=========== -macros- =========================*/
-
-/*----------------------------------
-  
-  FORALLfacet_( facetlist ) { ... }
-    assign 'facet' to each facet in facetlist
-    
-  notes:
-    uses 'facetT *facet;'
-    assumes last facet is a sentinel
-    
-  see:
-    FORALLfacets
-*/
-#define FORALLfacet_( facetlist ) if ( facetlist ) for( facet=( facetlist );facet && facet->next;facet=facet->next )
-
-/*----------------------------------
-  
-  FORALLnew_facets { ... } 
-    assign 'newfacet' to each facet in qh.newfacet_list
-    
-  notes:
-    uses 'facetT *newfacet;'
-    at exit, newfacet==NULL
-*/
-#define FORALLnew_facets for( newfacet=qh newfacet_list;newfacet && newfacet->next;newfacet=newfacet->next )
-
-/*----------------------------------
-  
-  FORALLvertex_( vertexlist ) { ... }
-    assign 'vertex' to each vertex in vertexlist
-    
-  notes:
-    uses 'vertexT *vertex;'
-    at exit, vertex==NULL
-*/
-#define FORALLvertex_( vertexlist ) for ( vertex=( vertexlist );vertex && vertex->next;vertex= vertex->next )
-
-/*----------------------------------
-  
-  FORALLvisible_facets { ... }
-    assign 'visible' to each visible facet in qh.visible_list
-    
-  notes:
-    uses 'vacetT *visible;'
-    at exit, visible==NULL
-*/
-#define FORALLvisible_facets for (visible=qh visible_list; visible && visible->visible; visible= visible->next)
-
-/*----------------------------------
-  
-  FORALLsame_( newfacet ) { ... } 
-    assign 'same' to each facet in newfacet->f.samecycle
-    
-  notes:
-    uses 'facetT *same;'
-    stops when it returns to newfacet
-*/
-#define FORALLsame_(newfacet) for (same= newfacet->f.samecycle; same != newfacet; same= same->f.samecycle)
-
-/*----------------------------------
-  
-  FORALLsame_cycle_( newfacet ) { ... } 
-    assign 'same' to each facet in newfacet->f.samecycle
-    
-  notes:
-    uses 'facetT *same;'
-    at exit, same == NULL
-*/
-#define FORALLsame_cycle_(newfacet) \
-     for (same= newfacet->f.samecycle; \
-         same; same= (same == newfacet ?  NULL : same->f.samecycle))
-
-/*----------------------------------
-  
-  FOREACHneighborA_( facet ) { ... }
-    assign 'neighborA' to each neighbor in facet->neighbors
-  
-  FOREACHneighborA_( vertex ) { ... }
-    assign 'neighborA' to each neighbor in vertex->neighbors
-  
-  declare:
-    facetT *neighborA, **neighborAp;
-
-  see:
-    FOREACHsetelement_
-*/
-#define FOREACHneighborA_(facet)  FOREACHsetelement_(facetT, facet->neighbors, neighborA)
-
-/*----------------------------------
-  
-  FOREACHvisible_( facets ) { ... } 
-    assign 'visible' to each facet in facets
-    
-  notes:
-    uses 'facetT *facet, *facetp;'
-    see FOREACHsetelement_
-*/
-#define FOREACHvisible_(facets) FOREACHsetelement_(facetT, facets, visible)
-
-/*----------------------------------
-  
-  FOREACHnewfacet_( facets ) { ... } 
-    assign 'newfacet' to each facet in facets
-    
-  notes:
-    uses 'facetT *newfacet, *newfacetp;'
-    see FOREACHsetelement_
-*/
-#define FOREACHnewfacet_(facets) FOREACHsetelement_(facetT, facets, newfacet)
-
-/*----------------------------------
-  
-  FOREACHvertexA_( vertices ) { ... } 
-    assign 'vertexA' to each vertex in vertices
-    
-  notes:
-    uses 'vertexT *vertexA, *vertexAp;'
-    see FOREACHsetelement_
-*/
-#define FOREACHvertexA_(vertices) FOREACHsetelement_(vertexT, vertices, vertexA)
-
-/*----------------------------------
-  
-  FOREACHvertexreverse12_( vertices ) { ... } 
-    assign 'vertex' to each vertex in vertices
-    reverse order of first two vertices
-    
-  notes:
-    uses 'vertexT *vertex, *vertexp;'
-    see FOREACHsetelement_
-*/
-#define FOREACHvertexreverse12_(vertices) FOREACHsetelementreverse12_(vertexT, vertices, vertex)
-
-
-/*=============== prototypes poly.c in alphabetical order ================*/
-
-void    qh_appendfacet(facetT *facet);
-void    qh_appendvertex(vertexT *vertex);
-void 	qh_attachnewfacets (void);
-boolT   qh_checkflipped (facetT *facet, realT *dist, boolT allerror);
-void	qh_delfacet(facetT *facet);
-void 	qh_deletevisible(void /*qh visible_list, qh horizon_list*/);
-setT   *qh_facetintersect (facetT *facetA, facetT *facetB, int *skipAp,int *skipBp, int extra);
-unsigned qh_gethash (int hashsize, setT *set, int size, int firstindex, void *skipelem);
-facetT *qh_makenewfacet(setT *vertices, boolT toporient, facetT *facet);
-void    qh_makenewplanes ( void /* newfacet_list */);
-facetT *qh_makenew_nonsimplicial (facetT *visible, vertexT *apex, int *numnew);
-facetT *qh_makenew_simplicial (facetT *visible, vertexT *apex, int *numnew);
-void    qh_matchneighbor (facetT *newfacet, int newskip, int hashsize,
-			  int *hashcount);
-void	qh_matchnewfacets (void);
-boolT   qh_matchvertices (int firstindex, setT *verticesA, int skipA, 
-			  setT *verticesB, int *skipB, boolT *same);
-facetT *qh_newfacet(void);
-ridgeT *qh_newridge(void);
-int     qh_pointid (pointT *point);
-void 	qh_removefacet(facetT *facet);
-void 	qh_removevertex(vertexT *vertex);
-void    qh_updatevertices (void);
-
-
-/*========== -prototypes poly2.c in alphabetical order ===========*/
-
-void    qh_addhash (void* newelem, setT *hashtable, int hashsize, unsigned hash);
-void 	qh_check_bestdist (void);
-void    qh_check_maxout (void);
-void    qh_check_output (void);
-void    qh_check_point (pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2);
-void   	qh_check_points(void);
-void 	qh_checkconvex(facetT *facetlist, int fault);
-void    qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp);
-void 	qh_checkflipped_all (facetT *facetlist);
-void 	qh_checkpolygon(facetT *facetlist);
-void    qh_checkvertex (vertexT *vertex);
-void 	qh_clearcenters (qh_CENTER type);
-void 	qh_createsimplex(setT *vertices);
-void 	qh_delridge(ridgeT *ridge);
-void    qh_delvertex (vertexT *vertex);
-setT   *qh_facet3vertex (facetT *facet);
-facetT *qh_findbestfacet (pointT *point, boolT bestoutside,
-           realT *bestdist, boolT *isoutside);
-facetT *qh_findfacet_all (pointT *point, realT *bestdist, boolT *isoutside,
-			  int *numpart);
-int 	qh_findgood (facetT *facetlist, int goodhorizon);
-void 	qh_findgood_all (facetT *facetlist);
-void    qh_furthestnext (void /* qh facet_list */);
-void    qh_furthestout (facetT *facet);
-void    qh_infiniteloop (facetT *facet);
-void 	qh_initbuild(void);
-void 	qh_initialhull(setT *vertices);
-setT   *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints);
-vertexT *qh_isvertex (pointT *point, setT *vertices);
-vertexT *qh_makenewfacets (pointT *point /*horizon_list, visible_list*/);
-void    qh_matchduplicates (facetT *atfacet, int atskip, int hashsize, int *hashcount);
-void    qh_nearcoplanar ( void /* qh.facet_list */);
-vertexT *qh_nearvertex (facetT *facet, pointT *point, realT *bestdistp);
-int 	qh_newhashtable(int newsize);
-vertexT *qh_newvertex(pointT *point);
-ridgeT *qh_nextridge3d (ridgeT *atridge, facetT *facet, vertexT **vertexp);
-void    qh_outcoplanar (void /* facet_list */);
-pointT *qh_point (int id);
-void 	qh_point_add (setT *set, pointT *point, void *elem);
-setT   *qh_pointfacet (void /*qh facet_list*/);
-setT   *qh_pointvertex (void /*qh facet_list*/);
-void 	qh_prependfacet(facetT *facet, facetT **facetlist);
-void	qh_printhashtable(FILE *fp);
-void    qh_printlists (void);
-void    qh_resetlists (boolT stats, boolT resetVisible /*qh newvertex_list newfacet_list visible_list*/);
-void    qh_setvoronoi_all (void);
-void	qh_triangulate (void /*qh facet_list*/);
-void    qh_triangulate_facet (facetT *facetA, vertexT **first_vertex);
-void    qh_triangulate_link (facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB);
-void	qh_triangulate_mirror (facetT *facetA, facetT *facetB);
-void    qh_triangulate_null (facetT *facetA);
-void    qh_vertexintersect(setT **vertexsetA,setT *vertexsetB);
-setT   *qh_vertexintersect_new(setT *vertexsetA,setT *vertexsetB);
-void    qh_vertexneighbors (void /*qh facet_list*/);
-boolT 	qh_vertexsubset(setT *vertexsetA, setT *vertexsetB);
-
-
-#endif /* qhDEFpoly */
diff --git a/extern/qhull/include/qhull/qhull.h b/extern/qhull/include/qhull/qhull.h
deleted file mode 100644
index 896ec1e9c18..00000000000
--- a/extern/qhull/include/qhull/qhull.h
+++ /dev/null
@@ -1,1048 +0,0 @@
-/*
  ---------------------------------
-
-   qhull.h
-   user-level header file for using qhull.a library
-
-   see qh-qhull.htm, qhull_a.h
-
-   copyright (c) 1993-2002, The Geometry Center
-
-   NOTE: access to qh_qh is via the 'qh' macro.  This allows
-   qh_qh to be either a pointer or a structure.  An example
-   of using qh is "qh DROPdim" which accesses the DROPdim
-   field of qh_qh.  Similarly, access to qh_qhstat is via
-   the 'qhstat' macro.
-
-   includes function prototypes for qhull.c, geom.c, global.c, io.c, user.c
-
-   use mem.h for mem.c
-   use qset.h for qset.c
-
-   see unix.c for an example of using qhull.h
-
-   recompile qhull if you change this file
-*/
-
-#ifndef qhDEFqhull
-#define qhDEFqhull 1
-
-/*=========================== -included files ==============*/
-
-#include 
-#include 
-#include 
-
-#if __MWERKS__ && __POWERPC__
-#include  
-#include  
-#include	
-#endif
-
-#ifndef __STDC__
-#ifndef __cplusplus
-#if     !_MSC_VER
-#error  Neither __STDC__ nor __cplusplus is defined.  Please use strict ANSI C or C++ to compile
-#error  Qhull.  You may need to turn off compiler extensions in your project configuration.  If
-#error  your compiler is a standard C compiler, you can delete this warning from qhull.h
-#endif
-#endif
-#endif
-
-#include "user.h"      /* user defineable constants */
-
-/*============ constants and basic types ====================*/
-
-/*----------------------------------
-
-  qh_VERSION
-    version string by year and date
-
-    the revision increases on code changes only
-
-  notes:
-    change date:    Changes.txt, Announce.txt, README.txt, qhull.man
-                    qhull-news.html, Eudora signatures, 
-    change version: README.txt, qhull.html, file_id.diz, Makefile
-    change year:    Copying.txt
-    check download size
-    recompile user_eg.c, rbox.c, qhull.c, qconvex.c, qdelaun.c qvoronoi.c, qhalf.c
-    make copy of qhull-news.html as qh-news.htm
-*/
-
-#define qh_VERSION "2002.1 2002/8/20"
-
-/*----------------------------------
-
-  coordT
-    coordinates and coefficients are stored as realT (i.e., double)
-
-  notes:
-    could use 'float' for data and 'double' for calculations (realT vs. coordT)
-      This requires many type casts, and adjusted error bounds.
-      Also C compilers may do expressions in double anyway.
-*/
-#define coordT realT
-
-/*----------------------------------
-
-  pointT
-    a point is an array of DIM3 coordinates
-*/
-#define pointT coordT
-
-/*----------------------------------
-
-  flagT
-    Boolean flag as a bit
-*/
-#define flagT unsigned int
-
-/*----------------------------------
-
-  boolT
-    boolean value, either True or False
-
-  notes:
-    needed for portability
-*/
-#define boolT unsigned int
-#ifdef False
-#undef False
-#endif
-#ifdef True
-#undef True
-#endif
-#define False 0
-#define True 1
-
-/*----------------------------------
-
-  qh_CENTER
-    to distinguish facet->center
-*/
-typedef enum
-{
-    qh_ASnone = 0, qh_ASvoronoi, qh_AScentrum
-}
-qh_CENTER;
-
-/*----------------------------------
-
-  qh_PRINT
-    output formats for printing (qh.PRINTout).
-    'Fa' 'FV' 'Fc' 'FC' 
-       
-
-   notes:
-   some of these names are similar to qh names.  The similar names are only
-   used in switch statements in qh_printbegin() etc.
-*/
-typedef enum {qh_PRINTnone= 0, 
-  qh_PRINTarea, qh_PRINTaverage,           /* 'Fa' 'FV' 'Fc' 'FC' */
-  qh_PRINTcoplanars, qh_PRINTcentrums, 
-  qh_PRINTfacets, qh_PRINTfacets_xridge,   /* 'f' 'FF' 'G' 'FI' 'Fi' 'Fn' */
-  qh_PRINTgeom, qh_PRINTids, qh_PRINTinner, qh_PRINTneighbors, 
-  qh_PRINTnormals, qh_PRINTouter,          /* 'n' 'Fo' 'i' 'm' 'Fm' 'o' */
-  qh_PRINTincidences, qh_PRINTmathematica, qh_PRINTmerges, qh_PRINToff, 
-  qh_PRINToptions, qh_PRINTpointintersect, /* 'FO' 'Fp' 'FP' 'p' 'FQ' 'FS' */
-  qh_PRINTpointnearest, qh_PRINTpoints, qh_PRINTqhull, qh_PRINTsize, 
-  qh_PRINTsummary, qh_PRINTtriangles,      /* 'Fs' 'Ft' 'Fv' 'FN' 'Fx' */
-  qh_PRINTvertices, qh_PRINTvneighbors, qh_PRINTextremes,
-  qh_PRINTEND} qh_PRINT;
-
-/*----------------------------------
-
-  qh_ALL
-    argument flag for selecting everything
-*/
-#define qh_ALL      True
-#define qh_NOupper  True     /* argument for qh_findbest */
-#define qh_IScheckmax  True     /* argument for qh_findbesthorizon */
-#define qh_ISnewfacets  True     /* argument for qh_findbest */
-#define qh_RESETvisible  True     /* argument for qh_resetlists */
-
-/*----------------------------------
-
-  qh_ERR
-    Qhull exit codes, for indicating errors
-*/
-#define qh_ERRnone  0    /* no error occurred during qhull */
-#define qh_ERRinput 1    /* input inconsistency */
-#define qh_ERRsingular 2 /* singular input data */
-#define qh_ERRprec  3    /* precision error */
-#define qh_ERRmem   4    /* insufficient memory, matches mem.h */
-#define qh_ERRqhull 5    /* internal error detected, matches mem.h */
-
-/* ============ -structures- ====================
-   each of the following structures is defined by a typedef
-   all realT and coordT fields occur at the beginning of a structure
-        (otherwise space may be wasted due to alignment)
-   define all flags together and pack into 32-bit number
-*/
-
-typedef struct vertexT vertexT;
-typedef struct ridgeT ridgeT;
-typedef struct facetT facetT;
-#ifndef DEFsetT
-#define DEFsetT 1
-typedef struct setT setT;          /* defined in qset.h */
-#endif
-
-/*----------------------------------
-
-  facetT
-    defines a facet
-
-  notes:
-   qhull() generates the hull as a list of facets.
-
-  topological information:
-    f.previous,next     doubly-linked list of facets
-    f.vertices          set of vertices
-    f.ridges            set of ridges
-    f.neighbors         set of neighbors
-    f.toporient         True if facet has top-orientation (else bottom)
-
-  geometric information:
-    f.offset,normal     hyperplane equation
-    f.maxoutside        offset to outer plane -- all points inside
-    f.center            centrum for testing convexity
-    f.simplicial        True if facet is simplicial
-    f.flipped           True if facet does not include qh.interior_point
-
-  for constructing hull:
-    f.visible           True if facet on list of visible facets (will be deleted)
-    f.newfacet          True if facet on list of newly created facets
-    f.coplanarset       set of points coplanar with this facet
-                        (includes near-inside points for later testing)
-    f.outsideset        set of points outside of this facet
-    f.furthestdist      distance to furthest point of outside set
-    f.visitid           marks visited facets during a loop
-    f.replace           replacement facet for to-be-deleted, visible facets
-    f.samecycle,newcycle cycle of facets for merging into horizon facet
-
-  see below for other flags and fields
-*/
-struct facetT {
-#if !qh_COMPUTEfurthest
-  coordT   furthestdist;/* distance to furthest point of outsideset */
-#endif
-#if qh_MAXoutside
-  coordT   maxoutside;  /* max computed distance of point to facet
-  			Before QHULLfinished this is an approximation
-  			since maxdist not always set for mergefacet
-			Actual outer plane is +DISTround and
-			computed outer plane is +2*DISTround */
-#endif
-  coordT   offset;      /* exact offset of hyperplane from origin */
-  coordT  *normal;      /* normal of hyperplane, hull_dim coefficients */
-			/*   if tricoplanar, shared with a neighbor */
-  union {               /* in order of testing */
-   realT   area;        /* area of facet, only in io.c if  ->isarea */
-   facetT *replace;	/*  replacement facet if ->visible and NEWfacets
-  			     is NULL only if qh_mergedegen_redundant or interior */
-   facetT *samecycle;   /*  cycle of facets from the same visible/horizon intersection,
-   			     if ->newfacet */
-   facetT *newcycle;    /*  in horizon facet, current samecycle of new facets */ 
-   facetT *trivisible;  /* visible facet for ->tricoplanar facets during qh_triangulate() */
-   facetT *triowner;    /* owner facet for ->tricoplanar, !isarea facets w/ ->keepcentrum */
-  }f;
-  coordT  *center;      /*  centrum for convexity, qh CENTERtype == qh_AScentrum */
-      			/*  Voronoi center, qh CENTERtype == qh_ASvoronoi */
-			/*   if tricoplanar, shared with a neighbor */
-  facetT  *previous;    /* previous facet in the facet_list */
-  facetT  *next;        /* next facet in the facet_list */
-  setT    *vertices;    /* vertices for this facet, inverse sorted by ID 
-                           if simplicial, 1st vertex was apex/furthest */
-  setT    *ridges;      /* explicit ridges for nonsimplicial facets.
-  			   for simplicial facets, neighbors defines ridge */
-  setT    *neighbors;   /* neighbors of the facet.  If simplicial, the kth
-			   neighbor is opposite the kth vertex, and the first
-			   neighbor is the horizon facet for the first vertex*/
-  setT    *outsideset;  /* set of points outside this facet
-		           if non-empty, last point is furthest
-			   if NARROWhull, includes coplanars for partitioning*/
-  setT    *coplanarset; /* set of points coplanar with this facet
-  			   > qh.min_vertex and <= facet->max_outside
-                           a point is assigned to the furthest facet
-		           if non-empty, last point is furthest away */
-  unsigned visitid;     /* visit_id, for visiting all neighbors,
-			   all uses are independent */
-  unsigned id;	        /* unique identifier from qh facet_id */
-  unsigned nummerge:9;  /* number of merges */
-#define qh_MAXnummerge 511 /*     2^9-1, 32 flags total, see "flags:" in io.c */
-  flagT    tricoplanar:1; /* True if TRIangulate and simplicial and coplanar with a neighbor */
-			  /*   all tricoplanars share the same ->center, ->normal, ->offset, ->maxoutside */
-			  /*   all tricoplanars share the same apex */
-                          /*   if ->degenerate, does not span facet (one logical ridge) */
-                          /*   one tricoplanar has ->keepcentrum and ->coplanarset */
-                          /*   during qh_triangulate, f.trivisible points to original facet */
-  flagT	   newfacet:1;  /* True if facet on qh newfacet_list (new or merged) */
-  flagT	   visible:1;   /* True if visible facet (will be deleted) */
-  flagT    toporient:1; /* True if created with top orientation
-			   after merging, use ridge orientation */
-  flagT    simplicial:1;/* True if simplicial facet, ->ridges may be implicit */
-  flagT    seen:1;      /* used to perform operations only once, like visitid */
-  flagT    seen2:1;     /* used to perform operations only once, like visitid */
-  flagT	   flipped:1;   /* True if facet is flipped */
-  flagT    upperdelaunay:1; /* True if facet is upper envelope of Delaunay triangulation */
-  flagT    notfurthest:1; /* True if last point of outsideset is not furthest*/
-
-/*-------- flags primarily for output ---------*/
-  flagT	   good:1;      /* True if a facet marked good for output */
-  flagT    isarea:1;    /* True if facet->f.area is defined */
-
-/*-------- flags for merging ------------------*/
-  flagT    dupridge:1;  /* True if duplicate ridge in facet */
-  flagT    mergeridge:1; /* True if facet or neighbor contains a qh_MERGEridge
-                            ->normal defined (also defined for mergeridge2) */
-  flagT    mergeridge2:1; /* True if neighbor contains a qh_MERGEridge (mark_dupridges */
-  flagT    coplanar:1;  /* True if horizon facet is coplanar at last use */
-  flagT     mergehorizon:1; /* True if will merge into horizon (->coplanar) */
-  flagT	    cycledone:1;/* True if mergecycle_all already done */
-  flagT    tested:1;    /* True if facet convexity has been tested (false after merge */
-  flagT    keepcentrum:1; /* True if keep old centrum after a merge, or marks owner for ->tricoplanar */
-  flagT	   newmerge:1;  /* True if facet is newly merged for reducevertices */
-  flagT	   degenerate:1; /* True if facet is degenerate (degen_mergeset or ->tricoplanar) */
-  flagT	   redundant:1;  /* True if facet is redundant (degen_mergeset) */
-};
-
-
-/*----------------------------------
-
-  ridgeT
-    defines a ridge
-
-  notes:
-  a ridge is DIM3-1 simplex between two neighboring facets.  If the
-  facets are non-simplicial, there may be more than one ridge between
-  two facets.  E.G. a 4-d hypercube has two triangles between each pair
-  of neighboring facets.
-
-  topological information:
-    vertices            a set of vertices
-    top,bottom          neighboring facets with orientation
-
-  geometric information:
-    tested              True if ridge is clearly convex
-    nonconvex           True if ridge is non-convex
-*/
-struct ridgeT {
-  setT    *vertices;    /* vertices belonging to this ridge, inverse sorted by ID 
-                           NULL if a degen ridge (matchsame) */
-  facetT  *top;         /* top facet this ridge is part of */
-  facetT  *bottom;      /* bottom facet this ridge is part of */
-  unsigned id:24;       /* unique identifier, =>room for 8 flags */
-  flagT    seen:1;      /* used to perform operations only once */
-  flagT    tested:1;    /* True when ridge is tested for convexity */
-  flagT    nonconvex:1; /* True if getmergeset detected a non-convex neighbor
-			   only one ridge between neighbors may have nonconvex */
-};
-
-/*----------------------------------
-
-  vertexT
-     defines a vertex
-
-  topological information:
-    next,previous       doubly-linked list of all vertices
-    neighbors           set of adjacent facets (only if qh.VERTEXneighbors)
-
-  geometric information:
-    point               array of DIM3 coordinates
-*/
-struct vertexT {
-  vertexT *next;        /* next vertex in vertex_list */
-  vertexT *previous;    /* previous vertex in vertex_list */
-  pointT  *point;       /* hull_dim coordinates (coordT) */
-  setT    *neighbors;   /* neighboring facets of vertex, qh_vertexneighbors()
-			   inits in io.c or after first merge */
-  unsigned visitid; /* for use with qh vertex_visit */
-  unsigned id:24;   /* unique identifier, =>room for 8 flags */
-  flagT    seen:1;      /* used to perform operations only once */
-  flagT    seen2:1;     /* another seen flag */
-  flagT    delridge:1;  /* vertex was part of a deleted ridge */
-  flagT	   deleted:1;   /* true if vertex on qh del_vertices */
-  flagT    newlist:1;   /* true if vertex on qh newvertex_list */
-};
-
-/*======= -global variables -qh ============================*/
-
-/*----------------------------------
-
-  qh
-   all global variables for qhull are in qh, qhmem, and qhstat
-
-  notes:
-   qhmem is defined in mem.h and qhstat is defined in stat.h
-   access to qh_qh is via the "qh" macro.  See qh_QHpointer in user.h
-*/
-typedef struct qhT qhT;
-#if qh_QHpointer
-#define qh qh_qh->
-extern qhT *qh_qh;     /* allocated in global.c */
-#else
-#define qh qh_qh.
-extern qhT qh_qh;
-#endif
-
-struct qhT {
-
-/*----------------------------------
-
-  qh constants
-    configuration flags and constants for Qhull
-
-  notes:
-    The user configures Qhull by defining flags.  They are
-    copied into qh by qh_setflags().  qh-quick.htm#options defines the flags.
-*/
-  boolT ALLpoints;        /* true 'Qs' if search all points for initial simplex */
-  boolT ANGLEmerge;	  /* true 'Qa' if sort potential merges by angle */
-  boolT APPROXhull;       /* true 'Wn' if MINoutside set */
-  realT MINoutside;       /*   'Wn' min. distance for an outside point */
-  boolT ATinfinity;       /* true 'Qz' if point num_points-1 is "at-infinity"
-                             for improving precision in Delaunay triangulations */
-  boolT AVOIDold;         /* true 'Q4' if avoid old->new merges */
-  boolT BESToutside;      /* true 'Qf' if partition points into best outsideset */
-  boolT CDDinput;         /* true 'Pc' if input uses CDD format (1.0/offset first) */
-  boolT CDDoutput;        /* true 'PC' if print normals in CDD format (offset first) */
-  boolT CHECKfrequently;  /* true 'Tc' if checking frequently */
-  realT premerge_cos;     /*   'A-n'   cos_max when pre merging */
-  realT postmerge_cos;    /*   'An'    cos_max when post merging */
-  boolT DELAUNAY;         /* true 'd' if computing DELAUNAY triangulation */
-  boolT DOintersections;  /* true 'Gh' if print hyperplane intersections */
-  int   DROPdim;          /* drops dim 'GDn' for 4-d -> 3-d output */
-  boolT FORCEoutput;      /* true 'Po' if forcing output despite degeneracies */
-  int   GOODpoint;        /* 1+n for 'QGn', good facet if visible/not(-) from point n*/
-  pointT *GOODpointp;     /*   the actual point */
-  boolT GOODthreshold;    /* true if qh lower_threshold/upper_threshold defined
-  			     false if qh SPLITthreshold */
-  int   GOODvertex;       /* 1+n, good facet if vertex for point n */
-  pointT *GOODvertexp;     /*   the actual point */
-  boolT HALFspace;        /* true 'Hn,n,n' if halfspace intersection */
-  int   IStracing;        /* trace execution, 0=none, 1=least, 4=most, -1=events */
-  int   KEEParea;         /* 'PAn' number of largest facets to keep */
-  boolT KEEPcoplanar;     /* true 'Qc' if keeping nearest facet for coplanar points */
-  boolT KEEPinside;       /* true 'Qi' if keeping nearest facet for inside points
-			      set automatically if 'd Qc' */
-  int   KEEPmerge;        /* 'PMn' number of facets to keep with most merges */
-  realT KEEPminArea;      /* 'PFn' minimum facet area to keep */
-  realT MAXcoplanar;      /* 'Un' max distance below a facet to be coplanar*/
-  boolT MERGEexact;	  /* true 'Qx' if exact merges (coplanar, degen, dupridge, flipped) */
-  boolT MERGEindependent; /* true 'Q2' if merging independent sets */
-  boolT MERGING;          /* true if exact-, pre- or post-merging, with angle and centrum tests */
-  realT   premerge_centrum;  /*   'C-n' centrum_radius when pre merging.  Default is round-off */
-  realT   postmerge_centrum; /*   'Cn' centrum_radius when post merging.  Default is round-off */
-  boolT MERGEvertices;	  /* true 'Q3' if merging redundant vertices */
-  realT MINvisible;       /* 'Vn' min. distance for a facet to be visible */
-  boolT NOnarrow;         /* true 'Q10' if no special processing for narrow distributions */
-  boolT NOnearinside;     /* true 'Q8' if ignore near-inside points when partitioning */
-  boolT NOpremerge;       /* true 'Q0' if no defaults for C-0 or Qx */
-  boolT ONLYgood; 	  /* true 'Qg' if process points with good visible or horizon facets */
-  boolT ONLYmax; 	  /* true 'Qm' if only process points that increase max_outside */
-  boolT PICKfurthest;     /* true 'Q9' if process furthest of furthest points*/
-  boolT POSTmerge;        /* true if merging after buildhull (Cn or An) */
-  boolT PREmerge;         /* true if merging during buildhull (C-n or A-n) */
-  			/* NOTE: some of these names are similar to qh_PRINT names */
-  boolT PRINTcentrums;	  /* true 'Gc' if printing centrums */
-  boolT PRINTcoplanar;    /* true 'Gp' if printing coplanar points */
-  int	PRINTdim;      	  /* print dimension for Geomview output */
-  boolT PRINTdots;        /* true 'Ga' if printing all points as dots */
-  boolT PRINTgood;        /* true 'Pg' if printing good facets */
-  boolT PRINTinner;	  /* true 'Gi' if printing inner planes */
-  boolT PRINTneighbors;	  /* true 'PG' if printing neighbors of good facets */
-  boolT PRINTnoplanes;	  /* true 'Gn' if printing no planes */
-  boolT PRINToptions1st;  /* true 'FO' if printing options to stderr */
-  boolT PRINTouter;	  /* true 'Go' if printing outer planes */
-  boolT PRINTprecision;   /* false 'Pp' if not reporting precision problems */
-  qh_PRINT PRINTout[qh_PRINTEND]; /* list of output formats to print */
-  boolT PRINTridges;      /* true 'Gr' if print ridges */
-  boolT PRINTspheres;     /* true 'Gv' if print vertices as spheres */
-  boolT PRINTstatistics;  /* true 'Ts' if printing statistics to stderr */
-  boolT PRINTsummary;     /* true 's' if printing summary to stderr */
-  boolT PRINTtransparent; /* true 'Gt' if print transparent outer ridges */
-  boolT PROJECTdelaunay;  /* true if DELAUNAY, no readpoints() and
-			     need projectinput() for Delaunay in qh_init_B */
-  int   PROJECTinput;     /* number of projected dimensions 'bn:0Bn:0' */
-  boolT QUICKhelp;	  /* true if quick help message for degen input */
-  boolT RANDOMdist;       /* true if randomly change distplane and setfacetplane */
-  realT RANDOMfactor;     /*    maximum random perturbation */
-  realT RANDOMa;         /*  qh_randomfactor is randr * RANDOMa + RANDOMb */
-  realT RANDOMb;
-  boolT RANDOMoutside;    /* true if select a random outside point */
-  int	REPORTfreq;       /* buildtracing reports every n facets */
-  int   REPORTfreq2;	  /* tracemerging reports every REPORTfreq/2 facets */
-  int	RERUN;            /* 'TRn' rerun qhull n times (qh.build_cnt) */
-  int	ROTATErandom;	  /* 'QRn' seed, 0 time, >= rotate input */
-  boolT SCALEinput;       /* true 'Qbk' if scaling input */
-  boolT SCALElast;        /* true 'Qbb' if scale last coord to max prev coord */
-  boolT SETroundoff;      /* true 'E' if qh DISTround is predefined */
-  boolT SKIPcheckmax;	  /* true 'Q5' if skip qh_check_maxout */
-  boolT SKIPconvex;       /* true 'Q6' if skip convexity testing during pre-merge */
-  boolT SPLITthresholds;  /* true if upper_/lower_threshold defines a region
-                               used only for printing (not for qh ONLYgood) */
-  int	STOPcone;         /* 'TCn' 1+n for stopping after cone for point n*/
-			  /*       also used by qh_build_withresart for err exit*/
-  int	STOPpoint;        /* 'TVn' 'TV-n' 1+n for stopping after/before(-)
-			                adding point n */
-  int	TESTpoints;	  /* 'QTn' num of test points after qh.num_points.  Test points always coplanar. */
-  boolT TESTvneighbors;   /*  true 'Qv' if test vertex neighbors at end */
-  int   TRACElevel;       /* 'Tn' conditional IStracing level */
-  int	TRACElastrun;	  /*  qh.TRACElevel applies to last qh.RERUN */
-  int   TRACEpoint;       /* 'TPn' start tracing when point n is a vertex */
-  realT TRACEdist;        /* 'TWn' start tracing when merge distance too big */
-  int   TRACEmerge;       /* 'TMn' start tracing before this merge */
-  boolT TRIangulate;	  /* true 'Qt' if triangulate non-simplicial facets */
-  boolT TRInormals;	  /* true 'Q11' if triangulate duplicates normals (sets Qt) */
-  boolT UPPERdelaunay;    /* true 'Qu' if computing furthest-site Delaunay */
-  boolT VERIFYoutput;     /* true 'Tv' if verify output at end of qhull */
-  boolT VIRTUALmemory;    /* true 'Q7' if depth-first processing in buildhull */
-  boolT VORONOI;	  /* true 'v' if computing Voronoi diagram */
-
-  /*--------input constants ---------*/
-  realT AREAfactor;       /* 1/(hull_dim-1)! for converting det's to area */
-  boolT DOcheckmax;       /* true if calling qh_check_maxout (qh_initqhull_globals) */
-  char	*feasible_string;  /* feasible point 'Hn,n,n' for halfspace intersection */
-  coordT *feasible_point;  /*    as coordinates, both malloc'd */
-  boolT GETarea;          /* true 'Fa', 'FA', 'FS', 'PAn', 'PFn' if compute facet area/Voronoi volume in io.c */
-  boolT KEEPnearinside;   /* true if near-inside points in coplanarset */
-  int 	hull_dim;         /* dimension of hull, set by initbuffers */
-  int 	input_dim;	  /* dimension of input, set by initbuffers */
-  int 	num_points;       /* number of input points */
-  pointT *first_point;    /* array of input points, see POINTSmalloc */
-  boolT POINTSmalloc;     /*   true if qh first_point/num_points allocated */
-  pointT *input_points;   /* copy of original qh.first_point for input points for qh_joggleinput */
-  boolT input_malloc;     /* true if qh input_points malloc'd */
-  char 	qhull_command[256];/* command line that invoked this program */
-  char 	rbox_command[256]; /* command line that produced the input points */
-  char  qhull_options[512];/* descriptive list of options */
-  int   qhull_optionlen;  /*    length of last line */
-  int   qhull_optionsiz;  /*     size of qhull_options before qh_initbuild */
-  boolT VERTEXneighbors;  /* true if maintaining vertex neighbors */
-  boolT ZEROcentrum;      /* true if 'C-0' or 'C-0 Qx'.  sets ZEROall_ok */
-  realT *upper_threshold; /* don't print if facet->normal[k]>=upper_threshold[k]
-                             must set either GOODthreshold or SPLITthreshold
-  			     if Delaunay, default is 0.0 for upper envelope */
-  realT *lower_threshold; /* don't print if facet->normal[k] <=lower_threshold[k] */
-  realT *upper_bound;     /* scale point[k] to new upper bound */
-  realT *lower_bound;     /* scale point[k] to new lower bound
-  			     project if both upper_ and lower_bound == 0 */
-
-/*----------------------------------
-
-  qh precision constants
-    precision constants for Qhull
-
-  notes:
-    qh_detroundoff() computes the maximum roundoff error for distance
-    and other computations.  It also sets default values for the
-    qh constants above.
-*/
-  realT ANGLEround;       /* max round off error for angles */
-  realT centrum_radius;   /* max centrum radius for convexity (roundoff added) */
-  realT cos_max;	  /* max cosine for convexity (roundoff added) */
-  realT DISTround;        /* max round off error for distances, 'E' overrides */
-  realT MAXabs_coord;     /* max absolute coordinate */
-  realT MAXlastcoord;     /* max last coordinate for qh_scalelast */
-  realT MAXsumcoord;      /* max sum of coordinates */
-  realT MAXwidth;         /* max rectilinear width of point coordinates */
-  realT MINdenom_1;       /* min. abs. value for 1/x */
-  realT MINdenom;         /*    use divzero if denominator < MINdenom */
-  realT MINdenom_1_2;     /* min. abs. val for 1/x that allows normalization */
-  realT MINdenom_2;       /*    use divzero if denominator < MINdenom_2 */
-  realT MINlastcoord;     /* min. last coordinate for qh_scalelast */
-  boolT NARROWhull;       /* set in qh_initialhull if angle < qh_MAXnarrow */
-  realT *NEARzero;        /* hull_dim array for near zero in gausselim */
-  realT NEARinside;       /* keep points for qh_check_maxout if close to facet */
-  realT ONEmerge;         /* max distance for merging simplicial facets */
-  realT outside_err;      /* application's epsilon for coplanar points
-                             qh_check_bestdist() qh_check_points() reports error if point outside */
-  realT WIDEfacet;        /* size of wide facet for skipping ridge in
-			     area computation and locking centrum */
-  
-/*----------------------------------
-
-  qh internal constants
-    internal constants for Qhull
-*/
-  char qhull[sizeof("qhull")]; /* for checking ownership */
-  void *old_stat;         /* pointer to saved qh_qhstat, qh_save_qhull */
-  jmp_buf errexit;        /* exit label for qh_errexit, defined by setjmp() */
-  char jmpXtra[40];       /* extra bytes in case jmp_buf is defined wrong by compiler */
-  jmp_buf restartexit;    /* restart label for qh_errexit, defined by setjmp() */
-  char jmpXtra2[40];      /* extra bytes in case jmp_buf is defined wrong by compiler*/
-  FILE *fin;              /* pointer to input file, init by qh_meminit */
-  FILE *fout;             /* pointer to output file */
-  FILE *ferr;             /* pointer to error file */
-  pointT *interior_point; /* center point of the initial simplex*/
-  int   normal_size;      /* size in bytes for facet normals and point coords*/
-  int   center_size;      /* size in bytes for Voronoi centers */
-  int   TEMPsize;         /* size for small, temporary sets (in quick mem) */
-
-/*----------------------------------
-
-  qh facet and vertex lists
-    defines lists of facets, new facets, visible facets, vertices, and
-    new vertices.  Includes counts, next ids, and trace ids.
-  see:
-    qh_resetlists()
-*/
-  facetT *facet_list;     /* first facet */
-  facetT  *facet_tail;     /* end of facet_list (dummy facet) */
-  facetT *facet_next;     /* next facet for buildhull()
-    			     previous facets do not have outside sets
-                             NARROWhull: previous facets may have coplanar outside sets for qh_outcoplanar */
-  facetT *newfacet_list;  /* list of new facets to end of facet_list */
-  facetT *visible_list;   /* list of visible facets preceeding newfacet_list,
-                             facet->visible set */
-  int       num_visible;  /* current number of visible facets */
-  unsigned tracefacet_id;  /* set at init, then can print whenever */
-  facetT *tracefacet;     /*   set in newfacet/mergefacet, undone in delfacet*/
-  unsigned tracevertex_id;  /* set at buildtracing, can print whenever */
-  vertexT *tracevertex;     /*   set in newvertex, undone in delvertex*/
-  vertexT *vertex_list;     /* list of all vertices, to vertex_tail */
-  vertexT  *vertex_tail;    /*      end of vertex_list (dummy vertex) */
-  vertexT *newvertex_list; /* list of vertices in newfacet_list, to vertex_tail
-                             all vertices have 'newlist' set */
-  int 	num_facets;	  /* number of facets in facet_list
-			     includes visble faces (num_visible) */
-  int 	num_vertices;     /* number of vertices in facet_list */
-  int   num_outside;      /* number of points in outsidesets (for tracing and RANDOMoutside)
-                               includes coplanar outsideset points for NARROWhull/qh_outcoplanar() */
-  int   num_good;         /* number of good facets (after findgood_all) */
-  unsigned facet_id;      /* ID of next, new facet from newfacet() */
-  unsigned ridge_id;      /* ID of next, new ridge from newridge() */
-  unsigned vertex_id;     /* ID of next, new vertex from newvertex() */
-
-/*----------------------------------
-
-  qh global variables
-    defines minimum and maximum distances, next visit ids, several flags,
-    and other global variables.
-    initialize in qh_initbuild or qh_maxmin if used in qh_buildhull
-*/
-  unsigned long hulltime; /* ignore time to set up input and randomize */
-                          /*   use unsigned to avoid wrap-around errors */
-  boolT ALLOWrestart;     /* true if qh_precision can use qh.restartexit */
-  int   build_cnt;        /* number of calls to qh_initbuild */
-  qh_CENTER CENTERtype;   /* current type of facet->center, qh_CENTER */
-  int 	furthest_id;      /* pointid of furthest point, for tracing */
-  facetT *GOODclosest;    /* closest facet to GOODthreshold in qh_findgood */
-  realT JOGGLEmax;        /* set 'QJn' if randomly joggle input */
-  boolT maxoutdone;       /* set qh_check_maxout(), cleared by qh_addpoint() */
-  realT max_outside;      /* maximum distance from a point to a facet,
-			       before roundoff, not simplicial vertices
-			       actual outer plane is +DISTround and
-			       computed outer plane is +2*DISTround */
-  realT max_vertex;       /* maximum distance (>0) from vertex to a facet,
-			       before roundoff, due to a merge */
-  realT min_vertex;       /* minimum distance (<0) from vertex to a facet,
-			       before roundoff, due to a merge
-			       if qh.JOGGLEmax, qh_makenewplanes sets it
-  			       recomputed if qh.DOcheckmax, default -qh.DISTround */
-  boolT NEWfacets;        /* true while visible facets invalid due to new or merge
-			      from makecone/attachnewfacets to deletevisible */
-  boolT findbestnew;	  /* true if partitioning calls qh_findbestnew */
-  boolT findbest_notsharp; /* true if new facets are at least 90 degrees */
-  boolT NOerrexit;        /* true if qh.errexit is not available */
-  realT PRINTcradius;     /* radius for printing centrums */
-  realT PRINTradius;      /* radius for printing vertex spheres and points */
-  boolT POSTmerging;      /* true when post merging */
-  int 	printoutvar;	  /* temporary variable for qh_printbegin, etc. */
-  int 	printoutnum;	  /* number of facets printed */
-  boolT QHULLfinished;    /* True after qhull() is finished */
-  realT totarea;          /* 'FA': total facet area computed by qh_getarea */
-  realT totvol;           /* 'FA': total volume computed by qh_getarea */
-  unsigned int visit_id;  /* unique ID for searching neighborhoods, */
-  unsigned int vertex_visit; /* unique ID for searching vertices */
-  boolT ZEROall_ok;       /* True if qh_checkzero always succeeds */
-  boolT WAScoplanar;      /* True if qh_partitioncoplanar (qh_check_maxout) */
-  
-/*----------------------------------
-
-  qh global sets
-    defines sets for merging, initial simplex, hashing, extra input points,
-    and deleted vertices
-*/
-  setT *facet_mergeset;   /* temporary set of merges to be done */
-  setT *degen_mergeset;   /* temporary set of degenerate and redundant merges */
-  setT *hash_table;	  /* hash table for matching ridges in qh_matchfacets
-                             size is setsize() */
-  setT *other_points;     /* additional points (first is qh interior_point) */
-  setT *del_vertices;     /* vertices to partition and delete with visible
-                             facets.  Have deleted set for checkfacet */
-
-/*----------------------------------
-
-  qh global buffers
-    defines buffers for maxtrix operations, input, and error messages
-*/
-  coordT *gm_matrix;      /* (dim+1)Xdim matrix for geom.c */
-  coordT **gm_row;        /* array of gm_matrix rows */
-  char* line;             /* malloc'd input line of maxline+1 chars */
-  int maxline;
-  coordT *half_space;     /* malloc'd input array for halfspace (qh normal_size+coordT) */
-  coordT *temp_malloc;    /* malloc'd input array for points */
-  
-/*----------------------------------
-
-  qh static variables
-    defines static variables for individual functions
-
-  notes:
-    do not use 'static' within a function.  Multiple instances of qhull
-    may exist.
-
-    do not assume zero initialization, 'QPn' may cause a restart
-*/
-  boolT ERREXITcalled;    /* true during errexit (prevents duplicate calls */
-  boolT firstcentrum; 	  /* for qh_printcentrum */
-  realT last_low;         /* qh_scalelast parameters for qh_setdelaunay */
-  realT last_high;
-  realT last_newhigh;
-  unsigned lastreport;    /* for qh_buildtracing */
-  int mergereport;        /* for qh_tracemerging */
-  boolT old_randomdist;   /* save RANDOMdist when io, tracing, or statistics */
-  int   ridgeoutnum;      /* number of ridges in 4OFF output */
-  void *old_qhstat;       /* for saving qh_qhstat in save_qhull() */
-  setT *old_tempstack;     /* for saving qhmem.tempstack in save_qhull */
-  setT *coplanarset;      /* set of coplanar facets for searching qh_findbesthorizon() */
-};
-
-/*=========== -macros- =========================*/
-
-/*----------------------------------
-
-  otherfacet_(ridge, facet)
-    return neighboring facet for a ridge in facet
-*/
-#define otherfacet_(ridge, facet) \
-                        (((ridge)->top == (facet)) ? (ridge)->bottom : (ridge)->top)
-
-/*----------------------------------
-
-  getid_(p)
-    return ID for facet, ridge, or vertex
-    return MAXINT if NULL (-1 causes type conversion error )
-*/
-#define getid_(p)       ((p) ? (p)->id : -1)
-
-/*============== FORALL macros ===================*/
-
-/*----------------------------------
-
-  FORALLfacets { ... }
-    assign 'facet' to each facet in qh.facet_list
-
-  notes:
-    uses 'facetT *facet;'
-    assumes last facet is a sentinel
-
-  see:
-    FORALLfacet_( facetlist )
-*/
-#define FORALLfacets for (facet=qh facet_list;facet && facet->next;facet=facet->next)
-
-/*----------------------------------
-
-  FORALLpoints { ... }
-    assign 'point' to each point in qh.first_point, qh.num_points
-
-  declare:
-    coordT *point, *pointtemp;
-*/
-#define FORALLpoints FORALLpoint_(qh first_point, qh num_points)
-
-/*----------------------------------
-
-  FORALLpoint_( points, num) { ... }
-    assign 'point' to each point in points array of num points
-
-  declare:
-    coordT *point, *pointtemp;
-*/
-#define FORALLpoint_(points, num) for(point= (points), \
-      pointtemp= (points)+qh hull_dim*(num); point < pointtemp; point += qh hull_dim)
-
-/*----------------------------------
-
-  FORALLvertices { ... }
-    assign 'vertex' to each vertex in qh.vertex_list
-
-  declare:
-    vertexT *vertex;
-
-  notes:
-    assumes qh.vertex_list terminated with a sentinel
-*/
-#define FORALLvertices for (vertex=qh vertex_list;vertex && vertex->next;vertex= vertex->next)
-
-/*----------------------------------
-
-  FOREACHfacet_( facets ) { ... }
-    assign 'facet' to each facet in facets
-
-  declare:
-    facetT *facet, **facetp;
-
-  see:
-    FOREACHsetelement_
-*/
-#define FOREACHfacet_(facets)    FOREACHsetelement_(facetT, facets, facet)
-
-/*----------------------------------
-
-  FOREACHneighbor_( facet ) { ... }
-    assign 'neighbor' to each neighbor in facet->neighbors
-
-  FOREACHneighbor_( vertex ) { ... }
-    assign 'neighbor' to each neighbor in vertex->neighbors
-
-  declare:
-    facetT *neighbor, **neighborp;
-
-  see:
-    FOREACHsetelement_
-*/
-#define FOREACHneighbor_(facet)  FOREACHsetelement_(facetT, facet->neighbors, neighbor)
-
-/*----------------------------------
-
-  FOREACHpoint_( points ) { ... }
-    assign 'point' to each point in points set
-
-  declare:
-    pointT *point, **pointp;
-
-  see:
-    FOREACHsetelement_
-*/
-#define FOREACHpoint_(points)    FOREACHsetelement_(pointT, points, point)
-
-/*----------------------------------
-
-  FOREACHridge_( ridges ) { ... }
-    assign 'ridge' to each ridge in ridges set
-
-  declare:
-    ridgeT *ridge, **ridgep;
-
-  see:
-    FOREACHsetelement_
-*/
-#define FOREACHridge_(ridges)    FOREACHsetelement_(ridgeT, ridges, ridge)
-
-/*----------------------------------
-
-  FOREACHvertex_( vertices ) { ... }
-    assign 'vertex' to each vertex in vertices set
-
-  declare:
-    vertexT *vertex, **vertexp;
-
-  see:
-    FOREACHsetelement_
-*/
-#define FOREACHvertex_(vertices) FOREACHsetelement_(vertexT, vertices,vertex)
-
-/*----------------------------------
-
-  FOREACHfacet_i_( facets ) { ... }
-    assign 'facet' and 'facet_i' for each facet in facets set
-
-  declare:
-    facetT *facet;
-    int     facet_n, facet_i;
-
-  see:
-    FOREACHsetelement_i_
-*/
-#define FOREACHfacet_i_(facets)    FOREACHsetelement_i_(facetT, facets, facet)
-
-/*----------------------------------
-
-  FOREACHneighbor_i_( facet ) { ... }
-    assign 'neighbor' and 'neighbor_i' for each neighbor in facet->neighbors
-
-  FOREACHneighbor_i_( vertex ) { ... }
-    assign 'neighbor' and 'neighbor_i' for each neighbor in vertex->neighbors
-
-  declare:
-    facetT *neighbor;
-    int     neighbor_n, neighbor_i;
-
-  see:
-    FOREACHsetelement_i_
-*/
-#define FOREACHneighbor_i_(facet)  FOREACHsetelement_i_(facetT, facet->neighbors, neighbor)
-
-/*----------------------------------
-
-  FOREACHpoint_i_( points ) { ... }
-    assign 'point' and 'point_i' for each point in points set
-
-  declare:
-    pointT *point;
-    int     point_n, point_i;
-
-  see:
-    FOREACHsetelement_i_
-*/
-#define FOREACHpoint_i_(points)    FOREACHsetelement_i_(pointT, points, point)
-
-/*----------------------------------
-
-  FOREACHridge_i_( ridges ) { ... }
-    assign 'ridge' and 'ridge_i' for each ridge in ridges set
-
-  declare:
-    ridgeT *ridge;
-    int     ridge_n, ridge_i;
-
-  see:
-    FOREACHsetelement_i_
-*/
-#define FOREACHridge_i_(ridges)    FOREACHsetelement_i_(ridgeT, ridges, ridge)
-
-/*----------------------------------
-
-  FOREACHvertex_i_( vertices ) { ... }
-    assign 'vertex' and 'vertex_i' for each vertex in vertices set
-
-  declare:
-    vertexT *vertex;
-    int     vertex_n, vertex_i;
-
-  see:
-    FOREACHsetelement_i_
- */
-#define FOREACHvertex_i_(vertices) FOREACHsetelement_i_(vertexT, vertices,vertex)
-
-/********* -qhull.c prototypes (duplicated from qhull_a.h) **********************/
-
-void    qh_qhull (void);
-boolT   qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist);
-void	qh_printsummary(FILE *fp);
-
-/********* -user.c prototypes (alphabetical) **********************/
-
-void 	qh_errexit(int exitcode, facetT *facet, ridgeT *ridge);
-void 	qh_errprint(char* string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex);
-int     qh_new_qhull (int dim, int numpoints, coordT *points, boolT ismalloc,
-		char *qhull_cmd, FILE *outfile, FILE *errfile);
-void    qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall);
-void 	qh_user_memsizes (void);
-
-/***** -geom.c/geom2.c prototypes (duplicated from geom.h) ****************/
-
-facetT *qh_findbest (pointT *point, facetT *startfacet,
-		     boolT bestoutside, boolT newfacets, boolT noupper,
-		     realT *dist, boolT *isoutside, int *numpart);
-facetT *qh_findbestnew (pointT *point, facetT *startfacet,
-                     realT *dist, boolT bestoutside, boolT *isoutside, int *numpart);
-boolT   qh_gram_schmidt(int dim, realT **rows);
-void    qh_outerinner (facetT *facet, realT *outerplane, realT *innerplane);
-void	qh_printsummary(FILE *fp);
-void    qh_projectinput (void);
-void    qh_randommatrix (realT *buffer, int dim, realT **row);
-void    qh_rotateinput (realT **rows);
-void    qh_scaleinput (void);
-void    qh_setdelaunay (int dim, int count, pointT *points);
-coordT  *qh_sethalfspace_all (int dim, int count, coordT *halfspaces, pointT *feasible);
-
-/***** -global.c prototypes (alphabetical) ***********************/
-
-unsigned long qh_clock (void);
-void 	qh_checkflags (char *command, char *hiddenflags);
-void 	qh_freebuffers (void);
-void    qh_freeqhull (boolT allmem);
-void    qh_init_A (FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]);
-void    qh_init_B (coordT *points, int numpoints, int dim, boolT ismalloc);
-void 	qh_init_qhull_command (int argc, char *argv[]);
-void    qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc);
-void 	qh_initflags (char *command);
-void 	qh_initqhull_buffers (void);
-void 	qh_initqhull_globals (coordT *points, int numpoints, int dim, boolT ismalloc);
-void    qh_initqhull_mem (void);
-void 	qh_initqhull_start (FILE *infile, FILE *outfile, FILE *errfile);
-void 	qh_initthresholds (char *command);
-void    qh_option (char *option, int *i, realT *r);
-#if qh_QHpointer
-void 	qh_restore_qhull (qhT **oldqh);
-qhT    *qh_save_qhull (void);
-#endif
-
-/***** -io.c prototypes (duplicated from io.h) ***********************/
-
-void    dfacet( unsigned id);
-void    dvertex( unsigned id);
-void	qh_printneighborhood (FILE *fp, int format, facetT *facetA, facetT *facetB, boolT printall);
-void	qh_produce_output(void);
-coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
-
-
-/********* -mem.c prototypes (duplicated from mem.h) **********************/
-
-void qh_meminit (FILE *ferr);
-void qh_memfreeshort (int *curlong, int *totlong);
-
-/********* -poly.c/poly2.c prototypes (duplicated from poly.h) **********************/
-
-void    qh_check_output (void);
-void    qh_check_points (void);
-setT   *qh_facetvertices (facetT *facetlist, setT *facets, boolT allfacets);
-facetT *qh_findbestfacet (pointT *point, boolT bestoutside,
-           realT *bestdist, boolT *isoutside);
-vertexT *qh_nearvertex (facetT *facet, pointT *point, realT *bestdistp);
-pointT *qh_point (int id);
-setT   *qh_pointfacet (void /*qh.facet_list*/);
-int     qh_pointid (pointT *point);
-setT   *qh_pointvertex (void /*qh.facet_list*/);
-void    qh_setvoronoi_all (void);
-void	qh_triangulate (void /*qh facet_list*/);
-
-/********* -stat.c prototypes (duplicated from stat.h) **********************/
-
-void    qh_collectstatistics (void);
-void    qh_printallstatistics (FILE *fp, char *string);
-
-#endif /* qhDEFqhull */
diff --git a/extern/qhull/include/qhull/qhull_a.h b/extern/qhull/include/qhull/qhull_a.h
deleted file mode 100644
index d4e69b071be..00000000000
--- a/extern/qhull/include/qhull/qhull_a.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
  ---------------------------------
-
-   qhull_a.h 
-   all header files for compiling qhull
-
-   see qh-qhull.htm
-
-   see qhull.h for user-level definitions
-   
-   see user.h for user-defineable constants
-   
-   defines internal functions for qhull.c global.c
-
-   copyright (c) 1993-2002, The Geometry Center
-
-   Notes:  grep for ((" and (" to catch fprintf("lkasdjf");
-           full parens around (x?y:z)
-	   use '#include qhull/qhull_a.h' to avoid name clashes
-*/
-
-#ifndef qhDEFqhulla
-#define qhDEFqhulla
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include     /* some compilers will not need float.h */
-#include 
-#include 
-#include 
-/*** uncomment here and qset.c
-     if string.h does not define memcpy()
-#include 
-*/
-#include "qhull.h"
-#include "mem.h"
-#include "qset.h"
-#include "geom.h"
-#include "merge.h"
-#include "poly.h"
-#include "io.h"
-#include "stat.h"
-
-#if qh_CLOCKtype == 2  /* defined in user.h from qhull.h */
-#include 
-#include 
-#include 
-#endif
-
-#ifdef _MSC_VER  /* Microsoft Visual C++ */
-#pragma warning( disable : 4056)  /* float constant expression.  Looks like a compiler bug */
-#pragma warning( disable : 4146)  /* unary minus applied to unsigned type */
-#pragma warning( disable : 4244)  /* conversion from 'unsigned long' to 'real' */
-#pragma warning( disable : 4305)  /* conversion from 'const double' to 'float' */
-#endif
-
-/* ======= -macros- =========== */
-
-/*----------------------------------
-  
-  traceN((fp.ferr, "format\n", vars));  
-    calls fprintf if qh.IStracing >= N
-  
-  notes:
-    removing tracing reduces code size but doesn't change execution speed
-*/
-#ifndef qh_NOtrace
-#define trace0(args) {if (qh IStracing) fprintf args;}
-#define trace1(args) {if (qh IStracing >= 1) fprintf args;}
-#define trace2(args) {if (qh IStracing >= 2) fprintf args;}
-#define trace3(args) {if (qh IStracing >= 3) fprintf args;}
-#define trace4(args) {if (qh IStracing >= 4) fprintf args;}
-#define trace5(args) {if (qh IStracing >= 5) fprintf args;}
-#else /* qh_NOtrace */
-#define trace0(args) {}
-#define trace1(args) {}
-#define trace2(args) {}
-#define trace3(args) {}
-#define trace4(args) {}
-#define trace5(args) {}
-#endif /* qh_NOtrace */
-
-/***** -qhull.c prototypes (alphabetical after qhull) ********************/
-
-void 	qh_qhull (void);
-boolT   qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist);
-void 	qh_buildhull(void);
-void    qh_buildtracing (pointT *furthest, facetT *facet);
-void    qh_build_withrestart (void);
-void 	qh_errexit2(int exitcode, facetT *facet, facetT *otherfacet);
-void    qh_findhorizon(pointT *point, facetT *facet, int *goodvisible,int *goodhorizon);
-pointT *qh_nextfurthest (facetT **visible);
-void 	qh_partitionall(setT *vertices, pointT *points,int npoints);
-void    qh_partitioncoplanar (pointT *point, facetT *facet, realT *dist);
-void    qh_partitionpoint (pointT *point, facetT *facet);
-void 	qh_partitionvisible(boolT allpoints, int *numpoints);
-void    qh_precision (char *reason);
-void	qh_printsummary(FILE *fp);
-
-/***** -global.c internal prototypes (alphabetical) ***********************/
-
-void    qh_appendprint (qh_PRINT format);
-void 	qh_freebuild (boolT allmem);
-void 	qh_freebuffers (void);
-void    qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc);
-int     qh_strtol (const char *s, char **endp);
-double  qh_strtod (const char *s, char **endp);
-
-/***** -stat.c internal prototypes (alphabetical) ***********************/
-
-void	qh_allstatA (void);
-void	qh_allstatB (void);
-void	qh_allstatC (void);
-void	qh_allstatD (void);
-void	qh_allstatE (void);
-void	qh_allstatE2 (void);
-void	qh_allstatF (void);
-void	qh_allstatG (void);
-void	qh_allstatH (void);
-void 	qh_freebuffers (void);
-void    qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc);
-
-#endif /* qhDEFqhulla */
diff --git a/extern/qhull/include/qhull/qset.h b/extern/qhull/include/qhull/qset.h
deleted file mode 100644
index 6c0ff758de4..00000000000
--- a/extern/qhull/include/qhull/qset.h
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
  ---------------------------------
-
-   qset.h
-     header file for qset.c that implements set
-
-   see qh-set.htm and qset.c
-   
-   only uses mem.c, malloc/free
-
-   for error handling, writes message and calls
-      qh_errexit (qhmem_ERRqhull, NULL, NULL);
-   
-   set operations satisfy the following properties:
-    - sets have a max size, the actual size (if different) is stored at the end
-    - every set is NULL terminated
-    - sets may be sorted or unsorted, the caller must distinguish this
-   
-   copyright (c) 1993-2002, The Geometry Center
-*/
-
-#ifndef qhDEFset
-#define qhDEFset 1
-
-/*================= -structures- ===============*/
-
-#ifndef DEFsetT
-#define DEFsetT 1
-typedef struct setT setT;   /* a set is a sorted or unsorted array of pointers */
-#endif
-
-/*------------------------------------------
-   
-setT
-  a set or list of pointers with maximum size and actual size.
-
-variations:
-  unsorted, unique   -- a list of unique pointers with NULL terminator
-  			   user guarantees uniqueness
-  sorted	     -- a sorted list of unique pointers with NULL terminator
-  			   qset.c guarantees uniqueness
-  unsorted           -- a list of pointers terminated with NULL
-  indexed  	     -- an array of pointers with NULL elements 
-
-structure for set of n elements:
-
-	--------------
-	|  maxsize 
-	--------------
-	|  e[0] - a pointer, may be NULL for indexed sets
-	--------------
-	|  e[1]
-	
-	--------------
-	|  ...
-	--------------
-	|  e[n-1]
-	--------------
-	|  e[n] = NULL
-	--------------
-	|  ...
-	--------------
-	|  e[maxsize] - n+1 or NULL (determines actual size of set)
-	--------------
-
-*/
-
-/*-- setelemT -- internal type to allow both pointers and indices
-*/
-typedef union setelemT setelemT;
-union setelemT {
-  void    *p;
-  int      i;         /* integer used for e[maxSize] */
-};
-
-struct setT {
-  int maxsize;          /* maximum number of elements (except NULL) */
-  setelemT e[1];        /* array of pointers, tail is NULL */
-                        /* last slot (unless NULL) is actual size+1 
-                           e[maxsize]==NULL or e[e[maxsize]-1]==NULL */
-                        /* this may generate a warning since e[] contains
-			   maxsize elements */
-};
-
-/*=========== -constants- =========================*/
-
-/*-------------------------------------
-   
-  SETelemsize
-    size of a set element in bytes
-*/
-#define SETelemsize sizeof(setelemT) 
-
-
-/*=========== -macros- =========================*/
-
-/*-------------------------------------
-   
-   FOREACHsetelement_(type, set, variable)
-     define FOREACH iterator
-
-   declare:  
-     assumes *variable and **variablep are declared
-     no space in "variable)" [DEC Alpha cc compiler]
-
-   each iteration:
-     variable is set element
-     variablep is one beyond variable.  
-
-   to repeat an element:
-     variablep--; / *repeat* /
-
-   at exit:
-     variable is NULL at end of loop
-
-   example:  
-     #define FOREACHfacet_( facets ) FOREACHsetelement_( facetT, facets, facet )
-
-   notes:
-     use FOREACHsetelement_i_() if need index or include NULLs
-
-   WARNING: 
-     nested loops can't use the same variable (define another FOREACH)
-   
-     needs braces if nested inside another FOREACH
-     this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
-*/
-#define FOREACHsetelement_(type, set, variable) \
-        if (((variable= NULL), set)) for(\
-          variable##p= (type **)&((set)->e[0].p); \
-	  (variable= *variable##p++);)
-
-/*------------------------------------------
-
-   FOREACHsetelement_i_(type, set, variable)
-     define indexed FOREACH iterator
-
-   declare:  
-     type *variable, variable_n, variable_i;
-
-   each iteration:
-     variable is set element, may be NULL
-     variable_i is index, variable_n is qh_setsize()
-
-   to repeat an element:
-     variable_i--; variable_n-- repeats for deleted element
-
-   at exit:
-     variable==NULL and variable_i==variable_n
-
-   example:
-     #define FOREACHfacet_i_( facets ) FOREACHsetelement_i_( facetT, facets, facet )
-   
-   WARNING: 
-     nested loops can't use the same variable (define another FOREACH)
-   
-     needs braces if nested inside another FOREACH
-     this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
-*/
-#define FOREACHsetelement_i_(type, set, variable) \
-        if (((variable= NULL), set)) for (\
-          variable##_i= 0, variable= (type *)((set)->e[0].p), \
-                   variable##_n= qh_setsize(set);\
-          variable##_i < variable##_n;\
-          variable= (type *)((set)->e[++variable##_i].p) )
-
-/*----------------------------------------
-
-   FOREACHsetelementreverse_(type, set, variable)- 
-     define FOREACH iterator in reverse order
-
-   declare:  
-     assumes *variable and **variablep are declared
-     also declare 'int variabletemp'
-
-   each iteration:
-     variable is set element
-
-   to repeat an element:
-     variabletemp++; / *repeat* /
-
-   at exit:
-     variable is NULL
-
-   example:
-     #define FOREACHvertexreverse_( vertices ) FOREACHsetelementreverse_( vertexT, vertices, vertex )
-  
-   notes:
-     use FOREACHsetelementreverse12_() to reverse first two elements
-     WARNING: needs braces if nested inside another FOREACH
-*/
-#define FOREACHsetelementreverse_(type, set, variable) \
-        if (((variable= NULL), set)) for(\
-	   variable##temp= qh_setsize(set)-1, variable= qh_setlast(set);\
-	   variable; variable= \
-	   ((--variable##temp >= 0) ? SETelemt_(set, variable##temp, type) : NULL))
-
-/*-------------------------------------
-
-   FOREACHsetelementreverse12_(type, set, variable)- 
-     define FOREACH iterator with e[1] and e[0] reversed
-
-   declare:  
-     assumes *variable and **variablep are declared
-
-   each iteration:
-     variable is set element
-     variablep is one after variable.  
-
-   to repeat an element:
-     variablep--; / *repeat* /
-
-   at exit:
-     variable is NULL at end of loop
-  
-   example
-     #define FOREACHvertexreverse12_( vertices ) FOREACHsetelementreverse12_( vertexT, vertices, vertex )
-
-   notes:
-     WARNING: needs braces if nested inside another FOREACH
-*/
-#define FOREACHsetelementreverse12_(type, set, variable) \
-        if (((variable= NULL), set)) for(\
-          variable##p= (type **)&((set)->e[1].p); \
-	  (variable= *variable##p); \
-          variable##p == ((type **)&((set)->e[0].p))?variable##p += 2: \
-	      (variable##p == ((type **)&((set)->e[1].p))?variable##p--:variable##p++))
-
-/*-------------------------------------
-
-   FOREACHelem_( set )- 
-     iterate elements in a set
-
-   declare:  
-     void *elem, *elemp;
-
-   each iteration:
-     elem is set element
-     elemp is one beyond
-
-   to repeat an element:
-     elemp--; / *repeat* /
-
-   at exit:
-     elem == NULL at end of loop
-  
-   example:
-     FOREACHelem_(set) {
-     
-   notes:
-     WARNING: needs braces if nested inside another FOREACH
-*/
-#define FOREACHelem_(set) FOREACHsetelement_(void, set, elem)
-
-/*-------------------------------------
-
-   FOREACHset_( set )- 
-     iterate a set of sets
-
-   declare:  
-     setT *set, **setp;
-
-   each iteration:
-     set is set element
-     setp is one beyond
-
-   to repeat an element:
-     setp--; / *repeat* /
-
-   at exit:
-     set == NULL at end of loop
-  
-   example
-     FOREACHset_(sets) {
-     
-   notes:
-     WARNING: needs braces if nested inside another FOREACH
-*/
-#define FOREACHset_(sets) FOREACHsetelement_(setT, sets, set)
-
-/*-------------------------------------------
-
-   SETindex_( set, elem )
-     return index of elem in set
-
-   notes:   
-     for use with FOREACH iteration
-
-   example:
-     i= SETindex_(ridges, ridge)
-*/
-#define SETindex_(set, elem) ((void **)elem##p - (void **)&(set)->e[1].p)
-
-/*-----------------------------------------
-
-   SETref_( elem )
-     l.h.s. for modifying the current element in a FOREACH iteration
-
-   example:
-     SETref_(ridge)= anotherridge;
-*/
-#define SETref_(elem) (elem##p[-1])
-
-/*-----------------------------------------
-
-   SETelem_(set, n)
-     return the n'th element of set
-   
-   notes:
-      assumes that n is valid [0..size] and that set is defined
-      use SETelemt_() for type cast
-*/
-#define SETelem_(set, n)           ((set)->e[n].p)
-
-/*-----------------------------------------
-
-   SETelemt_(set, n, type)
-     return the n'th element of set as a type
-   
-   notes:
-      assumes that n is valid [0..size] and that set is defined
-*/
-#define SETelemt_(set, n, type)    ((type*)((set)->e[n].p))
-
-/*-----------------------------------------
-
-   SETelemaddr_(set, n, type)
-     return address of the n'th element of a set
-   
-   notes:
-      assumes that n is valid [0..size] and set is defined 
-*/
-#define SETelemaddr_(set, n, type) ((type **)(&((set)->e[n].p)))
-
-/*-----------------------------------------
-
-   SETfirst_(set)
-     return first element of set
-   
-*/
-#define SETfirst_(set)             ((set)->e[0].p)
-
-/*-----------------------------------------
-
-   SETfirstt_(set, type)
-     return first element of set as a type
-   
-*/
-#define SETfirstt_(set, type)      ((type*)((set)->e[0].p))
-
-/*-----------------------------------------
-
-   SETsecond_(set)
-     return second element of set
-   
-*/
-#define SETsecond_(set)            ((set)->e[1].p)
-
-/*-----------------------------------------
-
-   SETsecondt_(set, type)
-     return second element of set as a type
-*/
-#define SETsecondt_(set, type)     ((type*)((set)->e[1].p))
-
-/*-----------------------------------------
-
-   SETaddr_(set, type)
-       return address of set's elements
-*/
-#define SETaddr_(set,type)	   ((type **)(&((set)->e[0].p)))
-
-/*-----------------------------------------
-
-   SETreturnsize_(set, size) 
-     return size of a set
-   
-   notes:
-      set must be defined
-      use qh_setsize(set) unless speed is critical
-*/
-#define SETreturnsize_(set, size) (((size)= ((set)->e[(set)->maxsize].i))?(--(size)):((size)= (set)->maxsize))
-
-/*-----------------------------------------
-
-   SETempty_(set) 
-     return true (1) if set is empty
-   
-   notes:
-      set may be NULL
-*/
-#define SETempty_(set) 	          (!set || (SETfirst_(set) ? 0:1))
-
-/*-----------------------------------------
-
-   SETtruncate_(set)
-     return first element of set
-
-   see:
-     qh_settruncate()
-   
-*/
-#define SETtruncate_(set, size) {set->e[set->maxsize].i= size+1; /* maybe overwritten */ \
-      set->e[size].p= NULL;}
-
-/*======= prototypes in alphabetical order ============*/
-
-void  qh_setaddsorted(setT **setp, void *elem);
-void  qh_setaddnth(setT **setp, int nth, void *newelem);
-void  qh_setappend(setT **setp, void *elem);
-void  qh_setappend_set(setT **setp, setT *setA);
-void  qh_setappend2ndlast(setT **setp, void *elem);
-void  qh_setcheck(setT *set, char *tname, int id);
-void  qh_setcompact(setT *set);
-setT *qh_setcopy(setT *set, int extra);
-void *qh_setdel(setT *set, void *elem);
-void *qh_setdellast(setT *set);
-void *qh_setdelnth(setT *set, int nth);
-void *qh_setdelnthsorted(setT *set, int nth);
-void *qh_setdelsorted(setT *set, void *newelem);
-setT *qh_setduplicate( setT *set, int elemsize);
-int   qh_setequal(setT *setA, setT *setB);
-int   qh_setequal_except (setT *setA, void *skipelemA, setT *setB, void *skipelemB);
-int   qh_setequal_skip (setT *setA, int skipA, setT *setB, int skipB);
-void  qh_setfree(setT **set);
-void  qh_setfree2( setT **setp, int elemsize);
-void  qh_setfreelong(setT **set);
-int   qh_setin(setT *set, void *setelem);
-int   qh_setindex(setT *set, void *setelem);
-void  qh_setlarger(setT **setp);
-void *qh_setlast(setT *set);
-setT *qh_setnew(int size);
-setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend);
-void  qh_setprint(FILE *fp, char* string, setT *set);
-void  qh_setreplace(setT *set, void *oldelem, void *newelem);
-int   qh_setsize(setT *set);
-setT *qh_settemp(int setsize);
-void  qh_settempfree(setT **set);
-void  qh_settempfree_all(void);
-setT *qh_settemppop(void);
-void  qh_settemppush(setT *set);
-void  qh_settruncate (setT *set, int size);
-int   qh_setunique (setT **set, void *elem);
-void  qh_setzero (setT *set, int index, int size);
-
-
-#endif /* qhDEFset */
diff --git a/extern/qhull/include/qhull/stat.h b/extern/qhull/include/qhull/stat.h
deleted file mode 100644
index 1dae54ed21d..00000000000
--- a/extern/qhull/include/qhull/stat.h
+++ /dev/null
@@ -1,520 +0,0 @@
-  /*
  ---------------------------------
-
-   stat.h 
-     contains all statistics that are collected for qhull
-
-   see qh-stat.htm and stat.c
-
-   copyright (c) 1993-2002, The Geometry Center
-
-   recompile qhull if you change this file
-
-   Integer statistics are Z* while real statistics are W*.  
-
-   define maydebugx to call a routine at every statistic event
-
-*/
-
-#ifndef qhDEFstat
-#define qhDEFstat 1
-
-
-/*---------------------------------
-
-  qh_KEEPstatistics
-    0 turns off statistic gathering (except zzdef/zzinc/zzadd/zzval/wwval)
-*/
-#ifndef qh_KEEPstatistics
-#define qh_KEEPstatistics 1
-#endif
-
-/*---------------------------------
-
-  Zxxx for integers, Wxxx for reals
-
-  notes:
-    be sure that all statistics are defined in stat.c
-      otherwise initialization may core dump
-    can pick up all statistics by:
-      grep '[zw].*_[(][ZW]' *.c >z.x
-    remove trailers with query">-
-    remove leaders with  query-replace-regexp [ ^I]+  (
-*/
-#if qh_KEEPstatistics
-enum statistics {     /* alphabetical after Z/W */
-    Zacoplanar,
-    Wacoplanarmax,
-    Wacoplanartot,
-    Zangle,
-    Wangle,
-    Wanglemax,
-    Wanglemin,
-    Zangletests,
-    Wareatot,
-    Wareamax,
-    Wareamin,
-    Zavoidold,
-    Wavoidoldmax,
-    Wavoidoldtot,
-    Zback0,
-    Zbestcentrum,
-    Zbestdist,
-    Zcentrumtests,
-    Zcheckpart,
-    Zcomputefurthest,
-    Zconcave,
-    Wconcavemax,
-    Wconcavetot,
-    Zconcaveridges,
-    Zconcaveridge,
-    Zcoplanar,
-    Wcoplanarmax,
-    Wcoplanartot,
-    Zcoplanarangle,
-    Zcoplanarcentrum,
-    Zcoplanarhorizon,
-    Zcoplanarinside,
-    Zcoplanarpart,
-    Zcoplanarridges,
-    Wcpu,
-    Zcyclefacetmax,
-    Zcyclefacettot,
-    Zcyclehorizon,
-    Zcyclevertex,
-    Zdegen,
-    Wdegenmax,
-    Wdegentot,
-    Zdegenvertex,
-    Zdelfacetdup, 
-    Zdelridge,
-    Zdelvertextot,
-    Zdelvertexmax,
-    Zdetsimplex,
-    Zdistcheck,
-    Zdistconvex,
-    Zdistgood,
-    Zdistio,
-    Zdistplane,
-    Zdiststat,
-    Zdistvertex,
-    Zdistzero,
-    Zdoc1,
-    Zdoc2,
-    Zdoc3,
-    Zdoc4,
-    Zdoc5,
-    Zdoc6,
-    Zdoc7,
-    Zdoc8,
-    Zdoc9,
-    Zdoc10,
-    Zdoc11,
-    Zdoc12,
-    Zdropdegen,
-    Zdropneighbor,
-    Zdupflip,
-    Zduplicate,
-    Wduplicatemax,
-    Wduplicatetot,
-    Zdupridge,
-    Zdupsame,
-    Zflipped, 
-    Wflippedmax, 
-    Wflippedtot, 
-    Zflippedfacets,
-    Zfindbest,
-    Zfindbestmax,
-    Zfindbesttot,
-    Zfindcoplanar,
-    Zfindfail,
-    Zfindhorizon,
-    Zfindhorizonmax,
-    Zfindhorizontot,
-    Zfindjump,
-    Zfindnew,
-    Zfindnewmax,
-    Zfindnewtot,
-    Zfindnewjump,
-    Zfindnewsharp,
-    Zgauss0,
-    Zgoodfacet,
-    Zhashlookup,
-    Zhashridge,
-    Zhashridgetest,
-    Zhashtests,
-    Zinsidevisible,
-    Zintersect,
-    Zintersectfail,
-    Zintersectmax,
-    Zintersectnum,
-    Zintersecttot,
-    Zmaxneighbors,
-    Wmaxout,
-    Wmaxoutside,
-    Zmaxridges,
-    Zmaxvertex,
-    Zmaxvertices,
-    Zmaxvneighbors,
-    Zmemfacets,
-    Zmempoints,
-    Zmemridges,
-    Zmemvertices,
-    Zmergeflipdup,
-    Zmergehorizon,
-    Zmergeinittot,
-    Zmergeinitmax,
-    Zmergeinittot2,
-    Zmergeintohorizon,
-    Zmergenew,
-    Zmergesettot,
-    Zmergesetmax,
-    Zmergesettot2,
-    Zmergesimplex,
-    Zmergevertex,
-    Wmindenom,
-    Wminvertex,
-    Zminnorm,
-    Zmultiridge,
-    Znearlysingular,
-    Zneighbor,
-    Wnewbalance,
-    Wnewbalance2,
-    Znewfacettot,
-    Znewfacetmax,
-    Znewvertex,
-    Wnewvertex,
-    Wnewvertexmax,
-    Znoarea,
-    Znonsimplicial,
-    Znowsimplicial,
-    Znotgood,
-    Znotgoodnew,
-    Znotmax,
-    Znumfacets,
-    Znummergemax,
-    Znummergetot,
-    Znumneighbors,
-    Znumridges,
-    Znumvertices,
-    Znumvisibility,
-    Znumvneighbors,
-    Zonehorizon,
-    Zpartangle,
-    Zpartcoplanar,
-    Zpartflip,
-    Zparthorizon,
-    Zpartinside,
-    Zpartition, 
-    Zpartitionall,
-    Zpartnear,
-    Zpbalance,
-    Wpbalance,
-    Wpbalance2, 
-    Zpostfacets, 
-    Zpremergetot,
-    Zprocessed,
-    Zremvertex,
-    Zremvertexdel,
-    Zrenameall,
-    Zrenamepinch,
-    Zrenameshare,
-    Zretry,
-    Wretrymax,
-    Zridge,
-    Wridge,
-    Wridgemax,
-    Zridge0,
-    Wridge0,
-    Wridge0max,
-    Zridgemid,
-    Wridgemid,
-    Wridgemidmax,
-    Zridgeok,
-    Wridgeok,
-    Wridgeokmax,
-    Zsearchpoints,
-    Zsetplane,
-    Ztestvneighbor,
-    Ztotcheck,
-    Ztothorizon,
-    Ztotmerge,
-    Ztotpartcoplanar,
-    Ztotpartition,
-    Ztotridges,
-    Ztotvertices,
-    Ztotvisible,
-    Ztricoplanar,
-    Ztricoplanarmax,
-    Ztricoplanartot,
-    Ztridegen,
-    Ztrimirror,
-    Ztrinull,
-    Wvertexmax,
-    Wvertexmin,
-    Zvertexridge,
-    Zvertexridgetot,
-    Zvertexridgemax,
-    Zvertices,
-    Zvisfacettot,
-    Zvisfacetmax,
-    Zvisvertextot,
-    Zvisvertexmax,
-    Zwidefacet,
-    Zwidevertices,
-    ZEND};
-
-/*---------------------------------
-
-  Zxxx/Wxxx statistics that remain defined if qh_KEEPstatistics=0
-
-  notes:
-    be sure to use zzdef, zzinc, etc. with these statistics (no double checking!)
-*/
-#else
-enum statistics {     /* for zzdef etc. macros */
-  Zback0,
-  Zbestdist,
-  Zcentrumtests,
-  Zcheckpart,
-  Zconcaveridges,
-  Zcoplanarhorizon,
-  Zcoplanarpart,
-  Zcoplanarridges,
-  Zcyclefacettot,
-  Zcyclehorizon,
-  Zdelvertextot,
-  Zdistcheck,
-  Zdistconvex,
-  Zdistzero,
-  Zdoc1,
-  Zdoc2,
-  Zdoc3,
-  Zdoc11,
-  Zflippedfacets,
-  Zgauss0,
-  Zminnorm,
-  Zmultiridge,
-  Znearlysingular,
-  Wnewvertexmax,
-  Znumvisibility,
-  Zpartcoplanar,
-  Zpartition,
-  Zpartitionall,
-  Zprocessed,
-  Zretry,
-  Zridge,
-  Wridge,
-  Wridgemax,
-  Zridge0,
-  Wridge0,
-  Wridge0max,
-  Zridgemid,
-  Wridgemid,
-  Wridgemidmax,
-  Zridgeok,
-  Wridgeok,
-  Wridgeokmax,
-  Zsetplane,
-  Ztotmerge,
-    ZEND};
-#endif
-
-/*---------------------------------
-  
-  ztype
-    the type of a statistic sets its initial value.  
-
-  notes:
-    The type should be the same as the macro for collecting the statistic
-*/
-enum ztypes {zdoc,zinc,zadd,zmax,zmin,ZTYPEreal,wadd,wmax,wmin,ZTYPEend};
-
-/*========== macros and constants =============*/
-
-/*----------------------------------
-  
-  MAYdebugx
-    define as maydebug() to be called frequently for error trapping
-*/
-#define MAYdebugx 
-
-/*----------------------------------
-  
-  zzdef_, zdef_( type, name, doc, -1)
-    define a statistic (assumes 'qhstat.next= 0;')
-
-  zdef_( type, name, doc, count)
-    define an averaged statistic
-    printed as name/count
-*/
-#define zzdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \
-   qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype
-#if qh_KEEPstatistics
-#define zdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \
-   qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype
-#else
-#define zdef_(type,name,doc,count)
-#endif
-
-/*----------------------------------
-  
-  zzinc_( name ), zinc_( name)
-    increment an integer statistic
-*/
-#define zzinc_(id) {MAYdebugx; qhstat stats[id].i++;}
-#if qh_KEEPstatistics
-#define zinc_(id) {MAYdebugx; qhstat stats[id].i++;}
-#else
-#define zinc_(id) {}
-#endif
-
-/*----------------------------------
-  
-  zzadd_( name, value ), zadd_( name, value ), wadd_( name, value )
-    add value to an integer or real statistic
-*/
-#define zzadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);}
-#define wwadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);}
-#if qh_KEEPstatistics
-#define zadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);}
-#define wadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);}
-#else
-#define zadd_(id, val) {}
-#define wadd_(id, val) {}
-#endif
-
-/*----------------------------------
-
-  zzval_( name ), zval_( name ), wwval_( name )
-    set or return value of a statistic
-*/
-#define zzval_(id) ((qhstat stats[id]).i)
-#define wwval_(id) ((qhstat stats[id]).r)
-#if qh_KEEPstatistics
-#define zval_(id) ((qhstat stats[id]).i)
-#define wval_(id) ((qhstat stats[id]).r)
-#else
-#define zval_(id) qhstat tempi
-#define wval_(id) qhstat tempr
-#endif
-
-/*----------------------------------
-
-  zmax_( id, val ), wmax_( id, value )
-    maximize id with val
-*/
-#define wwmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));}
-#if qh_KEEPstatistics
-#define zmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].i,(val));}
-#define wmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));}
-#else
-#define zmax_(id, val) {}
-#define wmax_(id, val) {}
-#endif
-
-/*----------------------------------
-
-  zmin_( id, val ), wmin_( id, value )
-    minimize id with val
-*/
-#if qh_KEEPstatistics
-#define zmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].i,(val));}
-#define wmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].r,(val));}
-#else
-#define zmin_(id, val) {}
-#define wmin_(id, val) {}
-#endif
-
-/*================== stat.h types ==============*/
-
-
-/*----------------------------------
- 
-  intrealT
-    union of integer and real, used for statistics
-*/
-typedef union intrealT intrealT;    /* union of int and realT */
-union intrealT {
-    int i;
-    realT r;
-};
-
-/*----------------------------------
-  
-  qhstat
-    global data structure for statistics
-  
-  notes:
-   access to qh_qhstat is via the "qhstat" macro.  There are two choices
-   qh_QHpointer = 1     access globals via a pointer
-                        enables qh_saveqhull() and qh_restoreqhull()
-		= 0     qh_qhstat is a static data structure
-		        only one instance of qhull() can be active at a time
-			default value
-   qh_QHpointer is defined in qhull.h
-
-   allocated in stat.c
-*/
-typedef struct qhstatT qhstatT; 
-#if qh_QHpointer
-#define qhstat qh_qhstat->
-extern qhstatT *qh_qhstat;
-#else
-#define qhstat qh_qhstat.
-extern qhstatT qh_qhstat; 
-#endif
-struct qhstatT {  
-  intrealT   stats[ZEND];     /* integer and real statistics */
-  unsigned   char id[ZEND+10]; /* id's in print order */
-  char      *doc[ZEND];       /* array of documentation strings */
-  short int  count[ZEND];     /* -1 if none, else index of count to use */
-  char       type[ZEND];      /* type, see ztypes above */
-  char       printed[ZEND];   /* true, if statistic has been printed */
-  intrealT   init[ZTYPEend];  /* initial values by types, set initstatistics */
-
-  int        next;            /* next index for zdef_ */
-  int        precision;       /* index for precision problems */
-  int        vridges;         /* index for Voronoi ridges */
-  int        tempi;
-  realT      tempr;
-};
-
-/*========== function prototypes ===========*/
-
-void    qh_allstatA(void);
-void    qh_allstatB(void);
-void    qh_allstatC(void);
-void    qh_allstatD(void);
-void    qh_allstatE(void);
-void    qh_allstatE2(void);
-void    qh_allstatF(void);
-void    qh_allstatG(void);
-void    qh_allstatH(void);
-void    qh_allstatI(void);
-void    qh_allstatistics (void);
-void    qh_collectstatistics (void);
-void	qh_freestatistics (void);
-void    qh_initstatistics (void);
-boolT 	qh_newstats (int index, int *nextindex);
-boolT 	qh_nostatistic (int i);
-void    qh_printallstatistics (FILE *fp, char *string);
-void    qh_printstatistics (FILE *fp, char *string);
-void  	qh_printstatlevel (FILE *fp, int id, int start);
-void  	qh_printstats (FILE *fp, int index, int *nextindex);
-realT   qh_stddev (int num, realT tot, realT tot2, realT *ave);
-
-#endif   /* qhDEFstat */
diff --git a/extern/qhull/include/qhull/user.h b/extern/qhull/include/qhull/user.h
deleted file mode 100644
index 79558967a52..00000000000
--- a/extern/qhull/include/qhull/user.h
+++ /dev/null
@@ -1,762 +0,0 @@
-/*
  ---------------------------------
-
-   user.h
-   user redefinable constants
-
-   see qh-user.htm.  see COPYING for copyright information.
-
-   before reading any code, review qhull.h for data structure definitions and 
-   the "qh" macro.
-*/
-
-#ifndef qhDEFuser
-#define qhDEFuser 1
-
-/*============= data types and configuration macros ==========*/
-
-/*----------------------------------
-  
-  realT
-    set the size of floating point numbers
-  
-  qh_REALdigits 
-    maximimum number of significant digits
-  
-  qh_REAL_1, qh_REAL_2n, qh_REAL_3n
-    format strings for printf
-  
-  qh_REALmax, qh_REALmin
-    maximum and minimum (near zero) values  
-  
-  qh_REALepsilon
-    machine roundoff.  Maximum roundoff error for addition and multiplication.
-    
-  notes:
-   Select whether to store floating point numbers in single precision (float)
-   or double precision (double).
-   
-   Use 'float' to save about 8% in time and 25% in space.  This is particularly
-   help if high-d where convex hulls are space limited.  Using 'float' also
-   reduces the printed size of Qhull's output since numbers have 8 digits of 
-   precision.
-   
-   Use 'double' when greater arithmetic precision is needed.  This is needed
-   for Delaunay triangulations and Voronoi diagrams when you are not merging 
-   facets.
-
-   If 'double' gives insufficient precision, your data probably includes
-   degeneracies.  If so you should use facet merging (done by default)
-   or exact arithmetic (see imprecision section of manual, qh-impre.htm).  
-   You may also use option 'Po' to force output despite precision errors.
-
-   You may use 'long double', but many format statements need to be changed
-   and you may need a 'long double' square root routine.  S. Grundmann
-   (sg@eeiwzb.et.tu-dresden.de) has done this.  He reports that the code runs 
-   much slower with little gain in precision.    
-
-   WARNING: on some machines,    int f(){realT a= REALmax;return (a == REALmax);}
-      returns False.  Use (a > REALmax/2) instead of (a == REALmax).
-
-   REALfloat =   1      all numbers are 'float' type
-             =   0      all numbers are 'double' type
-*/
-#define REALfloat 0
-
-#if (REALfloat == 1)
-#define realT float
-#define REALmax FLT_MAX
-#define REALmin FLT_MIN
-#define REALepsilon FLT_EPSILON
-#define qh_REALdigits 8   /* maximum number of significant digits */
-#define qh_REAL_1 "%6.8g "
-#define qh_REAL_2n "%6.8g %6.8g\n"
-#define qh_REAL_3n "%6.8g %6.8g %6.8g\n"
-
-#elif (REALfloat == 0)
-#define realT double
-#define REALmax DBL_MAX
-#define REALmin DBL_MIN
-#define REALepsilon DBL_EPSILON
-#define qh_REALdigits 16    /* maximum number of significant digits */
-#define qh_REAL_1 "%6.16g "
-#define qh_REAL_2n "%6.16g %6.16g\n"
-#define qh_REAL_3n "%6.16g %6.16g %6.16g\n"
-
-#else
-#error unknown float option
-#endif
-
-/*----------------------------------
-  
-  qh_CPUclock
-    define the clock() function for reporting the total time spent by Qhull
-    returns CPU ticks as a 'long int'
-    qh_CPUclock is only used for reporting the total time spent by Qhull
-
-  qh_SECticks 
-    the number of clock ticks per second
-
-  notes:
-    looks for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or assumes microseconds
-    to define a custom clock, set qh_CLOCKtype to 0
-
-    if your system does not use clock() to return CPU ticks, replace
-    qh_CPUclock with the corresponding function.  It is converted
-    to unsigned long to prevent wrap-around during long runs.
-   
-
-   Set qh_CLOCKtype to
-   
-     1	   	for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or microsecond
-                Note:  may fail if more than 1 hour elapsed time
-
-     2	   	use qh_clock() with POSIX times() (see global.c)
-*/
-#define qh_CLOCKtype 1  /* change to the desired number */
-
-#if (qh_CLOCKtype == 1)
-
-#if defined (CLOCKS_PER_SECOND)
-#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
-#define qh_SECticks CLOCKS_PER_SECOND
-
-#elif defined (CLOCKS_PER_SEC)
-#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
-#define qh_SECticks CLOCKS_PER_SEC
-
-#elif defined (CLK_TCK)
-#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
-#define qh_SECticks CLK_TCK
-
-#else
-#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
-#define qh_SECticks 1E6
-#endif
-
-#elif (qh_CLOCKtype == 2)
-#define qh_CPUclock    qh_clock()  /* return CPU clock */
-#define qh_SECticks 100
-
-#else /* qh_CLOCKtype == ? */
-#error unknown clock option
-#endif
-
-/*----------------------------------
-  
-  qh_RANDOMtype, qh_RANDOMmax, qh_RANDOMseed
-    define random number generator
-
-    qh_RANDOMint generates a random integer between 0 and qh_RANDOMmax.  
-    qh_RANDOMseed sets the random number seed for qh_RANDOMint
-
-  Set qh_RANDOMtype (default 5) to:
-    1       for random() with 31 bits (UCB)
-    2       for rand() with RAND_MAX or 15 bits (system 5)
-    3       for rand() with 31 bits (Sun)
-    4       for lrand48() with 31 bits (Solaris)
-    5       for qh_rand() with 31 bits (included with Qhull)
-  
-  notes:
-    Random numbers are used by rbox to generate point sets.  Random
-    numbers are used by Qhull to rotate the input ('QRn' option),
-    simulate a randomized algorithm ('Qr' option), and to simulate
-    roundoff errors ('Rn' option).
-
-    Random number generators differ between systems.  Most systems provide
-    rand() but the period varies.  The period of rand() is not critical
-    since qhull does not normally use random numbers.  
-
-    The default generator is Park & Miller's minimal standard random
-    number generator [CACM 31:1195 '88].  It is included with Qhull.
-
-    If qh_RANDOMmax is wrong, qhull will report a warning and Geomview 
-    output will likely be invisible.
-*/
-#define qh_RANDOMtype 5   /* *** change to the desired number *** */
-
-#if (qh_RANDOMtype == 1)
-#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, random()/MAX */
-#define qh_RANDOMint random()
-#define qh_RANDOMseed_(seed) srandom(seed);
-
-#elif (qh_RANDOMtype == 2)
-#ifdef RAND_MAX
-#define qh_RANDOMmax ((realT)RAND_MAX)
-#else
-#define qh_RANDOMmax ((realT)32767)   /* 15 bits (System 5) */
-#endif
-#define qh_RANDOMint  rand()
-#define qh_RANDOMseed_(seed) srand((unsigned)seed);
-  
-#elif (qh_RANDOMtype == 3)
-#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, Sun */
-#define qh_RANDOMint  rand()
-#define qh_RANDOMseed_(seed) srand((unsigned)seed);
-
-#elif (qh_RANDOMtype == 4)
-#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, lrand38()/MAX */
-#define qh_RANDOMint lrand48()
-#define qh_RANDOMseed_(seed) srand48(seed);
-
-#elif (qh_RANDOMtype == 5)
-#define qh_RANDOMmax ((realT)2147483646UL)  /* 31 bits, qh_rand/MAX */
-#define qh_RANDOMint qh_rand()
-#define qh_RANDOMseed_(seed) qh_srand(seed);
-/* unlike rand(), never returns 0 */
-
-#else
-#error: unknown random option
-#endif
-
-/*----------------------------------
-  
-  qh_ORIENTclock
-    0 for inward pointing normals by Geomview convention
-*/
-#define qh_ORIENTclock 0 
-
-
-/*========= performance related constants =========*/
-
-/*----------------------------------
-  
-  qh_HASHfactor
-    total hash slots / used hash slots.  Must be at least 1.1.
-      
-  notes:
-    =2 for at worst 50% occupancy for qh hash_table and normally 25% occupancy
-*/
-#define qh_HASHfactor 2
-
-/*----------------------------------
-  
-  qh_VERIFYdirect
-    with 'Tv' verify all points against all facets if op count is smaller
-
-  notes:
-    if greater, calls qh_check_bestdist() instead
-*/
-#define qh_VERIFYdirect 1000000 
-
-/*----------------------------------
-  
-  qh_INITIALsearch
-     if qh_INITIALmax, search points up to this dimension
-*/
-#define qh_INITIALsearch 6
-
-/*----------------------------------
-  
-  qh_INITIALmax
-    if dim >= qh_INITIALmax, use min/max coordinate points for initial simplex
-      
-  notes:
-    from points with non-zero determinants
-    use option 'Qs' to override (much slower)
-*/
-#define qh_INITIALmax 8
-
-/*----------------------------------
-  
-  qh_JOGGLEdefault
-    default qh.JOGGLEmax is qh.DISTround * qh_JOGGLEdefault
-
-  notes:
-    rbox s r 100 | qhull QJ1e-15 QR0 generates 90% faults at distround 7e-16
-    rbox s r 100 | qhull QJ1e-14 QR0 generates 70% faults
-    rbox s r 100 | qhull QJ1e-13 QR0 generates 35% faults
-    rbox s r 100 | qhull QJ1e-12 QR0 generates 8% faults
-    rbox s r 100 | qhull QJ1e-11 QR0 generates 1% faults
-    rbox s r 100 | qhull QJ1e-10 QR0 generates 0% faults
-    rbox 1000 W0 | qhull QJ1e-12 QR0 generates 86% faults
-    rbox 1000 W0 | qhull QJ1e-11 QR0 generates 20% faults
-    rbox 1000 W0 | qhull QJ1e-10 QR0 generates 2% faults
-    the later have about 20 points per facet, each of which may interfere
-
-    pick a value large enough to avoid retries on most inputs
-*/
-#define qh_JOGGLEdefault 30000.0
-
-/*----------------------------------
-  
-  qh_JOGGLEincrease
-    factor to increase qh.JOGGLEmax on qh_JOGGLEretry or qh_JOGGLEagain
-*/
-#define qh_JOGGLEincrease 10.0
-
-/*----------------------------------
-  
-  qh_JOGGLEretry
-    if ZZretry = qh_JOGGLEretry, increase qh.JOGGLEmax
-
-  notes:
-    try twice at the original value in case of bad luck the first time
-*/
-#define qh_JOGGLEretry 2
-
-/*----------------------------------
-  
-  qh_JOGGLEagain
-    every following qh_JOGGLEagain, increase qh.JOGGLEmax
-
-  notes:
-    1 is OK since it's already failed qh_JOGGLEretry times
-*/
-#define qh_JOGGLEagain 1
-
-/*----------------------------------
-  
-  qh_JOGGLEmaxincrease
-    maximum qh.JOGGLEmax due to qh_JOGGLEincrease
-    relative to qh.MAXwidth
-
-  notes:
-    qh.joggleinput will retry at this value until qh_JOGGLEmaxretry
-*/
-#define qh_JOGGLEmaxincrease 1e-2
-
-/*----------------------------------
-  
-  qh_JOGGLEmaxretry
-    stop after qh_JOGGLEmaxretry attempts
-*/
-#define qh_JOGGLEmaxretry 100
-
-/*========= memory constants =========*/
-
-/*----------------------------------
-  
-  qh_MEMalign
-    memory alignment for qh_meminitbuffers() in global.c
-    
-  notes:
-    to avoid bus errors, memory allocation must consider alignment requirements.
-    malloc() automatically takes care of alignment.   Since mem.c manages
-    its own memory, we need to explicitly specify alignment in
-    qh_meminitbuffers().
-
-    A safe choice is sizeof(double).  sizeof(float) may be used if doubles 
-    do not occur in data structures and pointers are the same size.  Be careful
-    of machines (e.g., DEC Alpha) with large pointers. 
-
-    If using gcc, best alignment is
-              #define qh_MEMalign fmax_(__alignof__(realT),__alignof__(void *))
-*/
-#define qh_MEMalign fmax_(sizeof(realT), sizeof(void *))
-
-/*----------------------------------
-  
-  qh_MEMbufsize
-    size of additional memory buffers
-    
-  notes:
-    used for qh_meminitbuffers() in global.c
-*/
-#define qh_MEMbufsize 0x10000       /* allocate 64K memory buffers */
-
-/*----------------------------------
-  
-  qh_MEMinitbuf
-    size of initial memory buffer
-    
-  notes:
-    use for qh_meminitbuffers() in global.c
-*/
-#define qh_MEMinitbuf 0x20000      /* initially allocate 128K buffer */
-
-/*----------------------------------
-  
-  qh_INFINITE
-    on output, indicates Voronoi center at infinity
-*/
-#define qh_INFINITE  -10.101
-
-/*----------------------------------
-  
-  qh_DEFAULTbox
-    default box size (Geomview expects 0.5)
-*/
-#define qh_DEFAULTbox 0.5 
-
-/*======= conditional compilation ============================*/
-
-/*----------------------------------
-
-  __cplusplus
-    defined by C++ compilers
-
-  __MSC_VER
-    defined by Microsoft Visual C++
-  
-  __MWERKS__ && __POWERPC__
-    defined by Metrowerks when compiling for the Power Macintosh
-
-  __STDC__
-    defined for strict ANSI C 
-*/
-
-/*----------------------------------
- 
-  qh_COMPUTEfurthest 
-    compute furthest distance to an outside point instead of storing it with the facet
-    =1 to compute furthest
-  
-  notes:
-    computing furthest saves memory but costs time
-      about 40% more distance tests for partitioning
-      removes facet->furthestdist 
-*/
-#define qh_COMPUTEfurthest 0
-                         
-/*----------------------------------
- 
-  qh_KEEPstatistics   
-    =0 removes most of statistic gathering and reporting
-
-  notes:
-    if 0, code size is reduced by about 4%.
-*/
-#define qh_KEEPstatistics 1
-                       
-/*----------------------------------
- 
-  qh_MAXoutside 
-    record outer plane for each facet
-    =1 to record facet->maxoutside
-  
-  notes:
-    this takes a realT per facet and slightly slows down qhull
-    it produces better outer planes for geomview output 
-*/
-#define qh_MAXoutside 1
-
-/*----------------------------------
- 
-  qh_NOmerge
-    disables facet merging if defined
-    
-  notes:
-    This saves about 10% space.
-    
-    Unless 'Q0'
-      qh_NOmerge sets 'QJ' to avoid precision errors
-
-    #define qh_NOmerge    
-
-  see:
-    qh_NOmem in mem.c
-    
-    see user.c/user_eg.c for removing io.o
-*/  
-    
-/*----------------------------------
- 
-  qh_NOtrace
-    no tracing if defined 
-  
-  notes:
-    This saves about 5% space.
-
-    #define qh_NOtrace
-*/    
-
-/*----------------------------------
-  
-  qh_QHpointer
-    access global data with pointer or static structure
-
-  qh_QHpointer  = 1     access globals via a pointer to allocated memory
-                        enables qh_saveqhull() and qh_restoreqhull()
-			costs about 8% in time and 2% in space
-
-		= 0     qh_qh and qh_qhstat are static data structures
-		        only one instance of qhull() can be active at a time
-			default value
-
-  notes:
-    all global variables for qhull are in qh, qhmem, and qhstat
-    qh is defined in qhull.h
-    qhmem is defined in mem.h
-    qhstat is defined in stat.h
-
-  see:
-    user_eg.c for an example
-*/
-#define qh_QHpointer 0
-#if 0  /* sample code */
-    qhT *oldqhA, *oldqhB;
-
-    exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
-                      flags, outfile, errfile); 
-    /* use results from first call to qh_new_qhull */
-    oldqhA= qh_save_qhull();
-    exitcode= qh_new_qhull (dimB, numpointsB, pointsB, ismalloc,
-                      flags, outfile, errfile); 
-    /* use results from second call to qh_new_qhull */
-    oldqhB= qh_save_qhull();
-    qh_restore_qhull (&oldqhA);
-    /* use results from first call to qh_new_qhull */
-    qh_freeqhull (qh_ALL);  /* frees all memory used by first call */
-    qh_restore_qhull (&oldqhB);
-    /* use results from second call to qh_new_qhull */
-    qh_freeqhull (!qh_ALL); /* frees long memory used by second call */
-    qh_memfreeshort (&curlong, &totlong);  /* frees short memory and memory allocator */
-#endif
-
-/*----------------------------------
- 
-  qh_QUICKhelp        
-    =1 to use abbreviated help messages, e.g., for degenerate inputs
-*/
-#define qh_QUICKhelp    0  
-
-/* ============ -merge constants- ====================
-
-   These constants effect facet merging.  You probably will not need
-   to modify these.  They effect the performance of facet merging.
-*/
-
-/*----------------------------------
-  
-  qh_DIMmergeVertex
-    max dimension for vertex merging (it is not effective in high-d)
-*/
-#define qh_DIMmergeVertex 6
-
-/*----------------------------------
-  
-  qh_DIMreduceBuild
-     max dimension for vertex reduction during build (slow in high-d)
-*/
-#define qh_DIMreduceBuild 5
-
-/*----------------------------------
-     
-  qh_BESTcentrum
-     if > 2*dim+n vertices, qh_findbestneighbor() tests centrums (faster)
-     else, qh_findbestneighbor() tests all vertices (much better merges)
-
-  qh_BESTcentrum2
-     if qh_BESTcentrum2 * DIM3 + BESTcentrum < #vertices tests centrums
-*/
-#define qh_BESTcentrum 20
-#define qh_BESTcentrum2 2
-
-/*----------------------------------
-  
-  qh_BESTnonconvex
-    if > dim+n neighbors, qh_findbestneighbor() tests nonconvex ridges.
-    
-  notes:
-    It is needed because qh_findbestneighbor is slow for large facets
-*/
-#define qh_BESTnonconvex 15 
-
-/*----------------------------------
-  
-  qh_MAXnewmerges
-    if >n newmerges, qh_merge_nonconvex() calls qh_reducevertices_centrums.
-     
-  notes:
-    It is needed because postmerge can merge many facets at once
-*/
-#define qh_MAXnewmerges 2
-
-/*----------------------------------
-  
-  qh_MAXnewcentrum
-    if <= dim+n vertices (n approximates the number of merges),
-      reset the centrum in qh_updatetested() and qh_mergecycle_facets()
-    
-  notes:
-    needed to reduce cost and because centrums may move too much if 
-    many vertices in high-d
-*/
-#define qh_MAXnewcentrum 5
-
-/*----------------------------------
-  
-  qh_COPLANARratio
-    for 3-d+ merging, qh.MINvisible is n*premerge_centrum
-
-  notes:
-    for non-merging, it's DISTround
-*/
-#define qh_COPLANARratio 3
-
-/*----------------------------------
-  
-  qh_DISToutside
-    When is a point clearly outside of a facet?  
-    Stops search in qh_findbestnew or qh_partitionall
-    qh_findbest uses qh.MINoutside since since it is only called if no merges.
-     
-  notes:
-    'Qf' always searches for best facet
-    if !qh.MERGING, same as qh.MINoutside. 
-    if qh_USEfindbestnew, increase value since neighboring facets may be ill-behaved
-      [Note: Zdelvertextot occurs normally with interior points]
-            RBOX 1000 s Z1 G1e-13 t1001188774 | QHULL Tv
-    When there is a sharp edge, need to move points to a
-    clearly good facet; otherwise may be lost in another partitioning.
-    if too big then O(n^2) behavior for partitioning in cone
-    if very small then important points not processed
-    Needed in qh_partitionall for
-      RBOX 1000 s Z1 G1e-13 t1001032651 | QHULL Tv
-    Needed in qh_findbestnew for many instances of
-      RBOX 1000 s Z1 G1e-13 t | QHULL Tv
-
-  See:  
-    qh_DISToutside -- when is a point clearly outside of a facet
-    qh_SEARCHdist -- when is facet coplanar with the best facet?
-    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
-*/
-#define qh_DISToutside ((qh_USEfindbestnew ? 2 : 1) * \
-     fmax_((qh MERGING ? 2 : 1)*qh MINoutside, qh max_outside))
-
-/*----------------------------------
-  
-  qh_RATIOnearinside
-    ratio of qh.NEARinside to qh.ONEmerge for retaining inside points for
-    qh_check_maxout().  
-  
-  notes:
-    This is overkill since do not know the correct value.
-    It effects whether 'Qc' reports all coplanar points
-    Not used for 'd' since non-extreme points are coplanar
-*/
-#define qh_RATIOnearinside 5
-
-/*----------------------------------
-  
-  qh_SEARCHdist
-    When is a facet coplanar with the best facet?  
-    qh_findbesthorizon: all coplanar facets of the best facet need to be searched.
-
-  See:
-    qh_DISToutside -- when is a point clearly outside of a facet
-    qh_SEARCHdist -- when is facet coplanar with the best facet?
-    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
-*/
-#define qh_SEARCHdist ((qh_USEfindbestnew ? 2 : 1) * \
-      (qh max_outside + 2 * qh DISTround + fmax_( qh MINvisible, qh MAXcoplanar)));
-
-/*----------------------------------
-  
-  qh_USEfindbestnew
-     Always use qh_findbestnew for qh_partitionpoint, otherwise use
-     qh_findbestnew if merged new facet or sharpnewfacets.
-  
-  See:
-    qh_DISToutside -- when is a point clearly outside of a facet
-    qh_SEARCHdist -- when is facet coplanar with the best facet?
-    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
-*/
-#define qh_USEfindbestnew (zzval_(Ztotmerge) > 50)
-
-/*----------------------------------
-  
-  qh_WIDEcoplanar
-    n*MAXcoplanar or n*MINvisible for a WIDEfacet 
-    
-    if vertex is further than qh.WIDEfacet from the hyperplane
-    then its ridges are not counted in computing the area, and
-    the facet's centrum is frozen. 
-    
-  notes:
-   qh.WIDEfacet= max(qh.MAXoutside,qh_WIDEcoplanar*qh.MAXcoplanar,
-      qh_WIDEcoplanar * qh.MINvisible);
-*/
-#define qh_WIDEcoplanar 6
-
-/*----------------------------------
-  
-  qh_MAXnarrow
-    max. cosine in initial hull that sets qh.NARROWhull
-       
-  notes:
-    If qh.NARROWhull, the initial partition does not make 
-    coplanar points.  If narrow, a coplanar point can be 
-    coplanar to two facets of opposite orientations and
-    distant from the exact convex hull.
-
-    Conservative estimate.  Don't actually see problems until it is -1.0
-*/
-#define qh_MAXnarrow -0.99999999
-
-/*----------------------------------
-  
-  qh_WARNnarrow
-    max. cosine in initial hull to warn about qh.NARROWhull
-      
-  notes:
-    this is a conservative estimate.  
-    Don't actually see problems until it is -1.0.  See qh-impre.htm
-*/
-#define qh_WARNnarrow -0.999999999999999
-
-/*----------------------------------
-  
-  qh_ZEROdelaunay
-    a zero Delaunay facet occurs for input sites coplanar with their convex hull
-    the last normal coefficient of a zero Delaunay facet is within
-        qh_ZEROdelaunay * qh.ANGLEround of 0
-      
-  notes:
-    qh_ZEROdelaunay does not allow for joggled input ('QJ').
-
-    You can avoid zero Delaunay facets by surrounding the input with a box.
-
-    Use option 'PDk:-n' to explicitly define zero Delaunay facets
-      k= dimension of input sites (e.g., 3 for 3-d Delaunay triangulation)
-      n= the cutoff for zero Delaunay facets (e.g., 'PD3:-1e-12')
-*/
-#define qh_ZEROdelaunay 2
-
-#endif /* qh_DEFuser */
-
-
-
diff --git a/extern/qhull/make/msvc_7_0/qhull.vcproj b/extern/qhull/make/msvc_7_0/qhull.vcproj
deleted file mode 100644
index 1b754d8e076..00000000000
--- a/extern/qhull/make/msvc_7_0/qhull.vcproj
+++ /dev/null
@@ -1,677 +0,0 @@
-
-
-	
-		
-	
-	
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-	
-		
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-
diff --git a/extern/qhull/make/msvc_9_0/qhull.vcproj b/extern/qhull/make/msvc_9_0/qhull.vcproj
deleted file mode 100644
index fe5b3e806b6..00000000000
--- a/extern/qhull/make/msvc_9_0/qhull.vcproj
+++ /dev/null
@@ -1,877 +0,0 @@
-
-
-	
-		
-	
-	
-	
-	
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-	
-		
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-
diff --git a/extern/qhull/src/Make-config.sh b/extern/qhull/src/Make-config.sh
deleted file mode 100755
index 90bbb958599..00000000000
--- a/extern/qhull/src/Make-config.sh
+++ /dev/null
@@ -1,285 +0,0 @@
-#!/bin/sh -e
-#
-# Make-config.sh
-#
-#     Setup for Debian build
-#
-#     Writes configure.in and Makefile.am files
-#     and runs automake and autoconfig
-#
-#     Use 'make dist' to build Unix distribution.
-#     Use 'configure; make' to build Qhull
-#
-#note:
-#     'configure; make' does not work under cygwin.
-#	src/unix.c:354: variable 'qh_qh' can't be auto-imported.
-#	Please read the documentation for ld's --enable-auto-import for details.
-
-###################################################
-###########  ../configure.in ######################
-###################################################
-
-echo Create ../configure.in
-cat >../configure.in <<\HERE-CONFIGURE
-dnl configure.in for the qhull package
-dnl Author: Rafael Laboissiere 
-dnl Created: Mon Dec  3 21:36:21 CET 2001
-
-AC_INIT(src/qhull.c)
-AM_INIT_AUTOMAKE(qhull, 2002.1)
-
-AC_PROG_CC
-AC_PROG_LIBTOOL
-
-AC_OUTPUT([Makefile src/Makefile html/Makefile eg/Makefile])
-
-HERE-CONFIGURE
-
-###################################################
-###########  ../Makefile.am #######################
-###################################################
-
-echo Create ../Makefile.am
-cat >../Makefile.am <<\HERE-TOP
-### Makefile.am for the qhull package (main)
-### Author: Rafael Laboissiere 
-### Created: Mon Dec  3 21:36:21 CET 2001
-
-### Documentation files
-
-# to:
-docdir = $(prefix)/share/doc/$(PACKAGE)
-
-# which:
-doc_DATA = \
-  Announce.txt \
-  COPYING.txt \
-  README.txt \
-  REGISTER.txt
-
-### Extra files to be included in the tarball
-
-EXTRA_DIST = \
-  $(doc_DATA) \
-  File_id.diz \
-  QHULL-GO.pif
-
-### Subdirectories for Automaking
-
-SUBDIRS = src html eg
-
-HERE-TOP
-
-###################################################
-###########  ../eg/Makefile.am ####################
-###################################################
-
-echo Create ../eg/Makefile.am
-cat >../eg/Makefile.am <<\HERE-AM
-### Makefile.am for the qhull package (eg)
-### Author: Rafael Laboissiere 
-### Created: Mon Dec  3 21:36:21 CET 2001
-
-### Documentation files
-
-# to:
-docdir = $(prefix)/share/doc/$(PACKAGE)
-examplesdir = $(docdir)/examples
-
-# which:
-examples_DATA = \
-  q_eg \
-  q_egtest \
-  q_test \
-  Qhull-go.bat \
-  q_test.bat
-
-### Extra files to be included in the tarball
-
-EXTRA_DIST = $(examples_DATA)
-
-HERE-AM
-
-###################################################
-###########  ../html/Makefile.am ##################
-###################################################
-
-echo Create ../html/Makefile.am
-cat >../html/Makefile.am <<\HERE-HTML
-### Makefile.am for the qhull package (html)
-### Author: Rafael Laboissiere 
-### Created: Mon Dec  3 21:36:21 CET 2001
-
-### Man pages (trick to get around .man extension)
-
-%.1: %.man
-	cp $< $@
-CLEANFILES = *.1
-man_MANS = rbox.1 qhull.1
-
-### Documentation files
-
-# to:
-docdir = $(prefix)/share/doc/$(PACKAGE)
-htmldir = $(docdir)/html
-
-# which:
-html_DATA = \
-  index.htm \
-  qconvex.htm \
-  qdelau_f.htm \
-  qdelaun.htm \
-  qh--4d.gif \
-  qh--cone.gif \
-  qh--dt.gif \
-  qh--geom.gif \
-  qh--half.gif \
-  qh--rand.gif \
-  qh-eg.htm \
-  qh-faq.htm \
-  qh-get.htm \
-  qh-home.htm \
-  qh-impre.htm \
-  qh-in.htm \
-  qh-optc.htm \
-  qh-optf.htm \
-  qh-optg.htm \
-  qh-opto.htm \
-  qh-optp.htm \
-  qh-optq.htm \
-  qh-optt.htm \
-  qh-quick.htm \
-  qhalf.htm \
-  qhull.htm \
-  qvoron_f.htm \
-  qvoronoi.htm \
-  rbox.htm
-
-### Extra files to be included in the tarball
-
-EXTRA_DIST = \
-  $(html_DATA) \
-  qhull.man \
-  qhull.txt \
-  rbox.man \
-  rbox.txt
-
-HERE-HTML
-
-###################################################
-###########  ../src/Makefile.am ###################
-###################################################
-
-echo Create ../src/Makefile.am
-cat >../src/Makefile.am <<\HERE-SRC
-### Makefile.am for the qhull package (src)
-### Author: Rafael Laboissiere 
-### Created: Mon Dec  3 21:36:21 CET 2001
-
-### Shared Library
-
-# to:
-lib_LTLIBRARIES = libqhull.la
-
-# from:
-libqhull_la_SOURCES = \
-  user.c \
-  global.c \
-  stat.c \
-  io.c \
-  geom2.c \
-  poly2.c \
-  merge.c \
-  qhull.c \
-  geom.c \
-  poly.c \
-  qset.c \
-  mem.c
-
-# how:
-libqhull_la_LDFLAGS = -version-info 0:0:0 -lm
-
-### Utility programs
-
-# to:
-bin_PROGRAMS = qhull rbox qconvex qdelaunay qvoronoi qhalf
-
-# from:
-qhull_SOURCES = unix.c
-rbox_SOURCES = rbox.c
-qconvex_SOURCES = qconvex.c
-qdelaunay_SOURCES = qdelaun.c
-qvoronoi_SOURCES = qvoronoi.c
-qhalf_SOURCES = qhalf.c
-
-# how:
-qhull_LDADD = libqhull.la
-rbox_LDADD = libqhull.la
-qconvex_LDADD = libqhull.la
-qdelaunay_LDADD = libqhull.la
-qvoronoi_LDADD = libqhull.la
-qhalf_LDADD = libqhull.la
-
-### Include files
-
-pkginclude_HEADERS = \
-  geom.h \
-  mem.h \
-  poly.h \
-  qhull_a.h \
-  stat.h \
-  io.h \
-  merge.h \
-  qhull.h  \
-  qset.h \
-  user.h
-
-
-### Example programs
-
-# to:
-docdir = $(prefix)/share/doc/$(PACKAGE)
-examplesdir = $(docdir)/examples
-
-# which:
-examples_DATA = \
-  user_eg.c \
-  user_eg2.c \
-  qhull_interface.cpp \
-  Makefile.txt \
-  Make-config.sh \
-  MBorland
-
-doc_DATA = Changes.txt \
-    index.htm \
-    qh-geom.htm \
-    qh-globa.htm \
-    qh-io.htm \
-    qh-mem.htm \
-    qh-merge.htm \
-    qh-poly.htm \
-    qh-qhull.htm \
-    qh-set.htm \
-    qh-stat.htm \
-    qh-user.htm
-
-
-### Extra files to be included in the tarball
-
-EXTRA_DIST = \
-  $(doc_DATA) \
-  $(examples_DATA)
-
-HERE-SRC
-
-###################################################
-###########  run automake autoconf ################
-###################################################
-
-
-echo Run automake, libtoolize, and autoconf
-cd ..; aclocal &&\
-  automake --foreign --add-missing --force-missing && \
-  libtoolize --force && \
-  autoconf
-
diff --git a/extern/qhull/src/Makefile b/extern/qhull/src/Makefile
deleted file mode 100644
index 81c06758cbb..00000000000
--- a/extern/qhull/src/Makefile
+++ /dev/null
@@ -1,55 +0,0 @@
-# -*- mode: gnumakefile; tab-width: 8; indent-tabs-mode: t; -*-
-# vim: tabstop=8
-#
-# $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.
-#
-# The Original Code is: all of this file.
-#
-# Contributor(s): GSR
-#
-# ***** END GPL LICENSE BLOCK *****
-#
-#
-
-LIBNAME = qhull
-DIR = $(OCGDIR)/extern/$(LIBNAME)
-
-CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
-
-CPPFLAGS += -I../include
-
-CSRCS = user.c global.c stat.c io.c geom2.c poly2.c \
-       merge.c qhull.c geom.c poly.c qset.c mem.c
-CCSRCS = 
-include nan_compile.mk 
-
-install: $(ALL_OR_DEBUG)
-	@[ -d $(NAN_QHULL) ] || mkdir -p $(NAN_QHULL)
-	@[ -d $(NAN_QHULL)/include/qhull ] || mkdir -p $(NAN_QHULL)/include/qhull
-	@[ -d $(NAN_QHULL)/lib/$(DEBUG_DIR) ] || mkdir -p $(NAN_QHULL)/lib/$(DEBUG_DIR)
-	@$(NANBLENDERHOME)/intern/tools/cpifdiff.sh $(DIR)/$(DEBUG_DIR)lib$(LIBNAME).a $(NAN_QHULL)/lib/$(DEBUG_DIR)
-ifeq ($(OS),darwin)
-	ranlib $(NAN_QHULL)/lib/$(DEBUG_DIR)lib$(LIBNAME).a
-endif
-	@$(NANBLENDERHOME)/intern/tools/cpifdiff.sh ../include/qhull/*.h $(NAN_QHULL)/include/qhull
-
-
diff --git a/extern/qhull/src/Makefile.txt b/extern/qhull/src/Makefile.txt
deleted file mode 100644
index e87b66b49bc..00000000000
--- a/extern/qhull/src/Makefile.txt
+++ /dev/null
@@ -1,190 +0,0 @@
-# Unix Makefile for qhull and rbox
-#
-#       see README.txt
-#
-#       make           to produce qhull qconvex qdelaunay qhalf qvoronoi rbox
-#       make qvoronoi  to produce qvoronoi (etc.)
-#       make qhullx    to produce qhull qconvex etc.  w/o using libqhull.a
-#       make doc       to print documentation
-#       make install   to copy qhull, rbox, qhull.1, rbox.1 to BINDIR, MANDIR
-#       make new       to rebuild qhull and rbox from source
-#
-#       make printall  to print all files
-#       make user_eg   to produce user_eg
-#       make user_eg2  to produce user_eg2
-#       make clean     to remove object files and core
-#       make cleanall  to remove all generated files
-#
-#       PRINTMAN --  command for printing manual pages
-#       PRINTC --  command for printing C files
-#       BINDIR -- directory where to copy executables
-#       MANDIR -- directory where to copy manual pages
-#       CC --     ANSI C or C++ compiler
-#       CCOPTS1 - options used to compile .c files
-#       CCOPTS2 -- options used to link .o files
-#
-#       CFILES -- .c files for printing
-#       HFILES -- .h files for printing
-#       DFILES -- documentation files
-#       MFILES -- man pages and html files
-#       TFILES -- .txt versions of html html files
-#       FILES -- all other files
-#       OBJS -- specifies the object files of libqhull.a
-#
-BINDIR  = /usr/local/bin
-MANDIR  = /usr/local/man/man1
-
-# if you do not have enscript, try a2ps or just use lpr.  The files are text.
-PRINTMAN = enscript -2rl
-PRINTC = enscript -2r
-# PRINTMAN = lpr
-# PRINTC = lpr
-
-#for Gnu's gcc compiler -O2 for optimization, -g for debugging, -Wall for check
-#
-CC     = gcc
-CCOPTS1 = -O2 -ansi 
-
-# for Sun's cc compiler, -fast or O2 for optimization, -g for debugging, -Xc for ANSI
-#CC = cc
-#CCOPTS1 = -Xc -v -fast
-
-# for Silicon Graphics cc compiler, -O2 for optimization, -g for debugging
-#CC = cc
-#CCOPTS1 = -ansi -O2
-
-# for Next cc compiler with fat executable
-#CC = cc
-#CCOPTS1 = -ansi -O2 -arch m68k -arch i386 -arch hppa
-
-# for loader, ld
-CCOPTS2 = $(CCOPTS1)
-
-# OBJS in execution frequency order.  CFILES after qhull.c are alphabetical
-OBJS = user.o global.o stat.o io.o geom2.o poly2.o \
-       merge.o qhull.o geom.o poly.o qset.o mem.o
-
-CFILES= unix.c qhull.c geom.c geom2.c global.c io.c mem.c merge.c poly.c \
-        poly2.c qset.c stat.c user.c qconvex.c qdelaun.c qhalf.c qvoronoi.c
-HFILES= user.h qhull.h qhull_a.h geom.h io.h mem.h merge.h poly.h qset.h stat.h
-TXTFILES= ../Announce.txt ../REGISTER.txt ../COPYING.txt ../README.txt Changes.txt
-DOCFILES= ../html/rbox.txt ../html/qhull.txt
-FILES=  Makefile rbox.c user_eg.c ../eg/q_test ../eg/q_egtest ../eg/q_eg
-HTMFILES= qhull.man rbox.man qh-in.htm qh-optg.htm qh-optt.htm qh-optp.htm \
-        index.htm qh-quick.htm qh-impre.htm qh-eg.htm \
-        qh-optc.htm qh-opto.htm qh-optf.htm qh-optq.htm \
-	    qh-c.htm qh-faq.htm qhull.htm qconvex.htm qdelaun.htm \
-		qh-geom.htm qh-globa.htm qh-io.htm qh-mem.htm qh-merge.htm \
-		qh-poly.htm qh-qhull.htm qh-set.htm qh-stat.htm qh-user.htm \
-		qdelau_f.htm qhalf.htm qvoronoi.htm qvoron_f.htm rbox.htm 
-
-all: rbox qconvex qdelaunay qhalf qvoronoi qhull
-
-unix.o:   qhull.h user.h mem.h
-qconvex.o:   qhull.h user.h mem.h
-qdelaun.o:   qhull.h user.h mem.h
-qhalf.o:   qhull.h user.h mem.h
-qvoronoi.o:   qhull.h user.h mem.h
-qhull.o:  $(HFILES)
-geom.o:   $(HFILES)
-geom2.o:  $(HFILES)
-global.o: $(HFILES)
-io.o:     $(HFILES)
-mem.o:    mem.h 
-merge.o:  $(HFILES)
-poly.o:   $(HFILES)
-poly2.o:  $(HFILES)
-qset.o:   qset.h mem.h 
-stat.o:   $(HFILES)
-user.o:   $(HFILES)
-
-.c.o:
-	$(CC) -c $(CCOPTS1) $<
-
-clean:
-	rm -f *.o ../core qconvex qdelaunay qhalf qvoronoi qhull libqhull.a \
-	    *.exe
-
-cleanall: clean
-	rm -f *~ ../rbox ../qhull ../qhalf ../qconvex ../qdelaunay ../qhalf\
-	   ../qvoronoi ../user_eg ../user_eg2 ../*.exe >/dev/null
-
-doc: 
-	$(PRINTMAN) $(TXTFILES) $(DOCFILES)
-
-install: all 
-	cp ../qconvex $(BINDIR)/qconvex
-	cp ../qdelaunay $(BINDIR)/qdelaunay
-	cp ../qhalf $(BINDIR)/qhalf
-	cp ../qhull $(BINDIR)/qhull
-	cp ../qvoronoi $(BINDIR)/qvoronoi
-	cp ../rbox $(BINDIR)/rbox
-	cp ../html/qhull.man $(MANDIR)/qhull.1
-	cp ../html/rbox.man $(MANDIR)/rbox.1
-
-new:    cleanall all
-
-printall: doc printh printc printf
-
-printh:
-	$(PRINTC) $(HFILES)
-
-printc:
-	$(PRINTC) $(CFILES)
-
-printf:
-	$(PRINTC) $(FILES) 
-
-libqhull.a: $(OBJS)
-	@echo if 'ar' or 'ranlib' fails, try 'make qhullx'
-	ar r libqhull.a $(OBJS)
-	@echo the next line may need to be removed.
-	-test -x /bin/ranlib -o -x /usr/bin/ranlib && ranlib libqhull.a
-
-# don't use ../qconvex.  Does not work on Red Hat Linux
-qconvex: qconvex.o libqhull.a
-	$(CC) -o qconvex $(CCOPTS2) qconvex.o -L. -lqhull -lm 
-	cp qconvex ..
-
-qdelaunay: qdelaun.o libqhull.a
-	$(CC) -o qdelaunay $(CCOPTS2) qdelaun.o -L. -lqhull -lm 
-	cp qdelaunay ..
-
-qhalf: qhalf.o libqhull.a
-	$(CC) -o qhalf $(CCOPTS2) qhalf.o -L. -lqhull -lm 
-	cp qhalf ..
-
-qvoronoi: qvoronoi.o libqhull.a
-	$(CC) -o qvoronoi $(CCOPTS2) qvoronoi.o -L. -lqhull -lm 
-	cp qvoronoi ..
-
-qhull: unix.o libqhull.a
-	$(CC) -o qhull $(CCOPTS2) unix.o -L. -lqhull -lm 
-	cp qhull ..
-	-chmod +x ../eg/q_test ../eg/q_eg ../eg/q_egtest
-	-cd ..; ./rbox D4 | ./qhull
-
-# compile qhull without using libqhull.a
-qhullx: qconvex.o qdelaun.o qhalf.o qvoronoi.o unix.o $(OBJS)
-	$(CC) -o qconvex $(CCOPTS2) qconvex.o $(OBJS) -lm 
-	$(CC) -o qdelaunay $(CCOPTS2) qdelaun.o $(OBJS) -lm 
-	$(CC) -o qhalf $(CCOPTS2) qhalf.o $(OBJS) -lm 
-	$(CC) -o qvoronoi $(CCOPTS2) qvoronoi.o $(OBJS) -lm 
-	$(CC) -o qhull $(CCOPTS2) unix.o $(OBJS) -lm 
-	cp qconvex qdelaunay qhalf qvoronoi qhull ..
-	-chmod +x ../eg/q_test ../eg/q_eg ../eg/q_egtest
-	-cd ..; ./rbox D4 | ./qhull
-
-rbox: rbox.o
-	$(CC) -o rbox rbox.o $(CCOPTS2) -lm
-	cp rbox ..
-
-user_eg: user_eg.o libqhull.a 
-	$(CC)  -o user_eg $(CCOPTS2) user_eg.o  -L. -lqhull -lm 
-	cp user_eg ..
-
-user_eg2: user_eg2.o libqhull.a 
-	$(CC)  -o user_eg2 $(CCOPTS2) user_eg2.o  -L. -lqhull -lm 
-	cp user_eg2 ..
-
-# end of Makefile
diff --git a/extern/qhull/src/geom.c b/extern/qhull/src/geom.c
deleted file mode 100644
index ca4bcaf2541..00000000000
--- a/extern/qhull/src/geom.c
+++ /dev/null
@@ -1,1230 +0,0 @@
-/*
  ---------------------------------
-
-   geom.c 
-   geometric routines of qhull
-
-   see qh-geom.htm and geom.h
-
-   copyright (c) 1993-2002 The Geometry Center        
-
-   infrequent code goes into geom2.c
-*/
-   
-#include "qhull_a.h"
-   
-/*---------------------------------
-  
-  qh_distplane( point, facet, dist )
-    return distance from point to facet
-
-  returns:
-    dist
-    if qh.RANDOMdist, joggles result
-  
-  notes:  
-    dist > 0 if point is above facet (i.e., outside)
-    does not error (for sortfacets)
-    
-  see:
-    qh_distnorm in geom2.c
-*/
-void qh_distplane (pointT *point, facetT *facet, realT *dist) {
-  coordT *normal= facet->normal, *coordp, randr;
-  int k;
-  
-  switch(qh hull_dim){
-  case 2:
-    *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1];
-    break;
-  case 3:
-    *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1] + point[2] * normal[2];
-    break;
-  case 4:
-    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3];
-    break;
-  case 5:
-    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4];
-    break;
-  case 6:
-    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5];
-    break;
-  case 7:  
-    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6];
-    break;
-  case 8:
-    *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6]+point[7]*normal[7];
-    break;
-  default:
-    *dist= facet->offset;
-    coordp= point;
-    for (k= qh hull_dim; k--; )
-      *dist += *coordp++ * *normal++;
-    break;
-  }
-  zinc_(Zdistplane);
-  if (!qh RANDOMdist && qh IStracing < 4)
-    return;
-  if (qh RANDOMdist) {
-    randr= qh_RANDOMint;
-    *dist += (2.0 * randr / qh_RANDOMmax - 1.0) *
-      qh RANDOMfactor * qh MAXabs_coord;
-  }
-  if (qh IStracing >= 4) {
-    fprintf (qh ferr, "qh_distplane: ");
-    fprintf (qh ferr, qh_REAL_1, *dist);
-    fprintf (qh ferr, "from p%d to f%d\n", qh_pointid(point), facet->id);
-  }
-  return;
-} /* distplane */
-
-
-/*---------------------------------
-  
-  qh_findbest( point, startfacet, bestoutside, qh_ISnewfacets, qh_NOupper, dist, isoutside, numpart )
-    find facet that is furthest below a point 
-    for upperDelaunay facets
-      returns facet only if !qh_NOupper and clearly above
-
-  input:
-    starts search at 'startfacet' (can not be flipped)
-    if !bestoutside (qh_ALL), stops at qh.MINoutside
-
-  returns:
-    best facet (reports error if NULL)
-    early out if isoutside defined and bestdist > qh.MINoutside
-    dist is distance to facet
-    isoutside is true if point is outside of facet
-    numpart counts the number of distance tests
-
-  see also:
-    qh_findbestnew()
-    
-  notes:
-    If merging (testhorizon), searches horizon facets of coplanar best facets because
-    after qh_distplane, this and qh_partitionpoint are the most expensive in 3-d
-      avoid calls to distplane, function calls, and real number operations.
-    caller traces result
-    Optimized for outside points.   Tried recording a search set for qh_findhorizon.
-    Made code more complicated.
-
-  when called by qh_partitionvisible():
-    indicated by qh_ISnewfacets
-    qh.newfacet_list is list of simplicial, new facets
-    qh_findbestnew set if qh_sharpnewfacets returns True (to use qh_findbestnew)
-    qh.bestfacet_notsharp set if qh_sharpnewfacets returns False
-
-  when called by qh_findfacet(), qh_partitionpoint(), qh_partitioncoplanar(), 
-                 qh_check_bestdist(), qh_addpoint()
-    indicated by !qh_ISnewfacets
-    returns best facet in neighborhood of given facet
-      this is best facet overall if dist > -   qh.MAXcoplanar 
-        or hull has at least a "spherical" curvature
-
-  design:
-    initialize and test for early exit
-    repeat while there are better facets
-      for each neighbor of facet
-        exit if outside facet found
-	test for better facet
-    if point is inside and partitioning
-      test for new facets with a "sharp" intersection
-      if so, future calls go to qh_findbestnew()
-    test horizon facets
-*/
-facetT *qh_findbest (pointT *point, facetT *startfacet, 
-		     boolT bestoutside, boolT isnewfacets, boolT noupper,
-		     realT *dist, boolT *isoutside, int *numpart) {
-  realT bestdist= -REALmax/2 /* avoid underflow */;
-  facetT *facet, *neighbor, **neighborp, *bestfacet= NULL;
- /* facetT *bestfacet_all= startfacet; */
-  int oldtrace= qh IStracing;
-  unsigned int visitid= ++qh visit_id;
-  int numpartnew=0;
-  boolT testhorizon = True; /* needed if precise, e.g., rbox c D6 | qhull Q0 Tv */
-
-  zinc_(Zfindbest);
-  if (qh IStracing >= 3 || (qh TRACElevel && qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid (point))) {
-    if (qh TRACElevel > qh IStracing)
-      qh IStracing= qh TRACElevel;
-    fprintf (qh ferr, "qh_findbest: point p%d starting at f%d isnewfacets? %d, unless %d exit if > %2.2g\n",
-	     qh_pointid(point), startfacet->id, isnewfacets, bestoutside, qh MINoutside);
-    fprintf(qh ferr, "  testhorizon? %d noupper? %d", testhorizon, noupper);
-    fprintf (qh ferr, "  Last point added was p%d.", qh furthest_id);
-    fprintf(qh ferr, "  Last merge was #%d.  max_outside %2.2g\n", zzval_(Ztotmerge), qh max_outside);
-  }
-  if (isoutside)
-    *isoutside= True;
-  if (!startfacet->flipped) {  /* test startfacet */
-    *numpart= 1;
-    qh_distplane (point, startfacet, dist);  /* this code is duplicated below */
-    if (!bestoutside && *dist >= qh MINoutside 
-    && (!startfacet->upperdelaunay || !noupper)) {
-      bestfacet= startfacet;
-      goto LABELreturn_best;
-    }
-    bestdist= *dist;
-    if (!startfacet->upperdelaunay) {
-      bestfacet= startfacet;
-    } 
-  }else 
-    *numpart= 0;
-  startfacet->visitid= visitid;
-  facet= startfacet;
-  while (facet) {
-    trace4((qh ferr, "qh_findbest: neighbors of f%d, bestdist %2.2g f%d\n", 
-                facet->id, bestdist, getid_(bestfacet)));
-    FOREACHneighbor_(facet) {
-      if (!neighbor->newfacet && isnewfacets)
-        continue;
-      if (neighbor->visitid == visitid)
-	continue;
-      neighbor->visitid= visitid;
-      if (!neighbor->flipped) {  /* code duplicated above */
-	(*numpart)++;
-	qh_distplane (point, neighbor, dist);
-	if (*dist > bestdist) {
-	  if (!bestoutside && *dist >= qh MINoutside 
-	  && (!neighbor->upperdelaunay || !noupper)) {
-	    bestfacet= neighbor;
-	    goto LABELreturn_best;
-	  }
-	  if (!neighbor->upperdelaunay) {
-	    bestfacet= neighbor;
-	    bestdist= *dist;
-	  }
-	  break; /* switch to neighor */
-	} /* end of *dist>bestdist */
-      } /* end of !flipped */
-    } /* end of FOREACHneighbor */
-    facet= neighbor;  /* non-NULL only if *dist>bestdist */
-  } /* end of while facet (directed search) */
-  if (isnewfacets) { 
-    if (!bestfacet) {
-      bestdist= -REALmax/2; 
-      bestfacet= qh_findbestnew (point, startfacet->next, &bestdist, bestoutside, isoutside, &numpartnew);
-      testhorizon= False; /* qh_findbestnew calls qh_findbesthorizon */
-    }else if (!qh findbest_notsharp && bestdist < - qh DISTround) {
-      if (qh_sharpnewfacets()) { 
-	/* seldom used, qh_findbestnew will retest all facets */
-	zinc_(Zfindnewsharp);
-	bestfacet= qh_findbestnew (point, bestfacet, &bestdist, bestoutside, isoutside, &numpartnew);
-	testhorizon= False; /* qh_findbestnew calls qh_findbesthorizon */
-	qh findbestnew= True;
-      }else
-	qh findbest_notsharp= True;
-    }
-  }
-  if (!bestfacet) {
-    fprintf(qh ferr, "\n\
-qh_findbest: all neighbors of facet %d are flipped or upper Delaunay.\n\
-Please report this error to qhull_bug@geom.umn.edu with the input and all of the output.\n",
-       startfacet->id);
-    qh_errexit (qh_ERRqhull, startfacet, NULL);
-  }
-  if (testhorizon) 
-    bestfacet= qh_findbesthorizon (!qh_IScheckmax, point, bestfacet, noupper, &bestdist, &numpartnew);
-  *dist= bestdist;
-  if (isoutside && bestdist < qh MINoutside)
-    *isoutside= False;
-LABELreturn_best:
-  zadd_(Zfindbesttot, *numpart);
-  zmax_(Zfindbestmax, *numpart);
-  (*numpart) += numpartnew;
-  qh IStracing= oldtrace;
-  return bestfacet;
-}  /* findbest */
-
-
-/*---------------------------------
-  
-  qh_findbesthorizon( qh_IScheckmax, point, startfacet, qh_NOupper, &bestdist, &numpart )
-    search coplanar and better horizon facets from startfacet/bestdist
-    ischeckmax turns off statistics and minsearch update
-    all arguments must be initialized
-  returns (ischeckmax):
-    best facet
-  returns (!ischeckmax):
-    best facet that is not upperdelaunay
-    allows upperdelaunay that is clearly outside
-  returns:
-    bestdist is distance to bestfacet
-    numpart -- updates number of distance tests
-
-  notes:
-    no early out -- use qh_findbest() or qh_findbestnew()
-    Searches coplanar or better horizon facets
-
-  when called by qh_check_maxout() (qh_IScheckmax)
-    startfacet must be closest to the point
-      Otherwise, if point is beyond and below startfacet, startfacet may be a local minimum
-      even though other facets are below the point.
-    updates facet->maxoutside for good, visited facets
-    may return NULL
-
-    searchdist is qh.max_outside + 2 * DISTround
-      + max( MINvisible('Vn'), MAXcoplanar('Un'));
-    This setting is a guess.  It must be at least max_outside + 2*DISTround 
-    because a facet may have a geometric neighbor across a vertex
-
-  design:
-    for each horizon facet of coplanar best facets
-      continue if clearly inside
-      unless upperdelaunay or clearly outside
-         update best facet
-*/
-facetT *qh_findbesthorizon (boolT ischeckmax, pointT* point, facetT *startfacet, boolT noupper, realT *bestdist, int *numpart) {
-  facetT *bestfacet= startfacet;
-  realT dist;
-  facetT *neighbor, **neighborp, *facet;
-  facetT *nextfacet= NULL; /* optimize last facet of coplanarset */
-  int numpartinit= *numpart, coplanarset_size;
-  unsigned int visitid= ++qh visit_id;
-  boolT newbest= False; /* for tracing */
-  realT minsearch, searchdist;  /* skip facets that are too far from point */
-
-  if (!ischeckmax) {
-    zinc_(Zfindhorizon);
-  }else {
-#if qh_MAXoutside
-    if ((!qh ONLYgood || startfacet->good) && *bestdist > startfacet->maxoutside)
-      startfacet->maxoutside= *bestdist;
-#endif
-  }
-  searchdist= qh_SEARCHdist; /* multiple of qh.max_outside and precision constants */
-  minsearch= *bestdist - searchdist;
-  if (ischeckmax) {
-    /* Always check coplanar facets.  Needed for RBOX 1000 s Z1 G1e-13 t996564279 | QHULL Tv */
-    minimize_(minsearch, -searchdist);
-  }
-  coplanarset_size= 0;
-  facet= startfacet;
-  while (True) {
-    trace4((qh ferr, "qh_findbesthorizon: neighbors of f%d bestdist %2.2g f%d ischeckmax? %d noupper? %d minsearch %2.2g searchdist %2.2g\n", 
-		facet->id, *bestdist, getid_(bestfacet), ischeckmax, noupper,
-		minsearch, searchdist));
-    FOREACHneighbor_(facet) {
-      if (neighbor->visitid == visitid) 
-	continue;
-      neighbor->visitid= visitid;
-      if (!neighbor->flipped) { 
-	qh_distplane (point, neighbor, &dist);
-	(*numpart)++;
-	if (dist > *bestdist) {
-	  if (!neighbor->upperdelaunay || ischeckmax || (!noupper && dist >= qh MINoutside)) {
-	    bestfacet= neighbor;
-	    *bestdist= dist;
-	    newbest= True;
-	    if (!ischeckmax) {
-	      minsearch= dist - searchdist;
-	      if (dist > *bestdist + searchdist) {
-		zinc_(Zfindjump);  /* everything in qh.coplanarset at least searchdist below */
-		coplanarset_size= 0;
-	      }
-	    }
-	  }
-	}else if (dist < minsearch) 
-	  continue;  /* if ischeckmax, dist can't be positive */
-#if qh_MAXoutside
-	if (ischeckmax && dist > neighbor->maxoutside)
-	  neighbor->maxoutside= dist;
-#endif      
-      } /* end of !flipped */
-      if (nextfacet) {
-	if (!coplanarset_size++) {
-	  SETfirst_(qh coplanarset)= nextfacet;
-	  SETtruncate_(qh coplanarset, 1);
-	}else
-  	  qh_setappend (&qh coplanarset, nextfacet); /* Was needed for RBOX 1000 s W1e-13 P0 t996547055 | QHULL d Qbb Qc Tv
-						 and RBOX 1000 s Z1 G1e-13 t996564279 | qhull Tv  */
-      }
-      nextfacet= neighbor;
-    } /* end of EACHneighbor */
-    facet= nextfacet;
-    if (facet) 
-      nextfacet= NULL;
-    else if (!coplanarset_size)
-      break; 
-    else if (!--coplanarset_size) {
-      facet= SETfirst_(qh coplanarset);
-      SETtruncate_(qh coplanarset, 0);
-    }else
-      facet= (facetT*)qh_setdellast (qh coplanarset);
-  } /* while True, for each facet in qh.coplanarset */
-  if (!ischeckmax) {
-    zadd_(Zfindhorizontot, *numpart - numpartinit);
-    zmax_(Zfindhorizonmax, *numpart - numpartinit);
-    if (newbest)
-      zinc_(Zparthorizon);
-  }
-  trace4((qh ferr, "qh_findbesthorizon: newbest? %d bestfacet f%d bestdist %2.2g\n", newbest, getid_(bestfacet), *bestdist));
-  return bestfacet;
-}  /* findbesthorizon */
-
-/*---------------------------------
-  
-  qh_findbestnew( point, startfacet, dist, isoutside, numpart )
-    find best newfacet for point
-    searches all of qh.newfacet_list starting at startfacet
-    searches horizon facets of coplanar best newfacets
-    searches all facets if startfacet == qh.facet_list
-  returns:
-    best new or horizon facet that is not upperdelaunay
-    early out if isoutside and not 'Qf'
-    dist is distance to facet
-    isoutside is true if point is outside of facet
-    numpart is number of distance tests
-
-  notes:
-    Always used for merged new facets (see qh_USEfindbestnew)
-    Avoids upperdelaunay facet unless (isoutside and outside)
-
-    Uses qh.visit_id, qh.coplanarset.  
-    If share visit_id with qh_findbest, coplanarset is incorrect.
-
-    If merging (testhorizon), searches horizon facets of coplanar best facets because
-    a point maybe coplanar to the bestfacet, below its horizon facet,
-    and above a horizon facet of a coplanar newfacet.  For example,
-      rbox 1000 s Z1 G1e-13 | qhull
-      rbox 1000 s W1e-13 P0 t992110337 | QHULL d Qbb Qc
-
-    qh_findbestnew() used if
-       qh_sharpnewfacets -- newfacets contains a sharp angle
-       if many merges, qh_premerge found a merge, or 'Qf' (qh.findbestnew)
-
-  see also:
-    qh_partitionall() and qh_findbest()
-
-  design:
-    for each new facet starting from startfacet
-      test distance from point to facet
-      return facet if clearly outside
-      unless upperdelaunay and a lowerdelaunay exists
-         update best facet
-    test horizon facets
-*/
-facetT *qh_findbestnew (pointT *point, facetT *startfacet,
-	   realT *dist, boolT bestoutside, boolT *isoutside, int *numpart) {
-  realT bestdist= -REALmax/2; /*, minsearch= -REALmax/2;*/
-  facetT *bestfacet= NULL, *facet;
-  int oldtrace= qh IStracing, i;
-  unsigned int visitid= ++qh visit_id;
-  realT distoutside= 0.0;
-  boolT isdistoutside; /* True if distoutside is defined */
-  boolT testhorizon = True; /* needed if precise, e.g., rbox c D6 | qhull Q0 Tv */
-
-  if (!startfacet) {
-    if (qh MERGING)
-      fprintf(qh ferr, "qhull precision error (qh_findbestnew): merging has formed and deleted a cone of new facets.  Can not continue.\n");
-    else
-      fprintf(qh ferr, "qhull internal error (qh_findbestnew): no new facets for point p%d\n",
-      	      qh furthest_id);      
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-  zinc_(Zfindnew);
-  if (qh BESToutside || bestoutside)
-    isdistoutside= False;
-  else {
-    isdistoutside= True;
-    distoutside= qh_DISToutside; /* multiple of qh.MINoutside & qh.max_outside, see user.h */
-  }
-  if (isoutside)
-    *isoutside= True;
-  *numpart= 0;
-  if (qh IStracing >= 3 || (qh TRACElevel && qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid (point))) {
-    if (qh TRACElevel > qh IStracing)
-      qh IStracing= qh TRACElevel;
-    fprintf(qh ferr, "qh_findbestnew: point p%d facet f%d. Stop? %d if dist > %2.2g\n",
-	     qh_pointid(point), startfacet->id, isdistoutside, distoutside);
-    fprintf(qh ferr, "  Last point added p%d visitid %d.",  qh furthest_id, visitid);
-    fprintf(qh ferr, "  Last merge was #%d.\n", zzval_(Ztotmerge));
-  }
-  /* visit all new facets starting with startfacet, maybe qh facet_list */
-  for (i= 0, facet= startfacet; i < 2; i++, facet= qh newfacet_list) {
-    FORALLfacet_(facet) {
-      if (facet == startfacet && i)
-	break;
-      facet->visitid= visitid;
-      if (!facet->flipped) {
-	qh_distplane (point, facet, dist);
-	(*numpart)++;
-	if (*dist > bestdist) {
-	  if (!facet->upperdelaunay || *dist >= qh MINoutside) {
-	    bestfacet= facet;
-	    if (isdistoutside && *dist >= distoutside)
-	      goto LABELreturn_bestnew;
-	    bestdist= *dist;
-  	  }
-	}
-      } /* end of !flipped */
-    } /* FORALLfacet from startfacet or qh newfacet_list */
-  }
-  if (testhorizon || !bestfacet)
-    bestfacet= qh_findbesthorizon (!qh_IScheckmax, point, bestfacet ? bestfacet : startfacet, 
-	                                !qh_NOupper, &bestdist, numpart);  
-  *dist= bestdist;
-  if (isoutside && *dist < qh MINoutside)
-    *isoutside= False;
-LABELreturn_bestnew:
-  zadd_(Zfindnewtot, *numpart);
-  zmax_(Zfindnewmax, *numpart);
-  trace4((qh ferr, "qh_findbestnew: bestfacet f%d bestdist %2.2g\n", getid_(bestfacet), *dist));
-  qh IStracing= oldtrace;
-  return bestfacet;
-}  /* findbestnew */
-
-/* ============ hyperplane functions -- keep code together [?] ============ */
-
-/*---------------------------------
-  
-  qh_backnormal( rows, numrow, numcol, sign, normal, nearzero )
-    given an upper-triangular rows array and a sign,
-    solve for normal equation x using back substitution over rows U
-
-  returns:
-     normal= x
-      
-     if will not be able to divzero() when normalized (qh.MINdenom_2 and qh.MINdenom_1_2),
-       if fails on last row
-         this means that the hyperplane intersects [0,..,1]
-         sets last coordinate of normal to sign
-       otherwise
-         sets tail of normal to [...,sign,0,...], i.e., solves for b= [0...0]
-         sets nearzero
-
-  notes:
-     assumes numrow == numcol-1
-
-     see Golub & van Loan 4.4-9 for back substitution
-
-     solves Ux=b where Ax=b and PA=LU
-     b= [0,...,0,sign or 0]  (sign is either -1 or +1)
-     last row of A= [0,...,0,1]
-
-     1) Ly=Pb == y=b since P only permutes the 0's of   b
-     
-  design:
-    for each row from end
-      perform back substitution
-      if near zero
-        use qh_divzero for division
-        if zero divide and not last row
-          set tail of normal to 0
-*/
-void qh_backnormal (realT **rows, int numrow, int numcol, boolT sign,
-  	coordT *normal, boolT *nearzero) {
-  int i, j;
-  coordT *normalp, *normal_tail, *ai, *ak;
-  realT diagonal;
-  boolT waszero;
-  int zerocol= -1;
-  
-  normalp= normal + numcol - 1;
-  *normalp--= (sign ? -1.0 : 1.0);
-  for(i= numrow; i--; ) {
-    *normalp= 0.0;
-    ai= rows[i] + i + 1;
-    ak= normalp+1;
-    for(j= i+1; j < numcol; j++)
-      *normalp -= *ai++ * *ak++;
-    diagonal= (rows[i])[i];
-    if (fabs_(diagonal) > qh MINdenom_2)
-      *(normalp--) /= diagonal;
-    else {
-      waszero= False;
-      *normalp= qh_divzero (*normalp, diagonal, qh MINdenom_1_2, &waszero);
-      if (waszero) {
-        zerocol= i;
-	*(normalp--)= (sign ? -1.0 : 1.0);
-	for (normal_tail= normalp+2; normal_tail < normal + numcol; normal_tail++)
-	  *normal_tail= 0.0;
-      }else
-	normalp--;
-    }
-  }
-  if (zerocol != -1) {
-    zzinc_(Zback0);
-    *nearzero= True;
-    trace4((qh ferr, "qh_backnormal: zero diagonal at column %d.\n", i));
-    qh_precision ("zero diagonal on back substitution");
-  }
-} /* backnormal */
-
-/*---------------------------------
-  
-  qh_gausselim( rows, numrow, numcol, sign )
-    Gaussian elimination with partial pivoting
-
-  returns:
-    rows is upper triangular (includes row exchanges)
-    flips sign for each row exchange
-    sets nearzero if pivot[k] < qh.NEARzero[k], else clears it
-
-  notes:
-    if nearzero, the determinant's sign may be incorrect.
-    assumes numrow <= numcol
-
-  design:
-    for each row
-      determine pivot and exchange rows if necessary
-      test for near zero
-      perform gaussian elimination step
-*/
-void qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero) {
-  realT *ai, *ak, *rowp, *pivotrow;
-  realT n, pivot, pivot_abs= 0.0, temp;
-  int i, j, k, pivoti, flip=0;
-  
-  *nearzero= False;
-  for(k= 0; k < numrow; k++) {
-    pivot_abs= fabs_((rows[k])[k]);
-    pivoti= k;
-    for(i= k+1; i < numrow; i++) {
-      if ((temp= fabs_((rows[i])[k])) > pivot_abs) {
-	pivot_abs= temp;
-	pivoti= i;
-      }
-    }
-    if (pivoti != k) {
-      rowp= rows[pivoti]; 
-      rows[pivoti]= rows[k]; 
-      rows[k]= rowp; 
-      *sign ^= 1;
-      flip ^= 1;
-    }
-    if (pivot_abs <= qh NEARzero[k]) {
-      *nearzero= True;
-      if (pivot_abs == 0.0) {   /* remainder of column == 0 */
-	if (qh IStracing >= 4) {
-	  fprintf (qh ferr, "qh_gausselim: 0 pivot at column %d. (%2.2g < %2.2g)\n", k, pivot_abs, qh DISTround);
-	  qh_printmatrix (qh ferr, "Matrix:", rows, numrow, numcol);
-	}
-	zzinc_(Zgauss0);
-        qh_precision ("zero pivot for Gaussian elimination");
-	goto LABELnextcol;
-      }
-    }
-    pivotrow= rows[k] + k;
-    pivot= *pivotrow++;  /* signed value of pivot, and remainder of row */
-    for(i= k+1; i < numrow; i++) {
-      ai= rows[i] + k;
-      ak= pivotrow;
-      n= (*ai++)/pivot;   /* divzero() not needed since |pivot| >= |*ai| */
-      for(j= numcol - (k+1); j--; )
-	*ai++ -= n * *ak++;
-    }
-  LABELnextcol:
-    ;
-  }
-  wmin_(Wmindenom, pivot_abs);  /* last pivot element */
-  if (qh IStracing >= 5)
-    qh_printmatrix (qh ferr, "qh_gausselem: result", rows, numrow, numcol);
-} /* gausselim */
-
-
-/*---------------------------------
-  
-  qh_getangle( vect1, vect2 )
-    returns the dot product of two vectors
-    if qh.RANDOMdist, joggles result
-
-  notes:
-    the angle may be > 1.0 or < -1.0 because of roundoff errors
-
-*/
-realT qh_getangle(pointT *vect1, pointT *vect2) {
-  realT angle= 0, randr;
-  int k;
-
-  for(k= qh hull_dim; k--; )
-    angle += *vect1++ * *vect2++;
-  if (qh RANDOMdist) {
-    randr= qh_RANDOMint;
-    angle += (2.0 * randr / qh_RANDOMmax - 1.0) *
-      qh RANDOMfactor;
-  }
-  trace4((qh ferr, "qh_getangle: %2.2g\n", angle));
-  return(angle);
-} /* getangle */
-
-
-/*---------------------------------
-  
-  qh_getcenter( vertices )
-    returns arithmetic center of a set of vertices as a new point
-
-  notes:
-    allocates point array for center
-*/
-pointT *qh_getcenter(setT *vertices) {
-  int k;
-  pointT *center, *coord;
-  vertexT *vertex, **vertexp;
-  int count= qh_setsize(vertices);
-
-  if (count < 2) {
-    fprintf (qh ferr, "qhull internal error (qh_getcenter): not defined for %d points\n", count);
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-  center= (pointT *)qh_memalloc(qh normal_size);
-  for (k=0; k < qh hull_dim; k++) {
-    coord= center+k;
-    *coord= 0.0;
-    FOREACHvertex_(vertices)
-      *coord += vertex->point[k];
-    *coord /= count;
-  }
-  return(center);
-} /* getcenter */
-
-
-/*---------------------------------
-  
-  qh_getcentrum( facet )
-    returns the centrum for a facet as a new point
-
-  notes:
-    allocates the centrum
-*/
-pointT *qh_getcentrum(facetT *facet) {
-  realT dist;
-  pointT *centrum, *point;
-
-  point= qh_getcenter(facet->vertices);
-  zzinc_(Zcentrumtests);
-  qh_distplane (point, facet, &dist);
-  centrum= qh_projectpoint(point, facet, dist);
-  qh_memfree(point, qh normal_size);
-  trace4((qh ferr, "qh_getcentrum: for f%d, %d vertices dist= %2.2g\n",
-	  facet->id, qh_setsize(facet->vertices), dist));
-  return centrum;
-} /* getcentrum */
-
-
-/*---------------------------------
-  
-  qh_getdistance( facet, neighbor, mindist, maxdist )
-    returns the maxdist and mindist distance of any vertex from neighbor
-
-  returns:
-    the max absolute value
-
-  design:
-    for each vertex of facet that is not in neighbor
-      test the distance from vertex to neighbor
-*/
-realT qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist) {
-  vertexT *vertex, **vertexp;
-  realT dist, maxd, mind;
-  
-  FOREACHvertex_(facet->vertices)
-    vertex->seen= False;
-  FOREACHvertex_(neighbor->vertices)
-    vertex->seen= True;
-  mind= 0.0;
-  maxd= 0.0;
-  FOREACHvertex_(facet->vertices) {
-    if (!vertex->seen) {
-      zzinc_(Zbestdist);
-      qh_distplane(vertex->point, neighbor, &dist);
-      if (dist < mind)
-	mind= dist;
-      else if (dist > maxd)
-	maxd= dist;
-    }
-  }
-  *mindist= mind;
-  *maxdist= maxd;
-  mind= -mind;
-  if (maxd > mind)
-    return maxd;
-  else
-    return mind;
-} /* getdistance */
-
-
-/*---------------------------------
-
-  qh_normalize( normal, dim, toporient )
-    normalize a vector and report if too small
-    does not use min norm
-  
-  see:
-    qh_normalize2
-*/
-void qh_normalize (coordT *normal, int dim, boolT toporient) {
-  qh_normalize2( normal, dim, toporient, NULL, NULL);
-} /* normalize */
-
-/*---------------------------------
-  
-  qh_normalize2( normal, dim, toporient, minnorm, ismin )
-    normalize a vector and report if too small
-    qh.MINdenom/MINdenom1 are the upper limits for divide overflow
-
-  returns:
-    normalized vector
-    flips sign if !toporient
-    if minnorm non-NULL, 
-      sets ismin if normal < minnorm
-
-  notes:
-    if zero norm
-       sets all elements to sqrt(1.0/dim)
-    if divide by zero (divzero ())
-       sets largest element to   +/-1
-       bumps Znearlysingular
-      
-  design:
-    computes norm
-    test for minnorm
-    if not near zero
-      normalizes normal
-    else if zero norm
-      sets normal to standard value
-    else
-      uses qh_divzero to normalize
-      if nearzero
-        sets norm to direction of maximum value
-*/
-void qh_normalize2 (coordT *normal, int dim, boolT toporient, 
-            realT *minnorm, boolT *ismin) {
-  int k;
-  realT *colp, *maxp, norm= 0, temp, *norm1, *norm2, *norm3;
-  boolT zerodiv;
-
-  norm1= normal+1;
-  norm2= normal+2;
-  norm3= normal+3;
-  if (dim == 2)
-    norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1));
-  else if (dim == 3)
-    norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2));
-  else if (dim == 4) {
-    norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2) 
-               + (*norm3)*(*norm3));
-  }else if (dim > 4) {
-    norm= (*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2) 
-               + (*norm3)*(*norm3);
-    for (k= dim-4, colp= normal+4; k--; colp++)
-      norm += (*colp) * (*colp);
-    norm= sqrt(norm);
-  }
-  if (minnorm) {
-    if (norm < *minnorm) 
-      *ismin= True;
-    else
-      *ismin= False;
-  }
-  wmin_(Wmindenom, norm);
-  if (norm > qh MINdenom) {
-    if (!toporient)
-      norm= -norm;
-    *normal /= norm;
-    *norm1 /= norm;
-    if (dim == 2)
-      ; /* all done */
-    else if (dim == 3)
-      *norm2 /= norm;
-    else if (dim == 4) {
-      *norm2 /= norm;
-      *norm3 /= norm;
-    }else if (dim >4) {
-      *norm2 /= norm;
-      *norm3 /= norm;
-      for (k= dim-4, colp= normal+4; k--; )
-        *colp++ /= norm;
-    }
-  }else if (norm == 0.0) {
-    temp= sqrt (1.0/dim);
-    for (k= dim, colp= normal; k--; )
-      *colp++ = temp;
-  }else {
-    if (!toporient)
-      norm= -norm;
-    for (k= dim, colp= normal; k--; colp++) { /* k used below */
-      temp= qh_divzero (*colp, norm, qh MINdenom_1, &zerodiv);
-      if (!zerodiv)
-	*colp= temp;
-      else {
-	maxp= qh_maxabsval(normal, dim);
-	temp= ((*maxp * norm >= 0.0) ? 1.0 : -1.0);
-	for (k= dim, colp= normal; k--; colp++)
-	  *colp= 0.0;
-	*maxp= temp;
-	zzinc_(Znearlysingular);
-	trace0((qh ferr, "qh_normalize: norm=%2.2g too small during p%d\n", 
-	       norm, qh furthest_id));
-	return;
-      }
-    }
-  }
-} /* normalize */
-
-
-/*---------------------------------
-  
-  qh_projectpoint( point, facet, dist )
-    project point onto a facet by dist
-
-  returns:
-    returns a new point
-    
-  notes:
-    if dist= distplane(point,facet)
-      this projects point to hyperplane
-    assumes qh_memfree_() is valid for normal_size
-*/
-pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist) {
-  pointT *newpoint, *np, *normal;
-  int normsize= qh normal_size,k;
-  void **freelistp; /* used !qh_NOmem */
-  
-  qh_memalloc_(normsize, freelistp, newpoint, pointT);
-  np= newpoint;
-  normal= facet->normal;
-  for(k= qh hull_dim; k--; )
-    *(np++)= *point++ - dist * *normal++;
-  return(newpoint);
-} /* projectpoint */
-
-  
-/*---------------------------------
-  
-  qh_setfacetplane( facet )
-    sets the hyperplane for a facet
-    if qh.RANDOMdist, joggles hyperplane
-
-  notes:
-    uses global buffers qh.gm_matrix and qh.gm_row
-    overwrites facet->normal if already defined
-    updates Wnewvertex if PRINTstatistics
-    sets facet->upperdelaunay if upper envelope of Delaunay triangulation
-
-  design:
-    copy vertex coordinates to qh.gm_matrix/gm_row
-    compute determinate
-    if nearzero
-      recompute determinate with gaussian elimination
-      if nearzero
-        force outside orientation by testing interior point
-*/
-void qh_setfacetplane(facetT *facet) {
-  pointT *point;
-  vertexT *vertex, **vertexp;
-  int k,i, normsize= qh normal_size, oldtrace= 0;
-  realT dist;
-  void **freelistp; /* used !qh_NOmem */
-  coordT *coord, *gmcoord;
-  pointT *point0= SETfirstt_(facet->vertices, vertexT)->point;
-  boolT nearzero= False;
-
-  zzinc_(Zsetplane);
-  if (!facet->normal)
-    qh_memalloc_(normsize, freelistp, facet->normal, coordT);
-  if (facet == qh tracefacet) {
-    oldtrace= qh IStracing;
-    qh IStracing= 5;
-    fprintf (qh ferr, "qh_setfacetplane: facet f%d created.\n", facet->id);
-    fprintf (qh ferr, "  Last point added to hull was p%d.", qh furthest_id);
-    if (zzval_(Ztotmerge))
-      fprintf(qh ferr, "  Last merge was #%d.", zzval_(Ztotmerge));
-    fprintf (qh ferr, "\n\nCurrent summary is:\n");
-      qh_printsummary (qh ferr);
-  }
-  if (qh hull_dim <= 4) {
-    i= 0;
-    if (qh RANDOMdist) {
-      gmcoord= qh gm_matrix;
-      FOREACHvertex_(facet->vertices) {
-        qh gm_row[i++]= gmcoord;
-	coord= vertex->point;
-	for (k= qh hull_dim; k--; )
-	  *(gmcoord++)= *coord++ * qh_randomfactor();
-      }	  
-    }else {
-      FOREACHvertex_(facet->vertices)
-       qh gm_row[i++]= vertex->point;
-    }
-    qh_sethyperplane_det(qh hull_dim, qh gm_row, point0, facet->toporient,
-                facet->normal, &facet->offset, &nearzero);
-  }
-  if (qh hull_dim > 4 || nearzero) {
-    i= 0;
-    gmcoord= qh gm_matrix;
-    FOREACHvertex_(facet->vertices) {
-      if (vertex->point != point0) {
-	qh gm_row[i++]= gmcoord;
-	coord= vertex->point;
-	point= point0;
-	for(k= qh hull_dim; k--; )
-	  *(gmcoord++)= *coord++ - *point++;
-      }
-    }
-    qh gm_row[i]= gmcoord;  /* for areasimplex */
-    if (qh RANDOMdist) {
-      gmcoord= qh gm_matrix;
-      for (i= qh hull_dim-1; i--; ) {
-	for (k= qh hull_dim; k--; )
-	  *(gmcoord++) *= qh_randomfactor();
-      }
-    }
-    qh_sethyperplane_gauss(qh hull_dim, qh gm_row, point0, facet->toporient,
-           	facet->normal, &facet->offset, &nearzero);
-    if (nearzero) { 
-      if (qh_orientoutside (facet)) {
-	trace0((qh ferr, "qh_setfacetplane: flipped orientation after testing interior_point during p%d\n", qh furthest_id));
-      /* this is part of using Gaussian Elimination.  For example in 5-d
-	   1 1 1 1 0
-	   1 1 1 1 1
-	   0 0 0 1 0
-	   0 1 0 0 0
-	   1 0 0 0 0
-	   norm= 0.38 0.38 -0.76 0.38 0
-	 has a determinate of 1, but g.e. after subtracting pt. 0 has
-	 0's in the diagonal, even with full pivoting.  It does work
-	 if you subtract pt. 4 instead. */
-      }
-    }
-  }
-  facet->upperdelaunay= False;
-  if (qh DELAUNAY) {
-    if (qh UPPERdelaunay) {     /* matches qh_triangulate_facet and qh.lower_threshold in qh_initbuild */
-      if (facet->normal[qh hull_dim -1] >= qh ANGLEround * qh_ZEROdelaunay)
-        facet->upperdelaunay= True;
-    }else {
-      if (facet->normal[qh hull_dim -1] > -qh ANGLEround * qh_ZEROdelaunay)
-        facet->upperdelaunay= True;
-    }
-  }
-  if (qh PRINTstatistics || qh IStracing || qh TRACElevel || qh JOGGLEmax < REALmax) {
-    qh old_randomdist= qh RANDOMdist;
-    qh RANDOMdist= False;
-    FOREACHvertex_(facet->vertices) {
-      if (vertex->point != point0) {
-	boolT istrace= False;
-	zinc_(Zdiststat);
-        qh_distplane(vertex->point, facet, &dist);
-        dist= fabs_(dist);
-        zinc_(Znewvertex);
-        wadd_(Wnewvertex, dist);
-        if (dist > wwval_(Wnewvertexmax)) {
-          wwval_(Wnewvertexmax)= dist;
-	  if (dist > qh max_outside) {
-	    qh max_outside= dist;  /* used by qh_maxouter() */
-	    if (dist > qh TRACEdist) 
-	      istrace= True;
-	  }
-	}else if (-dist > qh TRACEdist)
-	  istrace= True;
-	if (istrace) {
-	  fprintf (qh ferr, "qh_setfacetplane: ====== vertex p%d (v%d) increases max_outside to %2.2g for new facet f%d last p%d\n",
-	        qh_pointid(vertex->point), vertex->id, dist, facet->id, qh furthest_id);
-	  qh_errprint ("DISTANT", facet, NULL, NULL, NULL);
-	}
-      }
-    }
-    qh RANDOMdist= qh old_randomdist;
-  }
-  if (qh IStracing >= 3) {
-    fprintf (qh ferr, "qh_setfacetplane: f%d offset %2.2g normal: ",
-	     facet->id, facet->offset);
-    for (k=0; k < qh hull_dim; k++)
-      fprintf (qh ferr, "%2.2g ", facet->normal[k]);
-    fprintf (qh ferr, "\n");
-  }
-  if (facet == qh tracefacet)
-    qh IStracing= oldtrace;
-} /* setfacetplane */
-
-
-/*---------------------------------
-  
-  qh_sethyperplane_det( dim, rows, point0, toporient, normal, offset, nearzero )
-    given dim X dim array indexed by rows[], one row per point, 
-        toporient (flips all signs),
-        and point0 (any row)
-    set normalized hyperplane equation from oriented simplex
-
-  returns:
-    normal (normalized)
-    offset (places point0 on the hyperplane)
-    sets nearzero if hyperplane not through points
-
-  notes:
-    only defined for dim == 2..4
-    rows[] is not modified
-    solves det(P-V_0, V_n-V_0, ..., V_1-V_0)=0, i.e. every point is on hyperplane
-    see Bower & Woodworth, A programmer's geometry, Butterworths 1983.
-
-  derivation of 3-d minnorm
-    Goal: all vertices V_i within qh.one_merge of hyperplane
-    Plan: exactly translate the facet so that V_0 is the origin
-          exactly rotate the facet so that V_1 is on the x-axis and y_2=0.
-          exactly rotate the effective perturbation to only effect n_0
-	     this introduces a factor of sqrt(3)
-    n_0 = ((y_2-y_0)*(z_1-z_0) - (z_2-z_0)*(y_1-y_0)) / norm
-    Let M_d be the max coordinate difference
-    Let M_a be the greater of M_d and the max abs. coordinate
-    Let u be machine roundoff and distround be max error for distance computation
-    The max error for n_0 is sqrt(3) u M_a M_d / norm.  n_1 is approx. 1 and n_2 is approx. 0
-    The max error for distance of V_1 is sqrt(3) u M_a M_d M_d / norm.  Offset=0 at origin
-    Then minnorm = 1.8 u M_a M_d M_d / qh.ONEmerge
-    Note that qh.one_merge is approx. 45.5 u M_a and norm is usually about M_d M_d
-
-  derivation of 4-d minnorm
-    same as above except rotate the facet so that V_1 on x-axis and w_2, y_3, w_3=0
-     [if two vertices fixed on x-axis, can rotate the other two in yzw.]
-    n_0 = det3_(...) = y_2 det2_(z_1, w_1, z_3, w_3) = - y_2 w_1 z_3
-     [all other terms contain at least two factors nearly zero.]
-    The max error for n_0 is sqrt(4) u M_a M_d M_d / norm
-    Then minnorm = 2 u M_a M_d M_d M_d / qh.ONEmerge
-    Note that qh.one_merge is approx. 82 u M_a and norm is usually about M_d M_d M_d
-*/
-void qh_sethyperplane_det (int dim, coordT **rows, coordT *point0, 
-          boolT toporient, coordT *normal, realT *offset, boolT *nearzero) {
-  realT maxround, dist;
-  int i;
-  pointT *point;
-
-
-  if (dim == 2) {
-    normal[0]= dY(1,0);
-    normal[1]= dX(0,1);
-    qh_normalize2 (normal, dim, toporient, NULL, NULL);
-    *offset= -(point0[0]*normal[0]+point0[1]*normal[1]);
-    *nearzero= False;  /* since nearzero norm => incident points */
-  }else if (dim == 3) {
-    normal[0]= det2_(dY(2,0), dZ(2,0),
-		     dY(1,0), dZ(1,0));
-    normal[1]= det2_(dX(1,0), dZ(1,0),
-		     dX(2,0), dZ(2,0));
-    normal[2]= det2_(dX(2,0), dY(2,0),
-		     dX(1,0), dY(1,0));
-    qh_normalize2 (normal, dim, toporient, NULL, NULL);
-    *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
-	       + point0[2]*normal[2]);
-    maxround= qh DISTround;
-    for (i=dim; i--; ) {
-      point= rows[i];
-      if (point != point0) {
-        dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
-	       + point[2]*normal[2]);
-        if (dist > maxround || dist < -maxround) {
-  	  *nearzero= True;
-	  break;
-	}
-      }
-    }
-  }else if (dim == 4) {
-    normal[0]= - det3_(dY(2,0), dZ(2,0), dW(2,0),
-			dY(1,0), dZ(1,0), dW(1,0),
-			dY(3,0), dZ(3,0), dW(3,0));
-    normal[1]=   det3_(dX(2,0), dZ(2,0), dW(2,0),
-		        dX(1,0), dZ(1,0), dW(1,0),
-		        dX(3,0), dZ(3,0), dW(3,0));
-    normal[2]= - det3_(dX(2,0), dY(2,0), dW(2,0),
-			dX(1,0), dY(1,0), dW(1,0),
-			dX(3,0), dY(3,0), dW(3,0));
-    normal[3]=   det3_(dX(2,0), dY(2,0), dZ(2,0),
-		        dX(1,0), dY(1,0), dZ(1,0),
-		        dX(3,0), dY(3,0), dZ(3,0));
-    qh_normalize2 (normal, dim, toporient, NULL, NULL);
-    *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
-	       + point0[2]*normal[2] + point0[3]*normal[3]);
-    maxround= qh DISTround;
-    for (i=dim; i--; ) {
-      point= rows[i];
-      if (point != point0) {
-        dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
-	       + point[2]*normal[2] + point[3]*normal[3]);
-        if (dist > maxround || dist < -maxround) {
-  	  *nearzero= True;
-	  break;
-	}
-      }
-    }
-  }
-  if (*nearzero) {
-    zzinc_(Zminnorm);
-    trace0((qh ferr, "qh_sethyperplane_det: degenerate norm during p%d.\n", qh furthest_id));
-    zzinc_(Znearlysingular);
-  }
-} /* sethyperplane_det */
-
-
-/*---------------------------------
-  
-  qh_sethyperplane_gauss( dim, rows, point0, toporient, normal, offset, nearzero )
-    given (dim-1) X dim array of rows[i]= V_{i+1} - V_0 (point0)
-    set normalized hyperplane equation from oriented simplex
-
-  returns:
-    normal (normalized)
-    offset (places point0 on the hyperplane)
-
-  notes:
-    if nearzero
-      orientation may be incorrect because of incorrect sign flips in gausselim
-    solves [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0 .. 0 1] 
-        or [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0] 
-    i.e., N is normal to the hyperplane, and the unnormalized
-        distance to [0 .. 1] is either 1 or   0
-
-  design:
-    perform gaussian elimination
-    flip sign for negative values
-    perform back substitution 
-    normalize result
-    compute offset
-*/
-void qh_sethyperplane_gauss (int dim, coordT **rows, pointT *point0, 
-		boolT toporient, coordT *normal, coordT *offset, boolT *nearzero) {
-  coordT *pointcoord, *normalcoef;
-  int k;
-  boolT sign= toporient, nearzero2= False;
-  
-  qh_gausselim(rows, dim-1, dim, &sign, nearzero);
-  for(k= dim-1; k--; ) {
-    if ((rows[k])[k] < 0)
-      sign ^= 1;
-  }
-  if (*nearzero) {
-    zzinc_(Znearlysingular);
-    trace0((qh ferr, "qh_sethyperplane_gauss: nearly singular or axis parallel hyperplane during p%d.\n", qh furthest_id));
-    qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
-  }else {
-    qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
-    if (nearzero2) {
-      zzinc_(Znearlysingular);
-      trace0((qh ferr, "qh_sethyperplane_gauss: singular or axis parallel hyperplane at normalization during p%d.\n", qh furthest_id));
-    }
-  }
-  if (nearzero2)
-    *nearzero= True;
-  qh_normalize2(normal, dim, True, NULL, NULL);
-  pointcoord= point0;
-  normalcoef= normal;
-  *offset= -(*pointcoord++ * *normalcoef++);
-  for(k= dim-1; k--; )
-    *offset -= *pointcoord++ * *normalcoef++;
-} /* sethyperplane_gauss */
-
-  
-
diff --git a/extern/qhull/src/geom.h b/extern/qhull/src/geom.h
deleted file mode 100644
index 32440cff56f..00000000000
--- a/extern/qhull/src/geom.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
  ---------------------------------
-
-  geom.h 
-    header file for geometric routines
-
-   see qh-geom.htm and geom.c
-
-   copyright (c) 1993-2002 The Geometry Center        
-*/
-
-#ifndef qhDEFgeom
-#define qhDEFgeom 1
-
-/* ============ -macros- ======================== */
-
-/*----------------------------------
-   
-  fabs_(a)
-    returns the absolute value of a
-*/
-#define fabs_( a ) ((( a ) < 0 ) ? -( a ):( a ))
-               
-/*----------------------------------
-  
-  fmax_(a,b)
-    returns the maximum value of a and b
-*/
-#define fmax_( a,b )  ( ( a ) < ( b ) ? ( b ) : ( a ) )
-
-/*----------------------------------
-
-  fmin_(a,b)
-    returns the minimum value of a and b
-*/
-#define fmin_( a,b )  ( ( a ) > ( b ) ? ( b ) : ( a ) )
-
-/*----------------------------------
-
-  maximize_(maxval, val)
-    set maxval to val if val is greater than maxval
-*/
-#define maximize_( maxval, val ) {if (( maxval ) < ( val )) ( maxval )= ( val );}
-
-/*----------------------------------
-
-  minimize_(minval, val)
-    set minval to val if val is less than minval
-*/
-#define minimize_( minval, val ) {if (( minval ) > ( val )) ( minval )= ( val );}
-
-/*----------------------------------
-
-  det2_(a1, a2,     
-        b1, b2)
-  
-    compute a 2-d determinate
-*/
-#define det2_( a1,a2,b1,b2 ) (( a1 )*( b2 ) - ( a2 )*( b1 ))
-
-/*----------------------------------
-  
-  det3_(a1, a2, a3,    
-       b1, b2, b3,
-       c1, c2, c3)
-  
-    compute a 3-d determinate
-*/
-#define det3_( a1,a2,a3,b1,b2,b3,c1,c2,c3 ) ( ( a1 )*det2_( b2,b3,c2,c3 ) \
-                - ( b1 )*det2_( a2,a3,c2,c3 ) + ( c1 )*det2_( a2,a3,b2,b3 ) )
-
-/*----------------------------------
-  
-  dX( p1, p2 )
-  dY( p1, p2 )
-  dZ( p1, p2 )
-  
-    given two indices into rows[],
-
-    compute the difference between X, Y, or Z coordinates
-*/
-#define dX( p1,p2 )  ( *( rows[p1] ) - *( rows[p2] ))
-#define dY( p1,p2 )  ( *( rows[p1]+1 ) - *( rows[p2]+1 ))
-#define dZ( p1,p2 )  ( *( rows[p1]+2 ) - *( rows[p2]+2 ))
-#define dW( p1,p2 )  ( *( rows[p1]+3 ) - *( rows[p2]+3 ))
-
-/*============= prototypes in alphabetical order, infrequent at end ======= */
-
-void    qh_backnormal (realT **rows, int numrow, int numcol, boolT sign, coordT *normal, boolT *nearzero);
-void	qh_distplane (pointT *point, facetT *facet, realT *dist);
-facetT *qh_findbest (pointT *point, facetT *startfacet,
-		     boolT bestoutside, boolT isnewfacets, boolT noupper,
-		     realT *dist, boolT *isoutside, int *numpart);
-facetT *qh_findbesthorizon (boolT ischeckmax, pointT *point, 
-	             facetT *startfacet, boolT noupper, realT *bestdist, int *numpart);
-facetT *qh_findbestnew (pointT *point, facetT *startfacet, realT *dist, 
-		     boolT bestoutside, boolT *isoutside, int *numpart);
-void 	qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero);
-realT   qh_getangle(pointT *vect1, pointT *vect2);
-pointT *qh_getcenter(setT *vertices);
-pointT *qh_getcentrum(facetT *facet);
-realT   qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist);
-void    qh_normalize (coordT *normal, int dim, boolT toporient);
-void    qh_normalize2 (coordT *normal, int dim, boolT toporient, 
-            realT *minnorm, boolT *ismin);
-pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist);
-
-void    qh_setfacetplane(facetT *newfacets);
-void 	qh_sethyperplane_det (int dim, coordT **rows, coordT *point0, 
-              boolT toporient, coordT *normal, realT *offset, boolT *nearzero);
-void 	qh_sethyperplane_gauss (int dim, coordT **rows, pointT *point0, 
-	     boolT toporient, coordT *normal, coordT *offset, boolT *nearzero);
-boolT   qh_sharpnewfacets (void);
-
-/*========= infrequently used code in geom2.c =============*/
-
-
-coordT *qh_copypoints (coordT *points, int numpoints, int dimension);
-void    qh_crossproduct (int dim, realT vecA[3], realT vecB[3], realT vecC[3]);
-realT 	qh_determinant (realT **rows, int dim, boolT *nearzero);
-realT   qh_detjoggle (pointT *points, int numpoints, int dimension);
-void    qh_detroundoff (void);
-realT   qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero);
-realT   qh_distnorm (int dim, pointT *point, pointT *normal, realT *offsetp);
-realT   qh_distround (int dimension, realT maxabs, realT maxsumabs);
-realT   qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv);
-realT   qh_facetarea (facetT *facet);
-realT   qh_facetarea_simplex (int dim, coordT *apex, setT *vertices, 
-          vertexT *notvertex,  boolT toporient, coordT *normal, realT *offset);
-pointT *qh_facetcenter (setT *vertices);
-facetT *qh_findgooddist (pointT *point, facetT *facetA, realT *distp, facetT **facetlist);
-void    qh_getarea (facetT *facetlist);
-boolT   qh_gram_schmidt(int dim, realT **rows);
-boolT   qh_inthresholds (coordT *normal, realT *angle);
-void    qh_joggleinput (void);
-realT  *qh_maxabsval (realT *normal, int dim);
-setT   *qh_maxmin(pointT *points, int numpoints, int dimension);
-realT   qh_maxouter (void);
-void    qh_maxsimplex (int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex);
-realT   qh_minabsval (realT *normal, int dim);
-int     qh_mindiff (realT *vecA, realT *vecB, int dim);
-boolT   qh_orientoutside (facetT *facet);
-void    qh_outerinner (facetT *facet, realT *outerplane, realT *innerplane);
-coordT  qh_pointdist(pointT *point1, pointT *point2, int dim);
-void    qh_printmatrix (FILE *fp, char *string, realT **rows, int numrow, int numcol);
-void    qh_printpoints (FILE *fp, char *string, setT *points);
-void    qh_projectinput (void);
-void 	qh_projectpoints (signed char *project, int n, realT *points, 
-             int numpoints, int dim, realT *newpoints, int newdim);
-int     qh_rand( void);
-void    qh_srand( int seed);
-realT   qh_randomfactor (void);
-void    qh_randommatrix (realT *buffer, int dim, realT **row);
-void    qh_rotateinput (realT **rows);
-void    qh_rotatepoints (realT *points, int numpoints, int dim, realT **rows);
-void    qh_scaleinput (void);
-void    qh_scalelast (coordT *points, int numpoints, int dim, coordT low,
-		   coordT high, coordT newhigh);
-void 	qh_scalepoints (pointT *points, int numpoints, int dim,
-  		realT *newlows, realT *newhighs);
-boolT   qh_sethalfspace (int dim, coordT *coords, coordT **nextp, 
-              coordT *normal, coordT *offset, coordT *feasible);
-coordT *qh_sethalfspace_all (int dim, int count, coordT *halfspaces, pointT *feasible);
-pointT *qh_voronoi_center (int dim, setT *points);
-
-#endif /* qhDEFgeom */
-
-
-
diff --git a/extern/qhull/src/geom2.c b/extern/qhull/src/geom2.c
deleted file mode 100644
index bd58ce1282b..00000000000
--- a/extern/qhull/src/geom2.c
+++ /dev/null
@@ -1,2160 +0,0 @@
-/*
  ---------------------------------
-
-
-   geom2.c 
-   infrequently used geometric routines of qhull
-
-   see qh-geom.htm and geom.h
-
-   copyright (c) 1993-2002 The Geometry Center        
-
-   frequently used code goes into geom.c
-*/
-   
-#include "qhull_a.h"
-   
-/*================== functions in alphabetic order ============*/
-
-/*---------------------------------
-
-  qh_copypoints( points, numpoints, dimension)
-    return malloc'd copy of points
-*/
-coordT *qh_copypoints (coordT *points, int numpoints, int dimension) {
-  int size;
-  coordT *newpoints;
-
-  size= numpoints * dimension * sizeof(coordT);
-  if (!(newpoints=(coordT*)malloc(size))) {
-    fprintf(qh ferr, "qhull error: insufficient memory to copy %d points\n",
-        numpoints);
-    qh_errexit(qh_ERRmem, NULL, NULL);
-  }
-  memcpy ((char *)newpoints, (char *)points, size);
-  return newpoints;
-} /* copypoints */
-
-/*---------------------------------
-  
-  qh_crossproduct( dim, vecA, vecB, vecC )
-    crossproduct of 2 dim vectors
-    C= A x B
-  
-  notes:
-    from Glasner, Graphics Gems I, p. 639
-    only defined for dim==3
-*/
-void qh_crossproduct (int dim, realT vecA[3], realT vecB[3], realT vecC[3]){
-
-  if (dim == 3) {
-    vecC[0]=   det2_(vecA[1], vecA[2],
-		     vecB[1], vecB[2]);
-    vecC[1]= - det2_(vecA[0], vecA[2],
-		     vecB[0], vecB[2]);
-    vecC[2]=   det2_(vecA[0], vecA[1],
-		     vecB[0], vecB[1]);
-  }
-} /* vcross */
-
-/*---------------------------------
-  
-  qh_determinant( rows, dim, nearzero )
-    compute signed determinant of a square matrix
-    uses qh.NEARzero to test for degenerate matrices
-
-  returns:
-    determinant
-    overwrites rows and the matrix
-    if dim == 2 or 3
-      nearzero iff determinant < qh NEARzero[dim-1]
-      (not quite correct, not critical)
-    if dim >= 4
-      nearzero iff diagonal[k] < qh NEARzero[k]
-*/
-realT qh_determinant (realT **rows, int dim, boolT *nearzero) {
-  realT det=0;
-  int i;
-  boolT sign= False;
-
-  *nearzero= False;
-  if (dim < 2) {
-    fprintf (qh ferr, "qhull internal error (qh_determinate): only implemented for dimension >= 2\n");
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }else if (dim == 2) {
-    det= det2_(rows[0][0], rows[0][1],
-		 rows[1][0], rows[1][1]);
-    if (fabs_(det) < qh NEARzero[1])  /* not really correct, what should this be? */
-      *nearzero= True;
-  }else if (dim == 3) {
-    det= det3_(rows[0][0], rows[0][1], rows[0][2],
-		 rows[1][0], rows[1][1], rows[1][2],
-		 rows[2][0], rows[2][1], rows[2][2]);
-    if (fabs_(det) < qh NEARzero[2])  /* not really correct, what should this be? */
-      *nearzero= True;
-  }else {	
-    qh_gausselim(rows, dim, dim, &sign, nearzero);  /* if nearzero, diagonal still ok*/
-    det= 1.0;
-    for (i= dim; i--; )
-      det *= (rows[i])[i];
-    if (sign)
-      det= -det;
-  }
-  return det;
-} /* determinant */
-
-/*---------------------------------
-  
-  qh_detjoggle( points, numpoints, dimension )
-    determine default max joggle for point array
-      as qh_distround * qh_JOGGLEdefault
-
-  returns:
-    initial value for JOGGLEmax from points and REALepsilon
-
-  notes:
-    computes DISTround since qh_maxmin not called yet
-    if qh SCALElast, last dimension will be scaled later to MAXwidth
-
-    loop duplicated from qh_maxmin
-*/
-realT qh_detjoggle (pointT *points, int numpoints, int dimension) {
-  realT abscoord, distround, joggle, maxcoord, mincoord;
-  pointT *point, *pointtemp;
-  realT maxabs= -REALmax;
-  realT sumabs= 0;
-  realT maxwidth= 0;
-  int k;
-
-  for (k= 0; k < dimension; k++) {
-    if (qh SCALElast && k == dimension-1)
-      abscoord= maxwidth;
-    else if (qh DELAUNAY && k == dimension-1) /* will qh_setdelaunay() */
-      abscoord= 2 * maxabs * maxabs;  /* may be low by qh hull_dim/2 */
-    else {
-      maxcoord= -REALmax;
-      mincoord= REALmax;
-      FORALLpoint_(points, numpoints) {
-	maximize_(maxcoord, point[k]);
-        minimize_(mincoord, point[k]);
-      }
-      maximize_(maxwidth, maxcoord-mincoord);
-      abscoord= fmax_(maxcoord, -mincoord);
-    }
-    sumabs += abscoord;
-    maximize_(maxabs, abscoord);
-  } /* for k */
-  distround= qh_distround (qh hull_dim, maxabs, sumabs);
-  joggle= distround * qh_JOGGLEdefault;
-  maximize_(joggle, REALepsilon * qh_JOGGLEdefault);
-  trace2((qh ferr, "qh_detjoggle: joggle=%2.2g maxwidth=%2.2g\n", joggle, maxwidth));
-  return joggle;
-} /* detjoggle */
-
-/*---------------------------------
-  
-  qh_detroundoff()
-    determine maximum roundoff errors from
-      REALepsilon, REALmax, REALmin, qh.hull_dim, qh.MAXabs_coord, 
-      qh.MAXsumcoord, qh.MAXwidth, qh.MINdenom_1
-
-    accounts for qh.SETroundoff, qh.RANDOMdist, qh MERGEexact
-      qh.premerge_cos, qh.postmerge_cos, qh.premerge_centrum,
-      qh.postmerge_centrum, qh.MINoutside,
-      qh_RATIOnearinside, qh_COPLANARratio, qh_WIDEcoplanar
-
-  returns:
-    sets qh.DISTround, etc. (see below)
-    appends precision constants to qh.qhull_options
-
-  see:
-    qh_maxmin() for qh.NEARzero
-
-  design:
-    determine qh.DISTround for distance computations
-    determine minimum denominators for qh_divzero
-    determine qh.ANGLEround for angle computations
-    adjust qh.premerge_cos,... for roundoff error
-    determine qh.ONEmerge for maximum error due to a single merge
-    determine qh.NEARinside, qh.MAXcoplanar, qh.MINvisible,
-      qh.MINoutside, qh.WIDEfacet
-    initialize qh.max_vertex and qh.minvertex
-*/
-void qh_detroundoff (void) {
-
-  qh_option ("_max-width", NULL, &qh MAXwidth);
-  if (!qh SETroundoff) {
-    qh DISTround= qh_distround (qh hull_dim, qh MAXabs_coord, qh MAXsumcoord);
-    if (qh RANDOMdist)
-      qh DISTround += qh RANDOMfactor * qh MAXabs_coord;
-    qh_option ("Error-roundoff", NULL, &qh DISTround);
-  }
-  qh MINdenom= qh MINdenom_1 * qh MAXabs_coord;
-  qh MINdenom_1_2= sqrt (qh MINdenom_1 * qh hull_dim) ;  /* if will be normalized */
-  qh MINdenom_2= qh MINdenom_1_2 * qh MAXabs_coord;
-                                              /* for inner product */
-  qh ANGLEround= 1.01 * qh hull_dim * REALepsilon;
-  if (qh RANDOMdist)
-    qh ANGLEround += qh RANDOMfactor;
-  if (qh premerge_cos < REALmax/2) {
-    qh premerge_cos -= qh ANGLEround;
-    if (qh RANDOMdist) 
-      qh_option ("Angle-premerge-with-random", NULL, &qh premerge_cos);
-  }
-  if (qh postmerge_cos < REALmax/2) {
-    qh postmerge_cos -= qh ANGLEround;
-    if (qh RANDOMdist)
-      qh_option ("Angle-postmerge-with-random", NULL, &qh postmerge_cos);
-  }
-  qh premerge_centrum += 2 * qh DISTround;    /*2 for centrum and distplane()*/
-  qh postmerge_centrum += 2 * qh DISTround;
-  if (qh RANDOMdist && (qh MERGEexact || qh PREmerge))
-    qh_option ("Centrum-premerge-with-random", NULL, &qh premerge_centrum);
-  if (qh RANDOMdist && qh POSTmerge)
-    qh_option ("Centrum-postmerge-with-random", NULL, &qh postmerge_centrum);
-  { /* compute ONEmerge, max vertex offset for merging simplicial facets */
-    realT maxangle= 1.0, maxrho;
-    
-    minimize_(maxangle, qh premerge_cos);
-    minimize_(maxangle, qh postmerge_cos);
-    /* max diameter * sin theta + DISTround for vertex to its hyperplane */
-    qh ONEmerge= sqrt (qh hull_dim) * qh MAXwidth *
-      sqrt (1.0 - maxangle * maxangle) + qh DISTround;  
-    maxrho= qh hull_dim * qh premerge_centrum + qh DISTround;
-    maximize_(qh ONEmerge, maxrho);
-    maxrho= qh hull_dim * qh postmerge_centrum + qh DISTround;
-    maximize_(qh ONEmerge, maxrho);
-    if (qh MERGING)
-      qh_option ("_one-merge", NULL, &qh ONEmerge);
-  }
-  qh NEARinside= qh ONEmerge * qh_RATIOnearinside; /* only used if qh KEEPnearinside */
-  if (qh JOGGLEmax < REALmax/2 && (qh KEEPcoplanar || qh KEEPinside)) {
-    realT maxdist;	       /* adjust qh.NEARinside for joggle */
-    qh KEEPnearinside= True;   
-    maxdist= sqrt (qh hull_dim) * qh JOGGLEmax + qh DISTround;
-    maxdist= 2*maxdist;        /* vertex and coplanar point can joggle in opposite directions */
-    maximize_(qh NEARinside, maxdist);  /* must agree with qh_nearcoplanar() */
-  }
-  if (qh KEEPnearinside)
-    qh_option ("_near-inside", NULL, &qh NEARinside);
-  if (qh JOGGLEmax < qh DISTround) {
-    fprintf (qh ferr, "qhull error: the joggle for 'QJn', %.2g, is below roundoff for distance computations, %.2g\n",
-         qh JOGGLEmax, qh DISTround);
-    qh_errexit (qh_ERRinput, NULL, NULL);
-  }
-  if (qh MINvisible > REALmax/2) {
-    if (!qh MERGING)
-      qh MINvisible= qh DISTround;
-    else if (qh hull_dim <= 3)
-      qh MINvisible= qh premerge_centrum;
-    else
-      qh MINvisible= qh_COPLANARratio * qh premerge_centrum;
-    if (qh APPROXhull && qh MINvisible > qh MINoutside)
-      qh MINvisible= qh MINoutside;
-    qh_option ("Visible-distance", NULL, &qh MINvisible);
-  }
-  if (qh MAXcoplanar > REALmax/2) {
-    qh MAXcoplanar= qh MINvisible;
-    qh_option ("U-coplanar-distance", NULL, &qh MAXcoplanar);
-  }
-  if (!qh APPROXhull) {             /* user may specify qh MINoutside */
-    qh MINoutside= 2 * qh MINvisible;
-    if (qh premerge_cos < REALmax/2) 
-      maximize_(qh MINoutside, (1- qh premerge_cos) * qh MAXabs_coord);
-    qh_option ("Width-outside", NULL, &qh MINoutside);
-  }
-  qh WIDEfacet= qh MINoutside;
-  maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MAXcoplanar); 
-  maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MINvisible); 
-  qh_option ("_wide-facet", NULL, &qh WIDEfacet);
-  if (qh MINvisible > qh MINoutside + 3 * REALepsilon 
-  && !qh BESToutside && !qh FORCEoutput)
-    fprintf (qh ferr, "qhull input warning: minimum visibility V%.2g is greater than \nminimum outside W%.2g.  Flipped facets are likely.\n",
-	     qh MINvisible, qh MINoutside);
-  qh max_vertex= qh DISTround;
-  qh min_vertex= -qh DISTround;
-  /* numeric constants reported in printsummary */
-} /* detroundoff */
-
-/*---------------------------------
-  
-  qh_detsimplex( apex, points, dim, nearzero )
-    compute determinant of a simplex with point apex and base points
-
-  returns:
-     signed determinant and nearzero from qh_determinant
-
-  notes:
-     uses qh.gm_matrix/qh.gm_row (assumes they're big enough)
-
-  design:
-    construct qm_matrix by subtracting apex from points
-    compute determinate
-*/
-realT qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero) {
-  pointT *coorda, *coordp, *gmcoord, *point, **pointp;
-  coordT **rows;
-  int k,  i=0;
-  realT det;
-
-  zinc_(Zdetsimplex);
-  gmcoord= qh gm_matrix;
-  rows= qh gm_row;
-  FOREACHpoint_(points) {
-    if (i == dim)
-      break;
-    rows[i++]= gmcoord;
-    coordp= point;
-    coorda= apex;
-    for (k= dim; k--; )
-      *(gmcoord++)= *coordp++ - *coorda++;
-  }
-  if (i < dim) {
-    fprintf (qh ferr, "qhull internal error (qh_detsimplex): #points %d < dimension %d\n", 
-               i, dim);
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-  det= qh_determinant (rows, dim, nearzero);
-  trace2((qh ferr, "qh_detsimplex: det=%2.2g for point p%d, dim %d, nearzero? %d\n",
-	  det, qh_pointid(apex), dim, *nearzero)); 
-  return det;
-} /* detsimplex */
-
-/*---------------------------------
-  
-  qh_distnorm( dim, point, normal, offset )
-    return distance from point to hyperplane at normal/offset
-
-  returns:
-    dist
-  
-  notes:  
-    dist > 0 if point is outside of hyperplane
-  
-  see:
-    qh_distplane in geom.c
-*/
-realT qh_distnorm (int dim, pointT *point, pointT *normal, realT *offsetp) {
-  coordT *normalp= normal, *coordp= point;
-  realT dist;
-  int k;
-
-  dist= *offsetp;
-  for (k= dim; k--; )
-    dist += *(coordp++) * *(normalp++);
-  return dist;
-} /* distnorm */
-
-/*---------------------------------
-
-  qh_distround ( dimension, maxabs, maxsumabs )
-    compute maximum round-off error for a distance computation
-      to a normalized hyperplane
-    maxabs is the maximum absolute value of a coordinate
-    maxsumabs is the maximum possible sum of absolute coordinate values
-
-  returns:
-    max dist round for REALepsilon
-
-  notes:
-    calculate roundoff error according to
-    Lemma 3.2-1 of Golub and van Loan "Matrix Computation"
-    use sqrt(dim) since one vector is normalized
-      or use maxsumabs since one vector is < 1
-*/
-realT qh_distround (int dimension, realT maxabs, realT maxsumabs) {
-  realT maxdistsum, maxround;
-
-  maxdistsum= sqrt (dimension) * maxabs;
-  minimize_( maxdistsum, maxsumabs);
-  maxround= REALepsilon * (dimension * maxdistsum * 1.01 + maxabs);
-              /* adds maxabs for offset */
-  trace4((qh ferr, "qh_distround: %2.2g maxabs %2.2g maxsumabs %2.2g maxdistsum %2.2g\n",
-	         maxround, maxabs, maxsumabs, maxdistsum));
-  return maxround;
-} /* distround */
-
-/*---------------------------------
-  
-  qh_divzero( numer, denom, mindenom1, zerodiv )
-    divide by a number that's nearly zero
-    mindenom1= minimum denominator for dividing into 1.0
-
-  returns:
-    quotient
-    sets zerodiv and returns 0.0 if it would overflow
-  
-  design:
-    if numer is nearly zero and abs(numer) < abs(denom)
-      return numer/denom
-    else if numer is nearly zero
-      return 0 and zerodiv
-    else if denom/numer non-zero
-      return numer/denom
-    else
-      return 0 and zerodiv
-*/
-realT qh_divzero (realT numer, realT denom, realT mindenom1, boolT *zerodiv) {
-  realT temp, numerx, denomx;
-  
-
-  if (numer < mindenom1 && numer > -mindenom1) {
-    numerx= fabs_(numer);
-    denomx= fabs_(denom);
-    if (numerx < denomx) {
-      *zerodiv= False;
-      return numer/denom;
-    }else {
-      *zerodiv= True;
-      return 0.0;
-    }
-  }
-  temp= denom/numer;
-  if (temp > mindenom1 || temp < -mindenom1) {
-    *zerodiv= False;
-    return numer/denom;
-  }else {
-    *zerodiv= True;
-    return 0.0;
-  }
-} /* divzero */
-  
-
-/*---------------------------------
-
-  qh_facetarea( facet )
-    return area for a facet
-  
-  notes:
-    if non-simplicial, 
-      uses centrum to triangulate facet and sums the projected areas.
-    if (qh DELAUNAY),
-      computes projected area instead for last coordinate
-    assumes facet->normal exists
-    projecting tricoplanar facets to the hyperplane does not appear to make a difference
-  
-  design:
-    if simplicial
-      compute area
-    else
-      for each ridge
-        compute area from centrum to ridge
-    negate area if upper Delaunay facet
-*/
-realT qh_facetarea (facetT *facet) {
-  vertexT *apex;
-  pointT *centrum;
-  realT area= 0.0;
-  ridgeT *ridge, **ridgep;
-
-  if (facet->simplicial) {
-    apex= SETfirstt_(facet->vertices, vertexT);
-    area= qh_facetarea_simplex (qh hull_dim, apex->point, facet->vertices, 
-                    apex, facet->toporient, facet->normal, &facet->offset);
-  }else {
-    if (qh CENTERtype == qh_AScentrum)
-      centrum= facet->center;
-    else
-      centrum= qh_getcentrum (facet);
-    FOREACHridge_(facet->ridges) 
-      area += qh_facetarea_simplex (qh hull_dim, centrum, ridge->vertices, 
-                 NULL, (ridge->top == facet),  facet->normal, &facet->offset);
-    if (qh CENTERtype != qh_AScentrum)
-      qh_memfree (centrum, qh normal_size);
-  }
-  if (facet->upperdelaunay && qh DELAUNAY)
-    area= -area;  /* the normal should be [0,...,1] */
-  trace4((qh ferr, "qh_facetarea: f%d area %2.2g\n", facet->id, area)); 
-  return area;
-} /* facetarea */
-
-/*---------------------------------
-
-  qh_facetarea_simplex( dim, apex, vertices, notvertex, toporient, normal, offset )
-    return area for a simplex defined by 
-      an apex, a base of vertices, an orientation, and a unit normal
-    if simplicial or tricoplanar facet, 
-      notvertex is defined and it is skipped in vertices
-  
-  returns:
-    computes area of simplex projected to plane [normal,offset]
-    returns 0 if vertex too far below plane (qh WIDEfacet)
-      vertex can't be apex of tricoplanar facet
-  
-  notes:
-    if (qh DELAUNAY),
-      computes projected area instead for last coordinate
-    uses qh gm_matrix/gm_row and qh hull_dim
-    helper function for qh_facetarea
-  
-  design:
-    if Notvertex
-      translate simplex to apex
-    else
-      project simplex to normal/offset
-      translate simplex to apex
-    if Delaunay
-      set last row/column to 0 with -1 on diagonal 
-    else
-      set last row to Normal
-    compute determinate
-    scale and flip sign for area
-*/
-realT qh_facetarea_simplex (int dim, coordT *apex, setT *vertices, 
-        vertexT *notvertex,  boolT toporient, coordT *normal, realT *offset) {
-  pointT *coorda, *coordp, *gmcoord;
-  coordT **rows, *normalp;
-  int k,  i=0;
-  realT area, dist;
-  vertexT *vertex, **vertexp;
-  boolT nearzero;
-
-  gmcoord= qh gm_matrix;
-  rows= qh gm_row;
-  FOREACHvertex_(vertices) {
-    if (vertex == notvertex)
-      continue;
-    rows[i++]= gmcoord;
-    coorda= apex;
-    coordp= vertex->point;
-    normalp= normal;
-    if (notvertex) {
-      for (k= dim; k--; )
-	*(gmcoord++)= *coordp++ - *coorda++;
-    }else {
-      dist= *offset;
-      for (k= dim; k--; )
-	dist += *coordp++ * *normalp++;
-      if (dist < -qh WIDEfacet) {
-	zinc_(Znoarea);
-	return 0.0;
-      }
-      coordp= vertex->point;
-      normalp= normal;
-      for (k= dim; k--; )
-	*(gmcoord++)= (*coordp++ - dist * *normalp++) - *coorda++;
-    }
-  }
-  if (i != dim-1) {
-    fprintf (qh ferr, "qhull internal error (qh_facetarea_simplex): #points %d != dim %d -1\n", 
-               i, dim);
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-  rows[i]= gmcoord;
-  if (qh DELAUNAY) {
-    for (i= 0; i < dim-1; i++)
-      rows[i][dim-1]= 0.0;
-    for (k= dim; k--; )
-      *(gmcoord++)= 0.0;
-    rows[dim-1][dim-1]= -1.0;
-  }else {
-    normalp= normal;
-    for (k= dim; k--; )
-      *(gmcoord++)= *normalp++;
-  }
-  zinc_(Zdetsimplex);
-  area= qh_determinant (rows, dim, &nearzero);
-  if (toporient)
-    area= -area;
-  area *= qh AREAfactor;
-  trace4((qh ferr, "qh_facetarea_simplex: area=%2.2g for point p%d, toporient %d, nearzero? %d\n",
-	  area, qh_pointid(apex), toporient, nearzero)); 
-  return area;
-} /* facetarea_simplex */
-
-/*---------------------------------
-  
-  qh_facetcenter( vertices )
-    return Voronoi center (Voronoi vertex) for a facet's vertices
-
-  returns:
-    return temporary point equal to the center
-    
-  see:
-    qh_voronoi_center()
-*/
-pointT *qh_facetcenter (setT *vertices) {
-  setT *points= qh_settemp (qh_setsize (vertices));
-  vertexT *vertex, **vertexp;
-  pointT *center;
-  
-  FOREACHvertex_(vertices) 
-    qh_setappend (&points, vertex->point);
-  center= qh_voronoi_center (qh hull_dim-1, points);
-  qh_settempfree (&points);
-  return center;
-} /* facetcenter */
-
-/*---------------------------------
-  
-  qh_findgooddist( point, facetA, dist, facetlist )
-    find best good facet visible for point from facetA
-    assumes facetA is visible from point
-
-  returns:
-    best facet, i.e., good facet that is furthest from point
-      distance to best facet
-      NULL if none
-      
-    moves good, visible facets (and some other visible facets)
-      to end of qh facet_list
-
-  notes:
-    uses qh visit_id
-
-  design:
-    initialize bestfacet if facetA is good
-    move facetA to end of facetlist
-    for each facet on facetlist
-      for each unvisited neighbor of facet
-        move visible neighbors to end of facetlist
-        update best good neighbor
-        if no good neighbors, update best facet
-*/
-facetT *qh_findgooddist (pointT *point, facetT *facetA, realT *distp, 
-               facetT **facetlist) {
-  realT bestdist= -REALmax, dist;
-  facetT *neighbor, **neighborp, *bestfacet=NULL, *facet;
-  boolT goodseen= False;  
-
-  if (facetA->good) {
-    zinc_(Zcheckpart);  /* calls from check_bestdist occur after print stats */
-    qh_distplane (point, facetA, &bestdist);
-    bestfacet= facetA;
-    goodseen= True;
-  }
-  qh_removefacet (facetA);
-  qh_appendfacet (facetA);
-  *facetlist= facetA;
-  facetA->visitid= ++qh visit_id;
-  FORALLfacet_(*facetlist) {
-    FOREACHneighbor_(facet) {
-      if (neighbor->visitid == qh visit_id)
-        continue;
-      neighbor->visitid= qh visit_id;
-      if (goodseen && !neighbor->good)
-        continue;
-      zinc_(Zcheckpart); 
-      qh_distplane (point, neighbor, &dist);
-      if (dist > 0) {
-        qh_removefacet (neighbor);
-        qh_appendfacet (neighbor);
-        if (neighbor->good) {
-          goodseen= True;
-          if (dist > bestdist) {
-            bestdist= dist;
-            bestfacet= neighbor;
-          }
-        }
-      }
-    }
-  }
-  if (bestfacet) {
-    *distp= bestdist;
-    trace2((qh ferr, "qh_findgooddist: p%d is %2.2g above good facet f%d\n",
-      qh_pointid(point), bestdist, bestfacet->id));
-    return bestfacet;
-  }
-  trace4((qh ferr, "qh_findgooddist: no good facet for p%d above f%d\n", 
-      qh_pointid(point), facetA->id));
-  return NULL;
-}  /* findgooddist */
-    
-/*---------------------------------
-  
-  qh_getarea( facetlist )
-    set area of all facets in facetlist
-    collect statistics
-
-  returns:
-    sets qh totarea/totvol to total area and volume of convex hull
-    for Delaunay triangulation, computes projected area of the lower or upper hull
-      ignores upper hull if qh ATinfinity
-  
-  notes:
-    could compute outer volume by expanding facet area by rays from interior
-    the following attempt at perpendicular projection underestimated badly:
-      qh.totoutvol += (-dist + facet->maxoutside + qh DISTround) 
-                            * area/ qh hull_dim;
-  design:
-    for each facet on facetlist
-      compute facet->area
-      update qh.totarea and qh.totvol
-*/
-void qh_getarea (facetT *facetlist) {
-  realT area;
-  realT dist;
-  facetT *facet;
-
-  if (qh REPORTfreq)
-    fprintf (qh ferr, "computing area of each facet and volume of the convex hull\n");
-  else 
-    trace1((qh ferr, "qh_getarea: computing volume and area for each facet\n"));
-  qh totarea= qh totvol= 0.0;
-  FORALLfacet_(facetlist) {
-    if (!facet->normal)
-      continue;
-    if (facet->upperdelaunay && qh ATinfinity)
-      continue;
-    facet->f.area= area= qh_facetarea (facet);
-    facet->isarea= True;
-    if (qh DELAUNAY) {
-      if (facet->upperdelaunay == qh UPPERdelaunay)
-	qh totarea += area;
-    }else {
-      qh totarea += area;
-      qh_distplane (qh interior_point, facet, &dist);
-      qh totvol += -dist * area/ qh hull_dim;
-    }
-    if (qh PRINTstatistics) {
-      wadd_(Wareatot, area);
-      wmax_(Wareamax, area);
-      wmin_(Wareamin, area);
-    }
-  }
-} /* getarea */
-
-/*---------------------------------
-  
-  qh_gram_schmidt( dim, row )
-    implements Gram-Schmidt orthogonalization by rows
-
-  returns:
-    false if zero norm
-    overwrites rows[dim][dim]
-
-  notes:
-    see Golub & van Loan Algorithm 6.2-2
-    overflow due to small divisors not handled
-
-  design:
-    for each row
-      compute norm for row
-      if non-zero, normalize row
-      for each remaining rowA
-        compute inner product of row and rowA
-        reduce rowA by row * inner product
-*/
-boolT qh_gram_schmidt(int dim, realT **row) {
-  realT *rowi, *rowj, norm;
-  int i, j, k;
-  
-  for(i=0; i < dim; i++) {
-    rowi= row[i];
-    for (norm= 0.0, k= dim; k--; rowi++)
-      norm += *rowi * *rowi;
-    norm= sqrt(norm);
-    wmin_(Wmindenom, norm);
-    if (norm == 0.0)  /* either 0 or overflow due to sqrt */
-      return False;
-    for(k= dim; k--; )
-      *(--rowi) /= norm;  
-    for(j= i+1; j < dim; j++) {
-      rowj= row[j];
-      for(norm= 0.0, k=dim; k--; )
-	norm += *rowi++ * *rowj++;
-      for(k=dim; k--; )
-	*(--rowj) -= *(--rowi) * norm;
-    }
-  }
-  return True;
-} /* gram_schmidt */
-
-
-/*---------------------------------
-  
-  qh_inthresholds( normal, angle )
-    return True if normal within qh.lower_/upper_threshold
-
-  returns:
-    estimate of angle by summing of threshold diffs
-      angle may be NULL
-      smaller "angle" is better
-  
-  notes:
-    invalid if qh.SPLITthresholds
-
-  see:
-    qh.lower_threshold in qh_initbuild()
-    qh_initthresholds()
-
-  design:
-    for each dimension
-      test threshold
-*/
-boolT qh_inthresholds (coordT *normal, realT *angle) {
-  boolT within= True;
-  int k;
-  realT threshold;
-
-  if (angle)
-    *angle= 0.0;
-  for(k= 0; k < qh hull_dim; k++) {
-    threshold= qh lower_threshold[k];
-    if (threshold > -REALmax/2) {
-      if (normal[k] < threshold)
-        within= False;
-      if (angle) {
-	threshold -= normal[k];
-	*angle += fabs_(threshold);
-      }
-    }
-    if (qh upper_threshold[k] < REALmax/2) {
-      threshold= qh upper_threshold[k];
-      if (normal[k] > threshold)
-        within= False;
-      if (angle) {
-	threshold -= normal[k];
-	*angle += fabs_(threshold);
-      }
-    }
-  }
-  return within;
-} /* inthresholds */
-    
-
-/*---------------------------------
-  
-  qh_joggleinput()
-    randomly joggle input to Qhull by qh.JOGGLEmax
-    initial input is qh.first_point/qh.num_points of qh.hull_dim
-      repeated calls use qh.input_points/qh.num_points
- 
-  returns:
-    joggles points at qh.first_point/qh.num_points
-    copies data to qh.input_points/qh.input_malloc if first time
-    determines qh.JOGGLEmax if it was zero
-    if qh.DELAUNAY
-      computes the Delaunay projection of the joggled points
-
-  notes:
-    if qh.DELAUNAY, unnecessarily joggles the last coordinate
-    the initial 'QJn' may be set larger than qh_JOGGLEmaxincrease
-
-  design:
-    if qh.DELAUNAY
-      set qh.SCALElast for reduced precision errors
-    if first call
-      initialize qh.input_points to the original input points
-      if qh.JOGGLEmax == 0
-        determine default qh.JOGGLEmax
-    else
-      increase qh.JOGGLEmax according to qh.build_cnt
-    joggle the input by adding a random number in [-qh.JOGGLEmax,qh.JOGGLEmax]
-    if qh.DELAUNAY
-      sets the Delaunay projection
-*/
-void qh_joggleinput (void) {
-  int size, i, seed;
-  coordT *coordp, *inputp;
-  realT randr, randa, randb;
-
-  if (!qh input_points) { /* first call */
-    qh input_points= qh first_point;
-    qh input_malloc= qh POINTSmalloc;
-    size= qh num_points * qh hull_dim * sizeof(coordT);
-    if (!(qh first_point=(coordT*)malloc(size))) {
-      fprintf(qh ferr, "qhull error: insufficient memory to joggle %d points\n",
-          qh num_points);
-      qh_errexit(qh_ERRmem, NULL, NULL);
-    }
-    qh POINTSmalloc= True;
-    if (qh JOGGLEmax == 0.0) {
-      qh JOGGLEmax= qh_detjoggle (qh input_points, qh num_points, qh hull_dim);
-      qh_option ("QJoggle", NULL, &qh JOGGLEmax);
-    }
-  }else {                 /* repeated call */
-    if (!qh RERUN && qh build_cnt > qh_JOGGLEretry) {
-      if (((qh build_cnt-qh_JOGGLEretry-1) % qh_JOGGLEagain) == 0) {
-	realT maxjoggle= qh MAXwidth * qh_JOGGLEmaxincrease;
-	if (qh JOGGLEmax < maxjoggle) {
-	  qh JOGGLEmax *= qh_JOGGLEincrease;
-	  minimize_(qh JOGGLEmax, maxjoggle); 
-	}
-      }
-    }
-    qh_option ("QJoggle", NULL, &qh JOGGLEmax);
-  }
-  if (qh build_cnt > 1 && qh JOGGLEmax > fmax_(qh MAXwidth/4, 0.1)) {
-      fprintf (qh ferr, "qhull error: the current joggle for 'QJn', %.2g, is too large for the width\nof the input.  If possible, recompile Qhull with higher-precision reals.\n",
-	        qh JOGGLEmax);
-      qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-  /* for some reason, using qh ROTATErandom and qh_RANDOMseed does not repeat the run. Use 'TRn' instead */
-  seed= qh_RANDOMint;
-  qh_option ("_joggle-seed", &seed, NULL);
-  trace0((qh ferr, "qh_joggleinput: joggle input by %2.2g with seed %d\n", 
-    qh JOGGLEmax, seed));
-  inputp= qh input_points;
-  coordp= qh first_point;
-  randa= 2.0 * qh JOGGLEmax/qh_RANDOMmax;
-  randb= -qh JOGGLEmax;
-  size= qh num_points * qh hull_dim;
-  for (i= size; i--; ) {
-    randr= qh_RANDOMint;
-    *(coordp++)= *(inputp++) + (randr * randa + randb);
-  }
-  if (qh DELAUNAY) {
-    qh last_low= qh last_high= qh last_newhigh= REALmax;
-    qh_setdelaunay (qh hull_dim, qh num_points, qh first_point);
-  }
-} /* joggleinput */
-
-/*---------------------------------
-  
-  qh_maxabsval( normal, dim )
-    return pointer to maximum absolute value of a dim vector
-    returns NULL if dim=0
-*/
-realT *qh_maxabsval (realT *normal, int dim) {
-  realT maxval= -REALmax;
-  realT *maxp= NULL, *colp, absval;
-  int k;
-
-  for (k= dim, colp= normal; k--; colp++) {
-    absval= fabs_(*colp);
-    if (absval > maxval) {
-      maxval= absval;
-      maxp= colp;
-    }
-  }
-  return maxp;
-} /* maxabsval */
-
-
-/*---------------------------------
-  
-  qh_maxmin( points, numpoints, dimension )
-    return max/min points for each dimension      
-    determine max and min coordinates
-
-  returns:
-    returns a temporary set of max and min points
-      may include duplicate points. Does not include qh.GOODpoint
-    sets qh.NEARzero, qh.MAXabs_coord, qh.MAXsumcoord, qh.MAXwidth
-         qh.MAXlastcoord, qh.MINlastcoord
-    initializes qh.max_outside, qh.min_vertex, qh.WAScoplanar, qh.ZEROall_ok
-
-  notes:
-    loop duplicated in qh_detjoggle()
-
-  design:
-    initialize global precision variables
-    checks definition of REAL...
-    for each dimension
-      for each point
-        collect maximum and minimum point
-      collect maximum of maximums and minimum of minimums
-      determine qh.NEARzero for Gaussian Elimination
-*/
-setT *qh_maxmin(pointT *points, int numpoints, int dimension) {
-  int k;
-  realT maxcoord, temp;
-  pointT *minimum, *maximum, *point, *pointtemp;
-  setT *set;
-
-  qh max_outside= 0.0;
-  qh MAXabs_coord= 0.0;
-  qh MAXwidth= -REALmax;
-  qh MAXsumcoord= 0.0;
-  qh min_vertex= 0.0;
-  qh WAScoplanar= False;
-  if (qh ZEROcentrum)
-    qh ZEROall_ok= True;
-  if (REALmin < REALepsilon && REALmin < REALmax && REALmin > -REALmax
-  && REALmax > 0.0 && -REALmax < 0.0)
-    ; /* all ok */
-  else {
-    fprintf (qh ferr, "qhull error: floating point constants in user.h are wrong\n\
-REALepsilon %g REALmin %g REALmax %g -REALmax %g\n",
-	     REALepsilon, REALmin, REALmax, -REALmax);
-    qh_errexit (qh_ERRinput, NULL, NULL);
-  }
-  set= qh_settemp(2*dimension);
-  for(k= 0; k < dimension; k++) {
-    if (points == qh GOODpointp)
-      minimum= maximum= points + dimension;
-    else
-      minimum= maximum= points;
-    FORALLpoint_(points, numpoints) {
-      if (point == qh GOODpointp)
-	continue;
-      if (maximum[k] < point[k])
-	maximum= point;
-      else if (minimum[k] > point[k])
-	minimum= point;
-    }
-    if (k == dimension-1) {
-      qh MINlastcoord= minimum[k];
-      qh MAXlastcoord= maximum[k];
-    }
-    if (qh SCALElast && k == dimension-1)
-      maxcoord= qh MAXwidth;
-    else {
-      maxcoord= fmax_(maximum[k], -minimum[k]);
-      if (qh GOODpointp) {
-        temp= fmax_(qh GOODpointp[k], -qh GOODpointp[k]);
-        maximize_(maxcoord, temp);
-      }
-      temp= maximum[k] - minimum[k];
-      maximize_(qh MAXwidth, temp);
-    }
-    maximize_(qh MAXabs_coord, maxcoord);
-    qh MAXsumcoord += maxcoord;
-    qh_setappend (&set, maximum);
-    qh_setappend (&set, minimum);
-    /* calculation of qh NEARzero is based on error formula 4.4-13 of
-       Golub & van Loan, authors say n^3 can be ignored and 10 be used in
-       place of rho */
-    qh NEARzero[k]= 80 * qh MAXsumcoord * REALepsilon;
-  }
-  if (qh IStracing >=1)
-    qh_printpoints (qh ferr, "qh_maxmin: found the max and min points (by dim):", set);
-  return(set);
-} /* maxmin */
-
-/*---------------------------------
-
-  qh_maxouter()
-    return maximum distance from facet to outer plane
-    normally this is qh.max_outside+qh.DISTround
-    does not include qh.JOGGLEmax
-
-  see:
-    qh_outerinner()
-    
-  notes:
-    need to add another qh.DISTround if testing actual point with computation
-
-  for joggle:
-    qh_setfacetplane() updated qh.max_outer for Wnewvertexmax (max distance to vertex)
-    need to use Wnewvertexmax since could have a coplanar point for a high 
-      facet that is replaced by a low facet
-    need to add qh.JOGGLEmax if testing input points
-*/
-realT qh_maxouter (void) {
-  realT dist;
-
-  dist= fmax_(qh max_outside, qh DISTround);
-  dist += qh DISTround;
-  trace4((qh ferr, "qh_maxouter: max distance from facet to outer plane is %2.2g max_outside is %2.2g\n", dist, qh max_outside));
-  return dist;
-} /* maxouter */
-
-/*---------------------------------
-  
-  qh_maxsimplex( dim, maxpoints, points, numpoints, simplex )
-    determines maximum simplex for a set of points 
-    starts from points already in simplex
-    skips qh.GOODpointp (assumes that it isn't in maxpoints)
-  
-  returns:
-    simplex with dim+1 points
-
-  notes:
-    assumes at least pointsneeded points in points
-    maximizes determinate for x,y,z,w, etc.
-    uses maxpoints as long as determinate is clearly non-zero
-
-  design:
-    initialize simplex with at least two points
-      (find points with max or min x coordinate)
-    for each remaining dimension
-      add point that maximizes the determinate
-        (use points from maxpoints first)    
-*/
-void qh_maxsimplex (int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex) {
-  pointT *point, **pointp, *pointtemp, *maxpoint, *minx=NULL, *maxx=NULL;
-  boolT nearzero, maxnearzero= False;
-  int k, sizinit;
-  realT maxdet= -REALmax, det, mincoord= REALmax, maxcoord= -REALmax;
-
-  sizinit= qh_setsize (*simplex);
-  if (sizinit < 2) {
-    if (qh_setsize (maxpoints) >= 2) {
-      FOREACHpoint_(maxpoints) {
-        if (maxcoord < point[0]) {
-          maxcoord= point[0];
-          maxx= point;
-        }
-	if (mincoord > point[0]) {
-          mincoord= point[0];
-          minx= point;
-        }
-      }
-    }else {
-      FORALLpoint_(points, numpoints) {
-	if (point == qh GOODpointp)
-	  continue;
-        if (maxcoord < point[0]) {
-	  maxcoord= point[0];
-          maxx= point;
-        }
-	if (mincoord > point[0]) {
-          mincoord= point[0];
-          minx= point;
-	}
-      }
-    }
-    qh_setunique (simplex, minx);
-    if (qh_setsize (*simplex) < 2)
-      qh_setunique (simplex, maxx);
-    sizinit= qh_setsize (*simplex);
-    if (sizinit < 2) {
-      qh_precision ("input has same x coordinate");
-      if (zzval_(Zsetplane) > qh hull_dim+1) {
-	fprintf (qh ferr, "qhull precision error (qh_maxsimplex for voronoi_center):\n%d points with the same x coordinate.\n",
-		 qh_setsize(maxpoints)+numpoints);
-	qh_errexit (qh_ERRprec, NULL, NULL);
-      }else {
-	fprintf (qh ferr, "qhull input error: input is less than %d-dimensional since it has the same x coordinate\n", qh hull_dim);
-	qh_errexit (qh_ERRinput, NULL, NULL);
-      }
-    }
-  }
-  for(k= sizinit; k < dim+1; k++) {
-    maxpoint= NULL;
-    maxdet= -REALmax;
-    FOREACHpoint_(maxpoints) {
-      if (!qh_setin (*simplex, point)) {
-        det= qh_detsimplex(point, *simplex, k, &nearzero);
-        if ((det= fabs_(det)) > maxdet) {
-	  maxdet= det;
-          maxpoint= point;
-	  maxnearzero= nearzero;
-        }
-      }
-    }
-    if (!maxpoint || maxnearzero) {
-      zinc_(Zsearchpoints);
-      if (!maxpoint) {
-        trace0((qh ferr, "qh_maxsimplex: searching all points for %d-th initial vertex.\n", k+1));
-      }else {
-        trace0((qh ferr, "qh_maxsimplex: searching all points for %d-th initial vertex, better than p%d det %2.2g\n",
-		k+1, qh_pointid(maxpoint), maxdet));
-      }
-      FORALLpoint_(points, numpoints) {
-	if (point == qh GOODpointp)
-	  continue;
-        if (!qh_setin (*simplex, point)) {
-          det= qh_detsimplex(point, *simplex, k, &nearzero);
-          if ((det= fabs_(det)) > maxdet) {
-	    maxdet= det;
-            maxpoint= point;
-	    maxnearzero= nearzero;
-	  }
-        }
-      }
-    } /* !maxpoint */
-    if (!maxpoint) {
-      fprintf (qh ferr, "qhull internal error (qh_maxsimplex): not enough points available\n");
-      qh_errexit (qh_ERRqhull, NULL, NULL);
-    }
-    qh_setappend(simplex, maxpoint);
-    trace1((qh ferr, "qh_maxsimplex: selected point p%d for %d`th initial vertex, det=%2.2g\n",
-	    qh_pointid(maxpoint), k+1, maxdet));
-  } /* k */ 
-} /* maxsimplex */
-
-/*---------------------------------
-  
-  qh_minabsval( normal, dim )
-    return minimum absolute value of a dim vector
-*/
-realT qh_minabsval (realT *normal, int dim) {
-  realT minval= 0;
-  realT maxval= 0;
-  realT *colp;
-  int k;
-
-  for (k= dim, colp= normal; k--; colp++) {
-    maximize_(maxval, *colp);
-    minimize_(minval, *colp);
-  }
-  return fmax_(maxval, -minval);
-} /* minabsval */
-
-
-/*---------------------------------
-  
-  qh_mindif( vecA, vecB, dim )
-    return index of min abs. difference of two vectors
-*/
-int qh_mindiff (realT *vecA, realT *vecB, int dim) {
-  realT mindiff= REALmax, diff;
-  realT *vecAp= vecA, *vecBp= vecB;
-  int k, mink= 0;
-
-  for (k= 0; k < dim; k++) {
-    diff= *vecAp++ - *vecBp++;
-    diff= fabs_(diff);
-    if (diff < mindiff) {
-      mindiff= diff;
-      mink= k;
-    }
-  }
-  return mink;
-} /* mindiff */
-
-
-
-/*---------------------------------
-  
-  qh_orientoutside( facet  )
-    make facet outside oriented via qh.interior_point
-
-  returns:
-    True if facet reversed orientation.
-*/
-boolT qh_orientoutside (facetT *facet) {
-  int k;
-  realT dist;
-
-  qh_distplane (qh interior_point, facet, &dist);
-  if (dist > 0) {
-    for (k= qh hull_dim; k--; )
-      facet->normal[k]= -facet->normal[k];
-    facet->offset= -facet->offset;
-    return True;
-  }
-  return False;
-} /* orientoutside */
-
-/*---------------------------------
-  
-  qh_outerinner( facet, outerplane, innerplane  )
-    if facet and qh.maxoutdone (i.e., qh_check_maxout)
-      returns outer and inner plane for facet
-    else
-      returns maximum outer and inner plane
-    accounts for qh.JOGGLEmax
-
-  see:
-    qh_maxouter(), qh_check_bestdist(), qh_check_points()
-
-  notes:
-    outerplaner or innerplane may be NULL
-    
-    includes qh.DISTround for actual points
-    adds another qh.DISTround if testing with floating point arithmetic
-*/
-void qh_outerinner (facetT *facet, realT *outerplane, realT *innerplane) {
-  realT dist, mindist;
-  vertexT *vertex, **vertexp;
-
-  if (outerplane) {
-    if (!qh_MAXoutside || !facet || !qh maxoutdone) {
-      *outerplane= qh_maxouter();       /* includes qh.DISTround */
-    }else { /* qh_MAXoutside ... */
-#if qh_MAXoutside 
-      *outerplane= facet->maxoutside + qh DISTround;
-#endif
-      
-    }
-    if (qh JOGGLEmax < REALmax/2)
-      *outerplane += qh JOGGLEmax * sqrt (qh hull_dim);
-  }
-  if (innerplane) {
-    if (facet) {
-      mindist= REALmax;
-      FOREACHvertex_(facet->vertices) {
-        zinc_(Zdistio);
-        qh_distplane (vertex->point, facet, &dist);
-        minimize_(mindist, dist);
-      }
-      *innerplane= mindist - qh DISTround;
-    }else 
-      *innerplane= qh min_vertex - qh DISTround;
-    if (qh JOGGLEmax < REALmax/2)
-      *innerplane -= qh JOGGLEmax * sqrt (qh hull_dim);
-  }
-} /* outerinner */
-
-/*---------------------------------
-  
-  qh_pointdist( point1, point2, dim )
-    return distance between two points
-
-  notes:
-    returns distance squared if 'dim' is negative
-*/
-coordT qh_pointdist(pointT *point1, pointT *point2, int dim) {
-  coordT dist, diff;
-  int k;
-  
-  dist= 0.0;
-  for (k= (dim > 0 ? dim : -dim); k--; ) {
-    diff= *point1++ - *point2++;
-    dist += diff * diff;
-  }
-  if (dim > 0)
-    return(sqrt(dist));
-  return dist;
-} /* pointdist */
-
-
-/*---------------------------------
-  
-  qh_printmatrix( fp, string, rows, numrow, numcol )
-    print matrix to fp given by row vectors
-    print string as header
-
-  notes:
-    print a vector by qh_printmatrix(fp, "", &vect, 1, len)
-*/
-void qh_printmatrix (FILE *fp, char *string, realT **rows, int numrow, int numcol) {
-  realT *rowp;
-  realT r; /*bug fix*/
-  int i,k;
-
-  fprintf (fp, "%s\n", string);
-  for (i= 0; i < numrow; i++) {
-    rowp= rows[i];
-    for (k= 0; k < numcol; k++) {
-      r= *rowp++;
-      fprintf (fp, "%6.3g ", r);
-    }
-    fprintf (fp, "\n");
-  }
-} /* printmatrix */
-
-  
-/*---------------------------------
-  
-  qh_printpoints( fp, string, points )
-    print pointids to fp for a set of points
-    if string, prints string and 'p' point ids
-*/
-void qh_printpoints (FILE *fp, char *string, setT *points) {
-  pointT *point, **pointp;
-
-  if (string) {
-    fprintf (fp, "%s", string);
-    FOREACHpoint_(points) 
-      fprintf (fp, " p%d", qh_pointid(point));
-    fprintf (fp, "\n");
-  }else {
-    FOREACHpoint_(points) 
-      fprintf (fp, " %d", qh_pointid(point));
-    fprintf (fp, "\n");
-  }
-} /* printpoints */
-
-  
-/*---------------------------------
-  
-  qh_projectinput()
-    project input points using qh.lower_bound/upper_bound and qh DELAUNAY
-    if qh.lower_bound[k]=qh.upper_bound[k]= 0, 
-      removes dimension k 
-    if halfspace intersection
-      removes dimension k from qh.feasible_point
-    input points in qh first_point, num_points, input_dim
-
-  returns:
-    new point array in qh first_point of qh hull_dim coordinates
-    sets qh POINTSmalloc
-    if qh DELAUNAY 
-      projects points to paraboloid
-      lowbound/highbound is also projected
-    if qh ATinfinity
-      adds point "at-infinity"
-    if qh POINTSmalloc 
-      frees old point array
-
-  notes:
-    checks that qh.hull_dim agrees with qh.input_dim, PROJECTinput, and DELAUNAY
-
-
-  design:
-    sets project[k] to -1 (delete), 0 (keep), 1 (add for Delaunay)
-    determines newdim and newnum for qh hull_dim and qh num_points
-    projects points to newpoints
-    projects qh.lower_bound to itself
-    projects qh.upper_bound to itself
-    if qh DELAUNAY
-      if qh ATINFINITY
-        projects points to paraboloid
-        computes "infinity" point as vertex average and 10% above all points 
-      else
-        uses qh_setdelaunay to project points to paraboloid
-*/
-void qh_projectinput (void) {
-  int k,i;
-  int newdim= qh input_dim, newnum= qh num_points;
-  signed char *project;
-  int size= (qh input_dim+1)*sizeof(*project);
-  pointT *newpoints, *coord, *infinity;
-  realT paraboloid, maxboloid= 0;
-  
-  project= (signed char*)qh_memalloc (size);
-  memset ((char*)project, 0, size);
-  for (k= 0; k < qh input_dim; k++) {   /* skip Delaunay bound */
-    if (qh lower_bound[k] == 0 && qh upper_bound[k] == 0) {
-      project[k]= -1;
-      newdim--;
-    }
-  }
-  if (qh DELAUNAY) {
-    project[k]= 1;
-    newdim++;
-    if (qh ATinfinity)
-      newnum++;
-  }
-  if (newdim != qh hull_dim) {
-    fprintf(qh ferr, "qhull internal error (qh_projectinput): dimension after projection %d != hull_dim %d\n", newdim, qh hull_dim);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  if (!(newpoints=(coordT*)malloc(newnum*newdim*sizeof(coordT)))){
-    fprintf(qh ferr, "qhull error: insufficient memory to project %d points\n",
-           qh num_points);
-    qh_errexit(qh_ERRmem, NULL, NULL);
-  }
-  qh_projectpoints (project, qh input_dim+1, qh first_point,
-                    qh num_points, qh input_dim, newpoints, newdim);
-  trace1((qh ferr, "qh_projectinput: updating lower and upper_bound\n"));
-  qh_projectpoints (project, qh input_dim+1, qh lower_bound,
-                    1, qh input_dim+1, qh lower_bound, newdim+1);
-  qh_projectpoints (project, qh input_dim+1, qh upper_bound,
-                    1, qh input_dim+1, qh upper_bound, newdim+1);
-  if (qh HALFspace) {
-    if (!qh feasible_point) {
-      fprintf(qh ferr, "qhull internal error (qh_projectinput): HALFspace defined without qh.feasible_point\n");
-      qh_errexit(qh_ERRqhull, NULL, NULL);
-    }
-    qh_projectpoints (project, qh input_dim, qh feasible_point,
-		      1, qh input_dim, qh feasible_point, newdim);
-  }
-  qh_memfree(project, ((qh input_dim+1)*sizeof(*project)));
-  if (qh POINTSmalloc)
-    free (qh first_point);
-  qh first_point= newpoints;
-  qh POINTSmalloc= True;
-  if (qh DELAUNAY && qh ATinfinity) {
-    coord= qh first_point;
-    infinity= qh first_point + qh hull_dim * qh num_points;
-    for (k=qh hull_dim-1; k--; )
-      infinity[k]= 0.0;
-    for (i=qh num_points; i--; ) {
-      paraboloid= 0.0;
-      for (k=qh hull_dim-1; k--; ) {
-        paraboloid += *coord * *coord;
-	infinity[k] += *coord;
-        coord++;
-      }
-      *(coord++)= paraboloid;
-      maximize_(maxboloid, paraboloid);
-    }
-    /* coord == infinity */
-    for (k=qh hull_dim-1; k--; )
-      *(coord++) /= qh num_points;
-    *(coord++)= maxboloid * 1.1;
-    qh num_points++;
-    trace0((qh ferr, "qh_projectinput: projected points to paraboloid for Delaunay\n"));
-  }else if (qh DELAUNAY)  /* !qh ATinfinity */
-    qh_setdelaunay( qh hull_dim, qh num_points, qh first_point);
-} /* projectinput */
-
-  
-/*---------------------------------
-  
-  qh_projectpoints( project, n, points, numpoints, dim, newpoints, newdim )
-    project points/numpoints/dim to newpoints/newdim
-    if project[k] == -1
-      delete dimension k 
-    if project[k] == 1 
-      add dimension k by duplicating previous column
-    n is size of project
-
-  notes:
-    newpoints may be points if only adding dimension at end
-
-  design:
-    check that 'project' and 'newdim' agree
-    for each dimension
-      if project == -1
-        skip dimension
-      else
-        determine start of column in newpoints
-        determine start of column in points 
-          if project == +1, duplicate previous column
-        copy dimension (column) from points to newpoints
-*/
-void qh_projectpoints (signed char *project, int n, realT *points, 
-        int numpoints, int dim, realT *newpoints, int newdim) {
-  int testdim= dim, oldk=0, newk=0, i,j=0,k;
-  realT *newp, *oldp;
-  
-  for (k= 0; k < n; k++)
-    testdim += project[k];
-  if (testdim != newdim) {
-    fprintf (qh ferr, "qhull internal error (qh_projectpoints): newdim %d should be %d after projection\n",
-      newdim, testdim);
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-  for (j= 0; j= dim)
-	  continue;
-	oldp= points+oldk;
-      }else 
-	oldp= points+oldk++;
-      for (i=numpoints; i--; ) {
-        *newp= *oldp;
-        newp += newdim;
-        oldp += dim;
-      }
-    }
-    if (oldk >= dim)
-      break;
-  }
-  trace1((qh ferr, "qh_projectpoints: projected %d points from dim %d to dim %d\n", 
-    numpoints, dim, newdim));
-} /* projectpoints */
-        
-
-/*---------------------------------
-  
-  qh_rand() 
-  qh_srand( seed )
-    generate pseudo-random number between 1 and 2^31 -2
-
-  notes:
-    from Park & Miller's minimimal standard random number generator
-       Communications of the ACM, 31:1192-1201, 1988.
-    does not use 0 or 2^31 -1
-       this is silently enforced by qh_srand()
-    can make 'Rn' much faster by moving qh_rand to qh_distplane
-*/
-int qh_rand_seed= 1;  /* define as global variable instead of using qh */
-
-int qh_rand( void) {
-#define qh_rand_a 16807
-#define qh_rand_m 2147483647
-#define qh_rand_q 127773  /* m div a */
-#define qh_rand_r 2836    /* m mod a */
-  int lo, hi, test;
-  int seed = qh_rand_seed;
-
-  hi = seed / qh_rand_q;  /* seed div q */
-  lo = seed % qh_rand_q;  /* seed mod q */
-  test = qh_rand_a * lo - qh_rand_r * hi;
-  if (test > 0)
-    seed= test;
-  else
-    seed= test + qh_rand_m;
-  qh_rand_seed= seed;
-  /* seed = seed < qh_RANDOMmax/2 ? 0 : qh_RANDOMmax;  for testing */
-  /* seed = qh_RANDOMmax;  for testing */
-  return seed;
-} /* rand */
-
-void qh_srand( int seed) {
-  if (seed < 1)
-    qh_rand_seed= 1;
-  else if (seed >= qh_rand_m)
-    qh_rand_seed= qh_rand_m - 1;
-  else
-    qh_rand_seed= seed;
-} /* qh_srand */
-
-/*---------------------------------
-  
-  qh_randomfactor()
-    return a random factor within qh.RANDOMmax of 1.0
-
-  notes:
-    qh.RANDOMa/b are defined in global.c
-*/
-realT qh_randomfactor (void) {
-  realT randr;
-
-  randr= qh_RANDOMint;
-  return randr * qh RANDOMa + qh RANDOMb;
-} /* randomfactor */
-
-/*---------------------------------
-  
-  qh_randommatrix( buffer, dim, rows )
-    generate a random dim X dim matrix in range [-1,1]
-    assumes buffer is [dim+1, dim]
-
-  returns:
-    sets buffer to random numbers
-    sets rows to rows of buffer
-      sets row[dim] as scratch row
-*/
-void qh_randommatrix (realT *buffer, int dim, realT **rows) {
-  int i, k;
-  realT **rowi, *coord, realr;
-
-  coord= buffer;
-  rowi= rows;
-  for (i=0; i < dim; i++) {
-    *(rowi++)= coord;
-    for (k=0; k < dim; k++) {
-      realr= qh_RANDOMint;
-      *(coord++)= 2.0 * realr/(qh_RANDOMmax+1) - 1.0;
-    }
-  }
-  *rowi= coord;
-} /* randommatrix */
-
-        
-/*---------------------------------
-  
-  qh_rotateinput( rows )
-    rotate input using row matrix
-    input points given by qh first_point, num_points, hull_dim
-    assumes rows[dim] is a scratch buffer
-    if qh POINTSmalloc, overwrites input points, else mallocs a new array
-
-  returns:
-    rotated input
-    sets qh POINTSmalloc
-
-  design:
-    see qh_rotatepoints
-*/
-void qh_rotateinput (realT **rows) {
-
-  if (!qh POINTSmalloc) {
-    qh first_point= qh_copypoints (qh first_point, qh num_points, qh hull_dim);
-    qh POINTSmalloc= True;
-  }
-  qh_rotatepoints (qh first_point, qh num_points, qh hull_dim, rows);
-}  /* rotateinput */
-
-/*---------------------------------
-  
-  qh_rotatepoints( points, numpoints, dim, row )
-    rotate numpoints points by a d-dim row matrix
-    assumes rows[dim] is a scratch buffer
-
-  returns:
-    rotated points in place
-
-  design:
-    for each point
-      for each coordinate
-        use row[dim] to compute partial inner product
-      for each coordinate
-        rotate by partial inner product
-*/
-void qh_rotatepoints (realT *points, int numpoints, int dim, realT **row) {
-  realT *point, *rowi, *coord= NULL, sum, *newval;
-  int i,j,k;
-
-  if (qh IStracing >= 1)
-    qh_printmatrix (qh ferr, "qh_rotatepoints: rotate points by", row, dim, dim);
-  for (point= points, j= numpoints; j--; point += dim) {
-    newval= row[dim];
-    for (i= 0; i < dim; i++) {
-      rowi= row[i];
-      coord= point;
-      for (sum= 0.0, k= dim; k--; )
-        sum += *rowi++ * *coord++;
-      *(newval++)= sum;
-    }
-    for (k= dim; k--; )
-      *(--coord)= *(--newval);
-  }
-} /* rotatepoints */  
-  
-
-/*---------------------------------
-  
-  qh_scaleinput()
-    scale input points using qh low_bound/high_bound
-    input points given by qh first_point, num_points, hull_dim
-    if qh POINTSmalloc, overwrites input points, else mallocs a new array
-
-  returns:
-    scales coordinates of points to low_bound[k], high_bound[k]
-    sets qh POINTSmalloc
-
-  design:
-    see qh_scalepoints
-*/
-void qh_scaleinput (void) {
-
-  if (!qh POINTSmalloc) {
-    qh first_point= qh_copypoints (qh first_point, qh num_points, qh hull_dim);
-    qh POINTSmalloc= True;
-  }
-  qh_scalepoints (qh first_point, qh num_points, qh hull_dim,
-       qh lower_bound, qh upper_bound);
-}  /* scaleinput */
-  
-/*---------------------------------
-  
-  qh_scalelast( points, numpoints, dim, low, high, newhigh )
-    scale last coordinate to [0,m] for Delaunay triangulations
-    input points given by points, numpoints, dim
-
-  returns:
-    changes scale of last coordinate from [low, high] to [0, newhigh]
-    overwrites last coordinate of each point
-    saves low/high/newhigh in qh.last_low, etc. for qh_setdelaunay()
-
-  notes:
-    when called by qh_setdelaunay, low/high may not match actual data
-    
-  design:
-    compute scale and shift factors
-    apply to last coordinate of each point
-*/
-void qh_scalelast (coordT *points, int numpoints, int dim, coordT low,
-		   coordT high, coordT newhigh) {
-  realT scale, shift;
-  coordT *coord;
-  int i;
-  boolT nearzero= False;
-
-  trace4((qh ferr, "qh_scalelast: scale last coordinate from [%2.2g, %2.2g] to [0,%2.2g]\n",
-    low, high, newhigh));
-  qh last_low= low;
-  qh last_high= high;
-  qh last_newhigh= newhigh;
-  scale= qh_divzero (newhigh, high - low,
-                  qh MINdenom_1, &nearzero);
-  if (nearzero) {
-    if (qh DELAUNAY)
-      fprintf (qh ferr, "qhull input error: can not scale last coordinate.  Input is cocircular\n   or cospherical.   Use option 'Qz' to add a point at infinity.\n");
-    else
-      fprintf (qh ferr, "qhull input error: can not scale last coordinate.  New bounds [0, %2.2g] are too wide for\nexisting bounds [%2.2g, %2.2g] (width %2.2g)\n",
-		newhigh, low, high, high-low);
-    qh_errexit (qh_ERRinput, NULL, NULL);
-  }
-  shift= - low * newhigh / (high-low);
-  coord= points + dim - 1;
-  for (i= numpoints; i--; coord += dim)
-    *coord= *coord * scale + shift;
-} /* scalelast */
-
-/*---------------------------------
-  
-  qh_scalepoints( points, numpoints, dim, newlows, newhighs )
-    scale points to new lowbound and highbound
-    retains old bound when newlow= -REALmax or newhigh= +REALmax
-
-  returns:
-    scaled points
-    overwrites old points
-
-  design:
-    for each coordinate
-      compute current low and high bound
-      compute scale and shift factors
-      scale all points
-      enforce new low and high bound for all points
-*/
-void qh_scalepoints (pointT *points, int numpoints, int dim,
-	realT *newlows, realT *newhighs) {
-  int i,k;
-  realT shift, scale, *coord, low, high, newlow, newhigh, mincoord, maxcoord;
-  boolT nearzero= False;
-     
-  for (k= 0; k < dim; k++) {
-    newhigh= newhighs[k];
-    newlow= newlows[k];
-    if (newhigh > REALmax/2 && newlow < -REALmax/2)
-      continue;
-    low= REALmax;
-    high= -REALmax;
-    for (i= numpoints, coord= points+k; i--; coord += dim) {
-      minimize_(low, *coord);
-      maximize_(high, *coord);
-    }
-    if (newhigh > REALmax/2)
-      newhigh= high;
-    if (newlow < -REALmax/2)
-      newlow= low;
-    if (qh DELAUNAY && k == dim-1 && newhigh < newlow) {
-      fprintf (qh ferr, "qhull input error: 'Qb%d' or 'QB%d' inverts paraboloid since high bound %.2g < low bound %.2g\n",
-	       k, k, newhigh, newlow);
-      qh_errexit (qh_ERRinput, NULL, NULL);
-    }
-    scale= qh_divzero (newhigh - newlow, high - low,
-                  qh MINdenom_1, &nearzero);
-    if (nearzero) {
-      fprintf (qh ferr, "qhull input error: %d'th dimension's new bounds [%2.2g, %2.2g] too wide for\nexisting bounds [%2.2g, %2.2g]\n",
-              k, newlow, newhigh, low, high);
-      qh_errexit (qh_ERRinput, NULL, NULL);
-    }
-    shift= (newlow * high - low * newhigh)/(high-low);
-    coord= points+k;
-    for (i= numpoints; i--; coord += dim)
-      *coord= *coord * scale + shift;
-    coord= points+k;
-    if (newlow < newhigh) {
-      mincoord= newlow;
-      maxcoord= newhigh;
-    }else {
-      mincoord= newhigh;
-      maxcoord= newlow;
-    }
-    for (i= numpoints; i--; coord += dim) {
-      minimize_(*coord, maxcoord);  /* because of roundoff error */
-      maximize_(*coord, mincoord);
-    }
-    trace0((qh ferr, "qh_scalepoints: scaled %d'th coordinate [%2.2g, %2.2g] to [%.2g, %.2g] for %d points by %2.2g and shifted %2.2g\n",
-      k, low, high, newlow, newhigh, numpoints, scale, shift));
-  }
-} /* scalepoints */    
-
-       
-/*---------------------------------
-  
-  qh_setdelaunay( dim, count, points )
-    project count points to dim-d paraboloid for Delaunay triangulation
-    
-    dim is one more than the dimension of the input set
-    assumes dim is at least 3 (i.e., at least a 2-d Delaunay triangulation)
-
-    points is a dim*count realT array.  The first dim-1 coordinates
-    are the coordinates of the first input point.  array[dim] is
-    the first coordinate of the second input point.  array[2*dim] is
-    the first coordinate of the third input point.
-
-    if qh.last_low defined (i.e., 'Qbb' called qh_scalelast)
-      calls qh_scalelast to scale the last coordinate the same as the other points
-
-  returns:
-    for each point
-      sets point[dim-1] to sum of squares of coordinates
-    scale points to 'Qbb' if needed
-      
-  notes:
-    to project one point, use
-      qh_setdelaunay (qh hull_dim, 1, point)
-      
-    Do not use options 'Qbk', 'QBk', or 'QbB' since they scale 
-    the coordinates after the original projection.
-
-*/
-void qh_setdelaunay (int dim, int count, pointT *points) {
-  int i, k;
-  coordT *coordp, coord;
-  realT paraboloid;
-
-  trace0((qh ferr, "qh_setdelaunay: project %d points to paraboloid for Delaunay triangulation\n", count));
-  coordp= points;
-  for (i= 0; i < count; i++) {
-    coord= *coordp++;
-    paraboloid= coord*coord;
-    for (k= dim-2; k--; ) {
-      coord= *coordp++;
-      paraboloid += coord*coord;
-    }
-    *coordp++ = paraboloid;
-  }
-  if (qh last_low < REALmax/2) 
-    qh_scalelast (points, count, dim, qh last_low, qh last_high, qh last_newhigh);
-} /* setdelaunay */
-
-  
-/*---------------------------------
-  
-  qh_sethalfspace( dim, coords, nextp, normal, offset, feasible )
-    set point to dual of halfspace relative to feasible point
-    halfspace is normal coefficients and offset.
-
-  returns:
-    false if feasible point is outside of hull (error message already reported)
-    overwrites coordinates for point at dim coords
-    nextp= next point (coords)
-
-  design:
-    compute distance from feasible point to halfspace
-    divide each normal coefficient by -dist
-*/
-boolT qh_sethalfspace (int dim, coordT *coords, coordT **nextp, 
-         coordT *normal, coordT *offset, coordT *feasible) {
-  coordT *normp= normal, *feasiblep= feasible, *coordp= coords;
-  realT dist;
-  realT r; /*bug fix*/
-  int k;
-  boolT zerodiv;
-
-  dist= *offset;
-  for (k= dim; k--; )
-    dist += *(normp++) * *(feasiblep++);
-  if (dist > 0)
-    goto LABELerroroutside;
-  normp= normal;
-  if (dist < -qh MINdenom) {
-    for (k= dim; k--; )
-      *(coordp++)= *(normp++) / -dist;
-  }else {
-    for (k= dim; k--; ) {
-      *(coordp++)= qh_divzero (*(normp++), -dist, qh MINdenom_1, &zerodiv);
-      if (zerodiv) 
-        goto LABELerroroutside;
-    }
-  }
-  *nextp= coordp;
-  if (qh IStracing >= 4) {
-    fprintf (qh ferr, "qh_sethalfspace: halfspace at offset %6.2g to point: ", *offset);
-    for (k= dim, coordp= coords; k--; ) {
-      r= *coordp++;
-      fprintf (qh ferr, " %6.2g", r);
-    }
-    fprintf (qh ferr, "\n");
-  }
-  return True;
-LABELerroroutside:
-  feasiblep= feasible;
-  normp= normal;
-  fprintf(qh ferr, "qhull input error: feasible point is not clearly inside halfspace\nfeasible point: ");
-  for (k= dim; k--; )
-    fprintf (qh ferr, qh_REAL_1, r=*(feasiblep++));
-  fprintf (qh ferr, "\n     halfspace: "); 
-  for (k= dim; k--; )
-    fprintf (qh ferr, qh_REAL_1, r=*(normp++));
-  fprintf (qh ferr, "\n     at offset: ");
-  fprintf (qh ferr, qh_REAL_1, *offset);
-  fprintf (qh ferr, " and distance: ");
-  fprintf (qh ferr, qh_REAL_1, dist);
-  fprintf (qh ferr, "\n");
-  return False;
-} /* sethalfspace */
-
-/*---------------------------------
-  
-  qh_sethalfspace_all( dim, count, halfspaces, feasible )
-    generate dual for halfspace intersection with feasible point
-    array of count halfspaces
-      each halfspace is normal coefficients followed by offset 
-      the origin is inside the halfspace if the offset is negative
-
-  returns:
-    malloc'd array of count X dim-1 points
-
-  notes:
-    call before qh_init_B or qh_initqhull_globals 
-    unused/untested code: please email bradb@shore.net if this works ok for you
-    If using option 'Fp', also set qh feasible_point. It is a malloc'd array 
-      that is freed by qh_freebuffers.
-
-  design:
-    see qh_sethalfspace
-*/
-coordT *qh_sethalfspace_all (int dim, int count, coordT *halfspaces, pointT *feasible) {
-  int i, newdim;
-  pointT *newpoints;
-  coordT *coordp, *normalp, *offsetp;
-
-  trace0((qh ferr, "qh_sethalfspace_all: compute dual for halfspace intersection\n"));
-  newdim= dim - 1;
-  if (!(newpoints=(coordT*)malloc(count*newdim*sizeof(coordT)))){
-    fprintf(qh ferr, "qhull error: insufficient memory to compute dual of %d halfspaces\n",
-          count);
-    qh_errexit(qh_ERRmem, NULL, NULL);
-  }
-  coordp= newpoints;
-  normalp= halfspaces;
-  for (i= 0; i < count; i++) {
-    offsetp= normalp + newdim;
-    if (!qh_sethalfspace (newdim, coordp, &coordp, normalp, offsetp, feasible)) {
-      fprintf (qh ferr, "The halfspace was at index %d\n", i);
-      qh_errexit (qh_ERRinput, NULL, NULL);
-    }
-    normalp= offsetp + 1;
-  }
-  return newpoints;
-} /* sethalfspace_all */
-
-  
-/*---------------------------------
-  
-  qh_sharpnewfacets()
-
-  returns:
-    true if could be an acute angle (facets in different quadrants)
- 
-  notes:
-    for qh_findbest
-
-  design:
-    for all facets on qh.newfacet_list
-      if two facets are in different quadrants
-        set issharp
-*/
-boolT qh_sharpnewfacets () {
-  facetT *facet;
-  boolT issharp = False;
-  int *quadrant, k;
-  
-  quadrant= (int*)qh_memalloc (qh hull_dim * sizeof(int));
-  FORALLfacet_(qh newfacet_list) {
-    if (facet == qh newfacet_list) {
-      for (k= qh hull_dim; k--; )
-      	quadrant[ k]= (facet->normal[ k] > 0);
-    }else {
-      for (k= qh hull_dim; k--; ) {
-        if (quadrant[ k] != (facet->normal[ k] > 0)) {
-          issharp= True;
-          break;
-        }
-      }
-    }
-    if (issharp)
-      break;
-  }
-  qh_memfree( quadrant, qh hull_dim * sizeof(int));
-  trace3((qh ferr, "qh_sharpnewfacets: %d\n", issharp));
-  return issharp;
-} /* sharpnewfacets */
-
-/*---------------------------------
-  
-  qh_voronoi_center( dim, points )
-    return Voronoi center for a set of points
-    dim is the orginal dimension of the points
-    gh.gm_matrix/qh.gm_row are scratch buffers
-
-  returns:
-    center as a temporary point
-    if non-simplicial, 
-      returns center for max simplex of points
-
-  notes:
-    from Bowyer & Woodwark, A Programmer's Geometry, 1983, p. 65
-
-  design:
-    if non-simplicial
-      determine max simplex for points
-    translate point0 of simplex to origin
-    compute sum of squares of diagonal
-    compute determinate
-    compute Voronoi center (see Bowyer & Woodwark)
-*/
-pointT *qh_voronoi_center (int dim, setT *points) {
-  pointT *point, **pointp, *point0;
-  pointT *center= (pointT*)qh_memalloc (qh center_size);
-  setT *simplex;
-  int i, j, k, size= qh_setsize(points);
-  coordT *gmcoord;
-  realT *diffp, sum2, *sum2row, *sum2p, det, factor;
-  boolT nearzero, infinite;
-
-  if (size == dim+1)
-    simplex= points;
-  else if (size < dim+1) {
-    fprintf (qh ferr, "qhull internal error (qh_voronoi_center):\n  need at least %d points to construct a Voronoi center\n",
-	     dim+1);
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }else {
-    simplex= qh_settemp (dim+1);
-    qh_maxsimplex (dim, points, NULL, 0, &simplex);
-  }
-  point0= SETfirstt_(simplex, pointT);
-  gmcoord= qh gm_matrix;
-  for (k=0; k < dim; k++) {
-    qh gm_row[k]= gmcoord;
-    FOREACHpoint_(simplex) {
-      if (point != point0)
-        *(gmcoord++)= point[k] - point0[k];
-    }
-  }
-  sum2row= gmcoord;
-  for (i=0; i < dim; i++) {
-    sum2= 0.0;
-    for (k= 0; k < dim; k++) {
-      diffp= qh gm_row[k] + i;
-      sum2 += *diffp * *diffp;
-    }
-    *(gmcoord++)= sum2;
-  }
-  det= qh_determinant (qh gm_row, dim, &nearzero);
-  factor= qh_divzero (0.5, det, qh MINdenom, &infinite);
-  if (infinite) {
-    for (k=dim; k--; )
-      center[k]= qh_INFINITE;
-    if (qh IStracing)
-      qh_printpoints (qh ferr, "qh_voronoi_center: at infinity for ", simplex);
-  }else {
-    for (i=0; i < dim; i++) {
-      gmcoord= qh gm_matrix;
-      sum2p= sum2row;
-      for (k=0; k < dim; k++) {
-	qh gm_row[k]= gmcoord;
-	if (k == i) {
-	  for (j= dim; j--; )
-	    *(gmcoord++)= *sum2p++;
-	}else {
-	  FOREACHpoint_(simplex) {
-	    if (point != point0)
-	      *(gmcoord++)= point[k] - point0[k];
-	  }
-	}
-      }
-      center[i]= qh_determinant (qh gm_row, dim, &nearzero)*factor + point0[i];
-    }
-#ifndef qh_NOtrace
-    if (qh IStracing >= 3) {
-      fprintf (qh ferr, "qh_voronoi_center: det %2.2g factor %2.2g ", det, factor);
-      qh_printmatrix (qh ferr, "center:", ¢er, 1, dim);
-      if (qh IStracing >= 5) {
-	qh_printpoints (qh ferr, "points", simplex);
-	FOREACHpoint_(simplex)
-	  fprintf (qh ferr, "p%d dist %.2g, ", qh_pointid (point),
-		   qh_pointdist (point, center, dim));
-	fprintf (qh ferr, "\n");
-      }
-    }
-#endif
-  }
-  if (simplex != points)
-    qh_settempfree (&simplex);
-  return center;
-} /* voronoi_center */
-
diff --git a/extern/qhull/src/global.c b/extern/qhull/src/global.c
deleted file mode 100644
index d3e141aa985..00000000000
--- a/extern/qhull/src/global.c
+++ /dev/null
@@ -1,2018 +0,0 @@
-/*
  ---------------------------------
-
-   global.c
-   initializes all the globals of the qhull application
-
-   see README
-
-   see qhull.h for qh.globals and function prototypes
-
-   see qhull_a.h for internal functions
-
-   copyright (c) 1993-2002, The Geometry Center
- */
-
-#include "qhull_a.h"
-
-/*========= qh definition =======================*/
-
-#if qh_QHpointer
-qhT *qh_qh= NULL;	/* pointer to all global variables */
-#else
-qhT qh_qh;     		/* all global variables.
-			   Add "= {0}" if this causes a compiler error.
-			   Also qh_qhstat in stat.c and qhmem in mem.c.  */
-#endif
-
-/*---------------------------------
-
-  qh_appendprint( printFormat )
-    append printFormat to qh.PRINTout unless already defined
-*/
-void qh_appendprint (qh_PRINT format) {
-  int i;
-
-  for (i=0; i < qh_PRINTEND; i++) {
-    if (qh PRINTout[i] == format && format != qh_PRINTqhull)
-      break;
-    if (!qh PRINTout[i]) {
-      qh PRINTout[i]= format;
-      break;
-    }
-  }
-} /* appendprint */
-     
-/*---------------------------------
-  
-  qh_checkflags( commandStr, hiddenFlags )
-    errors if commandStr contains hiddenFlags
-    hiddenFlags starts and ends with a space and is space deliminated (checked)
-
-  notes:
-    ignores first word (e.g., "qconvex i")
-    use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
-  
-  see:
-    qh_initflags() initializes Qhull according to commandStr
-*/
-void qh_checkflags(char *command, char *hiddenflags) {
-  char *s= command, *t, *chkerr, key, opt, prevopt;
-  char chkkey[]= "   ";
-  char chkopt[]=  "    ";
-  char chkopt2[]= "     ";
-
-  if (*hiddenflags != ' ' || hiddenflags[strlen(hiddenflags)-1] != ' ') {
-    fprintf(qh ferr, "qhull error (qh_checkflags): hiddenflags must start and end with a space: \"%s\"", hiddenflags);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (strpbrk(hiddenflags, ",\n\r\t")) { 
-    fprintf(qh ferr, "qhull error (qh_checkflags): hiddenflags contains commas, newlines, or tabs: \"%s\"", hiddenflags);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  while (*s && !isspace(*s))  /* skip program name */
-    s++;
-  while (*s) {
-    while (*s && isspace(*s))
-      s++;
-    if (*s == '-')
-      s++;
-    if (!*s)
-      break;
-    key = *s++;
-    chkerr = NULL;
-    if (key == '\'') {         /* TO 'file name' */
-      t= strchr(s, '\'');
-      if (!t) {
-	fprintf(qh ferr, "qhull error (qh_checkflags): missing the 2nd single-quote for:\n%s\n", s-1);
-	qh_errexit(qh_ERRinput, NULL, NULL);
-      }
-      s= t+1;
-      continue;
-    }
-    chkkey[1]= key;
-    if (strstr(hiddenflags, chkkey)) {
-      chkerr= chkkey;
-    }else if (isupper(key)) {
-      opt= ' ';
-      prevopt= ' ';
-      chkopt[1]= key;
-      chkopt2[1]= key;
-      while (!chkerr && *s && !isspace(*s)) {
-	opt= *s++;
-	if (isalpha(opt)) {
-	  chkopt[2]= opt;
-	  if (strstr(hiddenflags, chkopt))
-	    chkerr= chkopt;
-	  if (prevopt != ' ') {
- 	    chkopt2[2]= prevopt;
- 	    chkopt2[3]= opt;
-	    if (strstr(hiddenflags, chkopt2))
-	      chkerr= chkopt2;
-	  }
-	}else if (key == 'Q' && isdigit(opt) && prevopt != 'b' 
-	      && (prevopt == ' ' || islower(prevopt))) {
-  	    chkopt[2]= opt;
-	    if (strstr(hiddenflags, chkopt))
-	      chkerr= chkopt;
-	}else {
-	  qh_strtod (s-1, &t);
-	  if (s < t)
-	    s= t;
-	}
-        prevopt= opt;
-      }
-    }
-    if (chkerr) {
-      *chkerr= '\'';
-      chkerr[strlen(chkerr)-1]=  '\'';
-      fprintf(qh ferr, "qhull error: option %s is not used with this program.\n             It may be used with qhull.\n", chkerr);
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-  }
-} /* checkflags */
-    
-/*---------------------------------
-  
-  qh_clock()
-    return user CPU time in 100ths (qh_SECtick)
-    only defined for qh_CLOCKtype == 2
-
-  notes:
-    use first value to determine time 0
-    from Stevens '92 8.15
-*/
-unsigned long qh_clock (void) {
-
-#if (qh_CLOCKtype == 2)
-  struct tms time;
-  static long clktck;  /* initialized first call */
-  double ratio, cpu;
-  unsigned long ticks;
-
-  if (!clktck) {
-    if ((clktck= sysconf (_SC_CLK_TCK)) < 0) {
-      fprintf (qh ferr, "qhull internal error (qh_clock): sysconf() failed.  Use qh_CLOCKtype 1 in user.h\n");
-      qh_errexit (qh_ERRqhull, NULL, NULL);
-    }
-  }
-  if (times (&time) == -1) {
-    fprintf (qh ferr, "qhull internal error (qh_clock): times() failed.  Use qh_CLOCKtype 1 in user.h\n");
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-  ratio= qh_SECticks / (double)clktck;
-  ticks= time.tms_utime * ratio;
-  return ticks;
-#else
-  fprintf (qh ferr, "qhull internal error (qh_clock): use qh_CLOCKtype 2 in user.h\n");
-  qh_errexit (qh_ERRqhull, NULL, NULL); /* never returns */
-  return 0;
-#endif
-} /* clock */
-
-/*---------------------------------
-
-  qh_freebuffers()
-    free up global memory buffers
-
-  notes:
-    must match qh_initbuffers()
-*/
-void qh_freebuffers (void) {
-
-  trace5((qh ferr, "qh_freebuffers: freeing up global memory buffers\n"));
-  /* allocated by qh_initqhull_buffers */
-  qh_memfree (qh NEARzero, qh hull_dim * sizeof(realT));
-  qh_memfree (qh lower_threshold, (qh input_dim+1) * sizeof(realT));
-  qh_memfree (qh upper_threshold, (qh input_dim+1) * sizeof(realT));
-  qh_memfree (qh lower_bound, (qh input_dim+1) * sizeof(realT));
-  qh_memfree (qh upper_bound, (qh input_dim+1) * sizeof(realT));
-  qh_memfree (qh gm_matrix, (qh hull_dim+1) * qh hull_dim * sizeof(coordT));
-  qh_memfree (qh gm_row, (qh hull_dim+1) * sizeof(coordT *));
-  qh NEARzero= qh lower_threshold= qh upper_threshold= NULL;
-  qh lower_bound= qh upper_bound= NULL;
-  qh gm_matrix= NULL;
-  qh gm_row= NULL;
-  qh_setfree (&qh other_points);
-  qh_setfree (&qh del_vertices);
-  qh_setfree (&qh coplanarset);
-  if (qh line)                /* allocated by qh_readinput, freed if no error */
-    free (qh line);
-  if (qh half_space)
-    free (qh half_space);
-  if (qh temp_malloc)
-    free (qh temp_malloc);
-  if (qh feasible_point)      /* allocated by qh_readfeasible */
-    free (qh feasible_point);
-  if (qh feasible_string)     /* allocated by qh_initflags */
-    free (qh feasible_string);
-  qh line= qh feasible_string= NULL;
-  qh half_space= qh feasible_point= qh temp_malloc= NULL;
-  /* usually allocated by qh_readinput */
-  if (qh first_point && qh POINTSmalloc) {
-    free(qh first_point);
-    qh first_point= NULL;
-  }
-  if (qh input_points && qh input_malloc) { /* set by qh_joggleinput */
-    free (qh input_points);
-    qh input_points= NULL;
-  }
-  trace5((qh ferr, "qh_freebuffers: finished\n"));
-} /* freebuffers */
-
-
-/*---------------------------------
-
-  qh_freebuild( allmem )
-    free global memory used by qh_initbuild and qh_buildhull
-    if !allmem,
-      does not free short memory (freed by qh_memfreeshort)
-
-  design:
-    free centrums
-    free each vertex
-    mark unattached ridges
-    for each facet
-      free ridges
-      free outside set, coplanar set, neighbor set, ridge set, vertex set
-      free facet
-    free hash table
-    free interior point
-    free merge set
-    free temporary sets
-*/
-void qh_freebuild (boolT allmem) {
-  facetT *facet;
-  vertexT *vertex;
-  ridgeT *ridge, **ridgep;
-  mergeT *merge, **mergep;
-
-  trace1((qh ferr, "qh_freebuild: free memory from qh_inithull and qh_buildhull\n"));
-  if (qh del_vertices)
-    qh_settruncate (qh del_vertices, 0);
-  if (allmem) {
-    qh_clearcenters (qh_ASnone);
-    while ((vertex= qh vertex_list)) {
-      if (vertex->next)
-        qh_delvertex (vertex);
-      else {
-        qh_memfree (vertex, sizeof(vertexT));
-        qh newvertex_list= qh vertex_list= NULL;
-      }
-    }
-  }else if (qh VERTEXneighbors) {
-    FORALLvertices
-      qh_setfreelong (&(vertex->neighbors));
-  }
-  qh VERTEXneighbors= False;
-  qh GOODclosest= NULL;
-  if (allmem) {
-    FORALLfacets {
-      FOREACHridge_(facet->ridges)
-        ridge->seen= False;
-    }
-    FORALLfacets {
-      if (facet->visible) {
-	FOREACHridge_(facet->ridges) {
-	  if (!otherfacet_(ridge, facet)->visible)
-	    ridge->seen= True;  /* an unattached ridge */
-	}
-      }
-    }
-    while ((facet= qh facet_list)) {
-      FOREACHridge_(facet->ridges) {
-        if (ridge->seen) {
-          qh_setfree(&(ridge->vertices));
-          qh_memfree(ridge, sizeof(ridgeT));
-        }else
-          ridge->seen= True;
-      }
-      qh_setfree (&(facet->outsideset));
-      qh_setfree (&(facet->coplanarset));
-      qh_setfree (&(facet->neighbors));
-      qh_setfree (&(facet->ridges));
-      qh_setfree (&(facet->vertices));
-      if (facet->next)
-        qh_delfacet (facet);
-      else {
-        qh_memfree (facet, sizeof(facetT));
-        qh visible_list= qh newfacet_list= qh facet_list= NULL;
-      }
-    }
-  }else {
-    FORALLfacets {
-      qh_setfreelong (&(facet->outsideset));
-      qh_setfreelong (&(facet->coplanarset));
-      if (!facet->simplicial) {
-        qh_setfreelong (&(facet->neighbors));
-        qh_setfreelong (&(facet->ridges));
-        qh_setfreelong (&(facet->vertices));
-      }
-    }
-  }
-  qh_setfree (&(qh hash_table));
-  qh_memfree (qh interior_point, qh normal_size);
-  qh interior_point= NULL;
-  FOREACHmerge_(qh facet_mergeset)  /* usually empty */
-    qh_memfree (merge, sizeof(mergeT));
-  qh facet_mergeset= NULL;  /* temp set */
-  qh degen_mergeset= NULL;  /* temp set */
-  qh_settempfree_all();
-} /* freebuild */
-
-/*---------------------------------
-
-  qh_freeqhull( allmem )
-    free global memory
-    if !allmem,
-      does not free short memory (freed by qh_memfreeshort)
-
-  notes:
-    sets qh.NOerrexit in case caller forgets to
-
-  design:
-    free global and temporary memory from qh_initbuild and qh_buildhull
-    free buffers
-    free statistics
-*/
-void qh_freeqhull (boolT allmem) {
-
-  trace1((qh ferr, "qh_freeqhull: free global memory\n"));
-  qh NOerrexit= True;  /* no more setjmp since called at exit */
-  qh_freebuild (allmem);
-  qh_freebuffers();
-  qh_freestatistics();
-#if qh_QHpointer
-  free (qh_qh);
-  qh_qh= NULL;
-#else
-  memset((char *)&qh_qh, 0, sizeof(qhT));
-  qh NOerrexit= True;
-#endif
-} /* freeqhull */
-
-/*---------------------------------
-
-  qh_init_A( infile, outfile, errfile, argc, argv )
-    initialize memory and stdio files
-    convert input options to option string (qh.qhull_command)
-
-  notes:
-    infile may be NULL if qh_readpoints() is not called
-
-    errfile should always be defined.  It is used for reporting
-    errors.  outfile is used for output and format options.
-
-    argc/argv may be 0/NULL
-
-    called before error handling initialized
-    qh_errexit() may not be used
-*/
-void qh_init_A (FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]) {
-  qh_meminit (errfile);
-  qh_initqhull_start (infile, outfile, errfile);
-  qh_init_qhull_command (argc, argv);
-} /* init_A */
-
-/*---------------------------------
-
-  qh_init_B( points, numpoints, dim, ismalloc )
-    initialize globals for points array
-
-    points has numpoints dim-dimensional points
-      points[0] is the first coordinate of the first point
-      points[1] is the second coordinate of the first point
-      points[dim] is the first coordinate of the second point
-
-    ismalloc=True
-      Qhull will call free(points) on exit or input transformation
-    ismalloc=False
-      Qhull will allocate a new point array if needed for input transformation
-
-    qh.qhull_command
-      is the option string.
-      It is defined by qh_init_B(), qh_qhull_command(), or qh_initflags
-
-  returns:
-    if qh.PROJECTinput or (qh.DELAUNAY and qh.PROJECTdelaunay)
-      projects the input to a new point array
-
-        if qh.DELAUNAY,
-          qh.hull_dim is increased by one
-        if qh.ATinfinity,
-          qh_projectinput adds point-at-infinity for Delaunay tri.
-
-    if qh.SCALEinput
-      changes the upper and lower bounds of the input, see qh_scaleinput()
-
-    if qh.ROTATEinput
-      rotates the input by a random rotation, see qh_rotateinput()
-      if qh.DELAUNAY
-        rotates about the last coordinate
-
-  notes:
-    called after points are defined
-    qh_errexit() may be used
-*/
-void qh_init_B (coordT *points, int numpoints, int dim, boolT ismalloc) {
-  qh_initqhull_globals (points, numpoints, dim, ismalloc);
-  if (qhmem.LASTsize == 0)
-    qh_initqhull_mem();
-  /* mem.c and qset.c are initialized */
-  qh_initqhull_buffers();
-  qh_initthresholds (qh qhull_command);
-  if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay))
-    qh_projectinput();
-  if (qh SCALEinput)
-    qh_scaleinput();
-  if (qh ROTATErandom >= 0) {
-    qh_randommatrix (qh gm_matrix, qh hull_dim, qh gm_row);
-    if (qh DELAUNAY) {
-      int k, lastk= qh hull_dim-1;
-      for (k= 0; k < lastk; k++) {
-        qh gm_row[k][lastk]= 0.0;
-        qh gm_row[lastk][k]= 0.0;
-      }
-      qh gm_row[lastk][lastk]= 1.0;
-    }
-    qh_gram_schmidt (qh hull_dim, qh gm_row);
-    qh_rotateinput (qh gm_row);
-  }
-} /* init_B */
-
-/*---------------------------------
-
-  qh_init_qhull_command( argc, argv )
-    build qh.qhull_command from argc/argv
-
-  returns:
-    a space-deliminated string of options (just as typed)
-
-  notes:
-    makes option string easy to input and output
-
-    argc/argv may be 0/NULL
-*/
-void qh_init_qhull_command(int argc, char *argv[]) {
-  int i;
-  char *s;
-
-  if (argc) {
-    if ((s= strrchr( argv[0], '\\'))) /* Borland gives full path */
-      strcpy (qh qhull_command, s+1);
-    else
-      strcpy (qh qhull_command, argv[0]);
-    if ((s= strstr (qh qhull_command, ".EXE"))
-    ||  (s= strstr (qh qhull_command, ".exe")))
-      *s= '\0';
-  }
-  for (i=1; i < argc; i++) {
-    if (strlen (qh qhull_command) + strlen(argv[i]) + 1 < sizeof(qh qhull_command)) {
-      strcat (qh qhull_command, " ");
-      strcat (qh qhull_command, argv[i]);
-    }else {
-      fprintf (qh ferr, "qhull input error: more than %d characters in command line\n",
-        (int)sizeof(qh qhull_command));
-      exit (1);  /* can not use qh_errexit */
-    }
-  }
-} /* init_qhull_command */
-
-/*---------------------------------
-
-  qh_initflags( commandStr )
-    set flags and initialized constants from commandStr
-
-  returns:
-    sets qh.qhull_command to command if needed
-
-  notes:
-    ignores first word (e.g., "qhull d")
-    use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
-
-  see:
-    qh_initthresholds() continues processing of 'Pdn' and 'PDn'
-    'prompt' in unix.c for documentation
-
-  design:
-    for each space-deliminated option group
-      if top-level option
-        check syntax
-        append approriate option to option string
-        set appropriate global variable or append printFormat to print options
-      else
-        for each sub-option
-          check syntax
-          append approriate option to option string
-          set appropriate global variable or append printFormat to print options
-
-
-*/
-void qh_initflags(char *command) {
-  int k, i, lastproject;
-  char *s= command, *t, *prev_s, *start, key;
-  boolT isgeom= False, wasproject;
-  realT r;
-
-  if (command != &qh qhull_command[0]) {
-    *qh qhull_command= '\0';
-    strncat( qh qhull_command, command, sizeof( qh qhull_command));
-  }
-  while (*s && !isspace(*s))  /* skip program name */
-    s++;
-  while (*s) {
-    while (*s && isspace(*s))
-      s++;
-    if (*s == '-')
-      s++;
-    if (!*s)
-      break;
-    prev_s= s;
-    switch (*s++) {
-    case 'd':
-      qh_option ("delaunay", NULL, NULL);
-      qh DELAUNAY= True;
-      break;
-    case 'f':
-      qh_option ("facets", NULL, NULL);
-      qh_appendprint (qh_PRINTfacets);
-      break;
-    case 'i':
-      qh_option ("incidence", NULL, NULL);
-      qh_appendprint (qh_PRINTincidences);
-      break;
-    case 'm':
-      qh_option ("mathematica", NULL, NULL);
-      qh_appendprint (qh_PRINTmathematica);
-      break;
-    case 'n':
-      qh_option ("normals", NULL, NULL);
-      qh_appendprint (qh_PRINTnormals);
-      break;
-    case 'o':
-      qh_option ("offFile", NULL, NULL);
-      qh_appendprint (qh_PRINToff);
-      break;
-    case 'p':
-      qh_option ("points", NULL, NULL);
-      qh_appendprint (qh_PRINTpoints);
-      break;
-    case 's':
-      qh_option ("summary", NULL, NULL);
-      qh PRINTsummary= True;
-      break;
-    case 'v':
-      qh_option ("voronoi", NULL, NULL);
-      qh VORONOI= True;
-      qh DELAUNAY= True;
-      break;
-    case 'A':
-      if (!isdigit(*s) && *s != '.' && *s != '-')
-	fprintf(qh ferr, "qhull warning: no maximum cosine angle given for option 'An'.  Ignored.\n");
-      else {
-	if (*s == '-') {
-	  qh premerge_cos= -qh_strtod (s, &s);
-          qh_option ("Angle-premerge-", NULL, &qh premerge_cos);
-	  qh PREmerge= True;
-	}else {
-	  qh postmerge_cos= qh_strtod (s, &s);
-          qh_option ("Angle-postmerge", NULL, &qh postmerge_cos);
-	  qh POSTmerge= True;
-	}
-	qh MERGING= True;
-      }
-      break;
-    case 'C':
-      if (!isdigit(*s) && *s != '.' && *s != '-')
-	fprintf(qh ferr, "qhull warning: no centrum radius given for option 'Cn'.  Ignored.\n");
-      else {
-	if (*s == '-') {
-	  qh premerge_centrum= -qh_strtod (s, &s);
-          qh_option ("Centrum-premerge-", NULL, &qh premerge_centrum);
-	  qh PREmerge= True;
-	}else {
-	  qh postmerge_centrum= qh_strtod (s, &s);
-          qh_option ("Centrum-postmerge", NULL, &qh postmerge_centrum);
-	  qh POSTmerge= True;
-	}
-	qh MERGING= True;
-      }
-      break;
-    case 'E':
-      if (*s == '-')
-	fprintf(qh ferr, "qhull warning: negative maximum roundoff given for option 'An'.  Ignored.\n");
-      else if (!isdigit(*s))
-	fprintf(qh ferr, "qhull warning: no maximum roundoff given for option 'En'.  Ignored.\n");
-      else {
-	qh DISTround= qh_strtod (s, &s);
-        qh_option ("Distance-roundoff", NULL, &qh DISTround);
-	qh SETroundoff= True;
-      }
-      break;
-    case 'H':
-      start= s;
-      qh HALFspace= True;
-      qh_strtod (s, &t);
-      while (t > s)  {
-        if (*t && !isspace (*t)) {
-	  if (*t == ',')
-	    t++;
-	  else
-	    fprintf (qh ferr, "qhull warning: origin for Halfspace intersection should be 'Hn,n,n,...'\n");
-	}
-        s= t;
-	qh_strtod (s, &t);
-      }
-      if (start < t) {
-        if (!(qh feasible_string= (char*)calloc (t-start+1, 1))) {
-          fprintf(qh ferr, "qhull error: insufficient memory for 'Hn,n,n'\n");
-          qh_errexit(qh_ERRmem, NULL, NULL);
-        }
-        strncpy (qh feasible_string, start, t-start);
-        qh_option ("Halfspace-about", NULL, NULL);
-        qh_option (qh feasible_string, NULL, NULL);
-      }else
-        qh_option ("Halfspace", NULL, NULL);
-      break;
-    case 'R':
-      if (!isdigit(*s))
-	fprintf(qh ferr, "qhull warning: missing random perturbation for option 'Rn'.  Ignored\n");
-      else {
-	qh RANDOMfactor= qh_strtod (s, &s);
-        qh_option ("Random_perturb", NULL, &qh RANDOMfactor);
-        qh RANDOMdist= True;
-      }
-      break;
-    case 'V':
-      if (!isdigit(*s) && *s != '-')
-	fprintf(qh ferr, "qhull warning: missing visible distance for option 'Vn'.  Ignored\n");
-      else {
-	qh MINvisible= qh_strtod (s, &s);
-        qh_option ("Visible", NULL, &qh MINvisible);
-      }
-      break;
-    case 'U':
-      if (!isdigit(*s) && *s != '-')
-	fprintf(qh ferr, "qhull warning: missing coplanar distance for option 'Un'.  Ignored\n");
-      else {
-	qh MAXcoplanar= qh_strtod (s, &s);
-        qh_option ("U-coplanar", NULL, &qh MAXcoplanar);
-      }
-      break;
-    case 'W':
-      if (*s == '-')
-	fprintf(qh ferr, "qhull warning: negative outside width for option 'Wn'.  Ignored.\n");
-      else if (!isdigit(*s))
-	fprintf(qh ferr, "qhull warning: missing outside width for option 'Wn'.  Ignored\n");
-      else {
-	qh MINoutside= qh_strtod (s, &s);
-        qh_option ("W-outside", NULL, &qh MINoutside);
-        qh APPROXhull= True;
-      }
-      break;
-    /************  sub menus ***************/
-    case 'F':
-      while (*s && !isspace(*s)) {
-	switch(*s++) {
-	case 'a':
-	  qh_option ("Farea", NULL, NULL);
-	  qh_appendprint (qh_PRINTarea);
-	  qh GETarea= True;
-	  break;
-	case 'A':
-	  qh_option ("FArea-total", NULL, NULL);
-	  qh GETarea= True;
-	  break;
-        case 'c':
-          qh_option ("Fcoplanars", NULL, NULL);
-          qh_appendprint (qh_PRINTcoplanars);
-          break;
-        case 'C':
-          qh_option ("FCentrums", NULL, NULL);
-          qh_appendprint (qh_PRINTcentrums);
-          break;
-	case 'd':
-          qh_option ("Fd-cdd-in", NULL, NULL);
-	  qh CDDinput= True;
-	  break;
-	case 'D':
-          qh_option ("FD-cdd-out", NULL, NULL);
-	  qh CDDoutput= True;
-	  break;
-	case 'F':
-	  qh_option ("FFacets-xridge", NULL, NULL);
-          qh_appendprint (qh_PRINTfacets_xridge);
-	  break;
-        case 'i':
-          qh_option ("Finner", NULL, NULL);
-          qh_appendprint (qh_PRINTinner);
-          break;
-        case 'I':
-          qh_option ("FIDs", NULL, NULL);
-          qh_appendprint (qh_PRINTids);
-          break;
-        case 'm':
-          qh_option ("Fmerges", NULL, NULL);
-          qh_appendprint (qh_PRINTmerges);
-          break;
-        case 'n':
-          qh_option ("Fneighbors", NULL, NULL);
-          qh_appendprint (qh_PRINTneighbors);
-          break;
-        case 'N':
-          qh_option ("FNeighbors-vertex", NULL, NULL);
-          qh_appendprint (qh_PRINTvneighbors);
-          break;
-        case 'o':
-          qh_option ("Fouter", NULL, NULL);
-          qh_appendprint (qh_PRINTouter);
-          break;
-	case 'O':
-	  if (qh PRINToptions1st) {
-	    qh_option ("FOptions", NULL, NULL);
-	    qh_appendprint (qh_PRINToptions);
-	  }else
-	    qh PRINToptions1st= True;
-	  break;
-	case 'p':
-	  qh_option ("Fpoint-intersect", NULL, NULL);
-	  qh_appendprint (qh_PRINTpointintersect);
-	  break;
-	case 'P':
-	  qh_option ("FPoint-nearest", NULL, NULL);
-	  qh_appendprint (qh_PRINTpointnearest);
-	  break;
-	case 'Q':
-	  qh_option ("FQhull", NULL, NULL);
-	  qh_appendprint (qh_PRINTqhull);
-	  break;
-        case 's':
-          qh_option ("Fsummary", NULL, NULL);
-          qh_appendprint (qh_PRINTsummary);
-          break;
-        case 'S':
-          qh_option ("FSize", NULL, NULL);
-          qh_appendprint (qh_PRINTsize);
-          qh GETarea= True;
-          break;
-        case 't':
-          qh_option ("Ftriangles", NULL, NULL);
-          qh_appendprint (qh_PRINTtriangles);
-          break;
-        case 'v':
-          /* option set in qh_initqhull_globals */
-          qh_appendprint (qh_PRINTvertices);
-          break;
-        case 'V':
-          qh_option ("FVertex-average", NULL, NULL);
-          qh_appendprint (qh_PRINTaverage);
-          break;
-	case 'x':
-	  qh_option ("Fxtremes", NULL, NULL);
-	  qh_appendprint (qh_PRINTextremes);
-	  break;
-	default:
-	  s--;
-	  fprintf (qh ferr, "qhull warning: unknown 'F' output option %c, rest ignored\n", (int)s[0]);
-	  while (*++s && !isspace(*s));
-	  break;
-	}
-      }
-      break;
-    case 'G':
-      isgeom= True;
-      qh_appendprint (qh_PRINTgeom);
-      while (*s && !isspace(*s)) {
-	switch(*s++) {
-        case 'a':
-          qh_option ("Gall-points", NULL, NULL);
-          qh PRINTdots= True;
-          break;
-        case 'c':
-          qh_option ("Gcentrums", NULL, NULL);
-          qh PRINTcentrums= True;
-          break;
-	case 'h':
-          qh_option ("Gintersections", NULL, NULL);
-	  qh DOintersections= True;
-	  break;
-	case 'i':
-          qh_option ("Ginner", NULL, NULL);
-	  qh PRINTinner= True;
-	  break;
-	case 'n':
-          qh_option ("Gno-planes", NULL, NULL);
-	  qh PRINTnoplanes= True;
-	  break;
-	case 'o':
-          qh_option ("Gouter", NULL, NULL);
-	  qh PRINTouter= True;
-	  break;
-	case 'p':
-          qh_option ("Gpoints", NULL, NULL);
-	  qh PRINTcoplanar= True;
-	  break;
-	case 'r':
-          qh_option ("Gridges", NULL, NULL);
-	  qh PRINTridges= True;
-	  break;
-	case 't':
-          qh_option ("Gtransparent", NULL, NULL);
-	  qh PRINTtransparent= True;
-	  break;
-	case 'v':
-          qh_option ("Gvertices", NULL, NULL);
-	  qh PRINTspheres= True;
-	  break;
-	case 'D':
-	  if (!isdigit (*s))
-	    fprintf (qh ferr, "qhull input error: missing dimension for option 'GDn'\n");
-	  else {
-	    if (qh DROPdim >= 0)
-	      fprintf (qh ferr, "qhull warning: can only drop one dimension.  Previous 'GD%d' ignored\n",
-	           qh DROPdim);
-  	    qh DROPdim= qh_strtol (s, &s);
-            qh_option ("GDrop-dim", &qh DROPdim, NULL);
-          }
-	  break;
-	default:
-	  s--;
-	  fprintf (qh ferr, "qhull warning: unknown 'G' print option %c, rest ignored\n", (int)s[0]);
-	  while (*++s && !isspace(*s));
-	  break;
-	}
-      }
-      break;
-    case 'P':
-      while (*s && !isspace(*s)) {
-	switch(*s++) {
-	case 'd': case 'D':  /* see qh_initthresholds() */
-	  key= s[-1];
-	  i= qh_strtol (s, &s);
-	  r= 0;
-	  if (*s == ':') {
-	    s++;
-	    r= qh_strtod (s, &s);
-	  }
-	  if (key == 'd')
-  	    qh_option ("Pdrop-facets-dim-less", &i, &r);
-  	  else
-  	    qh_option ("PDrop-facets-dim-more", &i, &r);
-	  break;
-        case 'g':
-          qh_option ("Pgood-facets", NULL, NULL);
-          qh PRINTgood= True;
-          break;
-        case 'G':
-          qh_option ("PGood-facet-neighbors", NULL, NULL);
-          qh PRINTneighbors= True;
-          break;
-        case 'o':
-          qh_option ("Poutput-forced", NULL, NULL);
-          qh FORCEoutput= True;
-          break;
-        case 'p':
-          qh_option ("Pprecision-ignore", NULL, NULL);
-          qh PRINTprecision= False;
-          break;
-	case 'A':
-	  if (!isdigit (*s))
-	    fprintf (qh ferr, "qhull input error: missing facet count for keep area option 'PAn'\n");
-	  else {
-  	    qh KEEParea= qh_strtol (s, &s);
-            qh_option ("PArea-keep", &qh KEEParea, NULL);
-            qh GETarea= True;
-          }
-	  break;
-	case 'F':
-	  if (!isdigit (*s))
-	    fprintf (qh ferr, "qhull input error: missing facet area for option 'PFn'\n");
-	  else {
-  	    qh KEEPminArea= qh_strtod (s, &s);
-            qh_option ("PFacet-area-keep", NULL, &qh KEEPminArea);
-            qh GETarea= True;
-          }
-	  break;
-	case 'M':
-	  if (!isdigit (*s))
-	    fprintf (qh ferr, "qhull input error: missing merge count for option 'PMn'\n");
-	  else {
-  	    qh KEEPmerge= qh_strtol (s, &s);
-            qh_option ("PMerge-keep", &qh KEEPmerge, NULL);
-          }
-	  break;
-	default:
-	  s--;
-	  fprintf (qh ferr, "qhull warning: unknown 'P' print option %c, rest ignored\n", (int)s[0]);
-	  while (*++s && !isspace(*s));
-	  break;
-	}
-      }
-      break;
-    case 'Q':
-      lastproject= -1;
-      while (*s && !isspace(*s)) {
-	switch(*s++) {
-	case 'b': case 'B':  /* handled by qh_initthresholds */
-	  key= s[-1];
-	  if (key == 'b' && *s == 'B') {
-	    s++;
-	    r= qh_DEFAULTbox;
-	    qh SCALEinput= True;
-	    qh_option ("QbBound-unit-box", NULL, &r);
-	    break;
-	  }
-	  if (key == 'b' && *s == 'b') {
-	    s++;
-	    qh SCALElast= True;
-	    qh_option ("Qbbound-last", NULL, NULL);
-	    break;
-	  }
-	  k= qh_strtol (s, &s);
-	  r= 0.0;
-	  wasproject= False;
-	  if (*s == ':') {
-	    s++;
-	    if ((r= qh_strtod(s, &s)) == 0.0) {
- 	      t= s;            /* need true dimension for memory allocation */
-	      while (*t && !isspace(*t)) {
-	        if (toupper(*t++) == 'B'
-	         && k == qh_strtol (t, &t)
-	         && *t++ == ':'
-	         && qh_strtod(t, &t) == 0.0) {
-	          qh PROJECTinput++;
-	          trace2((qh ferr, "qh_initflags: project dimension %d\n", k));
-	          qh_option ("Qb-project-dim", &k, NULL);
-		  wasproject= True;
-	          lastproject= k;
-	          break;
-		}
-	      }
-	    }
-  	  }
-	  if (!wasproject) {
-	    if (lastproject == k && r == 0.0)
-	      lastproject= -1;  /* doesn't catch all possible sequences */
-	    else if (key == 'b') {
-	      qh SCALEinput= True;
-	      if (r == 0.0)
-		r= -qh_DEFAULTbox;
-	      qh_option ("Qbound-dim-low", &k, &r);
-	    }else {
-	      qh SCALEinput= True;
-	      if (r == 0.0)
-		r= qh_DEFAULTbox;
-	      qh_option ("QBound-dim-high", &k, &r);
-	    }
-	  }
-	  break;
-	case 'c':
-	  qh_option ("Qcoplanar-keep", NULL, NULL);
-	  qh KEEPcoplanar= True;
-	  break;
-	case 'f':
-	  qh_option ("Qfurthest-outside", NULL, NULL);
-	  qh BESToutside= True;
-	  break;
-	case 'g':
-	  qh_option ("Qgood-facets-only", NULL, NULL);
-	  qh ONLYgood= True;
-	  break;
-	case 'i':
-	  qh_option ("Qinterior-keep", NULL, NULL);
-	  qh KEEPinside= True;
-	  break;
-	case 'm':
-	  qh_option ("Qmax-outside-only", NULL, NULL);
-	  qh ONLYmax= True;
-	  break;
-	case 'r':
-	  qh_option ("Qrandom-outside", NULL, NULL);
-	  qh RANDOMoutside= True;
-	  break;
-	case 's':
-	  qh_option ("Qsearch-initial-simplex", NULL, NULL);
-	  qh ALLpoints= True;
-	  break;
-	case 't':
-	  qh_option ("Qtriangulate", NULL, NULL);
-	  qh TRIangulate= True;
-	  break;
-	case 'T':
-	  qh_option ("QTestPoints", NULL, NULL);
-	  if (!isdigit (*s))
-	    fprintf (qh ferr, "qhull input error: missing number of test points for option 'QTn'\n");
-	  else {
-  	    qh TESTpoints= qh_strtol (s, &s);
-            qh_option ("QTestPoints", &qh TESTpoints, NULL);
-          }
-	  break;
-	case 'u':
-	  qh_option ("QupperDelaunay", NULL, NULL);
-	  qh UPPERdelaunay= True;
-	  break;
-	case 'v':
-	  qh_option ("Qvertex-neighbors-convex", NULL, NULL);
-	  qh TESTvneighbors= True;
-	  break;
-	case 'x':
-	  qh_option ("Qxact-merge", NULL, NULL);
-	  qh MERGEexact= True;
-	  break;
-	case 'z':
-	  qh_option ("Qz-infinity-point", NULL, NULL);
-	  qh ATinfinity= True;
-	  break;
-	case '0':
-	  qh_option ("Q0-no-premerge", NULL, NULL);
-	  qh NOpremerge= True;
-	  break;
-	case '1':
-	  if (!isdigit(*s)) {
-	    qh_option ("Q1-no-angle-sort", NULL, NULL);
-	    qh ANGLEmerge= False;
-	    break; 
-	  }
-	  switch(*s++) {
-  	  case '0':
-	    qh_option ("Q10-no-narrow", NULL, NULL);
-	    qh NOnarrow= True;
-	    break; 
-  	  case '1':
-	    qh_option ("Q11-trinormals Qtriangulate", NULL, NULL);
-	    qh TRInormals= True;
-	    qh TRIangulate= True;
-	    break; 
-	  default:
-	    s--;
-	    fprintf (qh ferr, "qhull warning: unknown 'Q' qhull option 1%c, rest ignored\n", (int)s[0]);
-	    while (*++s && !isspace(*s));
-	    break;
-	  }
-	  break;
-	case '2':
-	  qh_option ("Q2-no-merge-independent", NULL, NULL);
-	  qh MERGEindependent= False;
-	  goto LABELcheckdigit;
-	  break; /* no warnings */
-	case '3':
-	  qh_option ("Q3-no-merge-vertices", NULL, NULL);
-	  qh MERGEvertices= False;
-	LABELcheckdigit:
-	  if (isdigit(*s))
-	    fprintf (qh ferr, "qhull warning: can not follow '1', '2', or '3' with a digit.  '%c' skipped.\n",
-	             *s++);
-	  break;
-	case '4':
-	  qh_option ("Q4-avoid-old-into-new", NULL, NULL);
-	  qh AVOIDold= True;
-	  break;
-	case '5':
-	  qh_option ("Q5-no-check-outer", NULL, NULL);
-	  qh SKIPcheckmax= True;
-	  break;
-	case '6':
-	  qh_option ("Q6-no-concave-merge", NULL, NULL);
-	  qh SKIPconvex= True;
-	  break;
-	case '7':
-	  qh_option ("Q7-no-breadth-first", NULL, NULL);
-	  qh VIRTUALmemory= True;
-	  break;
-	case '8':
-	  qh_option ("Q8-no-near-inside", NULL, NULL);
-	  qh NOnearinside= True;
-	  break;
-	case '9':
-	  qh_option ("Q9-pick-furthest", NULL, NULL);
-	  qh PICKfurthest= True;
-	  break;
-	case 'G':
-	  i= qh_strtol (s, &t);
-	  if (qh GOODpoint)
-	    fprintf (qh ferr, "qhull warning: good point already defined for option 'QGn'.  Ignored\n");
-          else if (s == t)
-	    fprintf (qh ferr, "qhull warning: missing good point id for option 'QGn'.  Ignored\n");
-	  else if (i < 0 || *s == '-') {
- 	    qh GOODpoint= i-1;
-  	    qh_option ("QGood-if-dont-see-point", &i, NULL);
-	  }else {
- 	    qh GOODpoint= i+1;
-  	    qh_option ("QGood-if-see-point", &i, NULL);
-  	  }
- 	  s= t;
-	  break;
-	case 'J':
-          if (!isdigit(*s) && *s != '-')
-   	    qh JOGGLEmax= 0.0;
-	  else {
- 	    qh JOGGLEmax= (realT) qh_strtod (s, &s);
-            qh_option ("QJoggle", NULL, &qh JOGGLEmax);
-	  }
-	  break;
-	case 'R':
-          if (!isdigit(*s) && *s != '-')
-	    fprintf (qh ferr, "qhull warning: missing random seed for option 'QRn'.  Ignored\n");
-	  else {
- 	    qh ROTATErandom= i= qh_strtol(s, &s);
-   	    if (i > 0)
-   	      qh_option ("QRotate-id", &i, NULL );
-	    else if (i < -1)
-   	      qh_option ("QRandom-seed", &i, NULL );
-          }
-	  break;
-	case 'V':
-	  i= qh_strtol (s, &t);
-	  if (qh GOODvertex)
-	    fprintf (qh ferr, "qhull warning: good vertex already defined for option 'QVn'.  Ignored\n");
-          else if (s == t)
-	    fprintf (qh ferr, "qhull warning: no good point id given for option 'QVn'.  Ignored\n");
-	  else if (i < 0) {
- 	    qh GOODvertex= i - 1;
- 	    qh_option ("QV-good-facets-not-point", &i, NULL);
-	  }else {
-  	    qh_option ("QV-good-facets-point", &i, NULL);
-	    qh GOODvertex= i + 1;
-          }
- 	  s= t;
-	  break;
-	default:
-	  s--;
-	  fprintf (qh ferr, "qhull warning: unknown 'Q' qhull option %c, rest ignored\n", (int)s[0]);
-	  while (*++s && !isspace(*s));
-	  break;
-	}
-      }
-      break;
-    case 'T':
-      while (*s && !isspace(*s)) {
-	if (isdigit(*s) || *s == '-')
-	  qh IStracing= qh_strtol(s, &s);
-	else switch(*s++) {
-	case 'c':
-          qh_option ("Tcheck-frequently", NULL, NULL);
-	  qh CHECKfrequently= True;
-	  break;
-	case 's':
-          qh_option ("Tstatistics", NULL, NULL);
-	  qh PRINTstatistics= True;
-	  break;
-	case 'v':
-          qh_option ("Tverify", NULL, NULL);
-	  qh VERIFYoutput= True;
-	  break;
-	case 'z':
-	  if (!qh fout)
-	    fprintf (qh ferr, "qhull warning: output file undefined (stdout).  Option 'Tz' ignored.\n");
-	  else {
-	    qh_option ("Tz-stdout", NULL, NULL);
-  	    qh ferr= qh fout;
-  	    qhmem.ferr= qh fout;
-	  }
-	  break;
-	case 'C':
-	  if (!isdigit(*s))
-	    fprintf (qh ferr, "qhull warning: missing point id for cone for trace option 'TCn'.  Ignored\n");
-	  else {
-	    i= qh_strtol (s, &s);
-	    qh_option ("TCone-stop", &i, NULL);
-	    qh STOPcone= i + 1;
-          }
-	  break;
-	case 'F':
-	  if (!isdigit(*s))
-	    fprintf (qh ferr, "qhull warning: missing frequency count for trace option 'TFn'.  Ignored\n");
-	  else {
-	    qh REPORTfreq= qh_strtol (s, &s);
-            qh_option ("TFacet-log", &qh REPORTfreq, NULL);
-	    qh REPORTfreq2= qh REPORTfreq/2;  /* for tracemerging() */
-	  }
-	  break;
-	case 'I':
-	  if (s[0] != ' ' || s[1] == '\"' || s[1] == '\'' ||isspace (s[1])) {
-	    s++;
-	    fprintf (qh ferr, "qhull warning: option 'TI' mistyped.\nUse 'TI', one space, file name, and space or end-of-line.\nDo not use quotes.  Option 'FI' ignored.\n");
-	  }else {  /* not a procedure because of qh_option (filename, NULL, NULL); */
-	    char filename[500], *t= filename;
-
-	    s++;
-	    while (*s) {
-	      if (t - filename >= sizeof (filename)-2) {
-		fprintf (qh ferr, "qhull error: filename for 'TI' too long.\n");
-		qh_errexit (qh_ERRinput, NULL, NULL);
-	      }
-	      if (isspace (*s))
-		break;
-	      *(t++)= *s++;
-	    }
-	    *t= '\0';
-	    if (!freopen (filename, "r", stdin)) {
-	      fprintf (qh ferr, "qhull error: could not open file \"%s\".", filename);
-	      qh_errexit (qh_ERRinput, NULL, NULL);
-	    }else {
-	      qh_option ("TInput-file", NULL, NULL);
-	      qh_option (filename, NULL, NULL);
-	    }
-	  }
-	  break;
-	case 'O':
-	  if (s[0] != ' ' || s[1] == '\"' || isspace (s[1])) {
-	    s++;
-	    fprintf (qh ferr, "qhull warning: option 'TO' mistyped.\nUse 'TO', one space, file name, and space or end-of-line.\nThe file name may be enclosed in single quotes.\nDo not use double quotes.  Option 'FO' ignored.\n");
-	  }else {  /* not a procedure because of qh_option (filename, NULL, NULL); */
-	    char filename[500], *t= filename;
-	    boolT isquote= False;
-
-	    s++;
-	    if (*s == '\'') {
-	      isquote= True;
-	      s++;
-	    }
-	    while (*s) {
-	      if (t - filename >= sizeof (filename)-2) {
-		fprintf (qh ferr, "qhull error: filename for 'TO' too long.\n");
-		qh_errexit (qh_ERRinput, NULL, NULL);
-	      }
-	      if (isquote) {
-		if (*s == '\'') {
-		  s++;
-		  isquote= False;
-		  break;
-		}
-	      }else if (isspace (*s))
-		break;
-	      *(t++)= *s++;
-	    }
-	    *t= '\0';
-	    if (isquote)
-	      fprintf (qh ferr, "qhull error: missing end quote for option 'TO'.  Rest of line ignored.\n");
-	    else if (!freopen (filename, "w", stdout)) {
-	      fprintf (qh ferr, "qhull error: could not open file \"%s\".", filename);
-	      qh_errexit (qh_ERRinput, NULL, NULL);
-	    }else {
-	      qh_option ("TOutput-file", NULL, NULL);
-	      qh_option (filename, NULL, NULL);
-	    }
-	  }
-	  break;
-	case 'P':
-	  if (!isdigit(*s))
-	    fprintf (qh ferr, "qhull warning: missing point id for trace option 'TPn'.  Ignored\n");
-	  else {
-	    qh TRACEpoint= qh_strtol (s, &s);
-            qh_option ("Trace-point", &qh TRACEpoint, NULL);
-          }
-	  break;
-	case 'M':
-	  if (!isdigit(*s))
-	    fprintf (qh ferr, "qhull warning: missing merge id for trace option 'TMn'.  Ignored\n");
-	  else {
-	    qh TRACEmerge= qh_strtol (s, &s);
-            qh_option ("Trace-merge", &qh TRACEmerge, NULL);
-          }
-	  break;
-	case 'R':
-	  if (!isdigit(*s))
-	    fprintf (qh ferr, "qhull warning: missing rerun count for trace option 'TRn'.  Ignored\n");
-	  else {
-	    qh RERUN= qh_strtol (s, &s);
-            qh_option ("TRerun", &qh RERUN, NULL);
-          }
-	  break;
-	case 'V':
-	  i= qh_strtol (s, &t);
-	  if (s == t)
-	    fprintf (qh ferr, "qhull warning: missing furthest point id for trace option 'TVn'.  Ignored\n");
-	  else if (i < 0) {
-	    qh STOPpoint= i - 1;
-            qh_option ("TV-stop-before-point", &i, NULL);
-	  }else {
-	    qh STOPpoint= i + 1;
-            qh_option ("TV-stop-after-point", &i, NULL);
-          }
-          s= t;
-	  break;
-	case 'W':
-	  if (!isdigit(*s))
-	    fprintf (qh ferr, "qhull warning: missing max width for trace option 'TWn'.  Ignored\n");
-	  else {
- 	    qh TRACEdist= (realT) qh_strtod (s, &s);
-            qh_option ("TWide-trace", NULL, &qh TRACEdist);
-          }
-	  break;
-	default:
-	  s--;
-	  fprintf (qh ferr, "qhull warning: unknown 'T' trace option %c, rest ignored\n", (int)s[0]);
-	  while (*++s && !isspace(*s));
-	  break;
-	}
-      }
-      break;
-    default:
-      fprintf (qh ferr, "qhull warning: unknown flag %c (%x)\n", (int)s[-1],
-	       (int)s[-1]);
-      break;
-    }
-    if (s-1 == prev_s && *s && !isspace(*s)) {
-      fprintf (qh ferr, "qhull warning: missing space after flag %c (%x); reserved for menu. Skipped.\n",
-	       (int)*prev_s, (int)*prev_s);
-      while (*s && !isspace(*s))
-	s++;
-    }
-  }
-  if (isgeom && !qh FORCEoutput && qh PRINTout[1])
-    fprintf (qh ferr, "qhull warning: additional output formats are not compatible with Geomview\n");
-  /* set derived values in qh_initqhull_globals */
-} /* initflags */
-
-
-/*---------------------------------
-
-  qh_initqhull_buffers()
-    initialize global memory buffers
-
-  notes:
-    must match qh_freebuffers()
-*/
-void qh_initqhull_buffers (void) {
-  int k;
-
-  qh TEMPsize= (qhmem.LASTsize - sizeof (setT))/SETelemsize;
-  if (qh TEMPsize <= 0 || qh TEMPsize > qhmem.LASTsize)
-    qh TEMPsize= 8;  /* e.g., if qh_NOmem */
-  qh other_points= qh_setnew (qh TEMPsize);
-  qh del_vertices= qh_setnew (qh TEMPsize);
-  qh coplanarset= qh_setnew (qh TEMPsize);
-  qh NEARzero= (realT *)qh_memalloc(qh hull_dim * sizeof(realT));
-  qh lower_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
-  qh upper_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
-  qh lower_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
-  qh upper_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
-  for(k= qh input_dim+1; k--; ) {
-    qh lower_threshold[k]= -REALmax;
-    qh upper_threshold[k]= REALmax;
-    qh lower_bound[k]= -REALmax;
-    qh upper_bound[k]= REALmax;
-  }
-  qh gm_matrix= (coordT *)qh_memalloc((qh hull_dim+1) * qh hull_dim * sizeof(coordT));
-  qh gm_row= (coordT **)qh_memalloc((qh hull_dim+1) * sizeof(coordT *));
-} /* initqhull_buffers */
-
-/*---------------------------------
-
-  qh_initqhull_globals( points, numpoints, dim, ismalloc )
-    initialize globals
-    if ismalloc
-      points were malloc'd and qhull should free at end
-
-  returns:
-    sets qh.first_point, num_points, input_dim, hull_dim and others
-    seeds random number generator (seed=1 if tracing)
-    modifies qh.hull_dim if ((qh.DELAUNAY and qh.PROJECTdelaunay) or qh.PROJECTinput)
-    adjust user flags as needed
-    also checks DIM3 dependencies and constants
-
-  notes:
-    do not use qh_point() since an input transformation may move them elsewhere
-
-  see:
-    qh_initqhull_start() sets default values for non-zero globals
-
-  design:
-    initialize points array from input arguments
-    test for qh.ZEROcentrum
-      (i.e., use opposite vertex instead of cetrum for convexity testing)
-    test for qh.PRINTgood (i.e., only print 'good' facets)
-    initialize qh.CENTERtype, qh.normal_size,
-      qh.center_size, qh.TRACEpoint/level,
-    initialize and test random numbers
-    check for conflicting print output options
-*/
-void qh_initqhull_globals (coordT *points, int numpoints, int dim, boolT ismalloc) {
-  int seed, pointsneeded, extra= 0, i, randi, k;
-  boolT printgeom= False, printmath= False, printcoplanar= False;
-  realT randr;
-  realT factorial;
-
-  time_t timedata;
-
-  trace0((qh ferr, "qh_initqhull_globals: for %s | %s\n", qh rbox_command,
-      qh qhull_command));
-  qh POINTSmalloc= ismalloc;
-  qh first_point= points;
-  qh num_points= numpoints;
-  qh hull_dim= qh input_dim= dim;
-  if (!qh NOpremerge && !qh MERGEexact && !qh PREmerge && qh JOGGLEmax > REALmax/2) {
-    qh MERGING= True;
-    if (qh hull_dim <= 4) {
-      qh PREmerge= True;
-      qh_option ("_pre-merge", NULL, NULL);
-    }else {
-      qh MERGEexact= True;
-      qh_option ("Qxact_merge", NULL, NULL);
-    }
-  }else if (qh MERGEexact) 
-    qh MERGING= True;
-  if (!qh NOpremerge && qh JOGGLEmax > REALmax/2) {
-#ifdef qh_NOmerge
-    qh JOGGLEmax= 0.0;
-#endif
-  }
-  if (qh TRIangulate && qh JOGGLEmax < REALmax/2 && qh PRINTprecision)
-    fprintf(qh ferr, "qhull warning: joggle ('QJ') always produces simplicial output.  Triangulated output ('Qt') does nothing.\n");
-  if (qh JOGGLEmax < REALmax/2 && qh DELAUNAY && !qh SCALEinput && !qh SCALElast) {
-    qh SCALElast= True;
-    qh_option ("Qbbound-last-qj", NULL, NULL);
-  }
-  if (qh MERGING && !qh POSTmerge && qh premerge_cos > REALmax/2
-  && qh premerge_centrum == 0) {
-    qh ZEROcentrum= True;
-    qh ZEROall_ok= True;
-    qh_option ("_zero-centrum", NULL, NULL);
-  }
-  if (qh JOGGLEmax < REALmax/2 && REALepsilon > 2e-8 && qh PRINTprecision)
-    fprintf(qh ferr, "qhull warning: real epsilon, %2.2g, is probably too large for joggle ('QJn')\nRecompile with double precision reals (see user.h).\n",
-          REALepsilon);
-#ifdef qh_NOmerge
-  if (qh MERGING) {
-    fprintf (qh ferr, "qhull input error: merging not installed (qh_NOmerge + 'Qx', 'Cn' or 'An')\n");
-    qh_errexit (qh_ERRinput, NULL, NULL);
-  }
-#endif
-  if (!(qh PRINTgood || qh PRINTneighbors)) {
-    if (qh KEEParea || qh KEEPminArea < REALmax/2 || qh KEEPmerge || qh DELAUNAY
-	|| (!qh ONLYgood && (qh GOODvertex || qh GOODpoint))) {
-      qh PRINTgood= True;
-      qh_option ("Pgood", NULL, NULL);
-    }
-  }
-  if (qh DELAUNAY && qh KEEPcoplanar && !qh KEEPinside) {
-    qh KEEPinside= True;
-    qh_option ("Qinterior-keep", NULL, NULL);
-  }
-  if (qh DELAUNAY && qh HALFspace) {
-    fprintf (qh ferr, "qhull input error: can not use Delaunay ('d') or Voronoi ('v') with halfspace intersection ('H')\n");
-    qh_errexit (qh_ERRinput, NULL, NULL);
-  }
-  if (!qh DELAUNAY && (qh UPPERdelaunay || qh ATinfinity)) {
-    fprintf (qh ferr, "qhull input error: use upper-Delaunay ('Qu') or infinity-point ('Qz') with Delaunay ('d') or Voronoi ('v')\n");
-    qh_errexit (qh_ERRinput, NULL, NULL);
-  }
-  if (qh UPPERdelaunay && qh ATinfinity) {
-    fprintf (qh ferr, "qhull input error: can not use infinity-point ('Qz') with upper-Delaunay ('Qu')\n");
-    qh_errexit (qh_ERRinput, NULL, NULL);
-  }
-  if (qh SCALElast && !qh DELAUNAY && qh PRINTprecision)
-    fprintf (qh ferr, "qhull input warning: option 'Qbb' (scale-last-coordinate) is normally used with 'd' or 'v'\n");
-  qh DOcheckmax= (!qh SKIPcheckmax && qh MERGING );
-  qh KEEPnearinside= (qh DOcheckmax && !(qh KEEPinside && qh KEEPcoplanar) 
-                          && !qh NOnearinside);
-  if (qh MERGING)
-    qh CENTERtype= qh_AScentrum;
-  else if (qh VORONOI)
-    qh CENTERtype= qh_ASvoronoi;
-  if (qh TESTvneighbors && !qh MERGING) {
-    fprintf(qh ferr, "qhull input error: test vertex neighbors ('Qv') needs a merge option\n");
-    qh_errexit (qh_ERRinput, NULL ,NULL);
-  }
-  if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay)) {
-    qh hull_dim -= qh PROJECTinput;
-    if (qh DELAUNAY) {
-      qh hull_dim++;
-      extra= 1;
-    }
-  }
-  if (qh hull_dim <= 1) {
-    fprintf(qh ferr, "qhull error: dimension %d must be > 1\n", qh hull_dim);
-    qh_errexit (qh_ERRinput, NULL, NULL);
-  }
-  for (k= 2, factorial=1.0; k < qh hull_dim; k++)
-    factorial *= k;
-  qh AREAfactor= 1.0 / factorial;
-  trace2((qh ferr, "qh_initqhull_globals: initialize globals.  dim %d numpoints %d malloc? %d projected %d to hull_dim %d\n",
-	dim, numpoints, ismalloc, qh PROJECTinput, qh hull_dim));
-  qh normal_size= qh hull_dim * sizeof(coordT);
-  qh center_size= qh normal_size - sizeof(coordT);
-  pointsneeded= qh hull_dim+1;
-  if (qh hull_dim > qh_DIMmergeVertex) {
-    qh MERGEvertices= False;
-    qh_option ("Q3-no-merge-vertices-dim-high", NULL, NULL);
-  }
-  if (qh GOODpoint)
-    pointsneeded++;
-#ifdef qh_NOtrace
-  if (qh IStracing) {
-    fprintf (qh ferr, "qhull input error: tracing is not installed (qh_NOtrace in user.h)");
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-#endif
-  if (qh RERUN > 1) {
-    qh TRACElastrun= qh IStracing; /* qh_build_withrestart duplicates next conditional */
-    if (qh IStracing != -1)
-      qh IStracing= 0;
-  }else if (qh TRACEpoint != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) {
-    qh TRACElevel= (qh IStracing? qh IStracing : 3);
-    qh IStracing= 0;
-  }
-  if (qh ROTATErandom == 0 || qh ROTATErandom == -1) {
-    seed= time (&timedata);
-    if (qh ROTATErandom  == -1) {
-      seed= -seed;
-      qh_option ("QRandom-seed", &seed, NULL );
-    }else
-      qh_option ("QRotate-random", &seed, NULL);
-    qh ROTATErandom= seed;
-  }
-  seed= qh ROTATErandom;
-  if (seed == INT_MIN)    /* default value */
-    seed= 1;
-  else if (seed < 0)
-    seed= -seed;
-  qh_RANDOMseed_(seed);
-  randr= 0.0;
-  for (i= 1000; i--; ) {
-    randi= qh_RANDOMint;
-    randr += randi;
-    if (randi > qh_RANDOMmax) {
-      fprintf (qh ferr, "\
-qhull configuration error (qh_RANDOMmax in user.h):\n\
-   random integer %d > qh_RANDOMmax (%.8g)\n",
-	       randi, qh_RANDOMmax);
-      qh_errexit (qh_ERRinput, NULL, NULL);
-    }
-  }
-  qh_RANDOMseed_(seed);
-  randr = randr/1000;
-  if (randr < qh_RANDOMmax/10
-  || randr > qh_RANDOMmax * 5)
-    fprintf (qh ferr, "\
-qhull configuration warning (qh_RANDOMmax in user.h):\n\
-   average of 1000 random integers (%.2g) is much different than expected (%.2g).\n\
-   Is qh_RANDOMmax (%.2g) wrong?\n",
-	     randr, qh_RANDOMmax/2.0, qh_RANDOMmax);
-  qh RANDOMa= 2.0 * qh RANDOMfactor/qh_RANDOMmax;
-  qh RANDOMb= 1.0 - qh RANDOMfactor;
-  if (qh_HASHfactor < 1.1) {
-    fprintf(qh ferr, "qhull internal error (qh_initqhull_globals): qh_HASHfactor %d must be at least 1.1.  Qhull uses linear hash probing\n",
-      qh_HASHfactor);
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-  if (numpoints+extra < pointsneeded) {
-    fprintf(qh ferr,"qhull input error: not enough points (%d) to construct initial simplex (need %d)\n",
-	    numpoints, pointsneeded);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (qh PRINTtransparent) {
-    if (qh hull_dim != 4 || !qh DELAUNAY || qh VORONOI || qh DROPdim >= 0) {
-      fprintf(qh ferr,"qhull input error: transparent Delaunay ('Gt') needs 3-d Delaunay ('d') w/o 'GDn'\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    qh DROPdim = 3;
-    qh PRINTridges = True;
-  }
-  for (i= qh_PRINTEND; i--; ) {
-    if (qh PRINTout[i] == qh_PRINTgeom)
-      printgeom= True;
-    else if (qh PRINTout[i] == qh_PRINTmathematica)
-      printmath= True;
-    else if (qh PRINTout[i] == qh_PRINTcoplanars)
-      printcoplanar= True;
-    else if (qh PRINTout[i] == qh_PRINTpointnearest)
-      printcoplanar= True;
-    else if (qh PRINTout[i] == qh_PRINTpointintersect && !qh HALFspace) {
-      fprintf (qh ferr, "qhull input error: option 'Fp' is only used for \nhalfspace intersection ('Hn,n,n').\n");
-      qh_errexit (qh_ERRinput, NULL, NULL);
-    }else if (qh PRINTout[i] == qh_PRINTtriangles && (qh HALFspace || qh VORONOI)) {
-      fprintf (qh ferr, "qhull input error: option 'Ft' is not available for Voronoi vertices or halfspace intersection\n");
-      qh_errexit (qh_ERRinput, NULL, NULL);
-    }else if (qh PRINTout[i] == qh_PRINTcentrums && qh VORONOI) {
-      fprintf (qh ferr, "qhull input error: option 'FC' is not available for Voronoi vertices ('v')\n");
-      qh_errexit (qh_ERRinput, NULL, NULL);
-    }else if (qh PRINTout[i] == qh_PRINTvertices) {
-      if (qh VORONOI)
-        qh_option ("Fvoronoi", NULL, NULL);
-      else 
-        qh_option ("Fvertices", NULL, NULL);
-    }
-  }
-  if (printcoplanar && qh DELAUNAY && qh JOGGLEmax < REALmax/2) {
-    if (qh PRINTprecision) 
-      fprintf (qh ferr, "qhull input warning: 'QJ' (joggle) will usually prevent coincident input sites for options 'Fc' and 'FP'\n");
-  }
-  if (!qh KEEPcoplanar && !qh KEEPinside && !qh ONLYgood) {
-    if ((qh PRINTcoplanar && qh PRINTspheres) || printcoplanar) {
-      qh KEEPcoplanar = True;
-      qh_option ("Qcoplanar", NULL, NULL);
-    }
-  }
-  if (printmath && (qh hull_dim > 3 || qh VORONOI)) {
-    fprintf (qh ferr, "qhull input error: Mathematica output is only available for 2-d and 3-d convex hulls and 2-d Delaunay triangulations\n");
-    qh_errexit (qh_ERRinput, NULL, NULL);
-  }
-  if (printgeom) {
-    if (qh hull_dim > 4) {
-      fprintf (qh ferr, "qhull input error: Geomview output is only available for 2-d, 3-d and 4-d\n");
-      qh_errexit (qh_ERRinput, NULL, NULL);
-    }
-    if (qh PRINTnoplanes && !(qh PRINTcoplanar + qh PRINTcentrums
-     + qh PRINTdots + qh PRINTspheres + qh DOintersections + qh PRINTridges)) {
-      fprintf (qh ferr, "qhull input error: no output specified for Geomview\n");
-      qh_errexit (qh_ERRinput, NULL, NULL);
-    }
-    if (qh VORONOI && (qh hull_dim > 3 || qh DROPdim >= 0)) {
-      fprintf (qh ferr, "qhull input error: Geomview output for Voronoi diagrams only for 2-d\n");
-      qh_errexit (qh_ERRinput, NULL, NULL);
-    }
-    /* can not warn about furthest-site Geomview output: no lower_threshold */
-    if (qh hull_dim == 4 && qh DROPdim == -1 &&
-	(qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
-      fprintf (qh ferr, "qhull input warning: coplanars, vertices, and centrums output not\n\
-available for 4-d output (ignored).  Could use 'GDn' instead.\n");
-      qh PRINTcoplanar= qh PRINTspheres= qh PRINTcentrums= False;
-    }
-  }
-  qh PRINTdim= qh hull_dim;
-  if (qh DROPdim >=0) {    /* after Geomview checks */
-    if (qh DROPdim < qh hull_dim) {
-      qh PRINTdim--;
-      if (!printgeom || qh hull_dim < 3)
-        fprintf (qh ferr, "qhull input warning: drop dimension 'GD%d' is only available for 3-d/4-d Geomview\n", qh DROPdim);
-    }else
-      qh DROPdim= -1;
-  }else if (qh VORONOI) {
-    qh DROPdim= qh hull_dim-1;
-    qh PRINTdim= qh hull_dim-1;
-  }
-} /* initqhull_globals */
- 
-/*---------------------------------
-
-  qh_initqhull_mem(  )
-    initialize mem.c for qhull
-    qh.hull_dim and qh.normal_size determine some of the allocation sizes
-    if qh.MERGING,
-      includes ridgeT
-    calls qh_user_memsizes() to add up to 10 additional sizes for quick allocation
-      (see numsizes below)
-
-  returns:
-    mem.c already for qh_memalloc/qh_memfree (errors if called beforehand)
-
-  notes:
-    qh_produceoutput() prints memsizes
-
-*/
-void qh_initqhull_mem (void) {
-  int numsizes;
-  int i;
-
-  numsizes= 8+10;
-  qh_meminitbuffers (qh IStracing, qh_MEMalign, numsizes,
-                     qh_MEMbufsize,qh_MEMinitbuf);
-  qh_memsize(sizeof(vertexT));
-  if (qh MERGING) {
-    qh_memsize(sizeof(ridgeT));
-    qh_memsize(sizeof(mergeT));
-  }
-  qh_memsize(sizeof(facetT));
-  i= sizeof(setT) + (qh hull_dim - 1) * SETelemsize;  /* ridge.vertices */
-  qh_memsize(i);
-  qh_memsize(qh normal_size);        /* normal */
-  i += SETelemsize;                 /* facet.vertices, .ridges, .neighbors */
-  qh_memsize(i);
-  qh_user_memsizes();
-  qh_memsetup();
-} /* initqhull_mem */
-
-/*---------------------------------
-
-  qh_initqhull_start( infile, outfile, errfile )
-    start initialization of qhull
-    initialize statistics, stdio, default values for global variables
-
-  see:
-    qh_maxmin() determines the precision constants
-*/
-void qh_initqhull_start (FILE *infile, FILE *outfile, FILE *errfile) {
-
-  qh_CPUclock; /* start the clock */
-#if qh_QHpointer
-  if (!(qh_qh= (qhT *)malloc (sizeof(qhT)))) {
-    fprintf (errfile, "qhull error (qh_initqhull_globals): insufficient memory\n");
-    exit (qh_ERRmem);  /* no error handler */
-  }
-  memset((char *)qh_qh, 0, sizeof(qhT));   /* every field is 0, FALSE, NULL */
-#else
-  memset((char *)&qh_qh, 0, sizeof(qhT));
-#endif
-  strcat (qh qhull, "qhull");
-  qh_initstatistics();
-  qh ANGLEmerge= True;
-  qh DROPdim= -1;
-  qh ferr= errfile;
-  qh fin= infile;
-  qh fout= outfile;
-  qh furthest_id= -1;
-  qh JOGGLEmax= REALmax;
-  qh KEEPminArea = REALmax;
-  qh last_low= REALmax;
-  qh last_high= REALmax;
-  qh last_newhigh= REALmax;
-  qh max_outside= 0.0;
-  qh max_vertex= 0.0;
-  qh MAXabs_coord= 0.0;
-  qh MAXsumcoord= 0.0;
-  qh MAXwidth= -REALmax;
-  qh MERGEindependent= True;
-  qh MINdenom_1= fmax_(1.0/REALmax, REALmin); /* used by qh_scalepoints */
-  qh MINoutside= 0.0;
-  qh MINvisible= REALmax;
-  qh MAXcoplanar= REALmax;
-  qh outside_err= REALmax;
-  qh premerge_centrum= 0.0;
-  qh premerge_cos= REALmax;
-  qh PRINTprecision= True;
-  qh PRINTradius= 0.0;
-  qh postmerge_cos= REALmax;
-  qh postmerge_centrum= 0.0;
-  qh ROTATErandom= INT_MIN;
-  qh MERGEvertices= True;
-  qh totarea= 0.0;
-  qh totvol= 0.0;
-  qh TRACEdist= REALmax;
-  qh TRACEpoint= -1; /* recompile or use 'TPn' */
-  qh tracefacet_id= UINT_MAX;  /* recompile to trace a facet */
-  qh tracevertex_id= UINT_MAX; /* recompile to trace a vertex */
-  qh_RANDOMseed_(1);
-} /* initqhull_start */
-
-/*---------------------------------
-
-  qh_initthresholds( commandString )
-    set thresholds for printing and scaling from commandString
-
-  returns:
-    sets qh.GOODthreshold or qh.SPLITthreshold if 'Pd0D1' used
-
-  see:
-    qh_initflags(), 'Qbk' 'QBk' 'Pdk' and 'PDk'
-    qh_inthresholds()
-
-  design:
-    for each 'Pdn' or 'PDn' option
-      check syntax
-      set qh.lower_threshold or qh.upper_threshold
-    set qh.GOODthreshold if an unbounded threshold is used
-    set qh.SPLITthreshold if a bounded threshold is used
-*/
-void qh_initthresholds(char *command) {
-  realT value;
-  int index, maxdim, k;
-  char *s= command;
-  char key;
-
-  maxdim= qh input_dim;
-  if (qh DELAUNAY && (qh PROJECTdelaunay || qh PROJECTinput))
-    maxdim++;
-  while (*s) {
-    if (*s == '-')
-      s++;
-    if (*s == 'P') {
-      s++;
-      while (*s && !isspace(key= *s++)) {
-	if (key == 'd' || key == 'D') {
-	  if (!isdigit(*s)) {
-	    fprintf(qh ferr, "qhull warning: no dimension given for Print option '%c' at: %s.  Ignored\n",
-		    key, s-1);
-	    continue;
-	  }
-	  index= qh_strtol (s, &s);
-	  if (index >= qh hull_dim) {
-	    fprintf(qh ferr, "qhull warning: dimension %d for Print option '%c' is >= %d.  Ignored\n",
-	        index, key, qh hull_dim);
-	    continue;
-	  }
-	  if (*s == ':') {
-	    s++;
-	    value= qh_strtod(s, &s);
-	    if (fabs((double)value) > 1.0) {
-	      fprintf(qh ferr, "qhull warning: value %2.4g for Print option %c is > +1 or < -1.  Ignored\n",
-	              value, key);
-	      continue;
-	    }
-	  }else
-	    value= 0.0;
-	  if (key == 'd')
-	    qh lower_threshold[index]= value;
-	  else
-	    qh upper_threshold[index]= value;
-	}
-      }
-    }else if (*s == 'Q') {
-      s++;
-      while (*s && !isspace(key= *s++)) {
-	if (key == 'b' && *s == 'B') {
-	  s++;
-	  for (k=maxdim; k--; ) {
-	    qh lower_bound[k]= -qh_DEFAULTbox;
-	    qh upper_bound[k]= qh_DEFAULTbox;
-	  }
-	}else if (key == 'b' && *s == 'b')
-	  s++;
-	else if (key == 'b' || key == 'B') {
-	  if (!isdigit(*s)) {
-	    fprintf(qh ferr, "qhull warning: no dimension given for Qhull option %c.  Ignored\n",
-		    key);
-	    continue;
-	  }
-	  index= qh_strtol (s, &s);
-	  if (index >= maxdim) {
-	    fprintf(qh ferr, "qhull warning: dimension %d for Qhull option %c is >= %d.  Ignored\n",
-	        index, key, maxdim);
-	    continue;
-	  }
-	  if (*s == ':') {
-	    s++;
-	    value= qh_strtod(s, &s);
-	  }else if (key == 'b')
-	    value= -qh_DEFAULTbox;
-	  else
-	    value= qh_DEFAULTbox;
-	  if (key == 'b')
-	    qh lower_bound[index]= value;
-	  else
-	    qh upper_bound[index]= value;
-	}
-      }
-    }else {
-      while (*s && !isspace (*s))
-        s++;
-    }
-    while (isspace (*s))
-      s++;
-  }
-  for (k= qh hull_dim; k--; ) {
-    if (qh lower_threshold[k] > -REALmax/2) {
-      qh GOODthreshold= True;
-      if (qh upper_threshold[k] < REALmax/2) {
-        qh SPLITthresholds= True;
-        qh GOODthreshold= False;
-        break;
-      }
-    }else if (qh upper_threshold[k] < REALmax/2)
-      qh GOODthreshold= True;
-  }
-} /* initthresholds */
-
-/*---------------------------------
-
-  qh_option( option, intVal, realVal )
-    add an option description to qh.qhull_options
-
-  notes:
-    will be printed with statistics ('Ts') and errors
-    strlen(option) < 40
-*/
-void qh_option (char *option, int *i, realT *r) {
-  char buf[200];
-  int len, maxlen;
-
-  sprintf (buf, "  %s", option);
-  if (i)
-    sprintf (buf+strlen(buf), " %d", *i);
-  if (r)
-    sprintf (buf+strlen(buf), " %2.2g", *r);
-  len= strlen(buf);
-  qh qhull_optionlen += len;
-  maxlen= sizeof (qh qhull_options) - len -1;
-  maximize_(maxlen, 0);
-  if (qh qhull_optionlen >= 80 && maxlen > 0) {
-    qh qhull_optionlen= len;
-    strncat (qh qhull_options, "\n", maxlen--);
-  }
-  strncat (qh qhull_options, buf, maxlen);
-} /* option */
-
-#if qh_QHpointer
-/*---------------------------------
-
-  qh_restore_qhull( oldqh )
-    restores a previously saved qhull
-    also restores qh_qhstat and qhmem.tempstack
-
-  notes:
-    errors if current qhull hasn't been saved or freed
-    uses qhmem for error reporting
-
-  NOTE 1998/5/11:
-    Freeing memory after qh_save_qhull and qh_restore_qhull
-    is complicated.  The procedures will be redesigned.
-
-  see:
-    qh_save_qhull()
-*/
-void qh_restore_qhull (qhT **oldqh) {
-
-  if (*oldqh && strcmp ((*oldqh)->qhull, "qhull")) {
-    fprintf (qhmem.ferr, "qhull internal error (qh_restore_qhull): %p is not a qhull data structure\n",
-                  *oldqh);
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-  if (qh_qh) {
-    fprintf (qhmem.ferr, "qhull internal error (qh_restore_qhull): did not save or free existing qhull\n");
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-  if (!*oldqh || !(*oldqh)->old_qhstat) {
-    fprintf (qhmem.ferr, "qhull internal error (qh_restore_qhull): did not previously save qhull %p\n",
-                  *oldqh);
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-  qh_qh= *oldqh;
-  *oldqh= NULL;
-  qh_qhstat= qh old_qhstat;
-  qhmem.tempstack= qh old_tempstack;
-  trace1((qh ferr, "qh_restore_qhull: restored qhull from %p\n", *oldqh));
-} /* restore_qhull */
-
-/*---------------------------------
-
-  qh_save_qhull(  )
-    saves qhull for a later qh_restore_qhull
-    also saves qh_qhstat and qhmem.tempstack
-
-  returns:
-    qh_qh=NULL
-
-  notes:
-    need to initialize qhull or call qh_restore_qhull before continuing
-
-  NOTE 1998/5/11:
-    Freeing memory after qh_save_qhull and qh_restore_qhull
-    is complicated.  The procedures will be redesigned.
-
-  see:
-    qh_restore_qhull()
-*/
-qhT *qh_save_qhull (void) {
-  qhT *oldqh;
-
-  trace1((qhmem.ferr, "qh_save_qhull: save qhull %p\n", qh_qh));
-  if (!qh_qh) {
-    fprintf (qhmem.ferr, "qhull internal error (qh_save_qhull): qhull not initialized\n");
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-  qh old_qhstat= qh_qhstat;
-  qh_qhstat= NULL;
-  qh old_tempstack= qhmem.tempstack;
-  qhmem.tempstack= NULL;
-  oldqh= qh_qh;
-  qh_qh= NULL;
-  return oldqh;
-} /* save_qhull */
-
-#endif
-
-/*---------------------------------
-
-  qh_strtol( s, endp) qh_strtod( s, endp)
-    internal versions of strtol() and strtod()
-    does not skip trailing spaces
-  notes:
-    some implementations of strtol()/strtod() skip trailing spaces
-*/
-double qh_strtod (const char *s, char **endp) {
-  double result;
-
-  result= strtod (s, endp);
-  if (s < (*endp) && (*endp)[-1] == ' ')
-    (*endp)--;
-  return result;
-} /* strtod */
-
-int qh_strtol (const char *s, char **endp) {
-  int result;
-
-  result= (int) strtol (s, endp, 10);
-  if (s< (*endp) && (*endp)[-1] == ' ')
-    (*endp)--;
-  return result;
-} /* strtol */
diff --git a/extern/qhull/src/io.c b/extern/qhull/src/io.c
deleted file mode 100644
index 9b0ccdd0b24..00000000000
--- a/extern/qhull/src/io.c
+++ /dev/null
@@ -1,4089 +0,0 @@
-/*
  ---------------------------------
-
-   io.c 
-   Input/Output routines of qhull application
-
-   see qh-io.htm and io.h
-
-   see user.c for qh_errprint and qh_printfacetlist
-
-   unix.c calls qh_readpoints and qh_produce_output
-
-   unix.c and user.c are the only callers of io.c functions
-   This allows the user to avoid loading io.o from qhull.a
-
-   copyright (c) 1993-2002 The Geometry Center        
-*/
-
-#include "qhull_a.h"
-
-/*========= -prototypes for internal functions ========= */
-
-static int qh_compare_facetarea(const void *p1, const void *p2);
-static int qh_compare_facetmerge(const void *p1, const void *p2);
-static int qh_compare_facetvisit(const void *p1, const void *p2);
-int qh_compare_vertexpoint(const void *p1, const void *p2); /* not used */
-
-/*========= -functions in alphabetical order after qh_produce_output()  =====*/
-
-/*---------------------------------
-  
-  qh_produce_output()
-    prints out the result of qhull in desired format
-    if qh.GETarea
-      computes and prints area and volume
-    qh.PRINTout[] is an array of output formats
-
-  notes:
-    prints output in qh.PRINTout order
-*/
-void qh_produce_output(void) {
-  int i, tempsize= qh_setsize ((setT*)qhmem.tempstack), d_1;
-
-  if (qh VORONOI) {
-    qh_clearcenters (qh_ASvoronoi);
-    qh_vertexneighbors();
-  }
-  if (qh TRIangulate) {
-    qh_triangulate(); 
-    if (qh VERIFYoutput && !qh CHECKfrequently) 
-      qh_checkpolygon (qh facet_list);
-  }
-  qh_findgood_all (qh facet_list); 
-  if (qh GETarea)
-    qh_getarea(qh facet_list);
-  if (qh KEEParea || qh KEEPmerge || qh KEEPminArea < REALmax/2)
-    qh_markkeep (qh facet_list);
-  if (qh PRINTsummary)
-    qh_printsummary(qh ferr);
-  else if (qh PRINTout[0] == qh_PRINTnone)
-    qh_printsummary(qh fout);
-  for (i= 0; i < qh_PRINTEND; i++)
-    qh_printfacets (qh fout, qh PRINTout[i], qh facet_list, NULL, !qh_ALL);
-  qh_allstatistics();
-  if (qh PRINTprecision && !qh MERGING && (qh JOGGLEmax > REALmax/2 || qh RERUN))
-    qh_printstats (qh ferr, qhstat precision, NULL);
-  if (qh VERIFYoutput && (zzval_(Zridge) > 0 || zzval_(Zridgemid) > 0)) 
-    qh_printstats (qh ferr, qhstat vridges, NULL);
-  if (qh PRINTstatistics) {
-    qh_collectstatistics();
-    qh_printstatistics(qh ferr, "");
-    qh_memstatistics (qh ferr);
-    d_1= sizeof(setT) + (qh hull_dim - 1) * SETelemsize;
-    fprintf(qh ferr, "\
-    size in bytes: merge %ld ridge %ld vertex %ld facet %ld\n\
-         normal %d ridge vertices %d facet vertices or neighbors %ld\n",
-	    sizeof(mergeT), sizeof(ridgeT),
-	    sizeof(vertexT), sizeof(facetT),
-	    qh normal_size, d_1, d_1 + SETelemsize);
-  }
-  if (qh_setsize ((setT*)qhmem.tempstack) != tempsize) {
-    fprintf (qh ferr, "qhull internal error (qh_produce_output): temporary sets not empty (%d)\n",
-	     qh_setsize ((setT*)qhmem.tempstack));
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-} /* produce_output */
-
-
-/*---------------------------------
-  
-  dfacet( id )
-    print facet by id, for debugging
-
-*/
-void dfacet (unsigned id) {
-  facetT *facet;
-
-  FORALLfacets {
-    if (facet->id == id) {
-      qh_printfacet (qh fout, facet);
-      break;
-    }
-  }
-} /* dfacet */
-
-
-/*---------------------------------
-  
-  dvertex( id )
-    print vertex by id, for debugging
-*/
-void dvertex (unsigned id) {
-  vertexT *vertex;
-
-  FORALLvertices {
-    if (vertex->id == id) {
-      qh_printvertex (qh fout, vertex);
-      break;
-    }
-  }
-} /* dvertex */
-
-
-/*---------------------------------
-  
-  qh_compare_vertexpoint( p1, p2 )
-    used by qsort() to order vertices by point id 
-*/
-int qh_compare_vertexpoint(const void *p1, const void *p2) {
-  vertexT *a= *((vertexT **)p1), *b= *((vertexT **)p2);
- 
-  return ((qh_pointid(a->point) > qh_pointid(b->point)?1:-1));
-} /* compare_vertexpoint */
-
-/*---------------------------------
-  
-  qh_compare_facetarea( p1, p2 )
-    used by qsort() to order facets by area
-*/
-static int qh_compare_facetarea(const void *p1, const void *p2) {
-  facetT *a= *((facetT **)p1), *b= *((facetT **)p2);
-
-  if (!a->isarea)
-    return -1;
-  if (!b->isarea)
-    return 1; 
-  if (a->f.area > b->f.area)
-    return 1;
-  else if (a->f.area == b->f.area)
-    return 0;
-  return -1;
-} /* compare_facetarea */
-
-/*---------------------------------
-  
-  qh_compare_facetmerge( p1, p2 )
-    used by qsort() to order facets by number of merges
-*/
-static int qh_compare_facetmerge(const void *p1, const void *p2) {
-  facetT *a= *((facetT **)p1), *b= *((facetT **)p2);
- 
-  return (a->nummerge - b->nummerge);
-} /* compare_facetvisit */
-
-/*---------------------------------
-  
-  qh_compare_facetvisit( p1, p2 )
-    used by qsort() to order facets by visit id or id
-*/
-static int qh_compare_facetvisit(const void *p1, const void *p2) {
-  facetT *a= *((facetT **)p1), *b= *((facetT **)p2);
-  int i,j;
-
-  if (!(i= a->visitid))
-    i= - a->id; /* do not convert to int */
-  if (!(j= b->visitid))
-    j= - b->id;
-  return (i - j);
-} /* compare_facetvisit */
-
-/*---------------------------------
-  
-  qh_countfacets( facetlist, facets, printall, 
-          numfacets, numsimplicial, totneighbors, numridges, numcoplanar, numtricoplanars  )
-    count good facets for printing and set visitid
-    if allfacets, ignores qh_skipfacet()
-
-  notes:
-    qh_printsummary and qh_countfacets must match counts
-
-  returns:
-    numfacets, numsimplicial, total neighbors, numridges, coplanars
-    each facet with ->visitid indicating 1-relative position
-      ->visitid==0 indicates not good
-  
-  notes
-    numfacets >= numsimplicial
-    if qh.NEWfacets, 
-      does not count visible facets (matches qh_printafacet)
-
-  design:
-    for all facets on facetlist and in facets set
-      unless facet is skipped or visible (i.e., will be deleted)
-        mark facet->visitid
-        update counts
-*/
-void qh_countfacets (facetT *facetlist, setT *facets, boolT printall,
-    int *numfacetsp, int *numsimplicialp, int *totneighborsp, int *numridgesp, int *numcoplanarsp, int *numtricoplanarsp) {
-  facetT *facet, **facetp;
-  int numfacets= 0, numsimplicial= 0, numridges= 0, totneighbors= 0, numcoplanars= 0, numtricoplanars= 0;
-
-  FORALLfacet_(facetlist) {
-    if ((facet->visible && qh NEWfacets)
-    || (!printall && qh_skipfacet(facet)))
-      facet->visitid= 0;
-    else {
-      facet->visitid= ++numfacets;
-      totneighbors += qh_setsize (facet->neighbors);
-      if (facet->simplicial) {
-        numsimplicial++;
-	if (facet->keepcentrum && facet->tricoplanar)
-	  numtricoplanars++;
-      }else
-        numridges += qh_setsize (facet->ridges);
-      if (facet->coplanarset)
-        numcoplanars += qh_setsize (facet->coplanarset);
-    }
-  }
-  FOREACHfacet_(facets) {
-    if ((facet->visible && qh NEWfacets)
-    || (!printall && qh_skipfacet(facet)))
-      facet->visitid= 0;
-    else {
-      facet->visitid= ++numfacets;
-      totneighbors += qh_setsize (facet->neighbors);
-      if (facet->simplicial){
-        numsimplicial++;
-	if (facet->keepcentrum && facet->tricoplanar)
-	  numtricoplanars++;
-      }else
-        numridges += qh_setsize (facet->ridges);
-      if (facet->coplanarset)
-        numcoplanars += qh_setsize (facet->coplanarset);
-    }
-  }
-  qh visit_id += numfacets+1;
-  *numfacetsp= numfacets;
-  *numsimplicialp= numsimplicial;
-  *totneighborsp= totneighbors;
-  *numridgesp= numridges;
-  *numcoplanarsp= numcoplanars;
-  *numtricoplanarsp= numtricoplanars;
-} /* countfacets */
-
-/*---------------------------------
-  
-  qh_detvnorm( vertex, vertexA, centers, offset )
-    compute separating plane of the Voronoi diagram for a pair of input sites
-    centers= set of facets (i.e., Voronoi vertices)
-      facet->visitid= 0 iff vertex-at-infinity (i.e., unbounded)
-        
-  assumes:
-    qh_ASvoronoi and qh_vertexneighbors() already set
-  
-  returns:
-    norm
-      a pointer into qh.gm_matrix to qh.hull_dim-1 reals
-      copy the data before reusing qh.gm_matrix
-    offset
-      if 'QVn'
-        sign adjusted so that qh.GOODvertexp is inside
-      else
-        sign adjusted so that vertex is inside
-      
-    qh.gm_matrix= simplex of points from centers relative to first center
-    
-  notes:
-    in io.c so that code for 'v Tv' can be removed by removing io.c
-    returns pointer into qh.gm_matrix to avoid tracking of temporary memory
-  
-  design:
-    determine midpoint of input sites
-    build points as the set of Voronoi vertices
-    select a simplex from points (if necessary)
-      include midpoint if the Voronoi region is unbounded
-    relocate the first vertex of the simplex to the origin
-    compute the normalized hyperplane through the simplex
-    orient the hyperplane toward 'QVn' or 'vertex'
-    if 'Tv' or 'Ts'
-      if bounded
-        test that hyperplane is the perpendicular bisector of the input sites
-      test that Voronoi vertices not in the simplex are still on the hyperplane
-    free up temporary memory
-*/
-pointT *qh_detvnorm (vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp) {
-  facetT *facet, **facetp;
-  int  i, k, pointid, pointidA, point_i, point_n;
-  setT *simplex= NULL;
-  pointT *point, **pointp, *point0, *midpoint, *normal, *inpoint;
-  coordT *coord, *gmcoord, *normalp;
-  setT *points= qh_settemp (qh TEMPsize);
-  boolT nearzero= False;
-  boolT unbounded= False;
-  int numcenters= 0;
-  int dim= qh hull_dim - 1;
-  realT dist, offset, angle, zero= 0.0;
-
-  midpoint= qh gm_matrix + qh hull_dim * qh hull_dim;  /* last row */
-  for (k= 0; k < dim; k++)
-    midpoint[k]= (vertex->point[k] + vertexA->point[k])/2;
-  FOREACHfacet_(centers) {
-    numcenters++;
-    if (!facet->visitid)
-      unbounded= True;
-    else {
-      if (!facet->center)
-        facet->center= qh_facetcenter (facet->vertices);
-      qh_setappend (&points, facet->center);
-    }
-  }
-  if (numcenters > dim) {
-    simplex= qh_settemp (qh TEMPsize);
-    qh_setappend (&simplex, vertex->point);
-    if (unbounded)
-      qh_setappend (&simplex, midpoint);
-    qh_maxsimplex (dim, points, NULL, 0, &simplex);
-    qh_setdelnth (simplex, 0);
-  }else if (numcenters == dim) {
-    if (unbounded)
-      qh_setappend (&points, midpoint);
-    simplex= points; 
-  }else {
-    fprintf(qh ferr, "qh_detvnorm: too few points (%d) to compute separating plane\n", numcenters);
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-  i= 0;
-  gmcoord= qh gm_matrix;
-  point0= SETfirstt_(simplex, pointT);
-  FOREACHpoint_(simplex) {
-    if (qh IStracing >= 4)
-      qh_printmatrix(qh ferr, "qh_detvnorm: Voronoi vertex or midpoint", 
-                              &point, 1, dim);
-    if (point != point0) {
-      qh gm_row[i++]= gmcoord;
-      coord= point0;
-      for (k= dim; k--; )
-        *(gmcoord++)= *point++ - *coord++;
-    }
-  }
-  qh gm_row[i]= gmcoord;  /* does not overlap midpoint, may be used later for qh_areasimplex */
-  normal= gmcoord;
-  qh_sethyperplane_gauss (dim, qh gm_row, point0, True,
-           	normal, &offset, &nearzero);
-  if (qh GOODvertexp == vertexA->point)
-    inpoint= vertexA->point;
-  else
-    inpoint= vertex->point;
-  zinc_(Zdistio);
-  dist= qh_distnorm (dim, inpoint, normal, &offset);
-  if (dist > 0) {
-    offset= -offset;
-    normalp= normal;
-    for (k= dim; k--; ) {
-      *normalp= -(*normalp);
-      normalp++;
-    }
-  }
-  if (qh VERIFYoutput || qh PRINTstatistics) {
-    pointid= qh_pointid (vertex->point);
-    pointidA= qh_pointid (vertexA->point);
-    if (!unbounded) {
-      zinc_(Zdiststat);
-      dist= qh_distnorm (dim, midpoint, normal, &offset);
-      if (dist < 0)
-        dist= -dist;
-      zzinc_(Zridgemid);
-      wwmax_(Wridgemidmax, dist);
-      wwadd_(Wridgemid, dist);
-      trace4((qh ferr, "qh_detvnorm: points %d %d midpoint dist %2.2g\n",
-                 pointid, pointidA, dist));
-      for (k= 0; k < dim; k++) 
-        midpoint[k]= vertexA->point[k] - vertex->point[k];  /* overwrites midpoint! */
-      qh_normalize (midpoint, dim, False);
-      angle= qh_distnorm (dim, midpoint, normal, &zero); /* qh_detangle uses dim+1 */
-      if (angle < 0.0)
-	angle= angle + 1.0;
-      else
-	angle= angle - 1.0;
-      if (angle < 0.0)
-	angle -= angle;
-      trace4((qh ferr, "qh_detvnorm: points %d %d angle %2.2g nearzero %d\n",
-                 pointid, pointidA, angle, nearzero));
-      if (nearzero) {
-        zzinc_(Zridge0);
-        wwmax_(Wridge0max, angle);
-        wwadd_(Wridge0, angle);
-      }else {
-        zzinc_(Zridgeok)
-        wwmax_(Wridgeokmax, angle);
-        wwadd_(Wridgeok, angle);
-      }
-    }
-    if (simplex != points) {
-      FOREACHpoint_i_(points) {
-        if (!qh_setin (simplex, point)) {
-          facet= SETelemt_(centers, point_i, facetT);
-	  zinc_(Zdiststat);
-  	  dist= qh_distnorm (dim, point, normal, &offset);
-          if (dist < 0)
-            dist= -dist;
-	  zzinc_(Zridge);
-          wwmax_(Wridgemax, dist);
-          wwadd_(Wridge, dist);
-          trace4((qh ferr, "qh_detvnorm: points %d %d Voronoi vertex %d dist %2.2g\n",
-                             pointid, pointidA, facet->visitid, dist));
-        }
-      }
-    }
-  }
-  *offsetp= offset;
-  if (simplex != points)
-    qh_settempfree (&simplex);
-  qh_settempfree (&points);
-  return normal;
-} /* detvnorm */
-
-/*---------------------------------
-
-  qh_detvridge( vertexA )
-    determine Voronoi ridge from 'seen' neighbors of vertexA
-    include one vertex-at-infinite if an !neighbor->visitid
-
-  returns:
-    temporary set of centers (facets, i.e., Voronoi vertices)
-    sorted by center id
-*/
-setT *qh_detvridge (vertexT *vertex) {
-  setT *centers= qh_settemp (qh TEMPsize);
-  setT *tricenters= qh_settemp (qh TEMPsize);
-  facetT *neighbor, **neighborp;
-  boolT firstinf= True;
-  
-  FOREACHneighbor_(vertex) {
-    if (neighbor->seen) {
-      if (neighbor->visitid) {
-	if (!neighbor->tricoplanar || qh_setunique (&tricenters, neighbor->center)) 
-	  qh_setappend (¢ers, neighbor);
-      }else if (firstinf) {
-        firstinf= False;
-        qh_setappend (¢ers, neighbor);
-      }
-    }
-  }
-  qsort (SETaddr_(centers, facetT), qh_setsize (centers),
-             sizeof (facetT *), qh_compare_facetvisit);
-  qh_settempfree (&tricenters);
-  return centers;
-} /* detvridge */      
-
-/*---------------------------------
-
-  qh_detvridge3( atvertex, vertex )
-    determine 3-d Voronoi ridge from 'seen' neighbors of atvertex and vertex
-    include one vertex-at-infinite for !neighbor->visitid
-    assumes all facet->seen2= True
-
-  returns:
-    temporary set of centers (facets, i.e., Voronoi vertices)
-    listed in adjacency order (not oriented)
-    all facet->seen2= True
-
-  design:
-    mark all neighbors of atvertex
-    for each adjacent neighbor of both atvertex and vertex
-      if neighbor selected
-        add neighbor to set of Voronoi vertices
-*/
-setT *qh_detvridge3 (vertexT *atvertex, vertexT *vertex) {
-  setT *centers= qh_settemp (qh TEMPsize);
-  setT *tricenters= qh_settemp (qh TEMPsize);
-  facetT *neighbor, **neighborp, *facet= NULL;
-  boolT firstinf= True;
-  
-  FOREACHneighbor_(atvertex)
-    neighbor->seen2= False;
-  FOREACHneighbor_(vertex) {
-    if (!neighbor->seen2) {
-      facet= neighbor;
-      break;
-    }
-  }
-  while (facet) { 
-    facet->seen2= True;
-    if (neighbor->seen) {
-      if (facet->visitid) {
-	if (!facet->tricoplanar || qh_setunique (&tricenters, facet->center)) 
-	  qh_setappend (¢ers, facet);
-      }else if (firstinf) {
-        firstinf= False;
-        qh_setappend (¢ers, facet);
-      }
-    }
-    FOREACHneighbor_(facet) {
-      if (!neighbor->seen2) {
-	if (qh_setin (vertex->neighbors, neighbor))
-          break;
-	else
-	  neighbor->seen2= True;
-      }
-    }
-    facet= neighbor;
-  }
-  if (qh CHECKfrequently) {
-    FOREACHneighbor_(vertex) {
-      if (!neighbor->seen2) {
-	fprintf (stderr, "qh_detvridge3: neigbors of vertex p%d are not connected at facet %d\n",
-	         qh_pointid (vertex->point), neighbor->id);
-	qh_errexit (qh_ERRqhull, neighbor, NULL);
-      }
-    }
-  }
-  FOREACHneighbor_(atvertex) 
-    neighbor->seen2= True;
-  qh_settempfree (&tricenters);
-  return centers;
-} /* detvridge3 */      
-
-/*---------------------------------
-  
-  qh_eachvoronoi( fp, printvridge, vertex, visitall, innerouter, inorder )
-    if visitall,
-      visit all Voronoi ridges for vertex (i.e., an input site)
-    else
-      visit all unvisited Voronoi ridges for vertex
-      all vertex->seen= False if unvisited
-    assumes
-      all facet->seen= False
-      all facet->seen2= True (for qh_detvridge3)
-      all facet->visitid == 0 if vertex_at_infinity
-                         == index of Voronoi vertex 
-                         >= qh.num_facets if ignored
-    innerouter:
-      qh_RIDGEall--  both inner (bounded) and outer (unbounded) ridges
-      qh_RIDGEinner- only inner
-      qh_RIDGEouter- only outer
-      
-    if inorder
-      orders vertices for 3-d Voronoi diagrams
-  
-  returns:
-    number of visited ridges (does not include previously visited ridges)
-    
-    if printvridge,
-      calls printvridge( fp, vertex, vertexA, centers)
-        fp== any pointer (assumes FILE*)
-        vertex,vertexA= pair of input sites that define a Voronoi ridge
-        centers= set of facets (i.e., Voronoi vertices)
-                 ->visitid == index or 0 if vertex_at_infinity
-                 ordered for 3-d Voronoi diagram
-  notes:
-    uses qh.vertex_visit
-  
-  see:
-    qh_eachvoronoi_all()
-  
-  design:
-    mark selected neighbors of atvertex
-    for each selected neighbor (either Voronoi vertex or vertex-at-infinity)
-      for each unvisited vertex 
-        if atvertex and vertex share more than d-1 neighbors
-          bump totalcount
-          if printvridge defined
-            build the set of shared neighbors (i.e., Voronoi vertices)
-            call printvridge
-*/
-int qh_eachvoronoi (FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder) {
-  boolT unbounded;
-  int count;
-  facetT *neighbor, **neighborp, *neighborA, **neighborAp;
-  setT *centers;
-  setT *tricenters= qh_settemp (qh TEMPsize);
-
-  vertexT *vertex, **vertexp;
-  boolT firstinf;
-  unsigned int numfacets= (unsigned int)qh num_facets;
-  int totridges= 0;
-
-  qh vertex_visit++;
-  atvertex->seen= True;
-  if (visitall) {
-    FORALLvertices 
-      vertex->seen= False;
-  }
-  FOREACHneighbor_(atvertex) {
-    if (neighbor->visitid < numfacets) 
-      neighbor->seen= True;
-  }
-  FOREACHneighbor_(atvertex) {
-    if (neighbor->seen) {
-      FOREACHvertex_(neighbor->vertices) {
-        if (vertex->visitid != qh vertex_visit && !vertex->seen) {
-	  vertex->visitid= qh vertex_visit;
-          count= 0;
-          firstinf= True;
-	  qh_settruncate (tricenters, 0);
-          FOREACHneighborA_(vertex) {
-            if (neighborA->seen) {
-	      if (neighborA->visitid) {
-		if (!neighborA->tricoplanar || qh_setunique (&tricenters, neighborA->center))
-		  count++;
-              }else if (firstinf) {
-                count++;
-                firstinf= False;
-	      }
-	    }
-          }
-          if (count >= qh hull_dim - 1) {  /* e.g., 3 for 3-d Voronoi */
-            if (firstinf) {
-              if (innerouter == qh_RIDGEouter)
-                continue;
-              unbounded= False;
-            }else {
-              if (innerouter == qh_RIDGEinner)
-                continue;
-              unbounded= True;
-            }
-            totridges++;
-            trace4((qh ferr, "qh_eachvoronoi: Voronoi ridge of %d vertices between sites %d and %d\n",
-                  count, qh_pointid (atvertex->point), qh_pointid (vertex->point)));
-            if (printvridge) { 
-	      if (inorder && qh hull_dim == 3+1) /* 3-d Voronoi diagram */
-                centers= qh_detvridge3 (atvertex, vertex);
-	      else
-                centers= qh_detvridge (vertex);
-              (*printvridge) (fp, atvertex, vertex, centers, unbounded);
-              qh_settempfree (¢ers);
-            }
-          }
-        }
-      }
-    }
-  }
-  FOREACHneighbor_(atvertex) 
-    neighbor->seen= False;
-  qh_settempfree (&tricenters);
-  return totridges;
-} /* eachvoronoi */
-  
-
-/*---------------------------------
-  
-  qh_eachvoronoi_all( fp, printvridge, isupper, innerouter, inorder )
-    visit all Voronoi ridges
-    
-    innerouter:
-      see qh_eachvoronoi()
-      
-    if inorder
-      orders vertices for 3-d Voronoi diagrams
-    
-  returns
-    total number of ridges 
-
-    if isupper == facet->upperdelaunay  (i.e., a Vornoi vertex)
-      facet->visitid= Voronoi vertex index (same as 'o' format)
-    else 
-      facet->visitid= 0
-
-    if printvridge,
-      calls printvridge( fp, vertex, vertexA, centers)
-      [see qh_eachvoronoi]
-      
-  notes:
-    Not used for qhull.exe
-    same effect as qh_printvdiagram but ridges not sorted by point id
-*/
-int qh_eachvoronoi_all (FILE *fp, printvridgeT printvridge, boolT isupper, qh_RIDGE innerouter, boolT inorder) {
-  facetT *facet;
-  vertexT *vertex;
-  int numcenters= 1;  /* vertex 0 is vertex-at-infinity */
-  int totridges= 0;
-
-  qh_clearcenters (qh_ASvoronoi);
-  qh_vertexneighbors();
-  maximize_(qh visit_id, (unsigned) qh num_facets);
-  FORALLfacets {
-    facet->visitid= 0;
-    facet->seen= False;
-    facet->seen2= True;
-  }
-  FORALLfacets {
-    if (facet->upperdelaunay == isupper)
-      facet->visitid= numcenters++;
-  }
-  FORALLvertices 
-    vertex->seen= False;
-  FORALLvertices {
-    if (qh GOODvertex > 0 && qh_pointid(vertex->point)+1 != qh GOODvertex)
-      continue;
-    totridges += qh_eachvoronoi (fp, printvridge, vertex, 
-                   !qh_ALL, innerouter, inorder);
-  }
-  return totridges;
-} /* eachvoronoi_all */
-      
-/*---------------------------------
-  
-  qh_facet2point( facet, point0, point1, mindist )
-    return two projected temporary vertices for a 2-d facet
-    may be non-simplicial
-
-  returns:
-    point0 and point1 oriented and projected to the facet
-    returns mindist (maximum distance below plane)
-*/
-void qh_facet2point(facetT *facet, pointT **point0, pointT **point1, realT *mindist) {
-  vertexT *vertex0, *vertex1;
-  realT dist;
-  
-  if (facet->toporient ^ qh_ORIENTclock) {
-    vertex0= SETfirstt_(facet->vertices, vertexT);
-    vertex1= SETsecondt_(facet->vertices, vertexT);
-  }else {
-    vertex1= SETfirstt_(facet->vertices, vertexT);
-    vertex0= SETsecondt_(facet->vertices, vertexT);
-  }
-  zadd_(Zdistio, 2);
-  qh_distplane(vertex0->point, facet, &dist);
-  *mindist= dist;
-  *point0= qh_projectpoint(vertex0->point, facet, dist);
-  qh_distplane(vertex1->point, facet, &dist);
-  minimize_(*mindist, dist);		
-  *point1= qh_projectpoint(vertex1->point, facet, dist);
-} /* facet2point */
-
-
-/*---------------------------------
-  
-  qh_facetvertices( facetlist, facets, allfacets )
-    returns temporary set of vertices in a set and/or list of facets
-    if allfacets, ignores qh_skipfacet()
-
-  returns:
-    vertices with qh.vertex_visit
-    
-  notes:
-    optimized for allfacets of facet_list
-
-  design:
-    if allfacets of facet_list
-      create vertex set from vertex_list
-    else
-      for each selected facet in facets or facetlist
-        append unvisited vertices to vertex set
-*/
-setT *qh_facetvertices (facetT *facetlist, setT *facets, boolT allfacets) {
-  setT *vertices;
-  facetT *facet, **facetp;
-  vertexT *vertex, **vertexp;
-
-  qh vertex_visit++;
-  if (facetlist == qh facet_list && allfacets && !facets) {
-    vertices= qh_settemp (qh num_vertices);
-    FORALLvertices {
-      vertex->visitid= qh vertex_visit; 
-      qh_setappend (&vertices, vertex);
-    }
-  }else {
-    vertices= qh_settemp (qh TEMPsize);
-    FORALLfacet_(facetlist) {
-      if (!allfacets && qh_skipfacet (facet))
-        continue;
-      FOREACHvertex_(facet->vertices) {
-        if (vertex->visitid != qh vertex_visit) {
-          vertex->visitid= qh vertex_visit;
-          qh_setappend (&vertices, vertex);
-        }
-      }
-    }
-  }
-  FOREACHfacet_(facets) {
-    if (!allfacets && qh_skipfacet (facet))
-      continue;
-    FOREACHvertex_(facet->vertices) {
-      if (vertex->visitid != qh vertex_visit) {
-        vertex->visitid= qh vertex_visit;
-        qh_setappend (&vertices, vertex);
-      }
-    }
-  }
-  return vertices;
-} /* facetvertices */
-
-/*---------------------------------
-  
-  qh_geomplanes( facet, outerplane, innerplane )
-    return outer and inner planes for Geomview 
-    qh.PRINTradius is size of vertices and points (includes qh.JOGGLEmax)
-
-  notes:
-    assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
-*/
-void qh_geomplanes (facetT *facet, realT *outerplane, realT *innerplane) {
-  realT radius;
-
-  if (qh MERGING || qh JOGGLEmax < REALmax/2) {
-    qh_outerinner (facet, outerplane, innerplane);
-    radius= qh PRINTradius;
-    if (qh JOGGLEmax < REALmax/2)
-      radius -= qh JOGGLEmax * sqrt (qh hull_dim);  /* already accounted for in qh_outerinner() */
-    *outerplane += radius;
-    *innerplane -= radius;
-    if (qh PRINTcoplanar || qh PRINTspheres) {
-      *outerplane += qh MAXabs_coord * qh_GEOMepsilon;
-      *innerplane -= qh MAXabs_coord * qh_GEOMepsilon;
-    }
-  }else 
-    *innerplane= *outerplane= 0;
-} /* geomplanes */
-
-
-/*---------------------------------
-  
-  qh_markkeep( facetlist )
-    mark good facets that meet qh.KEEParea, qh.KEEPmerge, and qh.KEEPminArea
-    ignores visible facets (not part of convex hull)
-
-  returns:
-    may clear facet->good
-    recomputes qh.num_good
-
-  design:
-    get set of good facets
-    if qh.KEEParea
-      sort facets by area
-      clear facet->good for all but n largest facets
-    if qh.KEEPmerge
-      sort facets by merge count
-      clear facet->good for all but n most merged facets
-    if qh.KEEPminarea
-      clear facet->good if area too small
-    update qh.num_good    
-*/
-void qh_markkeep (facetT *facetlist) {
-  facetT *facet, **facetp;
-  setT *facets= qh_settemp (qh num_facets);
-  int size, count;
-
-  trace2((qh ferr, "qh_markkeep: only keep %d largest and/or %d most merged facets and/or min area %.2g\n",
-          qh KEEParea, qh KEEPmerge, qh KEEPminArea));
-  FORALLfacet_(facetlist) {
-    if (!facet->visible && facet->good)
-      qh_setappend (&facets, facet);
-  }
-  size= qh_setsize (facets);
-  if (qh KEEParea) {
-    qsort (SETaddr_(facets, facetT), size,
-             sizeof (facetT *), qh_compare_facetarea);
-    if ((count= size - qh KEEParea) > 0) {
-      FOREACHfacet_(facets) {
-        facet->good= False;
-        if (--count == 0)
-          break;
-      }
-    }
-  }
-  if (qh KEEPmerge) {
-    qsort (SETaddr_(facets, facetT), size,
-             sizeof (facetT *), qh_compare_facetmerge);
-    if ((count= size - qh KEEPmerge) > 0) {
-      FOREACHfacet_(facets) {
-        facet->good= False;
-        if (--count == 0)
-          break;
-      }
-    }
-  }
-  if (qh KEEPminArea < REALmax/2) {
-    FOREACHfacet_(facets) {
-      if (!facet->isarea || facet->f.area < qh KEEPminArea)
-	facet->good= False;
-    }
-  }
-  qh_settempfree (&facets);
-  count= 0;
-  FORALLfacet_(facetlist) {
-    if (facet->good)
-      count++;
-  }
-  qh num_good= count;
-} /* markkeep */
-
-
-/*---------------------------------
-  
-  qh_markvoronoi( facetlist, facets, printall, islower, numcenters )
-    mark voronoi vertices for printing by site pairs
-  
-  returns:
-    temporary set of vertices indexed by pointid
-    islower set if printing lower hull (i.e., at least one facet is lower hull)
-    numcenters= total number of Voronoi vertices
-    bumps qh.printoutnum for vertex-at-infinity
-    clears all facet->seen and sets facet->seen2
-    
-    if selected
-      facet->visitid= Voronoi vertex id
-    else if upper hull (or 'Qu' and lower hull)
-      facet->visitid= 0
-    else
-      facet->visitid >= qh num_facets
-  
-  notes:
-    ignores qh.ATinfinity, if defined
-*/
-setT *qh_markvoronoi (facetT *facetlist, setT *facets, boolT printall, boolT *islowerp, int *numcentersp) {
-  int numcenters=0;
-  facetT *facet, **facetp;
-  setT *vertices;
-  boolT islower= False;
-
-  qh printoutnum++;
-  qh_clearcenters (qh_ASvoronoi);  /* in case, qh_printvdiagram2 called by user */
-  qh_vertexneighbors();
-  vertices= qh_pointvertex();
-  if (qh ATinfinity) 
-    SETelem_(vertices, qh num_points-1)= NULL;
-  qh visit_id++;
-  maximize_(qh visit_id, (unsigned) qh num_facets);
-  FORALLfacet_(facetlist) { 
-    if (printall || !qh_skipfacet (facet)) {
-      if (!facet->upperdelaunay) {
-        islower= True;
-	break;
-      }
-    }
-  }
-  FOREACHfacet_(facets) {
-    if (printall || !qh_skipfacet (facet)) {
-      if (!facet->upperdelaunay) {
-        islower= True;
-	break;
-      }
-    }
-  }
-  FORALLfacets {
-    if (facet->normal && (facet->upperdelaunay == islower))
-      facet->visitid= 0;  /* facetlist or facets may overwrite */
-    else
-      facet->visitid= qh visit_id;
-    facet->seen= False;
-    facet->seen2= True;
-  }
-  numcenters++;  /* qh_INFINITE */
-  FORALLfacet_(facetlist) {
-    if (printall || !qh_skipfacet (facet))
-      facet->visitid= numcenters++;
-  }
-  FOREACHfacet_(facets) {
-    if (printall || !qh_skipfacet (facet))
-      facet->visitid= numcenters++;  
-  }
-  *islowerp= islower;
-  *numcentersp= numcenters;
-  trace2((qh ferr, "qh_markvoronoi: islower %d numcenters %d\n", islower, numcenters));
-  return vertices;
-} /* markvoronoi */
-
-/*---------------------------------
-  
-  qh_order_vertexneighbors( vertex )
-    order facet neighbors of a 2-d or 3-d vertex by adjacency
-
-  notes:
-    does not orient the neighbors
-
-  design:
-    initialize a new neighbor set with the first facet in vertex->neighbors
-    while vertex->neighbors non-empty
-      select next neighbor in the previous facet's neighbor set
-    set vertex->neighbors to the new neighbor set
-*/
-void qh_order_vertexneighbors(vertexT *vertex) {
-  setT *newset;
-  facetT *facet, *neighbor, **neighborp;
-
-  trace4((qh ferr, "qh_order_vertexneighbors: order neighbors of v%d for 3-d\n", vertex->id));
-  newset= qh_settemp (qh_setsize (vertex->neighbors));
-  facet= (facetT*)qh_setdellast (vertex->neighbors);
-  qh_setappend (&newset, facet);
-  while (qh_setsize (vertex->neighbors)) {
-    FOREACHneighbor_(vertex) {
-      if (qh_setin (facet->neighbors, neighbor)) {
-        qh_setdel(vertex->neighbors, neighbor);
-        qh_setappend (&newset, neighbor);
-        facet= neighbor;
-        break;
-      }
-    }
-    if (!neighbor) {
-      fprintf (qh ferr, "qhull internal error (qh_order_vertexneighbors): no neighbor of v%d for f%d\n",
-        vertex->id, facet->id);
-      qh_errexit (qh_ERRqhull, facet, NULL);
-    }
-  }
-  qh_setfree (&vertex->neighbors);
-  qh_settemppop ();
-  vertex->neighbors= newset;
-} /* order_vertexneighbors */
-
-/*---------------------------------
-  
-  qh_printafacet( fp, format, facet, printall )
-    print facet to fp in given output format (see qh.PRINTout)
-
-  returns:
-    nop if !printall and qh_skipfacet()
-    nop if visible facet and NEWfacets and format != PRINTfacets
-    must match qh_countfacets
-
-  notes
-    preserves qh.visit_id
-    facet->normal may be null if PREmerge/MERGEexact and STOPcone before merge
-
-  see
-    qh_printbegin() and qh_printend()
-
-  design:
-    test for printing facet
-    call appropriate routine for format
-    or output results directly
-*/
-void qh_printafacet(FILE *fp, int format, facetT *facet, boolT printall) {
-  realT color[4], offset, dist, outerplane, innerplane;
-  boolT zerodiv;
-  coordT *point, *normp, *coordp, **pointp, *feasiblep;
-  int k;
-  vertexT *vertex, **vertexp;
-  facetT *neighbor, **neighborp;
-
-  if (!printall && qh_skipfacet (facet))
-    return;
-  if (facet->visible && qh NEWfacets && format != qh_PRINTfacets)
-    return;
-  qh printoutnum++;
-  switch (format) {
-  case qh_PRINTarea:
-    if (facet->isarea) {
-      fprintf (fp, qh_REAL_1, facet->f.area);
-      fprintf (fp, "\n");
-    }else
-      fprintf (fp, "0\n");
-    break;
-  case qh_PRINTcoplanars:
-    fprintf (fp, "%d", qh_setsize (facet->coplanarset));
-    FOREACHpoint_(facet->coplanarset)
-      fprintf (fp, " %d", qh_pointid (point));
-    fprintf (fp, "\n");
-    break;
-  case qh_PRINTcentrums:
-    qh_printcenter (fp, format, NULL, facet);
-    break;
-  case qh_PRINTfacets:
-    qh_printfacet (fp, facet);
-    break;
-  case qh_PRINTfacets_xridge:
-    qh_printfacetheader (fp, facet);
-    break;
-  case qh_PRINTgeom:  /* either 2 , 3, or 4-d by qh_printbegin */
-    if (!facet->normal)
-      break;
-    for (k= qh hull_dim; k--; ) {
-      color[k]= (facet->normal[k]+1.0)/2.0;
-      maximize_(color[k], -1.0);
-      minimize_(color[k], +1.0);
-    }
-    qh_projectdim3 (color, color);
-    if (qh PRINTdim != qh hull_dim)
-      qh_normalize2 (color, 3, True, NULL, NULL);
-    if (qh hull_dim <= 2)
-      qh_printfacet2geom (fp, facet, color);
-    else if (qh hull_dim == 3) {
-      if (facet->simplicial)
-        qh_printfacet3geom_simplicial (fp, facet, color);
-      else
-        qh_printfacet3geom_nonsimplicial (fp, facet, color);
-    }else {
-      if (facet->simplicial)
-        qh_printfacet4geom_simplicial (fp, facet, color);
-      else
-        qh_printfacet4geom_nonsimplicial (fp, facet, color);
-    }
-    break;
-  case qh_PRINTids:
-    fprintf (fp, "%d\n", facet->id);
-    break;
-  case qh_PRINTincidences:
-  case qh_PRINToff:
-  case qh_PRINTtriangles:
-    if (qh hull_dim == 3 && format != qh_PRINTtriangles) 
-      qh_printfacet3vertex (fp, facet, format);
-    else if (facet->simplicial || qh hull_dim == 2 || format == qh_PRINToff)
-      qh_printfacetNvertex_simplicial (fp, facet, format);
-    else
-      qh_printfacetNvertex_nonsimplicial (fp, facet, qh printoutvar++, format);
-    break;
-  case qh_PRINTinner:
-    qh_outerinner (facet, NULL, &innerplane);
-    offset= facet->offset - innerplane;
-    goto LABELprintnorm;
-    break; /* prevent warning */
-  case qh_PRINTmerges:
-    fprintf (fp, "%d\n", facet->nummerge);
-    break;
-  case qh_PRINTnormals:
-    offset= facet->offset;
-    goto LABELprintnorm;
-    break; /* prevent warning */
-  case qh_PRINTouter:
-    qh_outerinner (facet, &outerplane, NULL);
-    offset= facet->offset - outerplane;
-  LABELprintnorm:
-    if (!facet->normal) {
-      fprintf (fp, "no normal for facet f%d\n", facet->id);
-      break;
-    }
-    if (qh CDDoutput) {
-      fprintf (fp, qh_REAL_1, -offset);
-      for (k=0; k < qh hull_dim; k++) 
-	fprintf (fp, qh_REAL_1, -facet->normal[k]);
-    }else {
-      for (k=0; k < qh hull_dim; k++) 
-	fprintf (fp, qh_REAL_1, facet->normal[k]);
-      fprintf (fp, qh_REAL_1, offset);
-    }
-    fprintf (fp, "\n");
-    break;
-  case qh_PRINTmathematica:  /* either 2 or 3-d by qh_printbegin */
-    if (qh hull_dim == 2)
-      qh_printfacet2math (fp, facet, qh printoutvar++);
-    else 
-      qh_printfacet3math (fp, facet, qh printoutvar++);
-    break;
-  case qh_PRINTneighbors:
-    fprintf (fp, "%d", qh_setsize (facet->neighbors));
-    FOREACHneighbor_(facet)
-      fprintf (fp, " %d", 
-	       neighbor->visitid ? neighbor->visitid - 1: - neighbor->id);
-    fprintf (fp, "\n");
-    break;
-  case qh_PRINTpointintersect:
-    if (!qh feasible_point) {
-      fprintf (fp, "qhull input error (qh_printafacet): option 'Fp' needs qh feasible_point\n");
-      qh_errexit( qh_ERRinput, NULL, NULL);
-    }
-    if (facet->offset > 0)
-      goto LABELprintinfinite;
-    point= coordp= (coordT*)qh_memalloc (qh normal_size);
-    normp= facet->normal;
-    feasiblep= qh feasible_point;
-    if (facet->offset < -qh MINdenom) {
-      for (k= qh hull_dim; k--; )
-        *(coordp++)= (*(normp++) / - facet->offset) + *(feasiblep++);
-    }else {
-      for (k= qh hull_dim; k--; ) {
-        *(coordp++)= qh_divzero (*(normp++), facet->offset, qh MINdenom_1,
-				 &zerodiv) + *(feasiblep++);
-        if (zerodiv) {
-          qh_memfree (point, qh normal_size);
-          goto LABELprintinfinite;
-        }
-      }
-    }
-    qh_printpoint (fp, NULL, point);
-    qh_memfree (point, qh normal_size);
-    break;
-  LABELprintinfinite:
-    for (k= qh hull_dim; k--; )
-      fprintf (fp, qh_REAL_1, qh_INFINITE);
-    fprintf (fp, "\n");   
-    break;
-  case qh_PRINTpointnearest:
-    FOREACHpoint_(facet->coplanarset) {
-      int id, id2;
-      vertex= qh_nearvertex (facet, point, &dist);
-      id= qh_pointid (vertex->point);
-      id2= qh_pointid (point);
-      fprintf (fp, "%d %d %d " qh_REAL_1 "\n", id, id2, facet->id, dist);
-    }
-    break;
-  case qh_PRINTpoints:  /* VORONOI only by qh_printbegin */
-    if (qh CDDoutput)
-      fprintf (fp, "1 ");
-    qh_printcenter (fp, format, NULL, facet);
-    break;
-  case qh_PRINTvertices:
-    fprintf (fp, "%d", qh_setsize (facet->vertices));
-    FOREACHvertex_(facet->vertices)
-      fprintf (fp, " %d", qh_pointid (vertex->point));
-    fprintf (fp, "\n");
-    break;
-  }
-} /* printafacet */
-
-/*---------------------------------
-  
-  qh_printbegin(  )
-    prints header for all output formats
-
-  returns:
-    checks for valid format
-  
-  notes:
-    uses qh.visit_id for 3/4off
-    changes qh.interior_point if printing centrums
-    qh_countfacets clears facet->visitid for non-good facets
-    
-  see
-    qh_printend() and qh_printafacet()
-    
-  design:
-    count facets and related statistics
-    print header for format
-*/
-void qh_printbegin (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) {
-  int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
-  int i, num;
-  facetT *facet, **facetp;
-  vertexT *vertex, **vertexp;
-  setT *vertices;
-  pointT *point, **pointp, *pointtemp;
-
-  qh printoutnum= 0;
-  qh_countfacets (facetlist, facets, printall, &numfacets, &numsimplicial, 
-      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
-  switch (format) {
-  case qh_PRINTnone:
-    break;
-  case qh_PRINTarea:
-    fprintf (fp, "%d\n", numfacets);
-    break;
-  case qh_PRINTcoplanars:
-    fprintf (fp, "%d\n", numfacets);
-    break;
-  case qh_PRINTcentrums:
-    if (qh CENTERtype == qh_ASnone)
-      qh_clearcenters (qh_AScentrum);
-    fprintf (fp, "%d\n%d\n", qh hull_dim, numfacets);
-    break;
-  case qh_PRINTfacets:
-  case qh_PRINTfacets_xridge:
-    if (facetlist)
-      qh_printvertexlist (fp, "Vertices and facets:\n", facetlist, facets, printall);
-    break;
-  case qh_PRINTgeom: 
-    if (qh hull_dim > 4)  /* qh_initqhull_globals also checks */
-      goto LABELnoformat;
-    if (qh VORONOI && qh hull_dim > 3)  /* PRINTdim == DROPdim == hull_dim-1 */
-      goto LABELnoformat;
-    if (qh hull_dim == 2 && (qh PRINTridges || qh DOintersections))
-      fprintf (qh ferr, "qhull warning: output for ridges and intersections not implemented in 2-d\n");
-    if (qh hull_dim == 4 && (qh PRINTinner || qh PRINTouter ||
-			     (qh PRINTdim == 4 && qh PRINTcentrums)))
-      fprintf (qh ferr, "qhull warning: output for outer/inner planes and centrums not implemented in 4-d\n");
-    if (qh PRINTdim == 4 && (qh PRINTspheres))
-      fprintf (qh ferr, "qhull warning: output for vertices not implemented in 4-d\n");
-    if (qh PRINTdim == 4 && qh DOintersections && qh PRINTnoplanes)
-      fprintf (qh ferr, "qhull warning: 'Gnh' generates no output in 4-d\n");
-    if (qh PRINTdim == 2) {
-      fprintf(fp, "{appearance {linewidth 3} LIST # %s | %s\n",
-	      qh rbox_command, qh qhull_command);
-    }else if (qh PRINTdim == 3) {
-      fprintf(fp, "{appearance {+edge -evert linewidth 2} LIST # %s | %s\n",
-	      qh rbox_command, qh qhull_command);
-    }else if (qh PRINTdim == 4) {
-      qh visit_id++;
-      num= 0;
-      FORALLfacet_(facetlist)    /* get number of ridges to be printed */
-        qh_printend4geom (NULL, facet, &num, printall);
-      FOREACHfacet_(facets)
-        qh_printend4geom (NULL, facet, &num, printall);
-      qh ridgeoutnum= num;
-      qh printoutvar= 0;  /* counts number of ridges in output */
-      fprintf (fp, "LIST # %s | %s\n", qh rbox_command, qh qhull_command);
-    }
-    if (qh PRINTdots) {
-      qh printoutnum++;
-      num= qh num_points + qh_setsize (qh other_points);
-      if (qh DELAUNAY && qh ATinfinity)
-	num--;
-      if (qh PRINTdim == 4)
-        fprintf (fp, "4VECT %d %d 1\n", num, num);
-      else
-	fprintf (fp, "VECT %d %d 1\n", num, num);
-      for (i= num; i--; ) {
-        if (i % 20 == 0)
-          fprintf (fp, "\n");
-	fprintf (fp, "1 ");
-      }
-      fprintf (fp, "# 1 point per line\n1 ");
-      for (i= num-1; i--; ) {
-        if (i % 20 == 0)
-          fprintf (fp, "\n");
-	fprintf (fp, "0 ");
-      }
-      fprintf (fp, "# 1 color for all\n");
-      FORALLpoints {
-        if (!qh DELAUNAY || !qh ATinfinity || qh_pointid(point) != qh num_points-1) {
-	  if (qh PRINTdim == 4)
-	    qh_printpoint (fp, NULL, point);
-	  else
-	    qh_printpoint3 (fp, point);
-	}
-      }
-      FOREACHpoint_(qh other_points) {
-	if (qh PRINTdim == 4)
-	  qh_printpoint (fp, NULL, point);
-	else
-	  qh_printpoint3 (fp, point);
-      }
-      fprintf (fp, "0 1 1 1  # color of points\n");
-    }
-    if (qh PRINTdim == 4  && !qh PRINTnoplanes)
-      /* 4dview loads up multiple 4OFF objects slowly */
-      fprintf(fp, "4OFF %d %d 1\n", 3*qh ridgeoutnum, qh ridgeoutnum);
-    qh PRINTcradius= 2 * qh DISTround;  /* include test DISTround */
-    if (qh PREmerge) {
-      maximize_(qh PRINTcradius, qh premerge_centrum + qh DISTround);
-    }else if (qh POSTmerge)
-      maximize_(qh PRINTcradius, qh postmerge_centrum + qh DISTround);
-    qh PRINTradius= qh PRINTcradius;
-    if (qh PRINTspheres + qh PRINTcoplanar)
-      maximize_(qh PRINTradius, qh MAXabs_coord * qh_MINradius);
-    if (qh premerge_cos < REALmax/2) {
-      maximize_(qh PRINTradius, (1- qh premerge_cos) * qh MAXabs_coord);
-    }else if (!qh PREmerge && qh POSTmerge && qh postmerge_cos < REALmax/2) {
-      maximize_(qh PRINTradius, (1- qh postmerge_cos) * qh MAXabs_coord);
-    }
-    maximize_(qh PRINTradius, qh MINvisible); 
-    if (qh JOGGLEmax < REALmax/2)
-      qh PRINTradius += qh JOGGLEmax * sqrt (qh hull_dim);
-    if (qh PRINTdim != 4 &&
-	(qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
-      vertices= qh_facetvertices (facetlist, facets, printall);
-      if (qh PRINTspheres && qh PRINTdim <= 3)
-         qh_printspheres (fp, vertices, qh PRINTradius);
-      if (qh PRINTcoplanar || qh PRINTcentrums) {
-        qh firstcentrum= True;
-        if (qh PRINTcoplanar&& !qh PRINTspheres) {
-          FOREACHvertex_(vertices) 
-            qh_printpointvect2 (fp, vertex->point, NULL,
-				qh interior_point, qh PRINTradius);
-	}
-        FORALLfacet_(facetlist) {
-	  if (!printall && qh_skipfacet(facet))
-	    continue;
-	  if (!facet->normal)
-	    continue;
-          if (qh PRINTcentrums && qh PRINTdim <= 3)
-            qh_printcentrum (fp, facet, qh PRINTcradius);
-	  if (!qh PRINTcoplanar)
-	    continue;
-          FOREACHpoint_(facet->coplanarset)
-            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
-          FOREACHpoint_(facet->outsideset)
-            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
-        }
-        FOREACHfacet_(facets) {
-	  if (!printall && qh_skipfacet(facet))
-	    continue;
-	  if (!facet->normal)
-	    continue;
-          if (qh PRINTcentrums && qh PRINTdim <= 3)
-            qh_printcentrum (fp, facet, qh PRINTcradius);
-	  if (!qh PRINTcoplanar)
-	    continue;
-          FOREACHpoint_(facet->coplanarset)
-            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
-          FOREACHpoint_(facet->outsideset)
-            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
-        }
-      }
-      qh_settempfree (&vertices);
-    }
-    qh visit_id++; /* for printing hyperplane intersections */
-    break;
-  case qh_PRINTids:
-    fprintf (fp, "%d\n", numfacets);
-    break;
-  case qh_PRINTincidences:
-    if (qh VORONOI && qh PRINTprecision)
-      fprintf (qh ferr, "qhull warning: writing Delaunay.  Use 'p' or 'o' for Voronoi centers\n");
-    qh printoutvar= qh vertex_id;  /* centrum id for non-simplicial facets */
-    if (qh hull_dim <= 3)
-      fprintf(fp, "%d\n", numfacets);
-    else
-      fprintf(fp, "%d\n", numsimplicial+numridges);
-    break;
-  case qh_PRINTinner:
-  case qh_PRINTnormals:
-  case qh_PRINTouter:
-    if (qh CDDoutput)
-      fprintf (fp, "%s | %s\nbegin\n    %d %d real\n", qh rbox_command, 
-              qh qhull_command, numfacets, qh hull_dim+1);
-    else
-      fprintf (fp, "%d\n%d\n", qh hull_dim+1, numfacets);
-    break;
-  case qh_PRINTmathematica:  
-    if (qh hull_dim > 3)  /* qh_initbuffers also checks */
-      goto LABELnoformat;
-    if (qh VORONOI)
-      fprintf (qh ferr, "qhull warning: output is the Delaunay triangulation\n");
-    fprintf(fp, "{\n");
-    qh printoutvar= 0;   /* counts number of facets for notfirst */
-    break;
-  case qh_PRINTmerges:
-    fprintf (fp, "%d\n", numfacets);
-    break;
-  case qh_PRINTpointintersect:
-    fprintf (fp, "%d\n%d\n", qh hull_dim, numfacets);
-    break;
-  case qh_PRINTneighbors:
-    fprintf (fp, "%d\n", numfacets);
-    break;
-  case qh_PRINToff:
-  case qh_PRINTtriangles:
-    if (qh VORONOI)
-      goto LABELnoformat;
-    num = qh hull_dim;
-    if (format == qh_PRINToff || qh hull_dim == 2)
-      fprintf (fp, "%d\n%d %d %d\n", num, 
-        qh num_points+qh_setsize (qh other_points), numfacets, totneighbors/2);
-    else { /* qh_PRINTtriangles */
-      qh printoutvar= qh num_points+qh_setsize (qh other_points); /* first centrum */
-      if (qh DELAUNAY)
-        num--;  /* drop last dimension */
-      fprintf (fp, "%d\n%d %d %d\n", num, qh printoutvar 
-	+ numfacets - numsimplicial, numsimplicial + numridges, totneighbors/2);
-    }
-    FORALLpoints
-      qh_printpointid (qh fout, NULL, num, point, -1);
-    FOREACHpoint_(qh other_points)
-      qh_printpointid (qh fout, NULL, num, point, -1);
-    if (format == qh_PRINTtriangles && qh hull_dim > 2) {
-      FORALLfacets {
-	if (!facet->simplicial && facet->visitid)
-          qh_printcenter (qh fout, format, NULL, facet);
-      }
-    }
-    break;
-  case qh_PRINTpointnearest:
-    fprintf (fp, "%d\n", numcoplanars);
-    break;
-  case qh_PRINTpoints:
-    if (!qh VORONOI)
-      goto LABELnoformat;
-    if (qh CDDoutput)
-      fprintf (fp, "%s | %s\nbegin\n%d %d real\n", qh rbox_command,
-             qh qhull_command, numfacets, qh hull_dim);
-    else
-      fprintf (fp, "%d\n%d\n", qh hull_dim-1, numfacets);
-    break;
-  case qh_PRINTvertices:
-    fprintf (fp, "%d\n", numfacets);
-    break;
-  case qh_PRINTsummary:
-  default:
-  LABELnoformat:
-    fprintf (qh ferr, "qhull internal error (qh_printbegin): can not use this format for dimension %d\n",
-         qh hull_dim);
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-} /* printbegin */
-
-/*---------------------------------
-  
-  qh_printcenter( fp, string, facet )
-    print facet->center as centrum or Voronoi center
-    string may be NULL.  Don't include '%' codes.
-    nop if qh CENTERtype neither CENTERvoronoi nor CENTERcentrum
-    if upper envelope of Delaunay triangulation and point at-infinity
-      prints qh_INFINITE instead;
-
-  notes:
-    defines facet->center if needed
-    if format=PRINTgeom, adds a 0 if would otherwise be 2-d
-*/
-void qh_printcenter (FILE *fp, int format, char *string, facetT *facet) {
-  int k, num;
-
-  if (qh CENTERtype != qh_ASvoronoi && qh CENTERtype != qh_AScentrum)
-    return;
-  if (string)
-    fprintf (fp, string, facet->id);
-  if (qh CENTERtype == qh_ASvoronoi) {
-    num= qh hull_dim-1;
-    if (!facet->normal || !facet->upperdelaunay || !qh ATinfinity) {
-      if (!facet->center)
-        facet->center= qh_facetcenter (facet->vertices);
-      for (k=0; k < num; k++)
-        fprintf (fp, qh_REAL_1, facet->center[k]);
-    }else {
-      for (k=0; k < num; k++)
-        fprintf (fp, qh_REAL_1, qh_INFINITE);
-    }
-  }else /* qh CENTERtype == qh_AScentrum */ {
-    num= qh hull_dim;
-    if (format == qh_PRINTtriangles && qh DELAUNAY) 
-      num--;
-    if (!facet->center) 
-      facet->center= qh_getcentrum (facet);
-    for (k=0; k < num; k++)
-      fprintf (fp, qh_REAL_1, facet->center[k]);
-  }
-  if (format == qh_PRINTgeom && num == 2)
-    fprintf (fp, " 0\n");
-  else
-    fprintf (fp, "\n");
-} /* printcenter */
-
-/*---------------------------------
-  
-  qh_printcentrum( fp, facet, radius )
-    print centrum for a facet in OOGL format
-    radius defines size of centrum
-    2-d or 3-d only
-
-  returns:
-    defines facet->center if needed
-*/
-void qh_printcentrum (FILE *fp, facetT *facet, realT radius) {
-  pointT *centrum, *projpt;
-  boolT tempcentrum= False;
-  realT xaxis[4], yaxis[4], normal[4], dist;
-  realT green[3]={0, 1, 0};
-  vertexT *apex;
-  int k;
-  
-  if (qh CENTERtype == qh_AScentrum) {
-    if (!facet->center)
-      facet->center= qh_getcentrum (facet);
-    centrum= facet->center;
-  }else {
-    centrum= qh_getcentrum (facet);
-    tempcentrum= True;
-  }
-  fprintf (fp, "{appearance {-normal -edge normscale 0} ");
-  if (qh firstcentrum) {
-    qh firstcentrum= False;
-    fprintf (fp, "{INST geom { define centrum CQUAD  # f%d\n\
--0.3 -0.3 0.0001     0 0 1 1\n\
- 0.3 -0.3 0.0001     0 0 1 1\n\
- 0.3  0.3 0.0001     0 0 1 1\n\
--0.3  0.3 0.0001     0 0 1 1 } transform { \n", facet->id);
-  }else
-    fprintf (fp, "{INST geom { : centrum } transform { # f%d\n", facet->id);
-  apex= SETfirstt_(facet->vertices, vertexT);
-  qh_distplane(apex->point, facet, &dist);
-  projpt= qh_projectpoint(apex->point, facet, dist);
-  for (k= qh hull_dim; k--; ) {
-    xaxis[k]= projpt[k] - centrum[k];
-    normal[k]= facet->normal[k];
-  }
-  if (qh hull_dim == 2) {
-    xaxis[2]= 0;
-    normal[2]= 0;
-  }else if (qh hull_dim == 4) {
-    qh_projectdim3 (xaxis, xaxis);
-    qh_projectdim3 (normal, normal);
-    qh_normalize2 (normal, qh PRINTdim, True, NULL, NULL);
-  }
-  qh_crossproduct (3, xaxis, normal, yaxis);
-  fprintf (fp, "%8.4g %8.4g %8.4g 0\n", xaxis[0], xaxis[1], xaxis[2]);
-  fprintf (fp, "%8.4g %8.4g %8.4g 0\n", yaxis[0], yaxis[1], yaxis[2]);
-  fprintf (fp, "%8.4g %8.4g %8.4g 0\n", normal[0], normal[1], normal[2]);
-  qh_printpoint3 (fp, centrum);
-  fprintf (fp, "1 }}}\n"); 
-  qh_memfree (projpt, qh normal_size);
-  qh_printpointvect (fp, centrum, facet->normal, NULL, radius, green);
-  if (tempcentrum)
-    qh_memfree (centrum, qh normal_size);
-} /* printcentrum */
-  
-/*---------------------------------
-  
-  qh_printend( fp, format )
-    prints trailer for all output formats
-
-  see:
-    qh_printbegin() and qh_printafacet()
-      
-*/
-void qh_printend (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) {
-  int num;
-  facetT *facet, **facetp;
-
-  if (!qh printoutnum)
-    fprintf (qh ferr, "qhull warning: no facets printed\n");
-  switch (format) {
-  case qh_PRINTgeom:
-    if (qh hull_dim == 4 && qh DROPdim < 0  && !qh PRINTnoplanes) {
-      qh visit_id++;
-      num= 0;
-      FORALLfacet_(facetlist)
-        qh_printend4geom (fp, facet,&num, printall);
-      FOREACHfacet_(facets) 
-        qh_printend4geom (fp, facet, &num, printall);
-      if (num != qh ridgeoutnum || qh printoutvar != qh ridgeoutnum) {
-	fprintf (qh ferr, "qhull internal error (qh_printend): number of ridges %d != number printed %d and at end %d\n", qh ridgeoutnum, qh printoutvar, num);
-	qh_errexit (qh_ERRqhull, NULL, NULL);
-      }
-    }else
-      fprintf(fp, "}\n");
-    break;
-  case qh_PRINTinner:
-  case qh_PRINTnormals:
-  case qh_PRINTouter:
-    if (qh CDDoutput) 
-      fprintf (fp, "end\n");
-    break;
-  case qh_PRINTmathematica:
-    fprintf(fp, "}\n");
-    break;
-  case qh_PRINTpoints:
-    if (qh CDDoutput)
-      fprintf (fp, "end\n");
-    break;
-  }
-} /* printend */
-
-/*---------------------------------
-  
-  qh_printend4geom( fp, facet, numridges, printall )
-    helper function for qh_printbegin/printend
-
-  returns:
-    number of printed ridges
-  
-  notes:
-    just counts printed ridges if fp=NULL
-    uses facet->visitid
-    must agree with qh_printfacet4geom...
-
-  design:
-    computes color for facet from its normal
-    prints each ridge of facet 
-*/
-void qh_printend4geom (FILE *fp, facetT *facet, int *nump, boolT printall) {
-  realT color[3];
-  int i, num= *nump;
-  facetT *neighbor, **neighborp;
-  ridgeT *ridge, **ridgep;
-  
-  if (!printall && qh_skipfacet(facet))
-    return;
-  if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
-    return;
-  if (!facet->normal)
-    return;
-  if (fp) {
-    for (i=0; i < 3; i++) {
-      color[i]= (facet->normal[i]+1.0)/2.0;
-      maximize_(color[i], -1.0);
-      minimize_(color[i], +1.0);
-    }
-  }
-  facet->visitid= qh visit_id;
-  if (facet->simplicial) {
-    FOREACHneighbor_(facet) {
-      if (neighbor->visitid != qh visit_id) {
-	if (fp)
-          fprintf (fp, "3 %d %d %d %8.4g %8.4g %8.4g 1 # f%d f%d\n",
-		 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
-		 facet->id, neighbor->id);
-	num++;
-      }
-    }
-  }else {
-    FOREACHridge_(facet->ridges) {
-      neighbor= otherfacet_(ridge, facet);
-      if (neighbor->visitid != qh visit_id) {
-	if (fp)
-          fprintf (fp, "3 %d %d %d %8.4g %8.4g %8.4g 1 #r%d f%d f%d\n",
-		 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
-		 ridge->id, facet->id, neighbor->id);
-	num++;
-      }
-    }
-  }
-  *nump= num;
-} /* printend4geom */
-
-/*---------------------------------
-  
-  qh_printextremes( fp, facetlist, facets, printall )
-    print extreme points for convex hulls or halfspace intersections
-
-  notes:
-    #points, followed by ids, one per line
-    
-    sorted by id
-    same order as qh_printpoints_out if no coplanar/interior points
-*/
-void qh_printextremes (FILE *fp, facetT *facetlist, setT *facets, int printall) {
-  setT *vertices, *points;
-  pointT *point;
-  vertexT *vertex, **vertexp;
-  int id;
-  int numpoints=0, point_i, point_n;
-  int allpoints= qh num_points + qh_setsize (qh other_points);
-
-  points= qh_settemp (allpoints);
-  qh_setzero (points, 0, allpoints);
-  vertices= qh_facetvertices (facetlist, facets, printall);
-  FOREACHvertex_(vertices) {
-    id= qh_pointid (vertex->point);
-    if (id >= 0) {
-      SETelem_(points, id)= vertex->point;
-      numpoints++;
-    }
-  }
-  qh_settempfree (&vertices);
-  fprintf (fp, "%d\n", numpoints);
-  FOREACHpoint_i_(points) {
-    if (point) 
-      fprintf (fp, "%d\n", point_i);
-  }
-  qh_settempfree (&points);
-} /* printextremes */
-
-/*---------------------------------
-  
-  qh_printextremes_2d( fp, facetlist, facets, printall )
-    prints point ids for facets in qh_ORIENTclock order
-
-  notes:
-    #points, followed by ids, one per line
-    if facetlist/facets are disjoint than the output includes skips
-    errors if facets form a loop
-    does not print coplanar points
-*/
-void qh_printextremes_2d (FILE *fp, facetT *facetlist, setT *facets, int printall) {
-  int numfacets, numridges, totneighbors, numcoplanars, numsimplicial, numtricoplanars;
-  setT *vertices;
-  facetT *facet, *startfacet, *nextfacet;
-  vertexT *vertexA, *vertexB;
-
-  qh_countfacets (facetlist, facets, printall, &numfacets, &numsimplicial, 
-      &totneighbors, &numridges, &numcoplanars, &numtricoplanars); /* marks qh visit_id */
-  vertices= qh_facetvertices (facetlist, facets, printall);
-  fprintf(fp, "%d\n", qh_setsize (vertices));
-  qh_settempfree (&vertices);
-  if (!numfacets)
-    return;
-  facet= startfacet= facetlist ? facetlist : SETfirstt_(facets, facetT);
-  qh vertex_visit++;
-  qh visit_id++;
-  do {
-    if (facet->toporient ^ qh_ORIENTclock) {
-      vertexA= SETfirstt_(facet->vertices, vertexT);
-      vertexB= SETsecondt_(facet->vertices, vertexT);
-      nextfacet= SETfirstt_(facet->neighbors, facetT);
-    }else {
-      vertexA= SETsecondt_(facet->vertices, vertexT);
-      vertexB= SETfirstt_(facet->vertices, vertexT);
-      nextfacet= SETsecondt_(facet->neighbors, facetT);
-    }
-    if (facet->visitid == qh visit_id) {
-      fprintf(qh ferr, "qh_printextremes_2d: loop in facet list.  facet %d nextfacet %d\n",
-                 facet->id, nextfacet->id);
-      qh_errexit2 (qh_ERRqhull, facet, nextfacet);
-    }
-    if (facet->visitid) {
-      if (vertexA->visitid != qh vertex_visit) {
-	vertexA->visitid= qh vertex_visit;
-	fprintf(fp, "%d\n", qh_pointid (vertexA->point));
-      }
-      if (vertexB->visitid != qh vertex_visit) {
-	vertexB->visitid= qh vertex_visit;
-	fprintf(fp, "%d\n", qh_pointid (vertexB->point));
-      }
-    }
-    facet->visitid= qh visit_id;
-    facet= nextfacet;
-  }while (facet && facet != startfacet);
-} /* printextremes_2d */
-
-/*---------------------------------
-  
-  qh_printextremes_d( fp, facetlist, facets, printall )
-    print extreme points of input sites for Delaunay triangulations
-
-  notes:
-    #points, followed by ids, one per line
-    
-    unordered
-*/
-void qh_printextremes_d (FILE *fp, facetT *facetlist, setT *facets, int printall) {
-  setT *vertices;
-  vertexT *vertex, **vertexp;
-  boolT upperseen, lowerseen;
-  facetT *neighbor, **neighborp;
-  int numpoints=0;
-
-  vertices= qh_facetvertices (facetlist, facets, printall);
-  qh_vertexneighbors();
-  FOREACHvertex_(vertices) {
-    upperseen= lowerseen= False;
-    FOREACHneighbor_(vertex) {
-      if (neighbor->upperdelaunay)
-        upperseen= True;
-      else
-        lowerseen= True;
-    }
-    if (upperseen && lowerseen) {
-      vertex->seen= True;
-      numpoints++;
-    }else
-      vertex->seen= False;
-  }
-  fprintf (fp, "%d\n", numpoints);
-  FOREACHvertex_(vertices) {
-    if (vertex->seen)
-      fprintf (fp, "%d\n", qh_pointid (vertex->point));
-  }
-  qh_settempfree (&vertices);
-} /* printextremes_d */
-
-/*---------------------------------
-  
-  qh_printfacet( fp, facet )
-    prints all fields of a facet to fp
-
-  notes:
-    ridges printed in neighbor order
-*/
-void qh_printfacet(FILE *fp, facetT *facet) {
-
-  qh_printfacetheader (fp, facet);
-  if (facet->ridges)
-    qh_printfacetridges (fp, facet);
-} /* printfacet */
-
-
-/*---------------------------------
-  
-  qh_printfacet2geom( fp, facet, color )
-    print facet as part of a 2-d VECT for Geomview
-  
-    notes:
-      assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
-      mindist is calculated within io.c.  maxoutside is calculated elsewhere
-      so a DISTround error may have occured.
-*/
-void qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]) {
-  pointT *point0, *point1;
-  realT mindist, innerplane, outerplane;
-  int k;
-
-  qh_facet2point (facet, &point0, &point1, &mindist);
-  qh_geomplanes (facet, &outerplane, &innerplane);
-  if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
-    qh_printfacet2geom_points(fp, point0, point1, facet, outerplane, color);
-  if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
-                outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
-    for(k= 3; k--; )
-      color[k]= 1.0 - color[k];
-    qh_printfacet2geom_points(fp, point0, point1, facet, innerplane, color);
-  }
-  qh_memfree (point1, qh normal_size);
-  qh_memfree (point0, qh normal_size); 
-} /* printfacet2geom */
-
-/*---------------------------------
-  
-  qh_printfacet2geom_points( fp, point1, point2, facet, offset, color )
-    prints a 2-d facet as a VECT with 2 points at some offset.   
-    The points are on the facet's plane.
-*/
-void qh_printfacet2geom_points(FILE *fp, pointT *point1, pointT *point2,
-			       facetT *facet, realT offset, realT color[3]) {
-  pointT *p1= point1, *p2= point2;
-
-  fprintf(fp, "VECT 1 2 1 2 1 # f%d\n", facet->id);
-  if (offset != 0.0) {
-    p1= qh_projectpoint (p1, facet, -offset);
-    p2= qh_projectpoint (p2, facet, -offset);
-  }
-  fprintf(fp, "%8.4g %8.4g %8.4g\n%8.4g %8.4g %8.4g\n",
-           p1[0], p1[1], 0.0, p2[0], p2[1], 0.0);
-  if (offset != 0.0) {
-    qh_memfree (p1, qh normal_size);
-    qh_memfree (p2, qh normal_size);
-  }
-  fprintf(fp, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
-} /* printfacet2geom_points */
-
-
-/*---------------------------------
-  
-  qh_printfacet2math( fp, facet, notfirst )
-    print 2-d Mathematica output for a facet
-    may be non-simplicial
-
-  notes:
-    use %16.8f since Mathematica 2.2 does not handle exponential format
-*/
-void qh_printfacet2math(FILE *fp, facetT *facet, int notfirst) {
-  pointT *point0, *point1;
-  realT mindist;
-  
-  qh_facet2point (facet, &point0, &point1, &mindist);
-  if (notfirst)
-    fprintf(fp, ",");
-  fprintf(fp, "Line[{{%16.8f, %16.8f}, {%16.8f, %16.8f}}]\n",
-	  point0[0], point0[1], point1[0], point1[1]);
-  qh_memfree (point1, qh normal_size);
-  qh_memfree (point0, qh normal_size);
-} /* printfacet2math */
-
-
-/*---------------------------------
-  
-  qh_printfacet3geom_nonsimplicial( fp, facet, color )
-    print Geomview OFF for a 3-d nonsimplicial facet.
-    if DOintersections, prints ridges to unvisited neighbors (qh visit_id) 
-
-  notes
-    uses facet->visitid for intersections and ridges
-*/
-void qh_printfacet3geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]) {
-  ridgeT *ridge, **ridgep;
-  setT *projectedpoints, *vertices;
-  vertexT *vertex, **vertexp, *vertexA, *vertexB;
-  pointT *projpt, *point, **pointp;
-  facetT *neighbor;
-  realT dist, outerplane, innerplane;
-  int cntvertices, k;
-  realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
-
-  qh_geomplanes (facet, &outerplane, &innerplane); 
-  vertices= qh_facet3vertex (facet); /* oriented */
-  cntvertices= qh_setsize(vertices);
-  projectedpoints= qh_settemp(cntvertices);
-  FOREACHvertex_(vertices) {
-    zinc_(Zdistio);
-    qh_distplane(vertex->point, facet, &dist);
-    projpt= qh_projectpoint(vertex->point, facet, dist);
-    qh_setappend (&projectedpoints, projpt);
-  }
-  if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
-    qh_printfacet3geom_points(fp, projectedpoints, facet, outerplane, color);
-  if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
-                outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
-    for (k=3; k--; )
-      color[k]= 1.0 - color[k];
-    qh_printfacet3geom_points(fp, projectedpoints, facet, innerplane, color);
-  }
-  FOREACHpoint_(projectedpoints)
-    qh_memfree (point, qh normal_size);
-  qh_settempfree(&projectedpoints);
-  qh_settempfree(&vertices);
-  if ((qh DOintersections || qh PRINTridges)
-  && (!facet->visible || !qh NEWfacets)) {
-    facet->visitid= qh visit_id;
-    FOREACHridge_(facet->ridges) {
-      neighbor= otherfacet_(ridge, facet);
-      if (neighbor->visitid != qh visit_id) {
-        if (qh DOintersections)
-          qh_printhyperplaneintersection(fp, facet, neighbor, ridge->vertices, black);
-        if (qh PRINTridges) {
-          vertexA= SETfirstt_(ridge->vertices, vertexT);
-          vertexB= SETsecondt_(ridge->vertices, vertexT);
-          qh_printline3geom (fp, vertexA->point, vertexB->point, green);
-        }
-      }
-    }
-  }
-} /* printfacet3geom_nonsimplicial */
-
-/*---------------------------------
-  
-  qh_printfacet3geom_points( fp, points, facet, offset )
-    prints a 3-d facet as OFF Geomview object. 
-    offset is relative to the facet's hyperplane
-    Facet is determined as a list of points
-*/
-void qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]) {
-  int k, n= qh_setsize(points), i;
-  pointT *point, **pointp;
-  setT *printpoints;
-
-  fprintf(fp, "{ OFF %d 1 1 # f%d\n", n, facet->id);
-  if (offset != 0.0) {
-    printpoints= qh_settemp (n);
-    FOREACHpoint_(points) 
-      qh_setappend (&printpoints, qh_projectpoint(point, facet, -offset));
-  }else
-    printpoints= points;
-  FOREACHpoint_(printpoints) {
-    for (k=0; k < qh hull_dim; k++) {
-      if (k == qh DROPdim)
-        fprintf(fp, "0 ");
-      else
-        fprintf(fp, "%8.4g ", point[k]);
-    }
-    if (printpoints != points)
-      qh_memfree (point, qh normal_size);
-    fprintf (fp, "\n");
-  }
-  if (printpoints != points)
-    qh_settempfree (&printpoints);
-  fprintf(fp, "%d ", n);
-  for(i= 0; i < n; i++)
-    fprintf(fp, "%d ", i);
-  fprintf(fp, "%8.4g %8.4g %8.4g 1.0 }\n", color[0], color[1], color[2]);
-} /* printfacet3geom_points */
-
-
-/*---------------------------------
-  
-  qh_printfacet3geom_simplicial(  )
-    print Geomview OFF for a 3-d simplicial facet.
-
-  notes:
-    may flip color
-    uses facet->visitid for intersections and ridges
-
-    assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
-    innerplane may be off by qh DISTround.  Maxoutside is calculated elsewhere
-    so a DISTround error may have occured.
-*/
-void qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]) {
-  setT *points, *vertices;
-  vertexT *vertex, **vertexp, *vertexA, *vertexB;
-  facetT *neighbor, **neighborp;
-  realT outerplane, innerplane;
-  realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
-  int k;
-
-  qh_geomplanes (facet, &outerplane, &innerplane); 
-  vertices= qh_facet3vertex (facet);
-  points= qh_settemp (qh TEMPsize);
-  FOREACHvertex_(vertices)
-    qh_setappend(&points, vertex->point);
-  if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
-    qh_printfacet3geom_points(fp, points, facet, outerplane, color);
-  if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
-              outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
-    for (k= 3; k--; )
-      color[k]= 1.0 - color[k];
-    qh_printfacet3geom_points(fp, points, facet, innerplane, color);
-  }
-  qh_settempfree(&points);
-  qh_settempfree(&vertices);
-  if ((qh DOintersections || qh PRINTridges)
-  && (!facet->visible || !qh NEWfacets)) {
-    facet->visitid= qh visit_id;
-    FOREACHneighbor_(facet) {
-      if (neighbor->visitid != qh visit_id) {
-	vertices= qh_setnew_delnthsorted (facet->vertices, qh hull_dim,
-	                  SETindex_(facet->neighbors, neighbor), 0);
-        if (qh DOintersections)
-	   qh_printhyperplaneintersection(fp, facet, neighbor, vertices, black); 
-        if (qh PRINTridges) {
-          vertexA= SETfirstt_(vertices, vertexT);
-          vertexB= SETsecondt_(vertices, vertexT);
-          qh_printline3geom (fp, vertexA->point, vertexB->point, green);
-        }
-	qh_setfree(&vertices);
-      }
-    }
-  }
-} /* printfacet3geom_simplicial */
-
-/*---------------------------------
-  
-  qh_printfacet3math( fp, facet, notfirst )
-    print 3-d Mathematica output for a facet
-
-  notes:
-    may be non-simplicial
-    use %16.8f since Mathematica 2.2 does not handle exponential format
-*/
-void qh_printfacet3math (FILE *fp, facetT *facet, int notfirst) {
-  vertexT *vertex, **vertexp;
-  setT *points, *vertices;
-  pointT *point, **pointp;
-  boolT firstpoint= True;
-  realT dist;
-  
-  if (notfirst)
-    fprintf(fp, ",\n");
-  vertices= qh_facet3vertex (facet);
-  points= qh_settemp (qh_setsize (vertices));
-  FOREACHvertex_(vertices) {
-    zinc_(Zdistio);
-    qh_distplane(vertex->point, facet, &dist);
-    point= qh_projectpoint(vertex->point, facet, dist);
-    qh_setappend (&points, point);
-  }
-  fprintf(fp, "Polygon[{");
-  FOREACHpoint_(points) {
-    if (firstpoint)
-      firstpoint= False;
-    else
-      fprintf(fp, ",\n");
-    fprintf(fp, "{%16.8f, %16.8f, %16.8f}", point[0], point[1], point[2]);
-  }
-  FOREACHpoint_(points)
-    qh_memfree (point, qh normal_size);
-  qh_settempfree(&points);
-  qh_settempfree(&vertices);
-  fprintf(fp, "}]");
-} /* printfacet3math */
-
-
-/*---------------------------------
-  
-  qh_printfacet3vertex( fp, facet, format )
-    print vertices in a 3-d facet as point ids
-
-  notes:
-    prints number of vertices first if format == qh_PRINToff
-    the facet may be non-simplicial
-*/
-void qh_printfacet3vertex(FILE *fp, facetT *facet, int format) {
-  vertexT *vertex, **vertexp;
-  setT *vertices;
-
-  vertices= qh_facet3vertex (facet);
-  if (format == qh_PRINToff)
-    fprintf (fp, "%d ", qh_setsize (vertices));
-  FOREACHvertex_(vertices) 
-    fprintf (fp, "%d ", qh_pointid(vertex->point));
-  fprintf (fp, "\n");
-  qh_settempfree(&vertices);
-} /* printfacet3vertex */
-
-
-/*---------------------------------
-  
-  qh_printfacet4geom_nonsimplicial(  )
-    print Geomview 4OFF file for a 4d nonsimplicial facet
-    prints all ridges to unvisited neighbors (qh.visit_id)
-    if qh.DROPdim
-      prints in OFF format
-  
-  notes:
-    must agree with printend4geom()
-*/
-void qh_printfacet4geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]) {
-  facetT *neighbor;
-  ridgeT *ridge, **ridgep;
-  vertexT *vertex, **vertexp;
-  pointT *point;
-  int k;
-  realT dist;
-  
-  facet->visitid= qh visit_id;
-  if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
-    return;
-  FOREACHridge_(facet->ridges) {
-    neighbor= otherfacet_(ridge, facet);
-    if (neighbor->visitid == qh visit_id) 
-      continue;
-    if (qh PRINTtransparent && !neighbor->good)
-      continue;  
-    if (qh DOintersections)
-      qh_printhyperplaneintersection(fp, facet, neighbor, ridge->vertices, color);
-    else {
-      if (qh DROPdim >= 0) 
-	fprintf(fp, "OFF 3 1 1 # f%d\n", facet->id);
-      else {
-	qh printoutvar++;
-	fprintf (fp, "# r%d between f%d f%d\n", ridge->id, facet->id, neighbor->id);
-      }
-      FOREACHvertex_(ridge->vertices) {
-	zinc_(Zdistio);
-	qh_distplane(vertex->point,facet, &dist);
-	point=qh_projectpoint(vertex->point,facet, dist);
-	for(k= 0; k < qh hull_dim; k++) {
-	  if (k != qh DROPdim)
-  	    fprintf(fp, "%8.4g ", point[k]);
-  	}
-	fprintf (fp, "\n");
-	qh_memfree (point, qh normal_size);
-      }
-      if (qh DROPdim >= 0)
-        fprintf(fp, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
-    }
-  }
-} /* printfacet4geom_nonsimplicial */
-
-
-/*---------------------------------
-  
-  qh_printfacet4geom_simplicial( fp, facet, color )
-    print Geomview 4OFF file for a 4d simplicial facet
-    prints triangles for unvisited neighbors (qh.visit_id)
-
-  notes:
-    must agree with printend4geom()
-*/
-void qh_printfacet4geom_simplicial(FILE *fp, facetT *facet, realT color[3]) {
-  setT *vertices;
-  facetT *neighbor, **neighborp;
-  vertexT *vertex, **vertexp;
-  int k;
-  
-  facet->visitid= qh visit_id;
-  if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
-    return;
-  FOREACHneighbor_(facet) {
-    if (neighbor->visitid == qh visit_id)
-      continue;
-    if (qh PRINTtransparent && !neighbor->good)
-      continue;  
-    vertices= qh_setnew_delnthsorted (facet->vertices, qh hull_dim,
-	                  SETindex_(facet->neighbors, neighbor), 0);
-    if (qh DOintersections)
-      qh_printhyperplaneintersection(fp, facet, neighbor, vertices, color);
-    else {
-      if (qh DROPdim >= 0) 
-	fprintf(fp, "OFF 3 1 1 # ridge between f%d f%d\n",
-		facet->id, neighbor->id);
-      else {
-	qh printoutvar++;
-	fprintf (fp, "# ridge between f%d f%d\n", facet->id, neighbor->id);
-      }
-      FOREACHvertex_(vertices) {
-	for(k= 0; k < qh hull_dim; k++) {
-	  if (k != qh DROPdim)
-  	    fprintf(fp, "%8.4g ", vertex->point[k]);
-  	}
-	fprintf (fp, "\n");
-      }
-      if (qh DROPdim >= 0) 
-        fprintf(fp, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
-    }
-    qh_setfree(&vertices);
-  }
-} /* printfacet4geom_simplicial */
-
-
-/*---------------------------------
-  
-  qh_printfacetNvertex_nonsimplicial( fp, facet, id, format )
-    print vertices for an N-d non-simplicial facet
-    triangulates each ridge to the id
-*/
-void qh_printfacetNvertex_nonsimplicial(FILE *fp, facetT *facet, int id, int format) {
-  vertexT *vertex, **vertexp;
-  ridgeT *ridge, **ridgep;
-
-  if (facet->visible && qh NEWfacets)
-    return;
-  FOREACHridge_(facet->ridges) {
-    if (format == qh_PRINTtriangles)
-      fprintf(fp, "%d ", qh hull_dim);
-    fprintf(fp, "%d ", id);
-    if ((ridge->top == facet) ^ qh_ORIENTclock) {
-      FOREACHvertex_(ridge->vertices)
-        fprintf(fp, "%d ", qh_pointid(vertex->point));
-    }else {
-      FOREACHvertexreverse12_(ridge->vertices)
-        fprintf(fp, "%d ", qh_pointid(vertex->point));
-    }
-    fprintf(fp, "\n");
-  }
-} /* printfacetNvertex_nonsimplicial */
-
-
-/*---------------------------------
-  
-  qh_printfacetNvertex_simplicial( fp, facet, format )
-    print vertices for an N-d simplicial facet
-    prints vertices for non-simplicial facets
-      2-d facets (orientation preserved by qh_mergefacet2d)
-      PRINToff ('o') for 4-d and higher
-*/
-void qh_printfacetNvertex_simplicial(FILE *fp, facetT *facet, int format) {
-  vertexT *vertex, **vertexp;
-
-  if (format == qh_PRINToff || format == qh_PRINTtriangles)
-    fprintf (fp, "%d ", qh_setsize (facet->vertices));
-  if ((facet->toporient ^ qh_ORIENTclock) 
-  || (qh hull_dim > 2 && !facet->simplicial)) {
-    FOREACHvertex_(facet->vertices)
-      fprintf(fp, "%d ", qh_pointid(vertex->point));
-  }else {
-    FOREACHvertexreverse12_(facet->vertices)
-      fprintf(fp, "%d ", qh_pointid(vertex->point));
-  }
-  fprintf(fp, "\n");
-} /* printfacetNvertex_simplicial */
-
-
-/*---------------------------------
-  
-  qh_printfacetheader( fp, facet )
-    prints header fields of a facet to fp
-    
-  notes:
-    for 'f' output and debugging
-*/
-void qh_printfacetheader(FILE *fp, facetT *facet) {
-  pointT *point, **pointp, *furthest;
-  facetT *neighbor, **neighborp;
-  realT dist;
-
-  if (facet == qh_MERGEridge) {
-    fprintf (fp, " MERGEridge\n");
-    return;
-  }else if (facet == qh_DUPLICATEridge) {
-    fprintf (fp, " DUPLICATEridge\n");
-    return;
-  }else if (!facet) {
-    fprintf (fp, " NULLfacet\n");
-    return;
-  }
-  qh old_randomdist= qh RANDOMdist;
-  qh RANDOMdist= False;
-  fprintf(fp, "- f%d\n", facet->id);
-  fprintf(fp, "    - flags:");
-  if (facet->toporient) 
-    fprintf(fp, " top");
-  else
-    fprintf(fp, " bottom");
-  if (facet->simplicial)
-    fprintf(fp, " simplicial");
-  if (facet->tricoplanar)
-    fprintf(fp, " tricoplanar");
-  if (facet->upperdelaunay)
-    fprintf(fp, " upperDelaunay");
-  if (facet->visible)
-    fprintf(fp, " visible");
-  if (facet->newfacet)
-    fprintf(fp, " new");
-  if (facet->tested)
-    fprintf(fp, " tested");
-  if (!facet->good)
-    fprintf(fp, " notG");
-  if (facet->seen)
-    fprintf(fp, " seen");
-  if (facet->coplanar)
-    fprintf(fp, " coplanar");
-  if (facet->mergehorizon)
-    fprintf(fp, " mergehorizon");
-  if (facet->keepcentrum)
-    fprintf(fp, " keepcentrum");
-  if (facet->dupridge)
-    fprintf(fp, " dupridge");
-  if (facet->mergeridge && !facet->mergeridge2)
-    fprintf(fp, " mergeridge1");
-  if (facet->mergeridge2)
-    fprintf(fp, " mergeridge2");
-  if (facet->newmerge)
-    fprintf(fp, " newmerge");
-  if (facet->flipped) 
-    fprintf(fp, " flipped");
-  if (facet->notfurthest) 
-    fprintf(fp, " notfurthest");
-  if (facet->degenerate)
-    fprintf(fp, " degenerate");
-  if (facet->redundant)
-    fprintf(fp, " redundant");
-  fprintf(fp, "\n");
-  if (facet->isarea)
-    fprintf(fp, "    - area: %2.2g\n", facet->f.area);
-  else if (qh NEWfacets && facet->visible && facet->f.replace)
-    fprintf(fp, "    - replacement: f%d\n", facet->f.replace->id);
-  else if (facet->newfacet) {
-    if (facet->f.samecycle && facet->f.samecycle != facet)
-      fprintf(fp, "    - shares same visible/horizon as f%d\n", facet->f.samecycle->id);
-  }else if (facet->tricoplanar /* !isarea */) {
-    if (facet->f.triowner)
-      fprintf(fp, "    - owner of normal & centrum is facet f%d\n", facet->f.triowner->id);
-  }else if (facet->f.newcycle)
-    fprintf(fp, "    - was horizon to f%d\n", facet->f.newcycle->id);
-  if (facet->nummerge)
-    fprintf(fp, "    - merges: %d\n", facet->nummerge);
-  qh_printpointid(fp, "    - normal: ", qh hull_dim, facet->normal, -1);
-  fprintf(fp, "    - offset: %10.7g\n", facet->offset);
-  if (qh CENTERtype == qh_ASvoronoi || facet->center)
-    qh_printcenter (fp, qh_PRINTfacets, "    - center: ", facet);
-#if qh_MAXoutside
-  if (facet->maxoutside > qh DISTround)
-    fprintf(fp, "    - maxoutside: %10.7g\n", facet->maxoutside);
-#endif
-  if (!SETempty_(facet->outsideset)) {
-    furthest= (pointT*)qh_setlast(facet->outsideset);
-    if (qh_setsize (facet->outsideset) < 6) {
-      fprintf(fp, "    - outside set (furthest p%d):\n", qh_pointid(furthest));
-      FOREACHpoint_(facet->outsideset)
-	qh_printpoint(fp, "     ", point);
-    }else if (qh_setsize (facet->outsideset) < 21) {
-      qh_printpoints(fp, "    - outside set:", facet->outsideset);
-    }else {
-      fprintf(fp, "    - outside set:  %d points.", qh_setsize(facet->outsideset));
-      qh_printpoint(fp, "  Furthest", furthest);
-    }
-#if !qh_COMPUTEfurthest
-    fprintf(fp, "    - furthest distance= %2.2g\n", facet->furthestdist);
-#endif
-  }
-  if (!SETempty_(facet->coplanarset)) {
-    furthest= (pointT*)qh_setlast(facet->coplanarset);
-    if (qh_setsize (facet->coplanarset) < 6) {
-      fprintf(fp, "    - coplanar set (furthest p%d):\n", qh_pointid(furthest));
-      FOREACHpoint_(facet->coplanarset)
-	qh_printpoint(fp, "     ", point);
-    }else if (qh_setsize (facet->coplanarset) < 21) {
-      qh_printpoints(fp, "    - coplanar set:", facet->coplanarset);
-    }else {
-      fprintf(fp, "    - coplanar set:  %d points.", qh_setsize(facet->coplanarset));
-      qh_printpoint(fp, "  Furthest", furthest);
-    }
-    zinc_(Zdistio);
-    qh_distplane (furthest, facet, &dist);
-    fprintf(fp, "      furthest distance= %2.2g\n", dist);
-  }
-  qh_printvertices (fp, "    - vertices:", facet->vertices);
-  fprintf(fp, "    - neighboring facets: ");
-  FOREACHneighbor_(facet) {
-    if (neighbor == qh_MERGEridge)
-      fprintf(fp, " MERGE");
-    else if (neighbor == qh_DUPLICATEridge)
-      fprintf(fp, " DUP");
-    else
-      fprintf(fp, " f%d", neighbor->id);
-  }
-  fprintf(fp, "\n");
-  qh RANDOMdist= qh old_randomdist;
-} /* printfacetheader */
-
-
-/*---------------------------------
-  
-  qh_printfacetridges( fp, facet )
-    prints ridges of a facet to fp
-
-  notes:
-    ridges printed in neighbor order
-    assumes the ridges exist
-    for 'f' output
-*/
-void qh_printfacetridges(FILE *fp, facetT *facet) {
-  facetT *neighbor, **neighborp;
-  ridgeT *ridge, **ridgep;
-  int numridges= 0;
-
-
-  if (facet->visible && qh NEWfacets) {
-    fprintf(fp, "    - ridges (ids may be garbage):");
-    FOREACHridge_(facet->ridges)
-      fprintf(fp, " r%d", ridge->id);
-    fprintf(fp, "\n");
-  }else {
-    fprintf(fp, "    - ridges:\n");
-    FOREACHridge_(facet->ridges)
-      ridge->seen= False;
-    if (qh hull_dim == 3) {
-      ridge= SETfirstt_(facet->ridges, ridgeT);
-      while (ridge && !ridge->seen) {
-	ridge->seen= True;
-	qh_printridge(fp, ridge);
-	numridges++;
-	ridge= qh_nextridge3d (ridge, facet, NULL);
-	}
-    }else {
-      FOREACHneighbor_(facet) {
-	FOREACHridge_(facet->ridges) {
-	  if (otherfacet_(ridge,facet) == neighbor) {
-	    ridge->seen= True;
-	    qh_printridge(fp, ridge);
-	    numridges++;
-	  }
-	}
-      }
-    }
-    if (numridges != qh_setsize (facet->ridges)) {
-      fprintf (fp, "     - all ridges:");
-      FOREACHridge_(facet->ridges) 
-	fprintf (fp, " r%d", ridge->id);
-        fprintf (fp, "\n");
-    }
-    FOREACHridge_(facet->ridges) {
-      if (!ridge->seen) 
-	qh_printridge(fp, ridge);
-    }
-  }
-} /* printfacetridges */
-
-/*---------------------------------
-  
-  qh_printfacets( fp, format, facetlist, facets, printall )
-    prints facetlist and/or facet set in output format
-  
-  notes:
-    also used for specialized formats ('FO' and summary)
-    turns off 'Rn' option since want actual numbers
-*/
-void qh_printfacets(FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) {
-  int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
-  facetT *facet, **facetp;
-  setT *vertices;
-  coordT *center;
-  realT outerplane, innerplane;
-
-  qh old_randomdist= qh RANDOMdist;
-  qh RANDOMdist= False;
-  if (qh CDDoutput && (format == qh_PRINTcentrums || format == qh_PRINTpointintersect || format == qh_PRINToff))
-    fprintf (qh ferr, "qhull warning: CDD format is not available for centrums, halfspace\nintersections, and OFF file format.\n");
-  if (format == qh_PRINTnone)
-    ; /* print nothing */
-  else if (format == qh_PRINTaverage) {
-    vertices= qh_facetvertices (facetlist, facets, printall);
-    center= qh_getcenter (vertices);
-    fprintf (fp, "%d 1\n", qh hull_dim);
-    qh_printpointid (fp, NULL, qh hull_dim, center, -1);
-    qh_memfree (center, qh normal_size);
-    qh_settempfree (&vertices);
-  }else if (format == qh_PRINTextremes) {
-    if (qh DELAUNAY)
-      qh_printextremes_d (fp, facetlist, facets, printall);
-    else if (qh hull_dim == 2)
-      qh_printextremes_2d (fp, facetlist, facets, printall);
-    else 
-      qh_printextremes (fp, facetlist, facets, printall);
-  }else if (format == qh_PRINToptions)
-    fprintf(fp, "Options selected for Qhull %s:\n%s\n", qh_VERSION, qh qhull_options);
-  else if (format == qh_PRINTpoints && !qh VORONOI)
-    qh_printpoints_out (fp, facetlist, facets, printall);
-  else if (format == qh_PRINTqhull)
-    fprintf (fp, "%s | %s\n", qh rbox_command, qh qhull_command);
-  else if (format == qh_PRINTsize) {
-    fprintf (fp, "0\n2 ");
-    fprintf (fp, qh_REAL_1, qh totarea);
-    fprintf (fp, qh_REAL_1, qh totvol);
-    fprintf (fp, "\n");
-  }else if (format == qh_PRINTsummary) {
-    qh_countfacets (facetlist, facets, printall, &numfacets, &numsimplicial, 
-      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
-    vertices= qh_facetvertices (facetlist, facets, printall); 
-    fprintf (fp, "10 %d %d %d %d %d %d %d %d %d %d\n2 ", qh hull_dim, 
-                qh num_points + qh_setsize (qh other_points),
-                qh num_vertices, qh num_facets - qh num_visible,
-                qh_setsize (vertices), numfacets, numcoplanars, 
-		numfacets - numsimplicial, zzval_(Zdelvertextot), 
-		numtricoplanars);
-    qh_settempfree (&vertices);
-    qh_outerinner (NULL, &outerplane, &innerplane);
-    fprintf (fp, qh_REAL_2n, outerplane, innerplane);
-  }else if (format == qh_PRINTvneighbors)
-    qh_printvneighbors (fp, facetlist, facets, printall);
-  else if (qh VORONOI && format == qh_PRINToff)
-    qh_printvoronoi (fp, format, facetlist, facets, printall);
-  else if (qh VORONOI && format == qh_PRINTgeom) {
-    qh_printbegin (fp, format, facetlist, facets, printall);
-    qh_printvoronoi (fp, format, facetlist, facets, printall);
-    qh_printend (fp, format, facetlist, facets, printall);
-  }else if (qh VORONOI 
-  && (format == qh_PRINTvertices || format == qh_PRINTinner || format == qh_PRINTouter))
-    qh_printvdiagram (fp, format, facetlist, facets, printall);
-  else {
-    qh_printbegin (fp, format, facetlist, facets, printall);
-    FORALLfacet_(facetlist)
-      qh_printafacet (fp, format, facet, printall);
-    FOREACHfacet_(facets) 
-      qh_printafacet (fp, format, facet, printall);
-    qh_printend (fp, format, facetlist, facets, printall);
-  }
-  qh RANDOMdist= qh old_randomdist;
-} /* printfacets */
-
-
-/*---------------------------------
-  
-  qh_printhelp_degenerate( fp )
-    prints descriptive message for precision error
-
-  notes:
-    no message if qh_QUICKhelp
-*/
-void qh_printhelp_degenerate(FILE *fp) {
-  
-  if (qh MERGEexact || qh PREmerge || qh JOGGLEmax < REALmax/2) 
-    fprintf(fp, "\n\
-A Qhull error has occurred.  Qhull should have corrected the above\n\
-precision error.  Please send the input and all of the output to\n\
-qhull_bug@geom.umn.edu\n");
-  else if (!qh_QUICKhelp) {
-    fprintf(fp, "\n\
-Precision problems were detected during construction of the convex hull.\n\
-This occurs because convex hull algorithms assume that calculations are\n\
-exact, but floating-point arithmetic has roundoff errors.\n\
-\n\
-To correct for precision problems, do not use 'Q0'.  By default, Qhull\n\
-selects 'C-0' or 'Qx' and merges non-convex facets.  With option 'QJ',\n\
-Qhull joggles the input to prevent precision problems.  See \"Imprecision\n\
-in Qhull\" (qh-impre.htm).\n\
-\n\
-If you use 'Q0', the output may include\n\
-coplanar ridges, concave ridges, and flipped facets.  In 4-d and higher,\n\
-Qhull may produce a ridge with four neighbors or two facets with the same \n\
-vertices.  Qhull reports these events when they occur.  It stops when a\n\
-concave ridge, flipped facet, or duplicate facet occurs.\n");
-#if REALfloat
-    fprintf (fp, "\
-\n\
-Qhull is currently using single precision arithmetic.  The following\n\
-will probably remove the precision problems:\n\
-  - recompile qhull for double precision (#define REALfloat 0 in user.h).\n");
-#endif
-    if (qh DELAUNAY && !qh SCALElast && qh MAXabs_coord > 1e4)
-      fprintf( fp, "\
-\n\
-When computing the Delaunay triangulation of coordinates > 1.0,\n\
-  - use 'Qbb' to scale the last coordinate to [0,m] (max previous coordinate)\n");
-    if (qh DELAUNAY && !qh ATinfinity) 
-      fprintf( fp, "\
-When computing the Delaunay triangulation:\n\
-  - use 'Qz' to add a point at-infinity.  This reduces precision problems.\n");
- 
-    fprintf(fp, "\
-\n\
-If you need triangular output:\n\
-  - use option 'Qt' to triangulate the output\n\
-  - use option 'QJ' to joggle the input points and remove precision errors\n\
-  - use option 'Ft'.  It triangulates non-simplicial facets with added points.\n\
-\n\
-If you must use 'Q0',\n\
-try one or more of the following options.  They can not guarantee an output.\n\
-  - use 'QbB' to scale the input to a cube.\n\
-  - use 'Po' to produce output and prevent partitioning for flipped facets\n\
-  - use 'V0' to set min. distance to visible facet as 0 instead of roundoff\n\
-  - use 'En' to specify a maximum roundoff error less than %2.2g.\n\
-  - options 'Qf', 'Qbb', and 'QR0' may also help\n",
-               qh DISTround);
-    fprintf(fp, "\
-\n\
-To guarantee simplicial output:\n\
-  - use option 'Qt' to triangulate the output\n\
-  - use option 'QJ' to joggle the input points and remove precision errors\n\
-  - use option 'Ft' to triangulate the output by adding points\n\
-  - use exact arithmetic (see \"Imprecision in Qhull\", qh-impre.htm)\n\
-");
-  }
-} /* printhelp_degenerate */
-
-
-/*---------------------------------
-  
-  qh_printhelp_singular( fp )
-    prints descriptive message for singular input
-*/
-void qh_printhelp_singular(FILE *fp) {
-  facetT *facet;
-  vertexT *vertex, **vertexp;
-  realT min, max, *coord, dist;
-  int i,k;
-  
-  fprintf(fp, "\n\
-The input to qhull appears to be less than %d dimensional, or a\n\
-computation has overflowed.\n\n\
-Qhull could not construct a clearly convex simplex from points:\n",
-           qh hull_dim);
-  qh_printvertexlist (fp, "", qh facet_list, NULL, qh_ALL);
-  if (!qh_QUICKhelp)
-    fprintf(fp, "\n\
-The center point is coplanar with a facet, or a vertex is coplanar\n\
-with a neighboring facet.  The maximum round off error for\n\
-computing distances is %2.2g.  The center point, facets and distances\n\
-to the center point are as follows:\n\n", qh DISTround);
-  qh_printpointid (fp, "center point", qh hull_dim, qh interior_point, -1);
-  fprintf (fp, "\n");
-  FORALLfacets {
-    fprintf (fp, "facet");
-    FOREACHvertex_(facet->vertices)
-      fprintf (fp, " p%d", qh_pointid(vertex->point));
-    zinc_(Zdistio);
-    qh_distplane(qh interior_point, facet, &dist);
-    fprintf (fp, " distance= %4.2g\n", dist);
-  }
-  if (!qh_QUICKhelp) {
-    if (qh HALFspace) 
-      fprintf (fp, "\n\
-These points are the dual of the given halfspaces.  They indicate that\n\
-the intersection is degenerate.\n");
-    fprintf (fp,"\n\
-These points either have a maximum or minimum x-coordinate, or\n\
-they maximize the determinant for k coordinates.  Trial points\n\
-are first selected from points that maximize a coordinate.\n");
-    if (qh hull_dim >= qh_INITIALmax)
-      fprintf (fp, "\n\
-Because of the high dimension, the min x-coordinate and max-coordinate\n\
-points are used if the determinant is non-zero.  Option 'Qs' will\n\
-do a better, though much slower, job.  Instead of 'Qs', you can change\n\
-the points by randomly rotating the input with 'QR0'.\n");
-  }
-  fprintf (fp, "\nThe min and max coordinates for each dimension are:\n");
-  for (k=0; k < qh hull_dim; k++) {
-    min= REALmax;
-    max= -REALmin;
-    for (i=qh num_points, coord= qh first_point+k; i--; coord += qh hull_dim) {
-      maximize_(max, *coord);
-      minimize_(min, *coord);
-    }
-    fprintf (fp, "  %d:  %8.4g  %8.4g  difference= %4.4g\n", k, min, max, max-min);
-  }
-  if (!qh_QUICKhelp) {
-    fprintf (fp, "\n\
-If the input should be full dimensional, you have several options that\n\
-may determine an initial simplex:\n\
-  - use 'QJ'  to joggle the input and make it full dimensional\n\
-  - use 'QbB' to scale the points to the unit cube\n\
-  - use 'QR0' to randomly rotate the input for different maximum points\n\
-  - use 'Qs'  to search all points for the initial simplex\n\
-  - use 'En'  to specify a maximum roundoff error less than %2.2g.\n\
-  - trace execution with 'T3' to see the determinant for each point.\n",
-                     qh DISTround);
-#if REALfloat
-    fprintf (fp, "\
-  - recompile qhull for double precision (#define REALfloat 0 in qhull.h).\n");
-#endif
-    fprintf (fp, "\n\
-If the input is lower dimensional:\n\
-  - use 'QJ' to joggle the input and make it full dimensional\n\
-  - use 'Qbk:0Bk:0' to delete coordinate k from the input.  You should\n\
-    pick the coordinate with the least range.  The hull will have the\n\
-    correct topology.\n\
-  - determine the flat containing the points, rotate the points\n\
-    into a coordinate plane, and delete the other coordinates.\n\
-  - add one or more points to make the input full dimensional.\n\
-");
-    if (qh DELAUNAY && !qh ATinfinity)
-      fprintf (fp, "\n\n\
-This is a Delaunay triangulation and the input is co-circular or co-spherical:\n\
-  - use 'Qz' to add a point \"at infinity\" (i.e., above the paraboloid)\n\
-  - or use 'QJ' to joggle the input and avoid co-circular data\n");
-  }
-} /* printhelp_singular */
-
-/*---------------------------------
-  
-  qh_printhyperplaneintersection( fp, facet1, facet2, vertices, color )
-    print Geomview OFF or 4OFF for the intersection of two hyperplanes in 3-d or 4-d
-*/
-void qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2,
-		   setT *vertices, realT color[3]) {
-  realT costheta, denominator, dist1, dist2, s, t, mindenom, p[4];
-  vertexT *vertex, **vertexp;
-  int i, k;
-  boolT nearzero1, nearzero2;
-  
-  costheta= qh_getangle(facet1->normal, facet2->normal);
-  denominator= 1 - costheta * costheta;
-  i= qh_setsize(vertices);
-  if (qh hull_dim == 3)
-    fprintf(fp, "VECT 1 %d 1 %d 1 ", i, i);
-  else if (qh hull_dim == 4 && qh DROPdim >= 0)
-    fprintf(fp, "OFF 3 1 1 ");
-  else
-    qh printoutvar++;
-  fprintf (fp, "# intersect f%d f%d\n", facet1->id, facet2->id);
-  mindenom= 1 / (10.0 * qh MAXabs_coord);
-  FOREACHvertex_(vertices) {
-    zadd_(Zdistio, 2);
-    qh_distplane(vertex->point, facet1, &dist1);
-    qh_distplane(vertex->point, facet2, &dist2);
-    s= qh_divzero (-dist1 + costheta * dist2, denominator,mindenom,&nearzero1);
-    t= qh_divzero (-dist2 + costheta * dist1, denominator,mindenom,&nearzero2);
-    if (nearzero1 || nearzero2)
-      s= t= 0.0;
-    for(k= qh hull_dim; k--; )
-      p[k]= vertex->point[k] + facet1->normal[k] * s + facet2->normal[k] * t;
-    if (qh PRINTdim <= 3) {
-      qh_projectdim3 (p, p);
-      fprintf(fp, "%8.4g %8.4g %8.4g # ", p[0], p[1], p[2]);
-    }else 
-      fprintf(fp, "%8.4g %8.4g %8.4g %8.4g # ", p[0], p[1], p[2], p[3]);
-    if (nearzero1+nearzero2)
-      fprintf (fp, "p%d (coplanar facets)\n", qh_pointid (vertex->point));
-    else
-      fprintf (fp, "projected p%d\n", qh_pointid (vertex->point));
-  }
-  if (qh hull_dim == 3)
-    fprintf(fp, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]); 
-  else if (qh hull_dim == 4 && qh DROPdim >= 0)  
-    fprintf(fp, "3 0 1 2 %8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
-} /* printhyperplaneintersection */
-
-/*---------------------------------
-  
-  qh_printline3geom( fp, pointA, pointB, color )
-    prints a line as a VECT
-    prints 0's for qh.DROPdim
-  
-  notes:
-    if pointA == pointB, 
-      it's a 1 point VECT
-*/
-void qh_printline3geom (FILE *fp, pointT *pointA, pointT *pointB, realT color[3]) {
-  int k;
-  realT pA[4], pB[4];
-
-  qh_projectdim3(pointA, pA);
-  qh_projectdim3(pointB, pB);
-  if ((fabs(pA[0] - pB[0]) > 1e-3) || 
-      (fabs(pA[1] - pB[1]) > 1e-3) || 
-      (fabs(pA[2] - pB[2]) > 1e-3)) {
-    fprintf (fp, "VECT 1 2 1 2 1\n");
-    for (k= 0; k < 3; k++)
-       fprintf (fp, "%8.4g ", pB[k]);
-    fprintf (fp, " # p%d\n", qh_pointid (pointB));
-  }else
-    fprintf (fp, "VECT 1 1 1 1 1\n");
-  for (k=0; k < 3; k++)
-    fprintf (fp, "%8.4g ", pA[k]);
-  fprintf (fp, " # p%d\n", qh_pointid (pointA));
-  fprintf (fp, "%8.4g %8.4g %8.4g 1\n", color[0], color[1], color[2]);
-}
-
-/*---------------------------------
-  
-  qh_printneighborhood( fp, format, facetA, facetB, printall )
-    print neighborhood of one or two facets
-
-  notes:
-    calls qh_findgood_all() 
-    bumps qh.visit_id
-*/
-void qh_printneighborhood (FILE *fp, int format, facetT *facetA, facetT *facetB, boolT printall) {
-  facetT *neighbor, **neighborp, *facet;
-  setT *facets;
-
-  if (format == qh_PRINTnone)
-    return;
-  qh_findgood_all (qh facet_list);
-  if (facetA == facetB)
-    facetB= NULL;
-  facets= qh_settemp (2*(qh_setsize (facetA->neighbors)+1));
-  qh visit_id++;
-  for (facet= facetA; facet; facet= ((facet == facetA) ? facetB : NULL)) {
-    if (facet->visitid != qh visit_id) {
-      facet->visitid= qh visit_id;
-      qh_setappend (&facets, facet);
-    }
-    FOREACHneighbor_(facet) {
-      if (neighbor->visitid == qh visit_id)
-        continue;
-      neighbor->visitid= qh visit_id;
-      if (printall || !qh_skipfacet (neighbor))
-        qh_setappend (&facets, neighbor);
-    }
-  }
-  qh_printfacets (fp, format, NULL, facets, printall);
-  qh_settempfree (&facets);
-} /* printneighborhood */
-
-/*---------------------------------
-  
-  qh_printpoint( fp, string, point )
-  qh_printpointid( fp, string, dim, point, id )
-    prints the coordinates of a point
-
-  returns:
-    if string is defined
-      prints 'string p%d' (skips p%d if id=-1)
-
-  notes:
-    nop if point is NULL
-    prints id unless it is undefined (-1)
-*/
-void qh_printpoint(FILE *fp, char *string, pointT *point) {
-  int id= qh_pointid( point);
-
-  qh_printpointid( fp, string, qh hull_dim, point, id);
-} /* printpoint */
-
-void qh_printpointid(FILE *fp, char *string, int dim, pointT *point, int id) {
-  int k;
-  realT r; /*bug fix*/
-  
-  if (!point)
-    return;
-  if (string) {
-    fputs (string, fp);
-   if (id != -1)
-      fprintf(fp, " p%d: ", id);
-  }
-  for(k= dim; k--; ) {
-    r= *point++;
-    if (string)
-      fprintf(fp, " %8.4g", r);
-    else
-      fprintf(fp, qh_REAL_1, r);
-  }
-  fprintf(fp, "\n");
-} /* printpointid */
-
-/*---------------------------------
-  
-  qh_printpoint3( fp, point )
-    prints 2-d, 3-d, or 4-d point as Geomview 3-d coordinates
-*/
-void qh_printpoint3 (FILE *fp, pointT *point) {
-  int k;
-  realT p[4];
-  
-  qh_projectdim3 (point, p);
-  for (k=0; k < 3; k++)
-    fprintf (fp, "%8.4g ", p[k]);
-  fprintf (fp, " # p%d\n", qh_pointid (point));
-} /* printpoint3 */
-
-/*----------------------------------------
--printpoints- print pointids for a set of points starting at index 
-   see geom.c
-*/
-
-/*---------------------------------
-  
-  qh_printpoints_out( fp, facetlist, facets, printall )
-    prints vertices, coplanar/inside points, for facets by their point coordinates
-    allows qh.CDDoutput
-
-  notes:
-    same format as qhull input
-    if no coplanar/interior points,
-      same order as qh_printextremes
-*/
-void qh_printpoints_out (FILE *fp, facetT *facetlist, setT *facets, int printall) {
-  int allpoints= qh num_points + qh_setsize (qh other_points);
-  int numpoints=0, point_i, point_n;
-  setT *vertices, *points;
-  facetT *facet, **facetp;
-  pointT *point, **pointp;
-  vertexT *vertex, **vertexp;
-  int id;
-
-  points= qh_settemp (allpoints);
-  qh_setzero (points, 0, allpoints);
-  vertices= qh_facetvertices (facetlist, facets, printall);
-  FOREACHvertex_(vertices) {
-    id= qh_pointid (vertex->point);
-    if (id >= 0)
-      SETelem_(points, id)= vertex->point;
-  }
-  if (qh KEEPinside || qh KEEPcoplanar || qh KEEPnearinside) {
-    FORALLfacet_(facetlist) {
-      if (!printall && qh_skipfacet(facet))
-        continue;
-      FOREACHpoint_(facet->coplanarset) {
-        id= qh_pointid (point);
-        if (id >= 0)
-          SETelem_(points, id)= point;
-      }
-    }
-    FOREACHfacet_(facets) {
-      if (!printall && qh_skipfacet(facet))
-        continue;
-      FOREACHpoint_(facet->coplanarset) {
-        id= qh_pointid (point);
-        if (id >= 0)
-          SETelem_(points, id)= point;
-      }
-    }
-  }
-  qh_settempfree (&vertices);
-  FOREACHpoint_i_(points) {
-    if (point)
-      numpoints++;
-  }
-  if (qh CDDoutput)
-    fprintf (fp, "%s | %s\nbegin\n%d %d real\n", qh rbox_command,
-             qh qhull_command, numpoints, qh hull_dim + 1);
-  else
-    fprintf (fp, "%d\n%d\n", qh hull_dim, numpoints);
-  FOREACHpoint_i_(points) {
-    if (point) {
-      if (qh CDDoutput)
-	fprintf (fp, "1 ");
-      qh_printpoint (fp, NULL, point);
-    }
-  }
-  if (qh CDDoutput)
-    fprintf (fp, "end\n");
-  qh_settempfree (&points);
-} /* printpoints_out */
-  
-
-/*---------------------------------
-  
-  qh_printpointvect( fp, point, normal, center, radius, color )
-    prints a 2-d, 3-d, or 4-d point as 3-d VECT's relative to normal or to center point
-*/
-void qh_printpointvect (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]) {
-  realT diff[4], pointA[4];
-  int k;
-  
-  for (k= qh hull_dim; k--; ) {
-    if (center)
-      diff[k]= point[k]-center[k];
-    else if (normal) 
-      diff[k]= normal[k];
-    else
-      diff[k]= 0;
-  }
-  if (center)
-    qh_normalize2 (diff, qh hull_dim, True, NULL, NULL);
-  for (k= qh hull_dim; k--; ) 
-    pointA[k]= point[k]+diff[k] * radius;
-  qh_printline3geom (fp, point, pointA, color);
-} /* printpointvect */  
-
-/*---------------------------------
-  
-  qh_printpointvect2( fp, point, normal, center, radius )
-    prints a 2-d, 3-d, or 4-d point as 2 3-d VECT's for an imprecise point
-*/
-void qh_printpointvect2 (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius) {
-  realT red[3]={1, 0, 0}, yellow[3]={1, 1, 0};
-
-  qh_printpointvect (fp, point, normal, center, radius, red);
-  qh_printpointvect (fp, point, normal, center, -radius, yellow);
-} /* printpointvect2 */
-
-/*---------------------------------
-  
-  qh_printridge( fp, ridge )
-    prints the information in a ridge
-
-  notes:
-    for qh_printfacetridges()
-*/
-void qh_printridge(FILE *fp, ridgeT *ridge) {
-  
-  fprintf(fp, "     - r%d", ridge->id);
-  if (ridge->tested)
-    fprintf (fp, " tested");
-  if (ridge->nonconvex)
-    fprintf (fp, " nonconvex");
-  fprintf (fp, "\n");
-  qh_printvertices (fp, "           vertices:", ridge->vertices);
-  if (ridge->top && ridge->bottom)
-    fprintf(fp, "           between f%d and f%d\n",
-	    ridge->top->id, ridge->bottom->id);
-} /* printridge */
-
-/*---------------------------------
-  
-  qh_printspheres( fp, vertices, radius )
-    prints 3-d vertices as OFF spheres
-
-  notes:
-    inflated octahedron from Stuart Levy earth/mksphere2
-*/
-void qh_printspheres(FILE *fp, setT *vertices, realT radius) {
-  vertexT *vertex, **vertexp;
-
-  qh printoutnum++;
-  fprintf (fp, "{appearance {-edge -normal normscale 0} {\n\
-INST geom {define vsphere OFF\n\
-18 32 48\n\
-\n\
-0 0 1\n\
-1 0 0\n\
-0 1 0\n\
--1 0 0\n\
-0 -1 0\n\
-0 0 -1\n\
-0.707107 0 0.707107\n\
-0 -0.707107 0.707107\n\
-0.707107 -0.707107 0\n\
--0.707107 0 0.707107\n\
--0.707107 -0.707107 0\n\
-0 0.707107 0.707107\n\
--0.707107 0.707107 0\n\
-0.707107 0.707107 0\n\
-0.707107 0 -0.707107\n\
-0 0.707107 -0.707107\n\
--0.707107 0 -0.707107\n\
-0 -0.707107 -0.707107\n\
-\n\
-3 0 6 11\n\
-3 0 7 6	\n\
-3 0 9 7	\n\
-3 0 11 9\n\
-3 1 6 8	\n\
-3 1 8 14\n\
-3 1 13 6\n\
-3 1 14 13\n\
-3 2 11 13\n\
-3 2 12 11\n\
-3 2 13 15\n\
-3 2 15 12\n\
-3 3 9 12\n\
-3 3 10 9\n\
-3 3 12 16\n\
-3 3 16 10\n\
-3 4 7 10\n\
-3 4 8 7\n\
-3 4 10 17\n\
-3 4 17 8\n\
-3 5 14 17\n\
-3 5 15 14\n\
-3 5 16 15\n\
-3 5 17 16\n\
-3 6 13 11\n\
-3 7 8 6\n\
-3 9 10 7\n\
-3 11 12 9\n\
-3 14 8 17\n\
-3 15 13 14\n\
-3 16 12 15\n\
-3 17 10 16\n} transforms { TLIST\n");
-  FOREACHvertex_(vertices) {
-    fprintf(fp, "%8.4g 0 0 0 # v%d\n 0 %8.4g 0 0\n0 0 %8.4g 0\n",
-      radius, vertex->id, radius, radius);
-    qh_printpoint3 (fp, vertex->point);
-    fprintf (fp, "1\n");
-  }
-  fprintf (fp, "}}}\n");
-} /* printspheres */
-
-
-/*----------------------------------------------
--printsummary-
-                see qhull.c
-*/
-
-/*---------------------------------
-  
-  qh_printvdiagram( fp, format, facetlist, facets, printall )
-    print voronoi diagram
-      # of pairs of input sites
-      #indices site1 site2 vertex1 ...
-    
-    sites indexed by input point id
-      point 0 is the first input point
-    vertices indexed by 'o' and 'p' order
-      vertex 0 is the 'vertex-at-infinity'
-      vertex 1 is the first Voronoi vertex
-
-  see:
-    qh_printvoronoi()
-    qh_eachvoronoi_all()
-
-  notes:
-    if all facets are upperdelaunay, 
-      prints upper hull (furthest-site Voronoi diagram)
-*/
-void qh_printvdiagram (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) {
-  setT *vertices;
-  int totcount, numcenters;
-  boolT islower;
-  qh_RIDGE innerouter= qh_RIDGEall;
-  printvridgeT printvridge= NULL;
-
-  if (format == qh_PRINTvertices) {
-    innerouter= qh_RIDGEall;
-    printvridge= qh_printvridge;
-  }else if (format == qh_PRINTinner) {
-    innerouter= qh_RIDGEinner;
-    printvridge= qh_printvnorm;
-  }else if (format == qh_PRINTouter) {
-    innerouter= qh_RIDGEouter;
-    printvridge= qh_printvnorm;
-  }else {
-    fprintf(qh ferr, "qh_printvdiagram: unknown print format %d.\n", format);
-    qh_errexit (qh_ERRinput, NULL, NULL);
-  }
-  vertices= qh_markvoronoi (facetlist, facets, printall, &islower, &numcenters);
-  totcount= qh_printvdiagram2 (NULL, NULL, vertices, innerouter, False);
-  fprintf (fp, "%d\n", totcount);
-  totcount= qh_printvdiagram2 (fp, printvridge, vertices, innerouter, True /* inorder*/);
-  qh_settempfree (&vertices);
-#if 0  /* for testing qh_eachvoronoi_all */
-  fprintf (fp, "\n");
-  totcount= qh_eachvoronoi_all(fp, printvridge, qh UPPERdelaunay, innerouter, True /* inorder*/);
-  fprintf (fp, "%d\n", totcount);
-#endif
-} /* printvdiagram */
-  
-/*---------------------------------
-  
-  qh_printvdiagram2( fp, printvridge, vertices, innerouter, inorder )
-    visit all pairs of input sites (vertices) for selected Voronoi vertices
-    vertices may include NULLs
-  
-  innerouter:
-    qh_RIDGEall   print inner ridges (bounded) and outer ridges (unbounded)
-    qh_RIDGEinner print only inner ridges
-    qh_RIDGEouter print only outer ridges
-  
-  inorder:
-    print 3-d Voronoi vertices in order
-  
-  assumes:
-    qh_markvoronoi marked facet->visitid for Voronoi vertices
-    all facet->seen= False
-    all facet->seen2= True
-  
-  returns:
-    total number of Voronoi ridges 
-    if printvridge,
-      calls printvridge( fp, vertex, vertexA, centers) for each ridge
-      [see qh_eachvoronoi()]
-  
-  see:
-    qh_eachvoronoi_all()
-*/
-int qh_printvdiagram2 (FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder) {
-  int totcount= 0;
-  int vertex_i, vertex_n;
-  vertexT *vertex;
-
-  FORALLvertices 
-    vertex->seen= False;
-  FOREACHvertex_i_(vertices) {
-    if (vertex) {
-      if (qh GOODvertex > 0 && qh_pointid(vertex->point)+1 != qh GOODvertex)
-	continue;
-      totcount += qh_eachvoronoi (fp, printvridge, vertex, !qh_ALL, innerouter, inorder);
-    }
-  }
-  return totcount;
-} /* printvdiagram2 */
-  
-/*---------------------------------
-  
-  qh_printvertex( fp, vertex )
-    prints the information in a vertex
-*/
-void qh_printvertex(FILE *fp, vertexT *vertex) {
-  pointT *point;
-  int k, count= 0;
-  facetT *neighbor, **neighborp;
-  realT r; /*bug fix*/
-
-  if (!vertex) {
-    fprintf (fp, "  NULLvertex\n");
-    return;
-  }
-  fprintf(fp, "- p%d (v%d):", qh_pointid(vertex->point), vertex->id);
-  point= vertex->point;
-  if (point) {
-    for(k= qh hull_dim; k--; ) {
-      r= *point++;
-      fprintf(fp, " %5.2g", r);
-    }
-  }
-  if (vertex->deleted)
-    fprintf(fp, " deleted");
-  if (vertex->delridge)
-    fprintf (fp, " ridgedeleted");
-  fprintf(fp, "\n");
-  if (vertex->neighbors) {
-    fprintf(fp, "  neighbors:");
-    FOREACHneighbor_(vertex) {
-      if (++count % 100 == 0)
-	fprintf (fp, "\n     ");
-      fprintf(fp, " f%d", neighbor->id);
-    }
-    fprintf(fp, "\n");
-  }
-} /* printvertex */
-
-
-/*---------------------------------
-  
-  qh_printvertexlist( fp, string, facetlist, facets, printall )
-    prints vertices used by a facetlist or facet set
-    tests qh_skipfacet() if !printall
-*/
-void qh_printvertexlist (FILE *fp, char* string, facetT *facetlist, 
-                         setT *facets, boolT printall) {
-  vertexT *vertex, **vertexp;
-  setT *vertices;
-  
-  vertices= qh_facetvertices (facetlist, facets, printall);
-  fputs (string, fp);
-  FOREACHvertex_(vertices)
-    qh_printvertex(fp, vertex);
-  qh_settempfree (&vertices);
-} /* printvertexlist */
-
-
-/*---------------------------------
-  
-  qh_printvertices( fp, string, vertices )
-    prints vertices in a set
-*/
-void qh_printvertices(FILE *fp, char* string, setT *vertices) {
-  vertexT *vertex, **vertexp;
-  
-  fputs (string, fp);
-  FOREACHvertex_(vertices) 
-    fprintf (fp, " p%d (v%d)", qh_pointid(vertex->point), vertex->id);
-  fprintf(fp, "\n");
-} /* printvertices */
-
-/*---------------------------------
-  
-  qh_printvneighbors( fp, facetlist, facets, printall )
-    print vertex neighbors of vertices in facetlist and facets ('FN')
-
-  notes:
-    qh_countfacets clears facet->visitid for non-printed facets
-
-  design:
-    collect facet count and related statistics
-    if necessary, build neighbor sets for each vertex
-    collect vertices in facetlist and facets
-    build a point array for point->vertex and point->coplanar facet
-    for each point
-      list vertex neighbors or coplanar facet
-*/
-void qh_printvneighbors (FILE *fp, facetT* facetlist, setT *facets, boolT printall) {
-  int numfacets, numsimplicial, numridges, totneighbors, numneighbors, numcoplanars, numtricoplanars;
-  setT *vertices, *vertex_points, *coplanar_points;
-  int numpoints= qh num_points + qh_setsize (qh other_points);
-  vertexT *vertex, **vertexp;
-  int vertex_i, vertex_n;
-  facetT *facet, **facetp, *neighbor, **neighborp;
-  pointT *point, **pointp;
-
-  qh_countfacets (facetlist, facets, printall, &numfacets, &numsimplicial, 
-      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);  /* sets facet->visitid */
-  fprintf (fp, "%d\n", numpoints);
-  qh_vertexneighbors();
-  vertices= qh_facetvertices (facetlist, facets, printall);
-  vertex_points= qh_settemp (numpoints);
-  coplanar_points= qh_settemp (numpoints);
-  qh_setzero (vertex_points, 0, numpoints);
-  qh_setzero (coplanar_points, 0, numpoints);
-  FOREACHvertex_(vertices)
-    qh_point_add (vertex_points, vertex->point, vertex);
-  FORALLfacet_(facetlist) {
-    FOREACHpoint_(facet->coplanarset)
-      qh_point_add (coplanar_points, point, facet);
-  }
-  FOREACHfacet_(facets) {
-    FOREACHpoint_(facet->coplanarset)
-      qh_point_add (coplanar_points, point, facet);
-  }
-  FOREACHvertex_i_(vertex_points) {
-    if (vertex) { 
-      numneighbors= qh_setsize (vertex->neighbors);
-      fprintf (fp, "%d", numneighbors);
-      if (qh hull_dim == 3)
-        qh_order_vertexneighbors (vertex);
-      else if (qh hull_dim >= 4)
-        qsort (SETaddr_(vertex->neighbors, facetT), numneighbors,
-             sizeof (facetT *), qh_compare_facetvisit);
-      FOREACHneighbor_(vertex) 
-        fprintf (fp, " %d", 
-		 neighbor->visitid ? neighbor->visitid - 1 : - neighbor->id);
-      fprintf (fp, "\n");
-    }else if ((facet= SETelemt_(coplanar_points, vertex_i, facetT)))
-      fprintf (fp, "1 %d\n",
-                  facet->visitid ? facet->visitid - 1 : - facet->id);
-    else
-      fprintf (fp, "0\n");
-  }
-  qh_settempfree (&coplanar_points);
-  qh_settempfree (&vertex_points);
-  qh_settempfree (&vertices);
-} /* printvneighbors */
-
-/*---------------------------------
-  
-  qh_printvoronoi( fp, format, facetlist, facets, printall )
-    print voronoi diagram in 'o' or 'G' format
-    for 'o' format
-      prints voronoi centers for each facet and for infinity
-      for each vertex, lists ids of printed facets or infinity
-      assumes facetlist and facets are disjoint
-    for 'G' format
-      prints an OFF object
-      adds a 0 coordinate to center
-      prints infinity but does not list in vertices
-
-  see:
-    qh_printvdiagram()
-
-  notes:
-    if 'o', 
-      prints a line for each point except "at-infinity"
-    if all facets are upperdelaunay, 
-      reverses lower and upper hull
-*/
-void qh_printvoronoi (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) {
-  int k, numcenters, numvertices= 0, numneighbors, numinf, vid=1, vertex_i, vertex_n;
-  facetT *facet, **facetp, *neighbor, **neighborp;
-  setT *vertices;
-  vertexT *vertex;
-  boolT islower;
-  unsigned int numfacets= (unsigned int) qh num_facets;
-
-  vertices= qh_markvoronoi (facetlist, facets, printall, &islower, &numcenters);
-  FOREACHvertex_i_(vertices) {
-    if (vertex) {
-      numvertices++;
-      numneighbors = numinf = 0;
-      FOREACHneighbor_(vertex) {
-        if (neighbor->visitid == 0)
-	  numinf= 1;
-        else if (neighbor->visitid < numfacets)
-          numneighbors++;
-      }
-      if (numinf && !numneighbors) {
-	SETelem_(vertices, vertex_i)= NULL;
-	numvertices--;
-      }
-    }
-  }
-  if (format == qh_PRINTgeom) 
-    fprintf (fp, "{appearance {+edge -face} OFF %d %d 1 # Voronoi centers and cells\n", 
-                numcenters, numvertices);
-  else
-    fprintf (fp, "%d\n%d %d 1\n", qh hull_dim-1, numcenters, qh_setsize(vertices));
-  if (format == qh_PRINTgeom) {
-    for (k= qh hull_dim-1; k--; )
-      fprintf (fp, qh_REAL_1, 0.0);
-    fprintf (fp, " 0 # infinity not used\n");
-  }else {
-    for (k= qh hull_dim-1; k--; )
-      fprintf (fp, qh_REAL_1, qh_INFINITE);
-    fprintf (fp, "\n");
-  }
-  FORALLfacet_(facetlist) {
-    if (facet->visitid && facet->visitid < numfacets) {
-      if (format == qh_PRINTgeom)
-        fprintf (fp, "# %d f%d\n", vid++, facet->id);
-      qh_printcenter (fp, format, NULL, facet);
-    }
-  }
-  FOREACHfacet_(facets) {
-    if (facet->visitid && facet->visitid < numfacets) {
-      if (format == qh_PRINTgeom)
-        fprintf (fp, "# %d f%d\n", vid++, facet->id);
-      qh_printcenter (fp, format, NULL, facet);
-    }
-  }
-  FOREACHvertex_i_(vertices) {
-    numneighbors= 0;
-    numinf=0;
-    if (vertex) {
-      if (qh hull_dim == 3)
-        qh_order_vertexneighbors(vertex);
-      else if (qh hull_dim >= 4)
-        qsort (SETaddr_(vertex->neighbors, vertexT), 
-	     qh_setsize (vertex->neighbors),
-	     sizeof (facetT *), qh_compare_facetvisit);
-      FOREACHneighbor_(vertex) {
-        if (neighbor->visitid == 0)
-	  numinf= 1;
-	else if (neighbor->visitid < numfacets)
-          numneighbors++;
-      }
-    }
-    if (format == qh_PRINTgeom) {
-      if (vertex) {
-	fprintf (fp, "%d", numneighbors);
-	if (vertex) {
-	  FOREACHneighbor_(vertex) {
-	    if (neighbor->visitid && neighbor->visitid < numfacets)
-	      fprintf (fp, " %d", neighbor->visitid);
-	  }
-	}
-	fprintf (fp, " # p%d (v%d)\n", vertex_i, vertex->id);
-      }else
-	fprintf (fp, " # p%d is coplanar or isolated\n", vertex_i);
-    }else {
-      if (numinf)
-	numneighbors++;
-      fprintf (fp, "%d", numneighbors);
-      if (vertex) {
-        FOREACHneighbor_(vertex) {
-  	  if (neighbor->visitid == 0) {
-  	    if (numinf) {
-  	      numinf= 0;
-	      fprintf (fp, " %d", neighbor->visitid);
-	    }
-	  }else if (neighbor->visitid < numfacets)
-	    fprintf (fp, " %d", neighbor->visitid);
-	}
-      }
-      fprintf (fp, "\n");
-    }
-  }
-  if (format == qh_PRINTgeom)
-    fprintf (fp, "}\n");
-  qh_settempfree (&vertices);
-} /* printvoronoi */
-  
-/*---------------------------------
-  
-  qh_printvnorm( fp, vertex, vertexA, centers, unbounded )
-    print one separating plane of the Voronoi diagram for a pair of input sites
-    unbounded==True if centers includes vertex-at-infinity
-  
-  assumes:
-    qh_ASvoronoi and qh_vertexneighbors() already set
-    
-  see:
-    qh_printvdiagram()
-    qh_eachvoronoi()
-*/
-void qh_printvnorm (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
-  pointT *normal;
-  realT offset;
-  int k;
-  
-  normal= qh_detvnorm (vertex, vertexA, centers, &offset);
-  fprintf (fp, "%d %d %d ", 
-      2+qh hull_dim, qh_pointid (vertex->point), qh_pointid (vertexA->point));
-  for (k= 0; k< qh hull_dim-1; k++)
-    fprintf (fp, qh_REAL_1, normal[k]);
-  fprintf (fp, qh_REAL_1, offset);
-  fprintf (fp, "\n");
-} /* printvnorm */
-
-/*---------------------------------
-  
-  qh_printvridge( fp, vertex, vertexA, centers, unbounded )
-    print one ridge of the Voronoi diagram for a pair of input sites
-    unbounded==True if centers includes vertex-at-infinity
-  
-  see:
-    qh_printvdiagram()
-  
-  notes:
-    the user may use a different function
-*/
-void qh_printvridge (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
-  facetT *facet, **facetp;
-
-  fprintf (fp, "%d %d %d", qh_setsize (centers)+2, 
-       qh_pointid (vertex->point), qh_pointid (vertexA->point));
-  FOREACHfacet_(centers) 
-    fprintf (fp, " %d", facet->visitid);
-  fprintf (fp, "\n");
-} /* printvridge */
-
-/*---------------------------------
-  
-  qh_projectdim3( source, destination )
-    project 2-d 3-d or 4-d point to a 3-d point
-    uses qh.DROPdim and qh.hull_dim
-    source and destination may be the same
-    
-  notes:
-    allocate 4 elements to destination just in case
-*/
-void qh_projectdim3 (pointT *source, pointT *destination) {
-  int i,k;
-
-  for (k= 0, i=0; k < qh hull_dim; k++) {
-    if (qh hull_dim == 4) {
-      if (k != qh DROPdim)
-        destination[i++]= source[k];
-    }else if (k == qh DROPdim)
-      destination[i++]= 0;
-    else
-      destination[i++]= source[k];
-  }
-  while (i < 3)
-    destination[i++]= 0.0;
-} /* projectdim3 */
-
-/*---------------------------------
-  
-  qh_readfeasible( dim, remainder )
-    read feasible point from remainder string and qh.fin
-
-  returns:
-    number of lines read from qh.fin
-    sets qh.FEASIBLEpoint with malloc'd coordinates
-
-  notes:
-    checks for qh.HALFspace
-    assumes dim > 1
-
-  see:
-    qh_setfeasible
-*/
-int qh_readfeasible (int dim, char *remainder) {
-  boolT isfirst= True;
-  int linecount= 0, tokcount= 0;
-  char *s, *t, firstline[qh_MAXfirst+1];
-  coordT *coords, value;
-
-  if (!qh HALFspace) {
-    fprintf  (qh ferr, "qhull input error: feasible point (dim 1 coords) is only valid for halfspace intersection\n");
-    qh_errexit (qh_ERRinput, NULL, NULL);
-  }  
-  if (qh feasible_string)
-    fprintf  (qh ferr, "qhull input warning: feasible point (dim 1 coords) overrides 'Hn,n,n' feasible point for halfspace intersection\n");
-  if (!(qh feasible_point= (coordT*)malloc (dim* sizeof(coordT)))) {
-    fprintf(qh ferr, "qhull error: insufficient memory for feasible point\n");
-    qh_errexit(qh_ERRmem, NULL, NULL);
-  }
-  coords= qh feasible_point;
-  while ((s= (isfirst ?  remainder : fgets(firstline, qh_MAXfirst, qh fin)))) {
-    if (isfirst)
-      isfirst= False;
-    else
-      linecount++;
-    while (*s) {
-      while (isspace(*s))
-        s++;
-      value= qh_strtod (s, &t);
-      if (s == t)
-        break;
-      s= t;
-      *(coords++)= value;
-      if (++tokcount == dim) {
-        while (isspace (*s))
-          s++;
-        qh_strtod (s, &t);
-        if (s != t) {
-          fprintf (qh ferr, "qhull input error: coordinates for feasible point do not finish out the line: %s\n",
-               s);
-          qh_errexit (qh_ERRinput, NULL, NULL);
-        }
-        return linecount;
-      }
-    }
-  }
-  fprintf (qh ferr, "qhull input error: only %d coordinates.  Could not read %d-d feasible point.\n",
-           tokcount, dim);
-  qh_errexit (qh_ERRinput, NULL, NULL);
-  return 0;
-} /* readfeasible */
-
-/*---------------------------------
-  
-  qh_readpoints( numpoints, dimension, ismalloc )
-    read points from qh.fin into qh.first_point, qh.num_points
-    qh.fin is lines of coordinates, one per vertex, first line number of points
-    if 'rbox D4',
-      gives message
-    if qh.ATinfinity,
-      adds point-at-infinity for Delaunay triangulations
-
-  returns:
-    number of points, array of point coordinates, dimension, ismalloc True
-    if qh.DELAUNAY & !qh.PROJECTinput, projects points to paraboloid
-        and clears qh.PROJECTdelaunay
-    if qh.HALFspace, reads optional feasible point, reads halfspaces,
-        converts to dual.
-
-  for feasible point in "cdd format" in 3-d:
-    3 1
-    coordinates
-    comments
-    begin
-    n 4 real/integer
-    ...
-    end
-
-  notes:
-    dimension will change in qh_initqhull_globals if qh.PROJECTinput
-    uses malloc() since qh_mem not initialized
-    FIXUP: this routine needs rewriting
-*/
-coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc) {
-  coordT *points, *coords, *infinity= NULL;
-  realT paraboloid, maxboloid= -REALmax, value;
-  realT *coordp= NULL, *offsetp= NULL, *normalp= NULL;
-  char *s, *t, firstline[qh_MAXfirst+1];
-  int diminput=0, numinput=0, dimfeasible= 0, newnum, k, tempi;
-  int firsttext=0, firstshort=0, firstlong=0, firstpoint=0;
-  int tokcount= 0, linecount=0, maxcount, coordcount=0;
-  boolT islong, isfirst= True, wasbegin= False;
-  boolT isdelaunay= qh DELAUNAY && !qh PROJECTinput;
-
-  if (qh CDDinput) {
-    while ((s= fgets(firstline, qh_MAXfirst, qh fin))) {
-      linecount++;
-      if (qh HALFspace && linecount == 1 && isdigit(*s)) {
-	dimfeasible= qh_strtol (s, &s);	
-	while (isspace(*s))
-          s++;
-        if (qh_strtol (s, &s) == 1)
-          linecount += qh_readfeasible (dimfeasible, s);
-        else
-          dimfeasible= 0;
-      }else if (!memcmp (firstline, "begin", 5) || !memcmp (firstline, "BEGIN", 5))
-        break;
-      else if (!*qh rbox_command)
-	strncat(qh rbox_command, s, sizeof (qh rbox_command)-1);
-    }
-    if (!s) {
-      fprintf (qh ferr, "qhull input error: missing \"begin\" for cdd-formated input\n");
-      qh_errexit (qh_ERRinput, NULL, NULL);
-    }
-  }
-  while(!numinput && (s= fgets(firstline, qh_MAXfirst, qh fin))) {
-    linecount++;
-    if (!memcmp (s, "begin", 5) || !memcmp (s, "BEGIN", 5))
-      wasbegin= True;
-    while (*s) {
-      while (isspace(*s))
-        s++;
-      if (!*s)
-        break;
-      if (!isdigit(*s)) {
-        if (!*qh rbox_command) {
-          strncat(qh rbox_command, s, sizeof (qh rbox_command)-1);
-	  firsttext= linecount;
-        }
-        break;
-      }
-      if (!diminput) 
-        diminput= qh_strtol (s, &s);
-      else {
-        numinput= qh_strtol (s, &s);
-        if (numinput == 1 && diminput >= 2 && qh HALFspace && !qh CDDinput) {
-          linecount += qh_readfeasible (diminput, s); /* checks if ok */
-          dimfeasible= diminput;
-          diminput= numinput= 0;
-        }else 
-          break;
-      }
-    }
-  }
-  if (!s) {
-    fprintf(qh ferr, "qhull input error: short input file.  Did not find dimension and number of points\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (diminput > numinput) {
-    tempi= diminput;	/* exchange dim and n, e.g., for cdd input format */
-    diminput= numinput;
-    numinput= tempi;
-  }
-  if (diminput < 2) {
-    fprintf(qh ferr,"qhull input error: dimension %d (first number) should be at least 2\n",
-	    diminput);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (isdelaunay) {
-    qh PROJECTdelaunay= False;
-    if (qh CDDinput)
-      *dimension= diminput;
-    else
-      *dimension= diminput+1;
-    *numpoints= numinput;
-    if (qh ATinfinity)
-      (*numpoints)++;
-  }else if (qh HALFspace) {
-    *dimension= diminput - 1;
-    *numpoints= numinput;
-    if (diminput < 3) {
-      fprintf(qh ferr,"qhull input error: dimension %d (first number, includes offset) should be at least 3 for halfspaces\n",
-  	    diminput);
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    if (dimfeasible) {
-      if (dimfeasible != *dimension) {
-        fprintf(qh ferr,"qhull input error: dimension %d of feasible point is not one less than dimension %d for halfspaces\n",
-          dimfeasible, diminput);
-        qh_errexit(qh_ERRinput, NULL, NULL);
-      }
-    }else 
-      qh_setfeasible (*dimension);
-  }else {
-    if (qh CDDinput) 
-      *dimension= diminput-1;
-    else
-      *dimension= diminput;
-    *numpoints= numinput;
-  }
-  qh normal_size= *dimension * sizeof(coordT); /* for tracing with qh_printpoint */
-  if (qh HALFspace) {
-    qh half_space= coordp= (coordT*) malloc (qh normal_size + sizeof(coordT));
-    if (qh CDDinput) {
-      offsetp= qh half_space;
-      normalp= offsetp + 1;
-    }else {
-      normalp= qh half_space;
-      offsetp= normalp + *dimension;
-    }
-  } 
-  qh maxline= diminput * (qh_REALdigits + 5);
-  maximize_(qh maxline, 500);
-  qh line= (char*)malloc ((qh maxline+1) * sizeof (char));
-  *ismalloc= True;  /* use malloc since memory not setup */
-  coords= points= qh temp_malloc= 
-        (coordT*)malloc((*numpoints)*(*dimension)*sizeof(coordT));
-  if (!coords || !qh line || (qh HALFspace && !qh half_space)) {
-    fprintf(qh ferr, "qhull error: insufficient memory to read %d points\n",
-	    numinput);
-    qh_errexit(qh_ERRmem, NULL, NULL);
-  }
-  if (isdelaunay && qh ATinfinity) {
-    infinity= points + numinput * (*dimension);
-    for (k= (*dimension) - 1; k--; )
-      infinity[k]= 0.0;
-  }
-  maxcount= numinput * diminput;
-  paraboloid= 0.0;
-  while ((s= (isfirst ?  s : fgets(qh line, qh maxline, qh fin)))) {
-    if (!isfirst) {
-      linecount++;
-      if (*s == 'e' || *s == 'E') {
-	if (!memcmp (s, "end", 3) || !memcmp (s, "END", 3)) {
-	  if (qh CDDinput )
-	    break;
-	  else if (wasbegin) 
-	    fprintf (qh ferr, "qhull input warning: the input appears to be in cdd format.  If so, use 'Fd'\n");
-	}
-      }
-    }
-    islong= False;
-    while (*s) {
-      while (isspace(*s))
-        s++;
-      value= qh_strtod (s, &t);
-      if (s == t) {
-        if (!*qh rbox_command)
- 	 strncat(qh rbox_command, s, sizeof (qh rbox_command)-1);
-        if (*s && !firsttext) 
-          firsttext= linecount;
-        if (!islong && !firstshort && coordcount)
-          firstshort= linecount;
-        break;
-      }
-      if (!firstpoint)
-	firstpoint= linecount;
-      s= t;
-      if (++tokcount > maxcount)
-        continue;
-      if (qh HALFspace) {
-	if (qh CDDinput) 
-	  *(coordp++)= -value; /* both coefficients and offset */
-	else
-	  *(coordp++)= value;
-      }else {
-        *(coords++)= value;
-        if (qh CDDinput && !coordcount) {
-          if (value != 1.0) {
-            fprintf (qh ferr, "qhull input error: for cdd format, point at line %d does not start with '1'\n",
-                   linecount);
-            qh_errexit (qh_ERRinput, NULL, NULL);
-          }
-          coords--;
-        }else if (isdelaunay) {
-	  paraboloid += value * value;
-	  if (qh ATinfinity) {
-	    if (qh CDDinput)
-	      infinity[coordcount-1] += value;
-	    else
-	      infinity[coordcount] += value;
-	  }
-	}
-      }
-      if (++coordcount == diminput) {
-        coordcount= 0;
-        if (isdelaunay) {
-          *(coords++)= paraboloid;
-          maximize_(maxboloid, paraboloid);
-          paraboloid= 0.0;
-        }else if (qh HALFspace) {
-          if (!qh_sethalfspace (*dimension, coords, &coords, normalp, offsetp, qh feasible_point)) {
-	    fprintf (qh ferr, "The halfspace was on line %d\n", linecount);
-	    if (wasbegin)
-	      fprintf (qh ferr, "The input appears to be in cdd format.  If so, you should use option 'Fd'\n");
-	    qh_errexit (qh_ERRinput, NULL, NULL);
-	  }
-          coordp= qh half_space;
-        }          
-        while (isspace(*s))
-          s++;
-        if (*s) {
-          islong= True;
-          if (!firstlong)
-            firstlong= linecount;
-	}
-      }
-    }
-    if (!islong && !firstshort && coordcount)
-      firstshort= linecount;
-    if (!isfirst && s - qh line >= qh maxline) {
-      fprintf(qh ferr, "qhull input error: line %d contained more than %d characters\n", 
-	      linecount, (int) (s - qh line));
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    isfirst= False;
-  }
-  if (tokcount != maxcount) {
-    newnum= fmin_(numinput, tokcount/diminput);
-    fprintf(qh ferr,"\
-qhull warning: instead of %d %d-dimensional points, input contains\n\
-%d points and %d extra coordinates.  Line %d is the first\npoint",
-       numinput, diminput, tokcount/diminput, tokcount % diminput, firstpoint);
-    if (firsttext)
-      fprintf(qh ferr, ", line %d is the first comment", firsttext);
-    if (firstshort)
-      fprintf(qh ferr, ", line %d is the first short\nline", firstshort);
-    if (firstlong)
-      fprintf(qh ferr, ", line %d is the first long line", firstlong);
-    fprintf(qh ferr, ".  Continue with %d points.\n", newnum);
-    numinput= newnum;
-    if (isdelaunay && qh ATinfinity) {
-      for (k= tokcount % diminput; k--; )
-	infinity[k] -= *(--coords);
-      *numpoints= newnum+1;
-    }else {
-      coords -= tokcount % diminput;
-      *numpoints= newnum;
-    }
-  }
-  if (isdelaunay && qh ATinfinity) {
-    for (k= (*dimension) -1; k--; )
-      infinity[k] /= numinput;
-    if (coords == infinity)
-      coords += (*dimension) -1;
-    else {
-      for (k= 0; k < (*dimension) -1; k++)
-	*(coords++)= infinity[k];
-    }
-    *(coords++)= maxboloid * 1.1;
-  }
-  if (qh rbox_command[0]) {
-    qh rbox_command[strlen(qh rbox_command)-1]= '\0';
-    if (!strcmp (qh rbox_command, "./rbox D4")) 
-      fprintf (qh ferr, "\n\
-This is the qhull test case.  If any errors or core dumps occur,\n\
-recompile qhull with 'make new'.  If errors still occur, there is\n\
-an incompatibility.  You should try a different compiler.  You can also\n\
-change the choices in user.h.  If you discover the source of the problem,\n\
-please send mail to qhull_bug@geom.umn.edu.\n\
-\n\
-Type 'qhull' for a short list of options.\n");
-  }
-  free (qh line);
-  qh line= NULL;
-  if (qh half_space) {
-    free (qh half_space);
-    qh half_space= NULL;
-  }
-  qh temp_malloc= NULL;
-  trace1((qh ferr,"qh_readpoints: read in %d %d-dimensional points\n",
-	  numinput, diminput));
-  return(points);
-} /* readpoints */
-
-
-/*---------------------------------
-  
-  qh_setfeasible( dim )
-    set qh.FEASIBLEpoint from qh.feasible_string in "n,n,n" or "n n n" format
-
-  notes:
-    "n,n,n" already checked by qh_initflags()
-    see qh_readfeasible()
-*/
-void qh_setfeasible (int dim) {
-  int tokcount= 0;
-  char *s;
-  coordT *coords, value;
-
-  if (!(s= qh feasible_string)) {
-    fprintf(qh ferr, "\
-qhull input error: halfspace intersection needs a feasible point.\n\
-Either prepend the input with 1 point or use 'Hn,n,n'.  See manual.\n");
-    qh_errexit (qh_ERRinput, NULL, NULL);
-  }
-  if (!(qh feasible_point= (pointT*)malloc (dim* sizeof(coordT)))) {
-    fprintf(qh ferr, "qhull error: insufficient memory for 'Hn,n,n'\n");
-    qh_errexit(qh_ERRmem, NULL, NULL);
-  }
-  coords= qh feasible_point;
-  while (*s) {
-    value= qh_strtod (s, &s);
-    if (++tokcount > dim) {
-      fprintf (qh ferr, "qhull input warning: more coordinates for 'H%s' than dimension %d\n",
-          qh feasible_string, dim);
-      break;
-    }
-    *(coords++)= value;
-    if (*s)
-      s++;
-  }
-  while (++tokcount <= dim)    
-    *(coords++)= 0.0;
-} /* setfeasible */
-
-/*---------------------------------
-  
-  qh_skipfacet( facet )
-    returns 'True' if this facet is not to be printed 
-
-  notes:
-    based on the user provided slice thresholds and 'good' specifications
-*/
-boolT qh_skipfacet(facetT *facet) {
-  facetT *neighbor, **neighborp;
-
-  if (qh PRINTneighbors) {
-    if (facet->good)
-      return !qh PRINTgood;
-    FOREACHneighbor_(facet) {
-      if (neighbor->good)
-	return False;
-    }
-    return True;
-  }else if (qh PRINTgood)
-    return !facet->good;
-  else if (!facet->normal)
-    return True;
-  return (!qh_inthresholds (facet->normal, NULL));
-} /* skipfacet */
-
diff --git a/extern/qhull/src/io.h b/extern/qhull/src/io.h
deleted file mode 100644
index 351d56b3708..00000000000
--- a/extern/qhull/src/io.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
  ---------------------------------
-
-   io.h 
-   declarations of Input/Output functions
-
-   see README, qhull.h and io.c
-
-   copyright (c) 1993-2002, The Geometry Center
-*/
-
-#ifndef qhDEFio
-#define qhDEFio 1
-
-/*============ constants and flags ==================*/
-
-/*----------------------------------
-  
-  qh_MAXfirst
-    maximum length of first two lines of stdin
-*/
-#define qh_MAXfirst  200
-
-/*----------------------------------
-  
-  qh_MINradius
-    min radius for Gp and Gv, fraction of maxcoord
-*/
-#define qh_MINradius 0.02
-
-/*----------------------------------
-  
-  qh_GEOMepsilon
-    adjust outer planes for 'lines closer' and geomview roundoff.  
-    This prevents bleed through.
-*/
-#define qh_GEOMepsilon 2e-3
-
-/*----------------------------------
-  
-  qh_WHITESPACE
-    possible values of white space
-*/
-#define qh_WHITESPACE " \n\t\v\r\f"
-
-
-/*----------------------------------
-  
-  qh_RIDGE
-    to select which ridges to print in qh_eachvoronoi
-*/
-typedef enum
-{
-    qh_RIDGEall = 0, qh_RIDGEinner, qh_RIDGEouter
-}
-qh_RIDGE;
-
-/*----------------------------------
-  
-  printvridgeT
-    prints results of qh_printvdiagram
-
-  see:
-    qh_printvridge for an example
-*/
-typedef void (*printvridgeT)(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
-
-/*============== -prototypes in alphabetical order =========*/
-
-void    dfacet( unsigned id);
-void    dvertex( unsigned id);
-void    qh_countfacets (facetT *facetlist, setT *facets, boolT printall, 
-              int *numfacetsp, int *numsimplicialp, int *totneighborsp, 
-              int *numridgesp, int *numcoplanarsp, int *numnumtricoplanarsp);
-pointT *qh_detvnorm (vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp);
-setT   *qh_detvridge (vertexT *vertex);
-setT   *qh_detvridge3 (vertexT *atvertex, vertexT *vertex);
-int     qh_eachvoronoi (FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder);
-int     qh_eachvoronoi_all (FILE *fp, printvridgeT printvridge, boolT isupper, qh_RIDGE innerouter, boolT inorder);
-void	qh_facet2point(facetT *facet, pointT **point0, pointT **point1, realT *mindist);
-setT   *qh_facetvertices (facetT *facetlist, setT *facets, boolT allfacets);
-void    qh_geomplanes (facetT *facet, realT *outerplane, realT *innerplane);
-void    qh_markkeep (facetT *facetlist);
-setT   *qh_markvoronoi (facetT *facetlist, setT *facets, boolT printall, boolT *islowerp, int *numcentersp);
-void    qh_order_vertexneighbors(vertexT *vertex);
-void	qh_printafacet(FILE *fp, int format, facetT *facet, boolT printall);
-void    qh_printbegin (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
-void 	qh_printcenter (FILE *fp, int format, char *string, facetT *facet);
-void    qh_printcentrum (FILE *fp, facetT *facet, realT radius);
-void    qh_printend (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
-void    qh_printend4geom (FILE *fp, facetT *facet, int *num, boolT printall);
-void    qh_printextremes (FILE *fp, facetT *facetlist, setT *facets, int printall);
-void    qh_printextremes_2d (FILE *fp, facetT *facetlist, setT *facets, int printall);
-void    qh_printextremes_d (FILE *fp, facetT *facetlist, setT *facets, int printall);
-void	qh_printfacet(FILE *fp, facetT *facet);
-void	qh_printfacet2math(FILE *fp, facetT *facet, int notfirst);
-void	qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]);
-void    qh_printfacet2geom_points(FILE *fp, pointT *point1, pointT *point2,
-			       facetT *facet, realT offset, realT color[3]);
-void	qh_printfacet3math (FILE *fp, facetT *facet, int notfirst);
-void	qh_printfacet3geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]);
-void	qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]);
-void	qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]);
-void	qh_printfacet3vertex(FILE *fp, facetT *facet, int format);
-void	qh_printfacet4geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]);
-void	qh_printfacet4geom_simplicial(FILE *fp, facetT *facet, realT color[3]);
-void	qh_printfacetNvertex_nonsimplicial(FILE *fp, facetT *facet, int id, int format);
-void	qh_printfacetNvertex_simplicial(FILE *fp, facetT *facet, int format);
-void    qh_printfacetheader(FILE *fp, facetT *facet);
-void    qh_printfacetridges(FILE *fp, facetT *facet);
-void	qh_printfacets(FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
-void	qh_printhelp_degenerate(FILE *fp);
-void	qh_printhelp_singular(FILE *fp);
-void	qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2,
-  		   setT *vertices, realT color[3]);
-void	qh_printneighborhood (FILE *fp, int format, facetT *facetA, facetT *facetB, boolT printall);
-void    qh_printline3geom (FILE *fp, pointT *pointA, pointT *pointB, realT color[3]);
-void	qh_printpoint(FILE *fp, char *string, pointT *point);
-void	qh_printpointid(FILE *fp, char *string, int dim, pointT *point, int id);
-void    qh_printpoint3 (FILE *fp, pointT *point);
-void    qh_printpoints_out (FILE *fp, facetT *facetlist, setT *facets, int printall);
-void    qh_printpointvect (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]);
-void    qh_printpointvect2 (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius);
-void	qh_printridge(FILE *fp, ridgeT *ridge);
-void    qh_printspheres(FILE *fp, setT *vertices, realT radius);
-void    qh_printvdiagram (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
-int     qh_printvdiagram2 (FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder);
-void	qh_printvertex(FILE *fp, vertexT *vertex);
-void	qh_printvertexlist (FILE *fp, char* string, facetT *facetlist,
-                         setT *facets, boolT printall);
-void	qh_printvertices (FILE *fp, char* string, setT *vertices);
-void    qh_printvneighbors (FILE *fp, facetT* facetlist, setT *facets, boolT printall);
-void    qh_printvoronoi (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall);
-void    qh_printvnorm (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
-void    qh_printvridge (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
-void	qh_produce_output(void);
-void    qh_projectdim3 (pointT *source, pointT *destination);
-int     qh_readfeasible (int dim, char *remainder);
-coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
-void    qh_setfeasible (int dim);
-boolT	qh_skipfacet(facetT *facet);
-
-#endif /* qhDEFio */
diff --git a/extern/qhull/src/mem.c b/extern/qhull/src/mem.c
deleted file mode 100644
index 72934626684..00000000000
--- a/extern/qhull/src/mem.c
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
  ---------------------------------
-
-  mem.c 
-    memory management routines for qhull
-
-  This is a standalone program.
-   
-  To initialize memory:
-
-    qh_meminit (stderr);  
-    qh_meminitbuffers (qh IStracing, qh_MEMalign, 7, qh_MEMbufsize,qh_MEMinitbuf);
-    qh_memsize(sizeof(facetT));
-    qh_memsize(sizeof(facetT));
-    ...
-    qh_memsetup();
-    
-  To free up all memory buffers:
-    qh_memfreeshort (&curlong, &totlong);
-         
-  if qh_NOmem, 
-    malloc/free is used instead of mem.c
-
-  notes: 
-    uses Quickfit algorithm (freelists for commonly allocated sizes)
-    assumes small sizes for freelists (it discards the tail of memory buffers)
-   
-  see:
-    qh-mem.htm and mem.h
-    global.c (qh_initbuffers) for an example of using mem.c 
-   
-  copyright (c) 1993-2002 The Geometry Center
-*/
-
-#include 
-#include 
-#include 
-#include "mem.h"
-
-#ifndef qhDEFqhull
-typedef struct ridgeT ridgeT;
-typedef struct facetT facetT;
-void    qh_errexit(int exitcode, facetT *, ridgeT *);
-#endif
-
-/*============ -global data structure ==============
-    see mem.h for definition
-*/
-
-qhmemT qhmem= {0};     /* remove "= {0}" if this causes a compiler error */
-
-#ifndef qh_NOmem
-
-/*============= internal functions ==============*/
-  
-static int qh_intcompare(const void *i, const void *j);
-
-/*========== functions in alphabetical order ======== */
-
-/*---------------------------------
-  
-  qh_intcompare( i, j )
-    used by qsort and bsearch to compare two integers
-*/
-static int qh_intcompare(const void *i, const void *j) {
-  return(*((int *)i) - *((int *)j));
-} /* intcompare */
-
-
-/*----------------------------------
-   
-  qh_memalloc( insize )  
-    returns object of insize bytes
-    qhmem is the global memory structure 
-    
-  returns:
-    pointer to allocated memory 
-    errors if insufficient memory
-
-  notes:
-    use explicit type conversion to avoid type warnings on some compilers
-    actual object may be larger than insize
-    use qh_memalloc_() for inline code for quick allocations
-    logs allocations if 'T5'
-  
-  design:
-    if size < qhmem.LASTsize
-      if qhmem.freelists[size] non-empty
-        return first object on freelist
-      else
-        round up request to size of qhmem.freelists[size]
-        allocate new allocation buffer if necessary
-        allocate object from allocation buffer
-    else
-      allocate object with malloc()
-*/
-void *qh_memalloc(int insize) {
-  void **freelistp, *newbuffer;
-  int index, size;
-  int outsize, bufsize;
-  void *object;
-
-  if ((unsigned) insize <= (unsigned) qhmem.LASTsize) {
-    index= qhmem.indextable[insize];
-    freelistp= qhmem.freelists+index;
-    if ((object= *freelistp)) {
-      qhmem.cntquick++;  
-      *freelistp= *((void **)*freelistp);  /* replace freelist with next object */
-      return (object);
-    }else {
-      outsize= qhmem.sizetable[index];
-      qhmem.cntshort++;
-      if (outsize > qhmem .freesize) {
-	if (!qhmem.curbuffer)
-	  bufsize= qhmem.BUFinit;
-        else
-	  bufsize= qhmem.BUFsize;
-        qhmem.totshort += bufsize;
-	if (!(newbuffer= malloc(bufsize))) {
-	  fprintf(qhmem.ferr, "qhull error (qh_memalloc): insufficient memory\n");
-	  qh_errexit(qhmem_ERRmem, NULL, NULL);
-	} 
-	*((void **)newbuffer)= qhmem.curbuffer;  /* prepend newbuffer to curbuffer 
-						    list */
-	qhmem.curbuffer= newbuffer;
-        size= (sizeof(void **) + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
-	qhmem.freemem= (void *)((char *)newbuffer+size);
-	qhmem.freesize= bufsize - size;
-      }
-      object= qhmem.freemem;
-      qhmem.freemem= (void *)((char *)qhmem.freemem + outsize);
-      qhmem.freesize -= outsize;
-      return object;
-    }
-  }else {                     /* long allocation */
-    if (!qhmem.indextable) {
-      fprintf (qhmem.ferr, "qhull internal error (qh_memalloc): qhmem has not been initialized.\n");
-      qh_errexit(qhmem_ERRqhull, NULL, NULL);
-    }
-    outsize= insize;
-    qhmem .cntlong++;
-    qhmem .curlong++;
-    qhmem .totlong += outsize;
-    if (qhmem.maxlong < qhmem.totlong)
-      qhmem.maxlong= qhmem.totlong;
-    if (!(object= malloc(outsize))) {
-      fprintf(qhmem.ferr, "qhull error (qh_memalloc): insufficient memory\n");
-      qh_errexit(qhmem_ERRmem, NULL, NULL);
-    }
-    if (qhmem.IStracing >= 5)
-      fprintf (qhmem.ferr, "qh_memalloc long: %d bytes at %p\n", outsize, object);
-  }
-  return (object);
-} /* memalloc */
-
-
-/*----------------------------------
-   
-  qh_memfree( object, size ) 
-    free up an object of size bytes
-    size is insize from qh_memalloc
-
-  notes:
-    object may be NULL
-    type checking warns if using (void **)object
-    use qh_memfree_() for quick free's of small objects
- 
-  design:
-    if size <= qhmem.LASTsize
-      append object to corresponding freelist
-    else
-      call free(object)
-*/
-void qh_memfree(void *object, int size) {
-  void **freelistp;
-
-  if (!object)
-    return;
-  if (size <= qhmem.LASTsize) {
-    qhmem .freeshort++;
-    freelistp= qhmem.freelists + qhmem.indextable[size];
-    *((void **)object)= *freelistp;
-    *freelistp= object;
-  }else {
-    qhmem .freelong++;
-    qhmem .totlong -= size;
-    free (object);
-    if (qhmem.IStracing >= 5)
-      fprintf (qhmem.ferr, "qh_memfree long: %d bytes at %p\n", size, object);
-  }
-} /* memfree */
-
-
-/*---------------------------------
-  
-  qh_memfreeshort( curlong, totlong )
-    frees up all short and qhmem memory allocations
-
-  returns:
-    number and size of current long allocations
-*/
-void qh_memfreeshort (int *curlong, int *totlong) {
-  void *buffer, *nextbuffer;
-
-  *curlong= qhmem .cntlong - qhmem .freelong;
-  *totlong= qhmem .totlong;
-  for(buffer= qhmem.curbuffer; buffer; buffer= nextbuffer) {
-    nextbuffer= *((void **) buffer);
-    free(buffer);
-  }
-  qhmem.curbuffer= NULL;
-  if (qhmem .LASTsize) {
-    free (qhmem .indextable);
-    free (qhmem .freelists);
-    free (qhmem .sizetable);
-  }
-  memset((char *)&qhmem, 0, sizeof qhmem);  /* every field is 0, FALSE, NULL */
-} /* memfreeshort */
-
-
-/*----------------------------------
-   
-  qh_meminit( ferr )
-    initialize qhmem and test sizeof( void*)
-*/
-void qh_meminit (FILE *ferr) {
-  
-  memset((char *)&qhmem, 0, sizeof qhmem);  /* every field is 0, FALSE, NULL */
-  qhmem.ferr= ferr;
-  if (sizeof(void*) < sizeof(int)) {
-    fprintf (ferr, "qhull internal error (qh_meminit): sizeof(void*) < sizeof(int).  qset.c will not work\n");
-    exit (1);  /* can not use qh_errexit() */
-  }
-} /* meminit */
-
-/*---------------------------------
-  
-  qh_meminitbuffers( tracelevel, alignment, numsizes, bufsize, bufinit )
-    initialize qhmem
-    if tracelevel >= 5, trace memory allocations
-    alignment= desired address alignment for memory allocations
-    numsizes= number of freelists
-    bufsize=  size of additional memory buffers for short allocations
-    bufinit=  size of initial memory buffer for short allocations
-*/
-void qh_meminitbuffers (int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
-
-  qhmem.IStracing= tracelevel;
-  qhmem.NUMsizes= numsizes;
-  qhmem.BUFsize= bufsize;
-  qhmem.BUFinit= bufinit;
-  qhmem.ALIGNmask= alignment-1;
-  if (qhmem.ALIGNmask & ~qhmem.ALIGNmask) {
-    fprintf (qhmem.ferr, "qhull internal error (qh_meminit): memory alignment %d is not a power of 2\n", alignment);
-    qh_errexit (qhmem_ERRqhull, NULL, NULL);
-  }
-  qhmem.sizetable= (int *) calloc (numsizes, sizeof(int));
-  qhmem.freelists= (void **) calloc (numsizes, sizeof(void *));
-  if (!qhmem.sizetable || !qhmem.freelists) {
-    fprintf(qhmem.ferr, "qhull error (qh_meminit): insufficient memory\n");
-    qh_errexit (qhmem_ERRmem, NULL, NULL);
-  }
-  if (qhmem.IStracing >= 1)
-    fprintf (qhmem.ferr, "qh_meminitbuffers: memory initialized with alignment %d\n", alignment);
-} /* meminitbuffers */
-
-/*---------------------------------
-  
-  qh_memsetup()
-    set up memory after running memsize()
-*/
-void qh_memsetup (void) {
-  int k,i;
-
-  qsort(qhmem.sizetable, qhmem.TABLEsize, sizeof(int), qh_intcompare);
-  qhmem.LASTsize= qhmem.sizetable[qhmem.TABLEsize-1];
-  if (qhmem .LASTsize >= qhmem .BUFsize || qhmem.LASTsize >= qhmem .BUFinit) {
-    fprintf (qhmem.ferr, "qhull error (qh_memsetup): largest mem size %d is >= buffer size %d or initial buffer size %d\n",
-            qhmem .LASTsize, qhmem .BUFsize, qhmem .BUFinit);
-    qh_errexit(qhmem_ERRmem, NULL, NULL);
-  }
-  if (!(qhmem.indextable= (int *)malloc((qhmem.LASTsize+1) * sizeof(int)))) {
-    fprintf(qhmem.ferr, "qhull error (qh_memsetup): insufficient memory\n");
-    qh_errexit(qhmem_ERRmem, NULL, NULL);
-  }
-  for(k=qhmem.LASTsize+1; k--; )
-    qhmem.indextable[k]= k;
-  i= 0;
-  for(k= 0; k <= qhmem.LASTsize; k++) {
-    if (qhmem.indextable[k] <= qhmem.sizetable[i])
-      qhmem.indextable[k]= i;
-    else
-      qhmem.indextable[k]= ++i;
-  }
-} /* memsetup */
-
-/*---------------------------------
-  
-  qh_memsize( size )
-    define a free list for this size
-*/
-void qh_memsize(int size) {
-  int k;
-
-  if (qhmem .LASTsize) {
-    fprintf (qhmem .ferr, "qhull error (qh_memsize): called after qhmem_setup\n");
-    qh_errexit (qhmem_ERRqhull, NULL, NULL);
-  }
-  size= (size + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
-  for(k= qhmem.TABLEsize; k--; ) {
-    if (qhmem.sizetable[k] == size)
-      return;
-  }
-  if (qhmem.TABLEsize < qhmem.NUMsizes)
-    qhmem.sizetable[qhmem.TABLEsize++]= size;
-  else
-    fprintf(qhmem.ferr, "qhull warning (memsize): free list table has room for only %d sizes\n", qhmem.NUMsizes);
-} /* memsize */
-
-
-/*---------------------------------
-  
-  qh_memstatistics( fp )
-    print out memory statistics
-
-  notes:
-    does not account for wasted memory at the end of each block
-*/
-void qh_memstatistics (FILE *fp) {
-  int i, count, totfree= 0;
-  void *object;
-  
-  for (i=0; i < qhmem.TABLEsize; i++) {
-    count=0;
-    for (object= qhmem .freelists[i]; object; object= *((void **)object))
-      count++;
-    totfree += qhmem.sizetable[i] * count;
-  }
-  fprintf (fp, "\nmemory statistics:\n\
-%7d quick allocations\n\
-%7d short allocations\n\
-%7d long allocations\n\
-%7d short frees\n\
-%7d long frees\n\
-%7d bytes of short memory in use\n\
-%7d bytes of short memory in freelists\n\
-%7d bytes of long memory allocated (except for input)\n\
-%7d bytes of long memory in use (in %d pieces)\n\
-%7d bytes per memory buffer (initially %d bytes)\n",
-	   qhmem .cntquick, qhmem.cntshort, qhmem.cntlong,
-	   qhmem .freeshort, qhmem.freelong, 
-	   qhmem .totshort - qhmem .freesize - totfree,
-	   totfree,
-	   qhmem .maxlong, qhmem .totlong, qhmem .cntlong - qhmem .freelong,
-	   qhmem .BUFsize, qhmem .BUFinit);
-  if (qhmem.cntlarger) {
-    fprintf (fp, "%7d calls to qh_setlarger\n%7.2g     average copy size\n",
-	   qhmem.cntlarger, ((float) qhmem.totlarger)/ qhmem.cntlarger);
-    fprintf (fp, "  freelists (bytes->count):");
-  }
-  for (i=0; i < qhmem.TABLEsize; i++) {
-    count=0;
-    for (object= qhmem .freelists[i]; object; object= *((void **)object))
-      count++;
-    fprintf (fp, " %d->%d", qhmem.sizetable[i], count);
-  }
-  fprintf (fp, "\n\n");
-} /* memstatistics */
-
-
-/*---------------------------------
-  
-  qh_NOmem
-    turn off quick-fit memory allocation
-
-  notes:
-    uses malloc() and free() instead
-*/
-#else /* qh_NOmem */
-
-void *qh_memalloc(int insize) {
-  void *object;
-
-  if (!(object= malloc(insize))) {
-    fprintf(qhmem.ferr, "qhull error (qh_memalloc): insufficient memory\n");
-    qh_errexit(qhmem_ERRmem, NULL, NULL);
-  }
-  if (qhmem.IStracing >= 5)
-    fprintf (qhmem.ferr, "qh_memalloc long: %d bytes at %p\n", insize, object);
-  return object;
-}
-
-void qh_memfree(void *object, int size) {
-
-  if (!object)
-    return;
-  free (object);
-  if (qhmem.IStracing >= 5)
-    fprintf (qhmem.ferr, "qh_memfree long: %d bytes at %p\n", size, object);
-}
-
-void qh_memfreeshort (int *curlong, int *totlong) {
-
-  memset((char *)&qhmem, 0, sizeof qhmem);  /* every field is 0, FALSE, NULL */
-  *curlong= 0;
-  *totlong= 0;
-}
-
-void qh_meminit (FILE *ferr) {
-
-  memset((char *)&qhmem, 0, sizeof qhmem);  /* every field is 0, FALSE, NULL */
-  qhmem.ferr= ferr;
-  if (sizeof(void*) < sizeof(int)) {
-    fprintf (ferr, "qhull internal error (qh_meminit): sizeof(void*) < sizeof(int).  qset.c will not work\n");
-    qh_errexit (qhmem_ERRqhull, NULL, NULL);
-  }
-}
-
-void qh_meminitbuffers (int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
-
-  qhmem.IStracing= tracelevel;
-
-}
-
-void qh_memsetup (void) {
-
-}
-
-void qh_memsize(int size) {
-
-}
-
-void qh_memstatistics (FILE *fp) {
-
-}
-
-#endif /* qh_NOmem */
diff --git a/extern/qhull/src/mem.h b/extern/qhull/src/mem.h
deleted file mode 100644
index e9ebd1bb9bc..00000000000
--- a/extern/qhull/src/mem.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
  ---------------------------------
-
-   mem.h 
-     prototypes for memory management functions
-
-   see qh-mem.htm, mem.c and qset.h
-
-   for error handling, writes message and calls
-     qh_errexit (qhmem_ERRmem, NULL, NULL) if insufficient memory
-       and
-     qh_errexit (qhmem_ERRqhull, NULL, NULL) otherwise
-
-   copyright (c) 1993-2002, The Geometry Center
-*/
-
-#ifndef qhDEFmem
-#define qhDEFmem
-
-/*---------------------------------
-  
-  qh_NOmem
-    turn off quick-fit memory allocation
-
-  notes:
-    mem.c implements Quickfit memory allocation for about 20% time
-    savings.  If it fails on your machine, try to locate the
-    problem, and send the answer to qhull@geom.umn.edu.  If this can
-    not be done, define qh_NOmem to use malloc/free instead.
-
-   #define qh_NOmem
-*/
-
-/*-------------------------------------------
-    to avoid bus errors, memory allocation must consider alignment requirements.
-    malloc() automatically takes care of alignment.   Since mem.c manages
-    its own memory, we need to explicitly specify alignment in
-    qh_meminitbuffers().
-
-    A safe choice is sizeof(double).  sizeof(float) may be used if doubles 
-    do not occur in data structures and pointers are the same size.  Be careful
-    of machines (e.g., DEC Alpha) with large pointers.  If gcc is available, 
-    use __alignof__(double) or fmax_(__alignof__(float), __alignof__(void *)).
-
-   see qh_MEMalign in user.h for qhull's alignment
-*/
-
-#define qhmem_ERRmem 4    /* matches qh_ERRmem in qhull.h */
-#define qhmem_ERRqhull 5  /* matches qh_ERRqhull in qhull.h */
-
-/*----------------------------------
-  
-  ptr_intT
-    for casting a void* to an integer-type
-  
-  notes:
-    On 64-bit machines, a pointer may be larger than an 'int'.  
-    qh_meminit() checks that 'long' holds a 'void*'
-*/
-typedef unsigned long ptr_intT;
-
-/*----------------------------------
- 
-  qhmemT
-    global memory structure for mem.c
- 
- notes:
-   users should ignore qhmem except for writing extensions
-   qhmem is allocated in mem.c 
-   
-   qhmem could be swapable like qh and qhstat, but then
-   multiple qh's and qhmem's would need to keep in synch.  
-   A swapable qhmem would also waste memory buffers.  As long
-   as memory operations are atomic, there is no problem with
-   multiple qh structures being active at the same time.
-   If you need separate address spaces, you can swap the
-   contents of qhmem.
-*/
-typedef struct qhmemT qhmemT;
-extern qhmemT qhmem; 
-
-struct qhmemT {               /* global memory management variables */
-  int      BUFsize;	      /* size of memory allocation buffer */
-  int      BUFinit;	      /* initial size of memory allocation buffer */
-  int      TABLEsize;         /* actual number of sizes in free list table */
-  int      NUMsizes;          /* maximum number of sizes in free list table */
-  int      LASTsize;          /* last size in free list table */
-  int      ALIGNmask;         /* worst-case alignment, must be 2^n-1 */
-  void	 **freelists;          /* free list table, linked by offset 0 */
-  int     *sizetable;         /* size of each freelist */
-  int     *indextable;        /* size->index table */
-  void    *curbuffer;         /* current buffer, linked by offset 0 */
-  void    *freemem;           /*   free memory in curbuffer */
-  int 	   freesize;          /*   size of free memory in bytes */
-  void 	  *tempstack;         /* stack of temporary memory, managed by users */
-  FILE    *ferr;              /* file for reporting errors */
-  int      IStracing;         /* =5 if tracing memory allocations */
-  int      cntquick;          /* count of quick allocations */
-                              /* remove statistics doesn't effect speed */
-  int      cntshort;          /* count of short allocations */
-  int      cntlong;           /* count of long allocations */
-  int      curlong;           /* current count of inuse, long allocations */
-  int      freeshort;	      /* count of short memfrees */
-  int      freelong;	      /* count of long memfrees */
-  int      totshort;          /* total size of short allocations */
-  int      totlong;           /* total size of long allocations */
-  int      maxlong;           /* maximum totlong */
-  int      cntlarger;         /* count of setlarger's */
-  int      totlarger;         /* total copied by setlarger */
-};
-
-
-/*==================== -macros ====================*/
-
-/*----------------------------------
-   
-  qh_memalloc_(size, object, type)  
-    returns object of size bytes 
-	assumes size<=qhmem.LASTsize and void **freelistp is a temp
-*/
-
-#ifdef qh_NOmem
-#define qh_memalloc_(size, freelistp, object, type) {\
-  object= (type*)qh_memalloc (size); }
-#else /* !qh_NOmem */
-
-#define qh_memalloc_(size, freelistp, object, type) {\
-  freelistp= qhmem.freelists + qhmem.indextable[size];\
-  if ((object= (type*)*freelistp)) {\
-    qhmem.cntquick++;  \
-    *freelistp= *((void **)*freelistp);\
-  }else object= (type*)qh_memalloc (size);}
-#endif
-
-/*----------------------------------
-   
-  qh_memfree_(object, size) 
-    free up an object
-
-  notes:
-    object may be NULL
-    assumes size<=qhmem.LASTsize and void **freelistp is a temp
-*/
-#ifdef qh_NOmem
-#define qh_memfree_(object, size, freelistp) {\
-  qh_memfree (object, size); }
-#else /* !qh_NOmem */
-
-#define qh_memfree_(object, size, freelistp) {\
-  if (object) { \
-    qhmem .freeshort++;\
-    freelistp= qhmem.freelists + qhmem.indextable[size];\
-    *((void **)object)= *freelistp;\
-    *freelistp= object;}}
-#endif
-
-/*=============== prototypes in alphabetical order ============*/
-
-void *qh_memalloc(int insize);
-void qh_memfree (void *object, int size);
-void qh_memfreeshort (int *curlong, int *totlong);
-void qh_meminit (FILE *ferr);
-void qh_meminitbuffers (int tracelevel, int alignment, int numsizes,
-			int bufsize, int bufinit);
-void qh_memsetup (void);
-void qh_memsize(int size);
-void qh_memstatistics (FILE *fp);
-
-#endif /* qhDEFmem */
diff --git a/extern/qhull/src/merge.c b/extern/qhull/src/merge.c
deleted file mode 100644
index 34ecda1865f..00000000000
--- a/extern/qhull/src/merge.c
+++ /dev/null
@@ -1,3626 +0,0 @@
-/*
  ---------------------------------
-
-   merge.c 
-   merges non-convex facets
-
-   see qh-merge.htm and merge.h
-
-   other modules call qh_premerge() and qh_postmerge()
-
-   the user may call qh_postmerge() to perform additional merges.
-
-   To remove deleted facets and vertices (qhull() in qhull.c):
-     qh_partitionvisible (!qh_ALL, &numoutside);  // visible_list, newfacet_list
-     qh_deletevisible ();         // qh.visible_list
-     qh_resetlists (False, qh_RESETvisible);       // qh.visible_list newvertex_list newfacet_list 
-
-   assumes qh.CENTERtype= centrum
-
-   merges occur in qh_mergefacet and in qh_mergecycle
-   vertex->neighbors not set until the first merge occurs
-
-   copyright (c) 1993-2002 The Geometry Center        
-*/
-
-#include "qhull_a.h"
-
-#ifndef qh_NOmerge
-
-/*=========== internal prototypes =========*/
-
-static int qh_compareangle(const void *p1, const void *p2);
-static int qh_comparemerge(const void *p1, const void *p2);
-static int qh_comparevisit (const void *p1, const void *p2);
-
-																														
-/*===== functions (alphabetical after premerge and postmerge) ======*/
-
-/*---------------------------------
-  
-  qh_premerge( apex, maxcentrum )
-    pre-merge nonconvex facets in qh.newfacet_list for apex
-    maxcentrum defines coplanar and concave (qh_test_appendmerge)
-
-  returns:
-    deleted facets added to qh.visible_list with facet->visible set
-
-  notes:
-    uses globals, qh.MERGEexact, qh.PREmerge
-
-  design:
-    mark duplicate ridges in qh.newfacet_list
-    merge facet cycles in qh.newfacet_list
-    merge duplicate ridges and concave facets in qh.newfacet_list
-    check merged facet cycles for degenerate and redundant facets
-    merge degenerate and redundant facets
-    collect coplanar and concave facets
-    merge concave, coplanar, degenerate, and redundant facets
-*/
-void qh_premerge (vertexT *apex, realT maxcentrum, realT maxangle) {
-  boolT othermerge= False;
-  facetT *newfacet;
-  
-  if (qh ZEROcentrum && qh_checkzero(!qh_ALL))
-    return;    
-  trace2((qh ferr, "qh_premerge: premerge centrum %2.2g angle %2.2g for apex v%d facetlist f%d\n",
-	    maxcentrum, maxangle, apex->id, getid_(qh newfacet_list)));
-  if (qh IStracing >= 4 && qh num_facets < 50)
-    qh_printlists();
-  qh centrum_radius= maxcentrum;
-  qh cos_max= maxangle;
-  qh degen_mergeset= qh_settemp (qh TEMPsize);
-  qh facet_mergeset= qh_settemp (qh TEMPsize);
-  if (qh hull_dim >=3) { 
-    qh_mark_dupridges (qh newfacet_list); /* facet_mergeset */
-    qh_mergecycle_all (qh newfacet_list, &othermerge);
-    qh_forcedmerges (&othermerge /* qh facet_mergeset */); 
-    FORALLnew_facets {  /* test samecycle merges */
-      if (!newfacet->simplicial && !newfacet->mergeridge)
-	qh_degen_redundant_neighbors (newfacet, NULL);
-    }
-    if (qh_merge_degenredundant())
-      othermerge= True;
-  }else /* qh hull_dim == 2 */
-    qh_mergecycle_all (qh newfacet_list, &othermerge);
-  qh_flippedmerges (qh newfacet_list, &othermerge);
-  if (!qh MERGEexact || zzval_(Ztotmerge)) {
-    zinc_(Zpremergetot);
-    qh POSTmerging= False;
-    qh_getmergeset_initial (qh newfacet_list);
-    qh_all_merges (othermerge, False);
-  }
-  qh_settempfree(&qh facet_mergeset);
-  qh_settempfree(&qh degen_mergeset);
-} /* premerge */
-  
-/*---------------------------------
-  
-  qh_postmerge( reason, maxcentrum, maxangle, vneighbors )
-    post-merge nonconvex facets as defined by maxcentrum and maxangle
-    'reason' is for reporting progress
-    if vneighbors, 
-      calls qh_test_vneighbors at end of qh_all_merge 
-    if firstmerge, 
-      calls qh_reducevertices before qh_getmergeset
-
-  returns:
-    if first call (qh.visible_list != qh.facet_list), 
-      builds qh.facet_newlist, qh.newvertex_list
-    deleted facets added to qh.visible_list with facet->visible
-    qh.visible_list == qh.facet_list
-
-  notes:
-
-
-  design:
-    if first call
-      set qh.visible_list and qh.newfacet_list to qh.facet_list
-      add all facets to qh.newfacet_list
-      mark non-simplicial facets, facet->newmerge
-      set qh.newvertext_list to qh.vertex_list
-      add all vertices to qh.newvertex_list
-      if a pre-merge occured
-        set vertex->delridge {will retest the ridge}
-        if qh.MERGEexact
-          call qh_reducevertices()
-      if no pre-merging 
-        merge flipped facets
-    determine non-convex facets
-    merge all non-convex facets
-*/
-void qh_postmerge (char *reason, realT maxcentrum, realT maxangle, 
-                      boolT vneighbors) {
-  facetT *newfacet;
-  boolT othermerges= False;
-  vertexT *vertex;
-
-  if (qh REPORTfreq || qh IStracing) {
-    qh_buildtracing (NULL, NULL);
-    qh_printsummary (qh ferr);
-    if (qh PRINTstatistics) 
-      qh_printallstatistics (qh ferr, "reason");
-    fprintf (qh ferr, "\n%s with 'C%.2g' and 'A%.2g'\n", 
-        reason, maxcentrum, maxangle);
-  }
-  trace2((qh ferr, "qh_postmerge: postmerge.  test vneighbors? %d\n",
-	    vneighbors));
-  qh centrum_radius= maxcentrum;
-  qh cos_max= maxangle;
-  qh POSTmerging= True;
-  qh degen_mergeset= qh_settemp (qh TEMPsize);
-  qh facet_mergeset= qh_settemp (qh TEMPsize);
-  if (qh visible_list != qh facet_list) {  /* first call */
-    qh NEWfacets= True;
-    qh visible_list= qh newfacet_list= qh facet_list;
-    FORALLnew_facets {
-      newfacet->newfacet= True;
-       if (!newfacet->simplicial)
-        newfacet->newmerge= True;
-     zinc_(Zpostfacets);
-    }
-    qh newvertex_list= qh vertex_list;
-    FORALLvertices
-      vertex->newlist= True;
-    if (qh VERTEXneighbors) { /* a merge has occurred */
-      FORALLvertices
-	vertex->delridge= True; /* test for redundant, needed? */
-      if (qh MERGEexact) {
-	if (qh hull_dim <= qh_DIMreduceBuild)
-	  qh_reducevertices(); /* was skipped during pre-merging */
-      }
-    }
-    if (!qh PREmerge && !qh MERGEexact) 
-      qh_flippedmerges (qh newfacet_list, &othermerges);
-  }
-  qh_getmergeset_initial (qh newfacet_list);
-  qh_all_merges (False, vneighbors);
-  qh_settempfree(&qh facet_mergeset);
-  qh_settempfree(&qh degen_mergeset);
-} /* post_merge */
-
-/*---------------------------------
-  
-  qh_all_merges( othermerge, vneighbors )
-    merge all non-convex facets
-    
-    set othermerge if already merged facets (for qh_reducevertices)
-    if vneighbors
-      tests vertex neighbors for convexity at end
-    qh.facet_mergeset lists the non-convex ridges in qh_newfacet_list
-    qh.degen_mergeset is defined
-    if qh.MERGEexact && !qh.POSTmerging, 
-      does not merge coplanar facets
-
-  returns:
-    deleted facets added to qh.visible_list with facet->visible
-    deleted vertices added qh.delvertex_list with vertex->delvertex
-  
-  notes:
-    unless !qh.MERGEindependent, 
-      merges facets in independent sets
-    uses qh.newfacet_list as argument since merges call qh_removefacet()
-
-  design:
-    while merges occur
-      for each merge in qh.facet_mergeset
-        unless one of the facets was already merged in this pass
-          merge the facets
-        test merged facets for additional merges
-        add merges to qh.facet_mergeset
-      if vertices record neighboring facets
-        rename redundant vertices
-          update qh.facet_mergeset
-    if vneighbors ??
-      tests vertex neighbors for convexity at end
-*/
-void qh_all_merges (boolT othermerge, boolT vneighbors) {
-  facetT *facet1, *facet2;
-  mergeT *merge;
-  boolT wasmerge= True, isreduce;
-  void **freelistp;  /* used !qh_NOmem */
-  vertexT *vertex;
-  mergeType mergetype;
-  int numcoplanar=0, numconcave=0, numdegenredun= 0, numnewmerges= 0;
-  
-  trace2((qh ferr, "qh_all_merges: starting to merge facets beginning from f%d\n",
-	    getid_(qh newfacet_list)));
-  while (True) {
-    wasmerge= False;
-    while (qh_setsize (qh facet_mergeset)) {
-      while ((merge= (mergeT*)qh_setdellast(qh facet_mergeset))) {
-	facet1= merge->facet1;
-	facet2= merge->facet2;
-	mergetype= merge->type;
-	qh_memfree_(merge, sizeof(mergeT), freelistp);
-	if (facet1->visible || facet2->visible) /*deleted facet*/
-	  continue;  
-	if ((facet1->newfacet && !facet1->tested)
-	        || (facet2->newfacet && !facet2->tested)) {
-	  if (qh MERGEindependent && mergetype <= MRGanglecoplanar)
-	    continue;      /* perform independent sets of merges */
-	}
-	qh_merge_nonconvex (facet1, facet2, mergetype);
-        numdegenredun += qh_merge_degenredundant();
-        numnewmerges++;
-        wasmerge= True;
-	if (mergetype == MRGconcave)
-	  numconcave++;
-	else /* MRGcoplanar or MRGanglecoplanar */
-	  numcoplanar++;
-      } /* while setdellast */
-      if (qh POSTmerging && qh hull_dim <= qh_DIMreduceBuild 
-      && numnewmerges > qh_MAXnewmerges) {
-	numnewmerges= 0;
-	qh_reducevertices();  /* otherwise large post merges too slow */
-      }
-      qh_getmergeset (qh newfacet_list); /* facet_mergeset */
-    } /* while mergeset */
-    if (qh VERTEXneighbors) {
-      isreduce= False;
-      if (qh hull_dim >=4 && qh POSTmerging) {
-	FORALLvertices  
-	  vertex->delridge= True;
-	isreduce= True;
-      }
-      if ((wasmerge || othermerge) && (!qh MERGEexact || qh POSTmerging) 
-	  && qh hull_dim <= qh_DIMreduceBuild) {
-	othermerge= False;
-	isreduce= True;
-      }
-      if (isreduce) {
-	if (qh_reducevertices()) {
-	  qh_getmergeset (qh newfacet_list); /* facet_mergeset */
-	  continue;
-	}
-      }
-    }
-    if (vneighbors && qh_test_vneighbors(/* qh newfacet_list */)) 
-      continue;
-    break;
-  } /* while (True) */
-  if (qh CHECKfrequently && !qh MERGEexact) {
-    qh old_randomdist= qh RANDOMdist;
-    qh RANDOMdist= False;
-    qh_checkconvex (qh newfacet_list, qh_ALGORITHMfault);
-    /* qh_checkconnect (); [this is slow and it changes the facet order] */
-    qh RANDOMdist= qh old_randomdist;
-  }
-  trace1((qh ferr, "qh_all_merges: merged %d coplanar facets %d concave facets and %d degen or redundant facets.\n",
-    numcoplanar, numconcave, numdegenredun));
-  if (qh IStracing >= 4 && qh num_facets < 50)
-    qh_printlists ();
-} /* all_merges */
-
-
-/*---------------------------------
-  
-  qh_appendmergeset( facet, neighbor, mergetype, angle )
-    appends an entry to qh.facet_mergeset or qh.degen_mergeset
-
-    angle ignored if NULL or !qh.ANGLEmerge
-
-  returns:
-    merge appended to facet_mergeset or degen_mergeset
-      sets ->degenerate or ->redundant if degen_mergeset
-  
-  see:
-    qh_test_appendmerge()
-
-  design:
-    allocate merge entry
-    if regular merge
-      append to qh.facet_mergeset
-    else if degenerate merge and qh.facet_mergeset is all degenerate
-      append to qh.degen_mergeset 
-    else if degenerate merge
-      prepend to qh.degen_mergeset 
-    else if redundant merge
-      append to qh.degen_mergeset 
-*/
-void qh_appendmergeset(facetT *facet, facetT *neighbor, mergeType mergetype, realT *angle) {
-  mergeT *merge, *lastmerge;
-  void **freelistp; /* used !qh_NOmem */
-
-  if (facet->redundant)
-    return;
-  if (facet->degenerate && mergetype == MRGdegen)
-    return;
-  qh_memalloc_(sizeof(mergeT), freelistp, merge, mergeT);
-  merge->facet1= facet;
-  merge->facet2= neighbor;
-  merge->type= mergetype;
-  if (angle && qh ANGLEmerge)
-    merge->angle= *angle;
-  if (mergetype < MRGdegen)
-    qh_setappend (&(qh facet_mergeset), merge);
-  else if (mergetype == MRGdegen) {
-    facet->degenerate= True;
-    if (!(lastmerge= (mergeT*)qh_setlast (qh degen_mergeset)) 
-    || lastmerge->type == MRGdegen)
-      qh_setappend (&(qh degen_mergeset), merge);
-    else
-      qh_setaddnth (&(qh degen_mergeset), 0, merge);
-  }else if (mergetype == MRGredundant) {
-    facet->redundant= True;
-    qh_setappend (&(qh degen_mergeset), merge);
-  }else /* mergetype == MRGmirror */ {
-    if (facet->redundant || neighbor->redundant) {
-      fprintf(qh ferr, "qhull error (qh_appendmergeset): facet f%d or f%d is already a mirrored facet\n",
-	   facet->id, neighbor->id);
-      qh_errexit2 (qh_ERRqhull, facet, neighbor);
-    }
-    if (!qh_setequal (facet->vertices, neighbor->vertices)) {
-      fprintf(qh ferr, "qhull error (qh_appendmergeset): mirrored facets f%d and f%d do not have the same vertices\n",
-	   facet->id, neighbor->id);
-      qh_errexit2 (qh_ERRqhull, facet, neighbor);
-    }
-    facet->redundant= True;
-    neighbor->redundant= True;
-    qh_setappend (&(qh degen_mergeset), merge);
-  }
-} /* appendmergeset */
-
-
-/*---------------------------------
-  
-  qh_basevertices( samecycle )
-    return temporary set of base vertices for samecycle
-    samecycle is first facet in the cycle
-    assumes apex is SETfirst_( samecycle->vertices )
-
-  returns:
-    vertices (settemp)
-    all ->seen are cleared
-
-  notes:
-    uses qh_vertex_visit;
-
-  design:
-    for each facet in samecycle
-      for each unseen vertex in facet->vertices
-        append to result  
-*/
-setT *qh_basevertices (facetT *samecycle) {
-  facetT *same;
-  vertexT *apex, *vertex, **vertexp;
-  setT *vertices= qh_settemp (qh TEMPsize);
-  
-  apex= SETfirstt_(samecycle->vertices, vertexT);
-  apex->visitid= ++qh vertex_visit;
-  FORALLsame_cycle_(samecycle) {
-    if (same->mergeridge)
-      continue;
-    FOREACHvertex_(same->vertices) {
-      if (vertex->visitid != qh vertex_visit) {
-        qh_setappend (&vertices, vertex);
-        vertex->visitid= qh vertex_visit;
-        vertex->seen= False;
-      }
-    }
-  }
-  trace4((qh ferr, "qh_basevertices: found %d vertices\n", 
-         qh_setsize (vertices)));
-  return vertices;
-} /* basevertices */
-
-/*---------------------------------
-  
-  qh_checkconnect()
-    check that new facets are connected
-    new facets are on qh.newfacet_list
-    
-  notes:
-    this is slow and it changes the order of the facets
-    uses qh.visit_id
-
-  design:
-    move first new facet to end of qh.facet_list
-    for all newly appended facets
-      append unvisited neighbors to end of qh.facet_list
-    for all new facets
-      report error if unvisited
-*/
-void qh_checkconnect (void /* qh newfacet_list */) {
-  facetT *facet, *newfacet, *errfacet= NULL, *neighbor, **neighborp;
-
-  facet= qh newfacet_list;
-  qh_removefacet (facet);
-  qh_appendfacet (facet);
-  facet->visitid= ++qh visit_id;
-  FORALLfacet_(facet) {
-    FOREACHneighbor_(facet) {
-      if (neighbor->visitid != qh visit_id) {
-        qh_removefacet (neighbor);
-        qh_appendfacet (neighbor);
-        neighbor->visitid= qh visit_id;
-      }
-    }
-  }
-  FORALLnew_facets {
-    if (newfacet->visitid == qh visit_id)
-      break;
-    fprintf(qh ferr, "qhull error: f%d is not attached to the new facets\n",
-         newfacet->id);
-    errfacet= newfacet;
-  }
-  if (errfacet)
-    qh_errexit (qh_ERRqhull, errfacet, NULL);
-} /* checkconnect */
-
-/*---------------------------------
-  
-  qh_checkzero( testall )
-    check that facets are clearly convex for qh.DISTround with qh.MERGEexact
-
-    if testall, 
-      test all facets for qh.MERGEexact post-merging
-    else 
-      test qh.newfacet_list
-      
-    if qh.MERGEexact, 
-      allows coplanar ridges
-      skips convexity test while qh.ZEROall_ok
-
-  returns:
-    True if all facets !flipped, !dupridge, normal
-         if all horizon facets are simplicial
-         if all vertices are clearly below neighbor
-         if all opposite vertices of horizon are below 
-    clears qh.ZEROall_ok if any problems or coplanar facets
-
-  notes:
-    uses qh.vertex_visit
-    horizon facets may define multiple new facets
-
-  design:
-    for all facets in qh.newfacet_list or qh.facet_list
-      check for flagged faults (flipped, etc.)
-    for all facets in qh.newfacet_list or qh.facet_list
-      for each neighbor of facet
-        skip horizon facets for qh.newfacet_list
-        test the opposite vertex
-      if qh.newfacet_list
-        test the other vertices in the facet's horizon facet
-*/
-boolT qh_checkzero (boolT testall) {
-  facetT *facet, *neighbor, **neighborp;
-  facetT *horizon, *facetlist;
-  int neighbor_i;
-  vertexT *vertex, **vertexp;
-  realT dist;
-
-  if (testall) 
-    facetlist= qh facet_list;
-  else {
-    facetlist= qh newfacet_list;
-    FORALLfacet_(facetlist) {
-      horizon= SETfirstt_(facet->neighbors, facetT);
-      if (!horizon->simplicial)
-        goto LABELproblem;
-      if (facet->flipped || facet->dupridge || !facet->normal)
-        goto LABELproblem;
-    }
-    if (qh MERGEexact && qh ZEROall_ok) {
-      trace2((qh ferr, "qh_checkzero: skip convexity check until first pre-merge\n"));
-      return True;
-    }
-  }
-  FORALLfacet_(facetlist) {
-    qh vertex_visit++;
-    neighbor_i= 0;
-    horizon= NULL;
-    FOREACHneighbor_(facet) {
-      if (!neighbor_i && !testall) {
-        horizon= neighbor;
-	neighbor_i++;
-        continue; /* horizon facet tested in qh_findhorizon */
-      }
-      vertex= SETelemt_(facet->vertices, neighbor_i++, vertexT);
-      vertex->visitid= qh vertex_visit;
-      zzinc_(Zdistzero);
-      qh_distplane (vertex->point, neighbor, &dist);
-      if (dist >= -qh DISTround) {
-        qh ZEROall_ok= False;
-        if (!qh MERGEexact || testall || dist > qh DISTround)
-          goto LABELnonconvex;
-      }
-    }
-    if (!testall) {
-      FOREACHvertex_(horizon->vertices) {
-	if (vertex->visitid != qh vertex_visit) {
-	  zzinc_(Zdistzero);
-	  qh_distplane (vertex->point, facet, &dist);
-	  if (dist >= -qh DISTround) {
-	    qh ZEROall_ok= False;
-	    if (!qh MERGEexact || dist > qh DISTround)
-	      goto LABELnonconvex;
-	  }
-	  break;
-	}
-      }
-    }
-  }
-  trace2((qh ferr, "qh_checkzero: testall %d, facets are %s\n", testall,
-        (qh MERGEexact && !testall) ? 
-           "not concave, flipped, or duplicate ridged" : "clearly convex"));
-  return True;
-
- LABELproblem:
-  qh ZEROall_ok= False;
-  trace2((qh ferr, "qh_checkzero: facet f%d needs pre-merging\n",
-       facet->id));
-  return False;
-
- LABELnonconvex:
-  trace2((qh ferr, "qh_checkzero: facet f%d and f%d are not clearly convex.  v%d dist %.2g\n",
-         facet->id, neighbor->id, vertex->id, dist));
-  return False;
-} /* checkzero */
-
-/*---------------------------------
-  
-  qh_compareangle( angle1, angle2 )
-    used by qsort() to order merges by angle
-*/
-static int qh_compareangle(const void *p1, const void *p2) {
-  mergeT *a= *((mergeT **)p1), *b= *((mergeT **)p2);
- 
-  return ((a->angle > b->angle) ? 1 : -1);
-} /* compareangle */
-
-/*---------------------------------
-  
-  qh_comparemerge( merge1, merge2 )
-    used by qsort() to order merges
-*/
-static int qh_comparemerge(const void *p1, const void *p2) {
-  mergeT *a= *((mergeT **)p1), *b= *((mergeT **)p2);
- 
-  return (a->type - b->type);
-} /* comparemerge */
-
-/*---------------------------------
-  
-  qh_comparevisit( vertex1, vertex2 )
-    used by qsort() to order vertices by their visitid
-*/
-static int qh_comparevisit (const void *p1, const void *p2) {
-  vertexT *a= *((vertexT **)p1), *b= *((vertexT **)p2);
- 
-  return (a->visitid - b->visitid);
-} /* comparevisit */
-
-/*---------------------------------
-  
-  qh_copynonconvex( atridge )
-    set non-convex flag on other ridges (if any) between same neighbors
-
-  notes:
-    may be faster if use smaller ridge set
-
-  design:
-    for each ridge of atridge's top facet
-      if ridge shares the same neighbor
-        set nonconvex flag
-*/
-void qh_copynonconvex (ridgeT *atridge) {
-  facetT *facet, *otherfacet;
-  ridgeT *ridge, **ridgep;
-
-  facet= atridge->top;
-  otherfacet= atridge->bottom;
-  FOREACHridge_(facet->ridges) {
-    if (otherfacet == otherfacet_(ridge, facet) && ridge != atridge) {
-      ridge->nonconvex= True;
-      trace4((qh ferr, "qh_copynonconvex: moved nonconvex flag from r%d to r%d\n",
-	      atridge->id, ridge->id));
-      break;
-    }
-  }
-} /* copynonconvex */
-
-/*---------------------------------
-  
-  qh_degen_redundant_facet( facet )
-    check facet for degen. or redundancy
-
-  notes:
-    bumps vertex_visit
-    called if a facet was redundant but no longer is (qh_merge_degenredundant)
-    qh_appendmergeset() only appends first reference to facet (i.e., redundant)
-
-  see:
-    qh_degen_redundant_neighbors()
-
-  design:
-    test for redundant neighbor
-    test for degenerate facet
-*/
-void qh_degen_redundant_facet (facetT *facet) {
-  vertexT *vertex, **vertexp;
-  facetT *neighbor, **neighborp;
-
-  trace4((qh ferr, "qh_degen_redundant_facet: test facet f%d for degen/redundant\n",
-	  facet->id));
-  FOREACHneighbor_(facet) {
-    qh vertex_visit++;
-    FOREACHvertex_(neighbor->vertices)
-      vertex->visitid= qh vertex_visit;
-    FOREACHvertex_(facet->vertices) {
-      if (vertex->visitid != qh vertex_visit)
-	break;
-    }
-    if (!vertex) {
-      qh_appendmergeset (facet, neighbor, MRGredundant, NULL);
-      trace2((qh ferr, "qh_degen_redundant_facet: f%d is contained in f%d.  merge\n", facet->id, neighbor->id)); 
-      return;
-    }
-  }
-  if (qh_setsize (facet->neighbors) < qh hull_dim) {
-    qh_appendmergeset (facet, facet, MRGdegen, NULL);
-    trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is degenerate.\n", facet->id));
-  }
-} /* degen_redundant_facet */
-
-
-/*---------------------------------
-  
-  qh_degen_redundant_neighbors( facet, delfacet,  )
-    append degenerate and redundant neighbors to facet_mergeset
-    if delfacet, 
-      only checks neighbors of both delfacet and facet
-    also checks current facet for degeneracy
-
-  notes:
-    bumps vertex_visit
-    called for each qh_mergefacet() and qh_mergecycle()
-    merge and statistics occur in merge_nonconvex
-    qh_appendmergeset() only appends first reference to facet (i.e., redundant)
-      it appends redundant facets after degenerate ones
-
-    a degenerate facet has fewer than hull_dim neighbors
-    a redundant facet's vertices is a subset of its neighbor's vertices
-    tests for redundant merges first (appendmergeset is nop for others)
-    in a merge, only needs to test neighbors of merged facet
-  
-  see:
-    qh_merge_degenredundant() and qh_degen_redundant_facet()
-
-  design:
-    test for degenerate facet
-    test for redundant neighbor
-    test for degenerate neighbor
-*/
-void qh_degen_redundant_neighbors (facetT *facet, facetT *delfacet) {
-  vertexT *vertex, **vertexp;
-  facetT *neighbor, **neighborp;
-  int size;
-
-  trace4((qh ferr, "qh_degen_redundant_neighbors: test neighbors of f%d with delfacet f%d\n", 
-	  facet->id, getid_(delfacet)));
-  if ((size= qh_setsize (facet->neighbors)) < qh hull_dim) {
-    qh_appendmergeset (facet, facet, MRGdegen, NULL);
-    trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is degenerate with %d neighbors.\n", facet->id, size));
-  }
-  if (!delfacet)
-    delfacet= facet;
-  qh vertex_visit++;
-  FOREACHvertex_(facet->vertices)
-    vertex->visitid= qh vertex_visit;
-  FOREACHneighbor_(delfacet) {
-    /* uses early out instead of checking vertex count */
-    if (neighbor == facet)
-      continue;
-    FOREACHvertex_(neighbor->vertices) {
-      if (vertex->visitid != qh vertex_visit)
-        break;
-    }
-    if (!vertex) {
-      qh_appendmergeset (neighbor, facet, MRGredundant, NULL);
-      trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is contained in f%d.  merge\n", neighbor->id, facet->id)); 
-    }
-  }
-  FOREACHneighbor_(delfacet) {   /* redundant merges occur first */
-    if (neighbor == facet)
-      continue;
-    if ((size= qh_setsize (neighbor->neighbors)) < qh hull_dim) {
-      qh_appendmergeset (neighbor, neighbor, MRGdegen, NULL);
-      trace2((qh ferr, "qh_degen_redundant_neighbors: f%d is degenerate with %d neighbors.  Neighbor of f%d.\n", neighbor->id, size, facet->id)); 
-    }
-  }
-} /* degen_redundant_neighbors */
-
-
-/*---------------------------------
-  
-  qh_find_newvertex( oldvertex, vertices, ridges )
-    locate new vertex for renaming old vertex
-    vertices is a set of possible new vertices
-      vertices sorted by number of deleted ridges
-
-  returns:
-    newvertex or NULL
-      each ridge includes both vertex and oldvertex
-    vertices sorted by number of deleted ridges
-      
-  notes:
-    modifies vertex->visitid
-    new vertex is in one of the ridges
-    renaming will not cause a duplicate ridge
-    renaming will minimize the number of deleted ridges
-    newvertex may not be adjacent in the dual (though unlikely)
-
-  design:
-    for each vertex in vertices
-      set vertex->visitid to number of references in ridges
-    remove unvisited vertices 
-    set qh.vertex_visit above all possible values
-    sort vertices by number of references in ridges
-    add each ridge to qh.hash_table
-    for each vertex in vertices
-      look for a vertex that would not cause a duplicate ridge after a rename
-*/
-vertexT *qh_find_newvertex (vertexT *oldvertex, setT *vertices, setT *ridges) {
-  vertexT *vertex, **vertexp;
-  setT *newridges;
-  ridgeT *ridge, **ridgep;
-  int size, hashsize;
-  int hash;
-
-#ifndef qh_NOtrace
-  if (qh IStracing >= 4) {
-    fprintf (qh ferr, "qh_find_newvertex: find new vertex for v%d from ",
-	     oldvertex->id);
-    FOREACHvertex_(vertices) 
-      fprintf (qh ferr, "v%d ", vertex->id);
-    FOREACHridge_(ridges)
-      fprintf (qh ferr, "r%d ", ridge->id);
-    fprintf (qh ferr, "\n");
-  }
-#endif
-  FOREACHvertex_(vertices) 
-    vertex->visitid= 0;
-  FOREACHridge_(ridges) {
-    FOREACHvertex_(ridge->vertices) 
-      vertex->visitid++;
-  }
-  FOREACHvertex_(vertices) {
-    if (!vertex->visitid) {
-      qh_setdelnth (vertices, SETindex_(vertices,vertex));
-      vertexp--; /* repeat since deleted this vertex */
-    }
-  }
-  qh vertex_visit += qh_setsize (ridges);
-  if (!qh_setsize (vertices)) {
-    trace4((qh ferr, "qh_find_newvertex: vertices not in ridges for v%d\n",
-	    oldvertex->id));
-    return NULL;
-  }
-  qsort (SETaddr_(vertices, vertexT), qh_setsize (vertices),
-	        sizeof (vertexT *), qh_comparevisit);
-  /* can now use qh vertex_visit */
-  if (qh PRINTstatistics) {
-    size= qh_setsize (vertices);
-    zinc_(Zintersect);
-    zadd_(Zintersecttot, size);
-    zmax_(Zintersectmax, size);
-  }
-  hashsize= qh_newhashtable (qh_setsize (ridges));
-  FOREACHridge_(ridges)
-    qh_hashridge (qh hash_table, hashsize, ridge, oldvertex);
-  FOREACHvertex_(vertices) {
-    newridges= qh_vertexridges (vertex);
-    FOREACHridge_(newridges) {
-      if (qh_hashridge_find (qh hash_table, hashsize, ridge, vertex, oldvertex, &hash)) {
-	zinc_(Zdupridge);
-	break;
-      }
-    }
-    qh_settempfree (&newridges);
-    if (!ridge)
-      break;  /* found a rename */
-  }
-  if (vertex) {
-    /* counted in qh_renamevertex */
-    trace2((qh ferr, "qh_find_newvertex: found v%d for old v%d from %d vertices and %d ridges.\n",
-      vertex->id, oldvertex->id, qh_setsize (vertices), qh_setsize (ridges)));
-  }else {
-    zinc_(Zfindfail);
-    trace0((qh ferr, "qh_find_newvertex: no vertex for renaming v%d (all duplicated ridges) during p%d\n",
-      oldvertex->id, qh furthest_id));
-  }
-  qh_setfree (&qh hash_table);
-  return vertex;
-} /* find_newvertex */
-
-/*---------------------------------
-  
-  qh_findbest_test( testcentrum, facet, neighbor, bestfacet, dist, mindist, maxdist )
-    test neighbor of facet for qh_findbestneighbor()
-    if testcentrum,
-      tests centrum (assumes it is defined)
-    else 
-      tests vertices
-
-  returns:
-    if a better facet (i.e., vertices/centrum of facet closer to neighbor)
-      updates bestfacet, dist, mindist, and maxdist
-*/
-void qh_findbest_test (boolT testcentrum, facetT *facet, facetT *neighbor,
-      facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp) {
-  realT dist, mindist, maxdist;
-
-  if (testcentrum) {
-    zzinc_(Zbestdist);
-    qh_distplane(facet->center, neighbor, &dist);
-    dist *= qh hull_dim; /* estimate furthest vertex */
-    if (dist < 0) {
-      maxdist= 0;
-      mindist= dist;
-      dist= -dist;
-    }else
-      maxdist= dist;
-  }else
-    dist= qh_getdistance (facet, neighbor, &mindist, &maxdist);
-  if (dist < *distp) {
-    *bestfacet= neighbor;
-    *mindistp= mindist;
-    *maxdistp= maxdist;
-    *distp= dist;
-  }
-} /* findbest_test */
-
-/*---------------------------------
-  
-  qh_findbestneighbor( facet, dist, mindist, maxdist )
-    finds best neighbor (least dist) of a facet for merging
-
-  returns:
-    returns min and max distances and their max absolute value
-  
-  notes:
-    avoids merging old into new
-    assumes ridge->nonconvex only set on one ridge between a pair of facets
-    could use an early out predicate but not worth it
-
-  design:
-    if a large facet
-      will test centrum
-    else
-      will test vertices
-    if a large facet
-      test nonconvex neighbors for best merge
-    else
-      test all neighbors for the best merge
-    if testing centrum
-      get distance information
-*/
-facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp) {
-  facetT *neighbor, **neighborp, *bestfacet= NULL;
-  ridgeT *ridge, **ridgep;
-  boolT nonconvex= True, testcentrum= False;
-  int size= qh_setsize (facet->vertices);
-
-  *distp= REALmax;
-  if (size > qh_BESTcentrum2 * qh hull_dim + qh_BESTcentrum) {
-    testcentrum= True;
-    zinc_(Zbestcentrum);
-    if (!facet->center)
-       facet->center= qh_getcentrum (facet);
-  }
-  if (size > qh hull_dim + qh_BESTnonconvex) {
-    FOREACHridge_(facet->ridges) {
-      if (ridge->nonconvex) {
-        neighbor= otherfacet_(ridge, facet);
-	qh_findbest_test (testcentrum, facet, neighbor,
-			  &bestfacet, distp, mindistp, maxdistp);
-      }
-    }
-  }
-  if (!bestfacet) {     
-    nonconvex= False;
-    FOREACHneighbor_(facet)
-      qh_findbest_test (testcentrum, facet, neighbor,
-			&bestfacet, distp, mindistp, maxdistp);
-  }
-  if (!bestfacet) {
-    fprintf (qh ferr, "qhull internal error (qh_findbestneighbor): no neighbors for f%d\n", facet->id);
-    
-    qh_errexit (qh_ERRqhull, facet, NULL);
-  }
-  if (testcentrum) 
-    qh_getdistance (facet, bestfacet, mindistp, maxdistp);
-  trace3((qh ferr, "qh_findbestneighbor: f%d is best neighbor for f%d testcentrum? %d nonconvex? %d dist %2.2g min %2.2g max %2.2g\n",
-     bestfacet->id, facet->id, testcentrum, nonconvex, *distp, *mindistp, *maxdistp));
-  return(bestfacet);
-} /* findbestneighbor */
-
-
-/*---------------------------------
-  
-  qh_flippedmerges( facetlist, wasmerge )
-    merge flipped facets into best neighbor
-    assumes qh.facet_mergeset at top of temporary stack
-
-  returns:
-    no flipped facets on facetlist
-    sets wasmerge if merge occurred
-    degen/redundant merges passed through
-
-  notes:
-    othermerges not needed since qh.facet_mergeset is empty before & after
-      keep it in case of change
-
-  design:
-    append flipped facets to qh.facetmergeset
-    for each flipped merge
-      find best neighbor
-      merge facet into neighbor
-      merge degenerate and redundant facets
-    remove flipped merges from qh.facet_mergeset
-*/
-void qh_flippedmerges(facetT *facetlist, boolT *wasmerge) {
-  facetT *facet, *neighbor, *facet1;
-  realT dist, mindist, maxdist;
-  mergeT *merge, **mergep;
-  setT *othermerges;
-  int nummerge=0;
-
-  trace4((qh ferr, "qh_flippedmerges: begin\n"));
-  FORALLfacet_(facetlist) {
-    if (facet->flipped && !facet->visible) 
-      qh_appendmergeset (facet, facet, MRGflip, NULL);
-  }
-  othermerges= qh_settemppop(); /* was facet_mergeset */
-  qh facet_mergeset= qh_settemp (qh TEMPsize);
-  qh_settemppush (othermerges);
-  FOREACHmerge_(othermerges) {
-    facet1= merge->facet1;
-    if (merge->type != MRGflip || facet1->visible) 
-      continue;
-    if (qh TRACEmerge-1 == zzval_(Ztotmerge))
-      qhmem.IStracing= qh IStracing= qh TRACElevel;
-    neighbor= qh_findbestneighbor (facet1, &dist, &mindist, &maxdist);
-    trace0((qh ferr, "qh_flippedmerges: merge flipped f%d into f%d dist %2.2g during p%d\n",
-      facet1->id, neighbor->id, dist, qh furthest_id));
-    qh_mergefacet (facet1, neighbor, &mindist, &maxdist, !qh_MERGEapex);
-    nummerge++;
-    if (qh PRINTstatistics) {
-      zinc_(Zflipped);
-      wadd_(Wflippedtot, dist);
-      wmax_(Wflippedmax, dist);
-    }
-    qh_merge_degenredundant();
-  }
-  FOREACHmerge_(othermerges) {
-    if (merge->facet1->visible || merge->facet2->visible)
-      qh_memfree (merge, sizeof(mergeT));
-    else
-      qh_setappend (&qh facet_mergeset, merge);
-  }
-  qh_settempfree (&othermerges);
-  if (nummerge)
-    *wasmerge= True;
-  trace1((qh ferr, "qh_flippedmerges: merged %d flipped facets into a good neighbor\n", nummerge));
-} /* flippedmerges */
-
-
-/*---------------------------------
-  
-  qh_forcedmerges( wasmerge )
-    merge duplicated ridges
-
-  returns:
-    removes all duplicate ridges on facet_mergeset
-    wasmerge set if merge
-    qh.facet_mergeset may include non-forced merges (none for now)
-    qh.degen_mergeset includes degen/redun merges
-
-  notes: 
-    duplicate ridges occur when the horizon is pinched,
-        i.e. a subridge occurs in more than two horizon ridges.
-     could rename vertices that pinch the horizon
-    assumes qh_merge_degenredundant() has not be called
-    othermerges isn't needed since facet_mergeset is empty afterwards
-      keep it in case of change
-
-  design:
-    for each duplicate ridge
-      find current facets by chasing f.replace links
-      determine best direction for facet
-      merge one facet into the other
-      remove duplicate ridges from qh.facet_mergeset
-*/
-void qh_forcedmerges(boolT *wasmerge) {
-  facetT *facet1, *facet2;
-  mergeT *merge, **mergep;
-  realT dist1, dist2, mindist1, mindist2, maxdist1, maxdist2;
-  setT *othermerges;
-  int nummerge=0, numflip=0;
-
-  if (qh TRACEmerge-1 == zzval_(Ztotmerge))
-    qhmem.IStracing= qh IStracing= qh TRACElevel;
-  trace4((qh ferr, "qh_forcedmerges: begin\n"));  
-  othermerges= qh_settemppop(); /* was facet_mergeset */
-  qh facet_mergeset= qh_settemp (qh TEMPsize);
-  qh_settemppush (othermerges);
-  FOREACHmerge_(othermerges) {
-    if (merge->type != MRGridge) 
-    	continue;
-    facet1= merge->facet1;
-    facet2= merge->facet2;
-    while (facet1->visible)    	 /* must exist, no qh_merge_degenredunant */
-      facet1= facet1->f.replace; /* previously merged facet */
-    while (facet2->visible)
-      facet2= facet2->f.replace; /* previously merged facet */
-    if (facet1 == facet2)
-      continue;
-    if (!qh_setin (facet2->neighbors, facet1)) {
-      fprintf (qh ferr, "qhull internal error (qh_forcedmerges): f%d and f%d had a duplicate ridge but as f%d and f%d they are no longer neighbors\n",
-	       merge->facet1->id, merge->facet2->id, facet1->id, facet2->id);
-      qh_errexit2 (qh_ERRqhull, facet1, facet2);
-    }
-    if (qh TRACEmerge-1 == zzval_(Ztotmerge))
-      qhmem.IStracing= qh IStracing= qh TRACElevel;
-    dist1= qh_getdistance (facet1, facet2, &mindist1, &maxdist1);
-    dist2= qh_getdistance (facet2, facet1, &mindist2, &maxdist2);
-    trace0((qh ferr, "qh_forcedmerges: duplicate ridge between f%d and f%d, dist %2.2g and reverse dist %2.2g during p%d\n",
-	    facet1->id, facet2->id, dist1, dist2, qh furthest_id));
-    if (dist1 < dist2) 
-      qh_mergefacet (facet1, facet2, &mindist1, &maxdist1, !qh_MERGEapex);
-    else {
-      qh_mergefacet (facet2, facet1, &mindist2, &maxdist2, !qh_MERGEapex);
-      dist1= dist2;
-      facet1= facet2;
-    }
-    if (facet1->flipped) {
-      zinc_(Zmergeflipdup);
-      numflip++;
-    }else
-      nummerge++;
-    if (qh PRINTstatistics) {
-      zinc_(Zduplicate);
-      wadd_(Wduplicatetot, dist1);
-      wmax_(Wduplicatemax, dist1);
-    }
-  }
-  FOREACHmerge_(othermerges) {
-    if (merge->type == MRGridge)
-      qh_memfree (merge, sizeof(mergeT));
-    else
-      qh_setappend (&qh facet_mergeset, merge);
-  }
-  qh_settempfree (&othermerges);
-  if (nummerge)
-    *wasmerge= True;
-  trace1((qh ferr, "qh_forcedmerges: merged %d facets and %d flipped facets across duplicated ridges\n", 
-                nummerge, numflip));
-} /* forcedmerges */
-
-
-/*---------------------------------
-  
-  qh_getmergeset( facetlist )
-    determines nonconvex facets on facetlist
-    tests !tested ridges and nonconvex ridges of !tested facets
-
-  returns:
-    returns sorted qh.facet_mergeset of facet-neighbor pairs to be merged
-    all ridges tested
-  
-  notes:
-    assumes no nonconvex ridges with both facets tested
-    uses facet->tested/ridge->tested to prevent duplicate tests
-    can not limit tests to modified ridges since the centrum changed
-    uses qh.visit_id
-  
-  see:
-    qh_getmergeset_initial()
-
-  design:
-    for each facet on facetlist
-      for each ridge of facet
-        if untested ridge
-          test ridge for convexity
-          if non-convex
-            append ridge to qh.facet_mergeset
-    sort qh.facet_mergeset by angle  
-*/
-void qh_getmergeset(facetT *facetlist) {
-  facetT *facet, *neighbor, **neighborp;
-  ridgeT *ridge, **ridgep;
-  int nummerges;
-  
-  nummerges= qh_setsize (qh facet_mergeset);
-  trace4((qh ferr, "qh_getmergeset: started.\n"));
-  qh visit_id++;
-  FORALLfacet_(facetlist) {
-    if (facet->tested)
-      continue;
-    facet->visitid= qh visit_id;
-    facet->tested= True;  /* must be non-simplicial due to merge */
-    FOREACHneighbor_(facet)
-      neighbor->seen= False;
-    FOREACHridge_(facet->ridges) {
-      if (ridge->tested && !ridge->nonconvex)
-	continue;
-      /* if tested & nonconvex, need to append merge */
-      neighbor= otherfacet_(ridge, facet);
-      if (neighbor->seen) {
-	ridge->tested= True;
-	ridge->nonconvex= False;
-      }else if (neighbor->visitid != qh visit_id) {
-        ridge->tested= True;
-        ridge->nonconvex= False;
-	neighbor->seen= True;      /* only one ridge is marked nonconvex */
-	if (qh_test_appendmerge (facet, neighbor))
-	  ridge->nonconvex= True;
-      }
-    }
-  }
-  nummerges= qh_setsize (qh facet_mergeset);
-  if (qh ANGLEmerge)
-    qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_compareangle);
-  else
-    qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_comparemerge);
-  if (qh POSTmerging) {
-    zadd_(Zmergesettot2, nummerges);
-  }else {
-    zadd_(Zmergesettot, nummerges);
-    zmax_(Zmergesetmax, nummerges);
-  }
-  trace2((qh ferr, "qh_getmergeset: %d merges found\n", nummerges));
-} /* getmergeset */
-
-
-/*---------------------------------
-  
-  qh_getmergeset_initial( facetlist )
-    determine initial qh.facet_mergeset for facets
-    tests all facet/neighbor pairs on facetlist
-
-  returns:
-    sorted qh.facet_mergeset with nonconvex ridges
-    sets facet->tested, ridge->tested, and ridge->nonconvex
-
-  notes:
-    uses visit_id, assumes ridge->nonconvex is False
-
-  see:
-    qh_getmergeset()
-
-  design:
-    for each facet on facetlist
-      for each untested neighbor of facet
-        test facet and neighbor for convexity
-        if non-convex
-          append merge to qh.facet_mergeset
-          mark one of the ridges as nonconvex
-    sort qh.facet_mergeset by angle
-*/
-void qh_getmergeset_initial (facetT *facetlist) {
-  facetT *facet, *neighbor, **neighborp;
-  ridgeT *ridge, **ridgep;
-  int nummerges;
-
-  qh visit_id++;
-  FORALLfacet_(facetlist) {
-    facet->visitid= qh visit_id;
-    facet->tested= True;
-    FOREACHneighbor_(facet) {
-      if (neighbor->visitid != qh visit_id) {
-        if (qh_test_appendmerge (facet, neighbor)) {
-          FOREACHridge_(neighbor->ridges) {
-            if (facet == otherfacet_(ridge, neighbor)) {
-              ridge->nonconvex= True;
-              break;	/* only one ridge is marked nonconvex */
-            }
-          }
-        }
-      }
-    }
-    FOREACHridge_(facet->ridges)
-      ridge->tested= True;
-  }
-  nummerges= qh_setsize (qh facet_mergeset);
-  if (qh ANGLEmerge)
-    qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_compareangle);
-  else
-    qsort(SETaddr_(qh facet_mergeset, mergeT), nummerges,sizeof(mergeT *),qh_comparemerge);
-  if (qh POSTmerging) {
-    zadd_(Zmergeinittot2, nummerges);
-  }else {
-    zadd_(Zmergeinittot, nummerges);
-    zmax_(Zmergeinitmax, nummerges);
-  }
-  trace2((qh ferr, "qh_getmergeset_initial: %d merges found\n", nummerges));
-} /* getmergeset_initial */
-
-
-/*---------------------------------
-  
-  qh_hashridge( hashtable, hashsize, ridge, oldvertex )
-    add ridge to hashtable without oldvertex
-
-  notes:
-    assumes hashtable is large enough
-
-  design:
-    determine hash value for ridge without oldvertex
-    find next empty slot for ridge
-*/
-void qh_hashridge (setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex) {
-  int hash;
-  ridgeT *ridgeA;
-
-  hash= (int)qh_gethash (hashsize, ridge->vertices, qh hull_dim-1, 0, oldvertex);
-  while (True) {
-    if (!(ridgeA= SETelemt_(hashtable, hash, ridgeT))) {
-      SETelem_(hashtable, hash)= ridge;
-      break;
-    }else if (ridgeA == ridge)
-      break;
-    if (++hash == hashsize)
-      hash= 0;
-  }
-} /* hashridge */
-
-
-/*---------------------------------
-  
-  qh_hashridge_find( hashtable, hashsize, ridge, vertex, oldvertex, hashslot )
-    returns matching ridge without oldvertex in hashtable 
-      for ridge without vertex
-    if oldvertex is NULL 
-      matches with any one skip
-
-  returns:
-    matching ridge or NULL
-    if no match,
-      if ridge already in   table
-        hashslot= -1 
-      else 
-        hashslot= next NULL index
-        
-  notes:
-    assumes hashtable is large enough
-    can't match ridge to itself
-
-  design:
-    get hash value for ridge without vertex
-    for each hashslot
-      return match if ridge matches ridgeA without oldvertex
-*/
-ridgeT *qh_hashridge_find (setT *hashtable, int hashsize, ridgeT *ridge, 
-              vertexT *vertex, vertexT *oldvertex, int *hashslot) {
-  int hash;
-  ridgeT *ridgeA;
-
-  *hashslot= 0;
-  zinc_(Zhashridge);
-  hash= (int)qh_gethash (hashsize, ridge->vertices, qh hull_dim-1, 0, vertex);
-  while ((ridgeA= SETelemt_(hashtable, hash, ridgeT))) {
-    if (ridgeA == ridge)
-      *hashslot= -1;      
-    else {
-      zinc_(Zhashridgetest);
-      if (qh_setequal_except (ridge->vertices, vertex, ridgeA->vertices, oldvertex))
-        return ridgeA;
-    }
-    if (++hash == hashsize)
-      hash= 0;
-  }
-  if (!*hashslot)
-    *hashslot= hash;
-  return NULL;
-} /* hashridge_find */
-
-
-/*---------------------------------
-  
-  qh_makeridges( facet )
-    creates explicit ridges between simplicial facets
-
-  returns:
-    facet with ridges and without qh_MERGEridge
-    ->simplicial is False
-  
-  notes:
-    allows qh_MERGEridge flag
-    uses existing ridges
-    duplicate neighbors ok if ridges already exist (qh_mergecycle_ridges)
-
-  see:
-    qh_mergecycle_ridges()
-
-  design:
-    look for qh_MERGEridge neighbors
-    mark neighbors that already have ridges
-    for each unprocessed neighbor of facet    
-      create a ridge for neighbor and facet
-    if any qh_MERGEridge neighbors
-      delete qh_MERGEridge flags (already handled by qh_mark_dupridges)
-*/
-void qh_makeridges(facetT *facet) {
-  facetT *neighbor, **neighborp;
-  ridgeT *ridge, **ridgep;
-  int neighbor_i, neighbor_n;
-  boolT toporient, mergeridge= False;
-  
-  if (!facet->simplicial)
-    return;
-  trace4((qh ferr, "qh_makeridges: make ridges for f%d\n", facet->id));
-  facet->simplicial= False;
-  FOREACHneighbor_(facet) {
-    if (neighbor == qh_MERGEridge)
-      mergeridge= True;
-    else
-      neighbor->seen= False;
-  }
-  FOREACHridge_(facet->ridges)
-    otherfacet_(ridge, facet)->seen= True;
-  FOREACHneighbor_i_(facet) {
-    if (neighbor == qh_MERGEridge)
-      continue;  /* fixed by qh_mark_dupridges */
-    else if (!neighbor->seen) {  /* no current ridges */
-      ridge= qh_newridge();
-      ridge->vertices= qh_setnew_delnthsorted (facet->vertices, qh hull_dim,
-					                  neighbor_i, 0);
-      toporient= facet->toporient ^ (neighbor_i & 0x1);
-      if (toporient) {
-        ridge->top= facet;
-        ridge->bottom= neighbor;
-      }else {
-        ridge->top= neighbor;
-        ridge->bottom= facet;
-      }
-#if 0 /* this also works */
-      flip= (facet->toporient ^ neighbor->toporient)^(skip1 & 0x1) ^ (skip2 & 0x1);
-      if (facet->toporient ^ (skip1 & 0x1) ^ flip) {
-        ridge->top= neighbor;
-        ridge->bottom= facet;
-      }else {
-        ridge->top= facet;
-        ridge->bottom= neighbor;
-      }
-#endif
-      qh_setappend(&(facet->ridges), ridge);
-      qh_setappend(&(neighbor->ridges), ridge);
-    }
-  }
-  if (mergeridge) {
-    while (qh_setdel (facet->neighbors, qh_MERGEridge))
-      ; /* delete each one */
-  }
-} /* makeridges */
-
-
-/*---------------------------------
-  
-  qh_mark_dupridges( facetlist )
-    add duplicated ridges to qh.facet_mergeset
-    facet->dupridge is true
-
-  returns:
-    duplicate ridges on qh.facet_mergeset
-    ->mergeridge/->mergeridge2 set
-    duplicate ridges marked by qh_MERGEridge and both sides facet->dupridge
-    no MERGEridges in neighbor sets
-    
-  notes:
-    duplicate ridges occur when the horizon is pinched,
-        i.e. a subridge occurs in more than two horizon ridges.
-    could rename vertices that pinch the horizon
-    uses qh.visit_id
-
-  design:
-    for all facets on facetlist
-      if facet contains a duplicate ridge
-        for each neighbor of facet
-          if neighbor marked qh_MERGEridge (one side of the merge)
-            set facet->mergeridge      
-          else
-            if neighbor contains a duplicate ridge 
-            and the back link is qh_MERGEridge
-              append duplicate ridge to qh.facet_mergeset
-   for each duplicate ridge
-     make ridge sets in preparation for merging
-     remove qh_MERGEridge from neighbor set
-   for each duplicate ridge
-     restore the missing neighbor from the neighbor set that was qh_MERGEridge
-     add the missing ridge for this neighbor
-*/
-void qh_mark_dupridges(facetT *facetlist) {
-  facetT *facet, *neighbor, **neighborp;
-  int nummerge=0;
-  mergeT *merge, **mergep;
-  
-
-  trace4((qh ferr, "qh_mark_dupridges: identify duplicate ridges\n"));  
-  FORALLfacet_(facetlist) {
-    if (facet->dupridge) {
-      FOREACHneighbor_(facet) {
-        if (neighbor == qh_MERGEridge) {
-	  facet->mergeridge= True;
-	  continue;
-	}
-        if (neighbor->dupridge
-	&& !qh_setin (neighbor->neighbors, facet)) { /* qh_MERGEridge */
-	  qh_appendmergeset (facet, neighbor, MRGridge, NULL);
-	  facet->mergeridge2= True;
-	  facet->mergeridge= True;
-	  nummerge++;
-	}
-      }
-    }
-  }
-  if (!nummerge)
-    return;
-  FORALLfacet_(facetlist) {            /* gets rid of qh_MERGEridge */
-    if (facet->mergeridge && !facet->mergeridge2)   
-      qh_makeridges (facet);
-  }
-  FOREACHmerge_(qh facet_mergeset) {   /* restore the missing neighbors */
-    if (merge->type == MRGridge) {
-      qh_setappend (&merge->facet2->neighbors, merge->facet1);
-      qh_makeridges (merge->facet1);   /* and the missing ridges */
-    }
-  }
-  trace1((qh ferr, "qh_mark_dupridges: found %d duplicated ridges\n", 
-                nummerge));
-} /* mark_dupridges */
-
-/*---------------------------------
-  
-  qh_maydropneighbor( facet )
-    drop neighbor relationship if no ridge between facet and neighbor
-
-  returns:
-    neighbor sets updated
-    appends degenerate facets to qh.facet_mergeset
-  
-  notes:
-    won't cause redundant facets since vertex inclusion is the same
-    may drop vertex and neighbor if no ridge
-    uses qh.visit_id
-
-  design:
-    visit all neighbors with ridges
-    for each unvisited neighbor of facet
-      delete neighbor and facet from the neighbor sets
-      if neighbor becomes degenerate
-        append neighbor to qh.degen_mergeset
-    if facet is degenerate
-      append facet to qh.degen_mergeset
-*/
-void qh_maydropneighbor (facetT *facet) {
-  ridgeT *ridge, **ridgep;
-  realT angledegen= qh_ANGLEdegen;
-  facetT *neighbor, **neighborp;
-
-  qh visit_id++;
-  trace4((qh ferr, "qh_maydropneighbor: test f%d for no ridges to a neighbor\n",
-	  facet->id));
-  FOREACHridge_(facet->ridges) {
-    ridge->top->visitid= qh visit_id;
-    ridge->bottom->visitid= qh visit_id;
-  }
-  FOREACHneighbor_(facet) {
-    if (neighbor->visitid != qh visit_id) {
-      trace0((qh ferr, "qh_maydropneighbor: facets f%d and f%d are no longer neighbors during p%d\n",
-	    facet->id, neighbor->id, qh furthest_id));
-      zinc_(Zdropneighbor);
-      qh_setdel (facet->neighbors, neighbor);
-      neighborp--;  /* repeat, deleted a neighbor */
-      qh_setdel (neighbor->neighbors, facet);
-      if (qh_setsize (neighbor->neighbors) < qh hull_dim) {
-        zinc_(Zdropdegen);
-        qh_appendmergeset (neighbor, neighbor, MRGdegen, &angledegen);
-        trace2((qh ferr, "qh_maydropneighbors: f%d is degenerate.\n", neighbor->id));
-      }
-    }
-  }
-  if (qh_setsize (facet->neighbors) < qh hull_dim) {
-    zinc_(Zdropdegen);
-    qh_appendmergeset (facet, facet, MRGdegen, &angledegen);
-    trace2((qh ferr, "qh_maydropneighbors: f%d is degenerate.\n", facet->id));
-  }
-} /* maydropneighbor */
-
-
-/*---------------------------------
-  
-  qh_merge_degenredundant()
-    merge all degenerate and redundant facets
-    qh.degen_mergeset contains merges from qh_degen_redundant_neighbors()
-
-  returns:
-    number of merges performed
-    resets facet->degenerate/redundant
-    if deleted (visible) facet has no neighbors
-      sets ->f.replace to NULL
-
-  notes:
-    redundant merges happen before degenerate ones
-    merging and renaming vertices can result in degen/redundant facets
-
-  design:
-    for each merge on qh.degen_mergeset
-      if redundant merge
-        if non-redundant facet merged into redundant facet
-          recheck facet for redundancy
-        else
-          merge redundant facet into other facet
-*/
-int qh_merge_degenredundant (void) {
-  int size;
-  mergeT *merge;
-  facetT *bestneighbor, *facet1, *facet2;
-  realT dist, mindist, maxdist;
-  vertexT *vertex, **vertexp;
-  int nummerges= 0;
-  mergeType mergetype;
-
-  while ((merge= (mergeT*)qh_setdellast (qh degen_mergeset))) {
-    facet1= merge->facet1;
-    facet2= merge->facet2;
-    mergetype= merge->type;
-    qh_memfree (merge, sizeof(mergeT));
-    if (facet1->visible)
-      continue;
-    facet1->degenerate= False; 
-    facet1->redundant= False; 
-    if (qh TRACEmerge-1 == zzval_(Ztotmerge))
-      qhmem.IStracing= qh IStracing= qh TRACElevel;
-    if (mergetype == MRGredundant) {
-      zinc_(Zneighbor);
-      while (facet2->visible) {
-        if (!facet2->f.replace) {
-          fprintf (qh ferr, "qhull internal error (qh_merge_degenredunant): f%d redundant but f%d has no replacement\n",
-	       facet1->id, facet2->id);
-          qh_errexit2 (qh_ERRqhull, facet1, facet2);
-        }
-        facet2= facet2->f.replace;
-      }
-      if (facet1 == facet2) {
-	qh_degen_redundant_facet (facet1); /* in case of others */
-	continue;
-      }
-      trace2((qh ferr, "qh_merge_degenredundant: facet f%d is contained in f%d, will merge\n",
-	    facet1->id, facet2->id));
-      qh_mergefacet(facet1, facet2, NULL, NULL, !qh_MERGEapex);
-      /* merge distance is already accounted for */
-      nummerges++;
-    }else {  /* mergetype == MRGdegen, other merges may have fixed */
-      if (!(size= qh_setsize (facet1->neighbors))) {
-        zinc_(Zdelfacetdup);
-        trace2((qh ferr, "qh_merge_degenredundant: facet f%d has no neighbors.  Deleted\n", facet1->id));
-        qh_willdelete (facet1, NULL);
-        FOREACHvertex_(facet1->vertices) {
-  	  qh_setdel (vertex->neighbors, facet1);
-	  if (!SETfirst_(vertex->neighbors)) {
-	    zinc_(Zdegenvertex);
-	    trace2((qh ferr, "qh_merge_degenredundant: deleted v%d because f%d has no neighbors\n",
-         	 vertex->id, facet1->id));
-	    vertex->deleted= True;
-	    qh_setappend (&qh del_vertices, vertex);
-	  }
-        }
-        nummerges++;
-      }else if (size < qh hull_dim) {
-        bestneighbor= qh_findbestneighbor(facet1, &dist, &mindist, &maxdist);
-        trace2((qh ferr, "qh_merge_degenredundant: facet f%d has %d neighbors, merge into f%d dist %2.2g\n",
-	      facet1->id, size, bestneighbor->id, dist));
-        qh_mergefacet(facet1, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
-        nummerges++;
-        if (qh PRINTstatistics) {
-	  zinc_(Zdegen);
-	  wadd_(Wdegentot, dist);
-	  wmax_(Wdegenmax, dist);
-        }
-      }	/* else, another merge fixed the degeneracy and redundancy tested */
-    }
-  }
-  return nummerges;
-} /* merge_degenredundant */
-
-/*---------------------------------
-  
-  qh_merge_nonconvex( facet1, facet2, mergetype )
-    remove non-convex ridge between facet1 into facet2 
-    mergetype gives why the facet's are non-convex
-
-  returns:
-    merges one of the facets into the best neighbor
-    
-  design:
-    if one of the facets is a new facet
-      prefer merging new facet into old facet
-    find best neighbors for both facets
-    merge the nearest facet into its best neighbor
-    update the statistics
-*/
-void qh_merge_nonconvex (facetT *facet1, facetT *facet2, mergeType mergetype) {
-  facetT *bestfacet, *bestneighbor, *neighbor;
-  realT dist, dist2, mindist, mindist2, maxdist, maxdist2;
-
-  if (qh TRACEmerge-1 == zzval_(Ztotmerge))
-    qhmem.IStracing= qh IStracing= qh TRACElevel;
-  trace3((qh ferr, "qh_merge_nonconvex: merge #%d for f%d and f%d type %d\n",
-      zzval_(Ztotmerge) + 1, facet1->id, facet2->id, mergetype));
-  /* concave or coplanar */
-  if (!facet1->newfacet) {
-    bestfacet= facet2;   /* avoid merging old facet if new is ok */
-    facet2= facet1;
-    facet1= bestfacet;
-  }else
-    bestfacet= facet1;
-  bestneighbor= qh_findbestneighbor(bestfacet, &dist, &mindist, &maxdist);
-  neighbor= qh_findbestneighbor(facet2, &dist2, &mindist2, &maxdist2);
-  if (dist < dist2) {
-    qh_mergefacet(bestfacet, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
-  }else if (qh AVOIDold && !facet2->newfacet
-  && ((mindist >= -qh MAXcoplanar && maxdist <= qh max_outside)
-       || dist * 1.5 < dist2)) {
-    zinc_(Zavoidold);
-    wadd_(Wavoidoldtot, dist);
-    wmax_(Wavoidoldmax, dist);
-    trace2((qh ferr, "qh_merge_nonconvex: avoid merging old facet f%d dist %2.2g.  Use f%d dist %2.2g instead\n",
-           facet2->id, dist2, facet1->id, dist2));
-    qh_mergefacet(bestfacet, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
-  }else {
-    qh_mergefacet(facet2, neighbor, &mindist2, &maxdist2, !qh_MERGEapex);
-    dist= dist2;
-  }
-  if (qh PRINTstatistics) {
-    if (mergetype == MRGanglecoplanar) {
-      zinc_(Zacoplanar);
-      wadd_(Wacoplanartot, dist);
-      wmax_(Wacoplanarmax, dist);
-    }else if (mergetype == MRGconcave) {
-      zinc_(Zconcave);
-      wadd_(Wconcavetot, dist);
-      wmax_(Wconcavemax, dist);
-    }else { /* MRGcoplanar */
-      zinc_(Zcoplanar);
-      wadd_(Wcoplanartot, dist);
-      wmax_(Wcoplanarmax, dist);
-    }
-  }
-} /* merge_nonconvex */
-
-/*---------------------------------
-  
-  qh_mergecycle( samecycle, newfacet )
-    merge a cycle of facets starting at samecycle into a newfacet 
-    newfacet is a horizon facet with ->normal
-    samecycle facets are simplicial from an apex
-
-  returns:
-    initializes vertex neighbors on first merge
-    samecycle deleted (placed on qh.visible_list)
-    newfacet at end of qh.facet_list
-    deleted vertices on qh.del_vertices
-
-  see:
-    qh_mergefacet()
-    called by qh_mergecycle_all() for multiple, same cycle facets
-
-  design:
-    make vertex neighbors if necessary
-    make ridges for newfacet
-    merge neighbor sets of samecycle into newfacet
-    merge ridges of samecycle into newfacet
-    merge vertex neighbors of samecycle into newfacet
-    make apex of samecycle the apex of newfacet
-    if newfacet wasn't a new facet
-      add its vertices to qh.newvertex_list
-    delete samecycle facets a make newfacet a newfacet
-*/
-void qh_mergecycle (facetT *samecycle, facetT *newfacet) {
-  int traceonce= False, tracerestore= 0;
-  vertexT *apex;
-#ifndef qh_NOtrace
-  facetT *same;
-#endif
-
-  if (newfacet->tricoplanar) {
-    if (!qh TRInormals) {
-      fprintf (qh ferr, "qh_mergecycle: does not work for tricoplanar facets.  Use option 'Q11'\n");
-      qh_errexit (qh_ERRqhull, newfacet, NULL);
-    }
-    newfacet->tricoplanar= False;
-    newfacet->keepcentrum= False;
-  }
-  if (!qh VERTEXneighbors)
-    qh_vertexneighbors();
-  zzinc_(Ztotmerge);
-  if (qh REPORTfreq2 && qh POSTmerging) {
-    if (zzval_(Ztotmerge) > qh mergereport + qh REPORTfreq2)
-      qh_tracemerging();
-  }
-#ifndef qh_NOtrace
-  if (qh TRACEmerge == zzval_(Ztotmerge))
-    qhmem.IStracing= qh IStracing= qh TRACElevel;
-  trace2((qh ferr, "qh_mergecycle: merge #%d for facets from cycle f%d into coplanar horizon f%d\n", 
-        zzval_(Ztotmerge), samecycle->id, newfacet->id));
-  if (newfacet == qh tracefacet) {
-    tracerestore= qh IStracing;
-    qh IStracing= 4;
-    fprintf (qh ferr, "qh_mergecycle: ========= trace merge %d of samecycle %d into trace f%d, furthest is p%d\n",
-	       zzval_(Ztotmerge), samecycle->id, newfacet->id,  qh furthest_id);
-    traceonce= True;
-  }
-  if (qh IStracing >=4) {
-    fprintf (qh ferr, "  same cycle:");
-    FORALLsame_cycle_(samecycle)
-      fprintf(qh ferr, " f%d", same->id);
-    fprintf (qh ferr, "\n");
-  }
-  if (qh IStracing >=4)
-    qh_errprint ("MERGING CYCLE", samecycle, newfacet, NULL, NULL);
-#endif /* !qh_NOtrace */
-  apex= SETfirstt_(samecycle->vertices, vertexT);
-  qh_makeridges (newfacet);
-  qh_mergecycle_neighbors (samecycle, newfacet);
-  qh_mergecycle_ridges (samecycle, newfacet);
-  qh_mergecycle_vneighbors (samecycle, newfacet);
-  if (SETfirstt_(newfacet->vertices, vertexT) != apex) 
-    qh_setaddnth (&newfacet->vertices, 0, apex);  /* apex has last id */
-  if (!newfacet->newfacet)
-    qh_newvertices (newfacet->vertices);
-  qh_mergecycle_facets (samecycle, newfacet);
-  qh_tracemerge (samecycle, newfacet);
-  /* check for degen_redundant_neighbors after qh_forcedmerges() */
-  if (traceonce) {
-    fprintf (qh ferr, "qh_mergecycle: end of trace facet\n");
-    qh IStracing= tracerestore;
-  }
-} /* mergecycle */
-
-/*---------------------------------
-  
-  qh_mergecycle_all( facetlist, wasmerge )
-    merge all samecycles of coplanar facets into horizon
-    don't merge facets with ->mergeridge (these already have ->normal)
-    all facets are simplicial from apex
-    all facet->cycledone == False
-
-  returns:
-    all newfacets merged into coplanar horizon facets
-    deleted vertices on  qh.del_vertices
-    sets wasmerge if any merge
-
-  see:
-    calls qh_mergecycle for multiple, same cycle facets
-
-  design:
-    for each facet on facetlist
-      skip facets with duplicate ridges and normals
-      check that facet is in a samecycle (->mergehorizon)
-      if facet only member of samecycle
-	sets vertex->delridge for all vertices except apex
-        merge facet into horizon
-      else
-        mark all facets in samecycle
-        remove facets with duplicate ridges from samecycle
-        merge samecycle into horizon (deletes facets from facetlist)
-*/
-void qh_mergecycle_all (facetT *facetlist, boolT *wasmerge) {
-  facetT *facet, *same, *prev, *horizon;
-  facetT *samecycle= NULL, *nextfacet, *nextsame;
-  vertexT *apex, *vertex, **vertexp;
-  int cycles=0, total=0, facets, nummerge;
-
-  trace2((qh ferr, "qh_mergecycle_all: begin\n"));
-  for (facet= facetlist; facet && (nextfacet= facet->next); facet= nextfacet) {
-    if (facet->normal)
-      continue;
-    if (!facet->mergehorizon) {
-      fprintf (qh ferr, "qh_mergecycle_all: f%d without normal\n", facet->id);
-      qh_errexit (qh_ERRqhull, facet, NULL);
-    }
-    horizon= SETfirstt_(facet->neighbors, facetT);
-    if (facet->f.samecycle == facet) {
-      zinc_(Zonehorizon);  
-      /* merge distance done in qh_findhorizon */
-      apex= SETfirstt_(facet->vertices, vertexT);
-      FOREACHvertex_(facet->vertices) {
-	if (vertex != apex)
-          vertex->delridge= True;
-      }
-      horizon->f.newcycle= NULL;
-      qh_mergefacet (facet, horizon, NULL, NULL, qh_MERGEapex);
-    }else {
-      samecycle= facet;
-      facets= 0;
-      prev= facet;
-      for (same= facet->f.samecycle; same;  /* FORALLsame_cycle_(facet) */
-	   same= (same == facet ? NULL :nextsame)) { /* ends at facet */
-	nextsame= same->f.samecycle;
-        if (same->cycledone || same->visible)
-          qh_infiniteloop (same);
-        same->cycledone= True;
-        if (same->normal) { 
-          prev->f.samecycle= same->f.samecycle; /* unlink ->mergeridge */
-	  same->f.samecycle= NULL;
-        }else {
-          prev= same;
-	  facets++;
-	}
-      }
-      while (nextfacet && nextfacet->cycledone)  /* will delete samecycle */
-	nextfacet= nextfacet->next;
-      horizon->f.newcycle= NULL;
-      qh_mergecycle (samecycle, horizon);
-      nummerge= horizon->nummerge + facets;
-      if (nummerge > qh_MAXnummerge) 
-      	horizon->nummerge= qh_MAXnummerge;
-      else
-        horizon->nummerge= nummerge;
-      zzinc_(Zcyclehorizon);
-      total += facets;
-      zzadd_(Zcyclefacettot, facets);
-      zmax_(Zcyclefacetmax, facets);
-    }
-    cycles++;
-  }
-  if (cycles)
-    *wasmerge= True;
-  trace1((qh ferr, "qh_mergecycle_all: merged %d same cycles or facets into coplanar horizons\n", cycles));
-} /* mergecycle_all */
-
-/*---------------------------------
-  
-  qh_mergecycle_facets( samecycle, newfacet )
-    finish merge of samecycle into newfacet
-
-  returns:
-    samecycle prepended to visible_list for later deletion and partitioning
-      each facet->f.replace == newfacet
-      
-    newfacet moved to end of qh.facet_list
-      makes newfacet a newfacet (get's facet1->id if it was old)
-      sets newfacet->newmerge
-      clears newfacet->center (unless merging into a large facet)
-      clears newfacet->tested and ridge->tested for facet1
-      
-    adds neighboring facets to facet_mergeset if redundant or degenerate
-
-  design:
-    make newfacet a new facet and set its flags
-    move samecycle facets to qh.visible_list for later deletion
-    unless newfacet is large
-      remove its centrum
-*/
-void qh_mergecycle_facets (facetT *samecycle, facetT *newfacet) {
-  facetT *same, *next;
-  
-  trace4((qh ferr, "qh_mergecycle_facets: make newfacet new and samecycle deleted\n"));  
-  qh_removefacet(newfacet);  /* append as a newfacet to end of qh facet_list */
-  qh_appendfacet(newfacet);
-  newfacet->newfacet= True;
-  newfacet->simplicial= False;
-  newfacet->newmerge= True;
-  
-  for (same= samecycle->f.samecycle; same; same= (same == samecycle ?  NULL : next)) {
-    next= same->f.samecycle;  /* reused by willdelete */
-    qh_willdelete (same, newfacet);
-  }
-  if (newfacet->center 
-      && qh_setsize (newfacet->vertices) <= qh hull_dim + qh_MAXnewcentrum) {
-    qh_memfree (newfacet->center, qh normal_size);
-    newfacet->center= NULL;
-  }
-  trace3((qh ferr, "qh_mergecycle_facets: merged facets from cycle f%d into f%d\n", 
-             samecycle->id, newfacet->id));
-} /* mergecycle_facets */
-
-/*---------------------------------
-  
-  qh_mergecycle_neighbors( samecycle, newfacet )
-    add neighbors for samecycle facets to newfacet
-
-  returns:
-    newfacet with updated neighbors and vice-versa
-    newfacet has ridges
-    all neighbors of newfacet marked with qh.visit_id
-    samecycle facets marked with qh.visit_id-1
-    ridges updated for simplicial neighbors of samecycle with a ridge
-
-  notes:
-    assumes newfacet not in samecycle
-    usually, samecycle facets are new, simplicial facets without internal ridges 
-      not so if horizon facet is coplanar to two different samecycles
-  
-  see:
-    qh_mergeneighbors()
-
-  design:
-    check samecycle
-    delete neighbors from newfacet that are also in samecycle
-    for each neighbor of a facet in samecycle
-      if neighbor is simplicial
-        if first visit
-          move the neighbor relation to newfacet
-          update facet links for its ridges
-        else
-          make ridges for neighbor
-          remove samecycle reference
-      else
-        update neighbor sets
-*/
-void qh_mergecycle_neighbors(facetT *samecycle, facetT *newfacet) {
-  facetT *same, *neighbor, **neighborp;
-  int delneighbors= 0, newneighbors= 0;
-  unsigned int samevisitid;
-  ridgeT *ridge, **ridgep;
-
-  samevisitid= ++qh visit_id;
-  FORALLsame_cycle_(samecycle) {
-    if (same->visitid == samevisitid || same->visible)
-      qh_infiniteloop (samecycle);
-    same->visitid= samevisitid;
-  }
-  newfacet->visitid= ++qh visit_id;
-  trace4((qh ferr, "qh_mergecycle_neighbors: delete shared neighbors from newfacet\n"));  
-  FOREACHneighbor_(newfacet) {
-    if (neighbor->visitid == samevisitid) {
-      SETref_(neighbor)= NULL;  /* samecycle neighbors deleted */
-      delneighbors++;
-    }else
-      neighbor->visitid= qh visit_id;
-  }
-  qh_setcompact (newfacet->neighbors);
-
-  trace4((qh ferr, "qh_mergecycle_neighbors: update neighbors\n"));  
-  FORALLsame_cycle_(samecycle) {
-    FOREACHneighbor_(same) {
-      if (neighbor->visitid == samevisitid)
-	continue;
-      if (neighbor->simplicial) {
-	if (neighbor->visitid != qh visit_id) {
-	  qh_setappend (&newfacet->neighbors, neighbor);
-	  qh_setreplace (neighbor->neighbors, same, newfacet);
-	  newneighbors++;
-	  neighbor->visitid= qh visit_id;
-	  FOREACHridge_(neighbor->ridges) { /* update ridge in case of qh_makeridges */
-	    if (ridge->top == same) {
-	      ridge->top= newfacet;
-	      break;
-	    }else if (ridge->bottom == same) {
-	      ridge->bottom= newfacet;
-	      break;
-	    }
-	  }
-	}else {
-	  qh_makeridges (neighbor);
-	  qh_setdel (neighbor->neighbors, same);
-	  /* same can't be horizon facet for neighbor */
-	}
-      }else { /* non-simplicial neighbor */
-        qh_setdel (neighbor->neighbors, same);
-        if (neighbor->visitid != qh visit_id) {
-          qh_setappend (&neighbor->neighbors, newfacet);
-          qh_setappend (&newfacet->neighbors, neighbor);
-          neighbor->visitid= qh visit_id;
-          newneighbors++;
-        } 
-      }
-    }
-  }
-  trace2((qh ferr, "qh_mergecycle_neighbors: deleted %d neighbors and added %d\n", 
-             delneighbors, newneighbors));
-} /* mergecycle_neighbors */
-
-/*---------------------------------
-  
-  qh_mergecycle_ridges( samecycle, newfacet )
-    add ridges/neighbors for facets in samecycle to newfacet
-    all new/old neighbors of newfacet marked with qh.visit_id
-    facets in samecycle marked with qh.visit_id-1
-    newfacet marked with qh.visit_id
-
-  returns:
-    newfacet has merged ridges
-  
-  notes:
-    ridge already updated for simplicial neighbors of samecycle with a ridge
-
-  see:
-    qh_mergeridges()
-    qh_makeridges()
-
-  design:
-    remove ridges between newfacet and samecycle
-    for each facet in samecycle
-      for each ridge in facet
-        update facet pointers in ridge
-        skip ridges processed in qh_mergecycle_neighors
-        free ridges between newfacet and samecycle
-        free ridges between facets of samecycle (on 2nd visit)
-        append remaining ridges to newfacet
-      if simpilicial facet
-        for each neighbor of facet
-          if simplicial facet
-          and not samecycle facet or newfacet
-            make ridge between neighbor and newfacet
-*/
-void qh_mergecycle_ridges(facetT *samecycle, facetT *newfacet) {
-  facetT *same, *neighbor= NULL;
-  int numold=0, numnew=0;
-  int neighbor_i, neighbor_n;
-  unsigned int samevisitid;
-  ridgeT *ridge, **ridgep;
-  boolT toporient;
-  void **freelistp; /* used !qh_NOmem */
-
-  trace4((qh ferr, "qh_mergecycle_ridges: delete shared ridges from newfacet\n"));  
-  samevisitid= qh visit_id -1;
-  FOREACHridge_(newfacet->ridges) {
-    neighbor= otherfacet_(ridge, newfacet);
-    if (neighbor->visitid == samevisitid)
-      SETref_(ridge)= NULL; /* ridge free'd below */  
-  }
-  qh_setcompact (newfacet->ridges);
-  
-  trace4((qh ferr, "qh_mergecycle_ridges: add ridges to newfacet\n"));  
-  FORALLsame_cycle_(samecycle) {
-    FOREACHridge_(same->ridges) {
-      if (ridge->top == same) {
-        ridge->top= newfacet;
-	neighbor= ridge->bottom;
-      }else if (ridge->bottom == same) {
-	ridge->bottom= newfacet;
-	neighbor= ridge->top;
-      }else if (ridge->top == newfacet || ridge->bottom == newfacet) {
-        qh_setappend (&newfacet->ridges, ridge);
-        numold++;  /* already set by qh_mergecycle_neighbors */
-	continue;  
-      }else {
-	fprintf (qh ferr, "qhull internal error (qh_mergecycle_ridges): bad ridge r%d\n", ridge->id);
-	qh_errexit (qh_ERRqhull, NULL, ridge);
-      }
-      if (neighbor == newfacet) {
-        qh_setfree(&(ridge->vertices)); 
-        qh_memfree_(ridge, sizeof(ridgeT), freelistp);
-        numold++;
-      }else if (neighbor->visitid == samevisitid) {
-	qh_setdel (neighbor->ridges, ridge);
-	qh_setfree(&(ridge->vertices)); 
-	qh_memfree_(ridge, sizeof(ridgeT), freelistp);
-	numold++;
-      }else {
-        qh_setappend (&newfacet->ridges, ridge);
-        numold++;
-      }
-    }
-    if (same->ridges)
-      qh_settruncate (same->ridges, 0);
-    if (!same->simplicial)
-      continue;
-    FOREACHneighbor_i_(same) {       /* note: !newfact->simplicial */
-      if (neighbor->visitid != samevisitid && neighbor->simplicial) {
-        ridge= qh_newridge();
-        ridge->vertices= qh_setnew_delnthsorted (same->vertices, qh hull_dim,
-  					                  neighbor_i, 0);
-        toporient= same->toporient ^ (neighbor_i & 0x1);
-        if (toporient) {
-          ridge->top= newfacet;
-          ridge->bottom= neighbor;
-        }else {
-          ridge->top= neighbor;
-          ridge->bottom= newfacet;
-        }
-        qh_setappend(&(newfacet->ridges), ridge);
-        qh_setappend(&(neighbor->ridges), ridge);
-        numnew++;
-      }
-    }
-  }
-
-  trace2((qh ferr, "qh_mergecycle_ridges: found %d old ridges and %d new ones\n", 
-             numold, numnew));
-} /* mergecycle_ridges */
-
-/*---------------------------------
-  
-  qh_mergecycle_vneighbors( samecycle, newfacet )
-    create vertex neighbors for newfacet from vertices of facets in samecycle
-    samecycle marked with visitid == qh.visit_id - 1
-
-  returns:
-    newfacet vertices with updated neighbors
-    marks newfacet with qh.visit_id-1
-    deletes vertices that are merged away
-    sets delridge on all vertices (faster here than in mergecycle_ridges)
-
-  see:
-    qh_mergevertex_neighbors()
-
-  design:
-    for each vertex of samecycle facet
-      set vertex->delridge
-      delete samecycle facets from vertex neighbors
-      append newfacet to vertex neighbors
-      if vertex only in newfacet
-        delete it from newfacet
-        add it to qh.del_vertices for later deletion
-*/
-void qh_mergecycle_vneighbors (facetT *samecycle, facetT *newfacet) {
-  facetT *neighbor, **neighborp;
-  unsigned int mergeid;
-  vertexT *vertex, **vertexp, *apex;
-  setT *vertices;
-  
-  trace4((qh ferr, "qh_mergecycle_vneighbors: update vertex neighbors for newfacet\n"));  
-  mergeid= qh visit_id - 1;
-  newfacet->visitid= mergeid;
-  vertices= qh_basevertices (samecycle); /* temp */
-  apex= SETfirstt_(samecycle->vertices, vertexT);
-  qh_setappend (&vertices, apex);
-  FOREACHvertex_(vertices) {
-    vertex->delridge= True;
-    FOREACHneighbor_(vertex) {
-      if (neighbor->visitid == mergeid)
-        SETref_(neighbor)= NULL;
-    }
-    qh_setcompact (vertex->neighbors);
-    qh_setappend (&vertex->neighbors, newfacet);
-    if (!SETsecond_(vertex->neighbors)) {
-      zinc_(Zcyclevertex);
-      trace2((qh ferr, "qh_mergecycle_vneighbors: deleted v%d when merging cycle f%d into f%d\n",
-        vertex->id, samecycle->id, newfacet->id));
-      qh_setdelsorted (newfacet->vertices, vertex);
-      vertex->deleted= True;
-      qh_setappend (&qh del_vertices, vertex);
-    }
-  }
-  qh_settempfree (&vertices);
-  trace3((qh ferr, "qh_mergecycle_vneighbors: merged vertices from cycle f%d into f%d\n", 
-             samecycle->id, newfacet->id));
-} /* mergecycle_vneighbors */
-
-/*---------------------------------
-  
-  qh_mergefacet( facet1, facet2, mindist, maxdist, mergeapex )
-    merges facet1 into facet2
-    mergeapex==qh_MERGEapex if merging new facet into coplanar horizon
-    
-  returns:
-    qh.max_outside and qh.min_vertex updated
-    initializes vertex neighbors on first merge
-
-  returns:
-    facet2 contains facet1's vertices, neighbors, and ridges
-      facet2 moved to end of qh.facet_list
-      makes facet2 a newfacet
-      sets facet2->newmerge set
-      clears facet2->center (unless merging into a large facet)
-      clears facet2->tested and ridge->tested for facet1
-
-    facet1 prepended to visible_list for later deletion and partitioning
-      facet1->f.replace == facet2
-
-    adds neighboring facets to facet_mergeset if redundant or degenerate
-
-  notes: 
-    mindist/maxdist may be NULL
-    traces merge if fmax_(maxdist,-mindist) > TRACEdist
-
-  see: 
-    qh_mergecycle()
-
-  design:
-    trace merge and check for degenerate simplex
-    make ridges for both facets
-    update qh.max_outside, qh.max_vertex, qh.min_vertex
-    update facet2->maxoutside and keepcentrum
-    update facet2->nummerge
-    update tested flags for facet2
-    if facet1 is simplicial
-      merge facet1 into facet2
-    else
-      merge facet1's neighbors into facet2
-      merge facet1's ridges into facet2
-      merge facet1's vertices into facet2
-      merge facet1's vertex neighbors into facet2
-      add facet2's vertices to qh.new_vertexlist
-      unless qh_MERGEapex
-        test facet2 for degenerate or redundant neighbors
-      move facet1 to qh.visible_list for later deletion
-      move facet2 to end of qh.newfacet_list
-*/
-void qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, boolT mergeapex) {
-  boolT traceonce= False;
-  vertexT *vertex, **vertexp;
-  int tracerestore=0, nummerge;
-
-  if (facet1->tricoplanar || facet2->tricoplanar) {
-    if (!qh TRInormals) {
-      fprintf (qh ferr, "qh_mergefacet: does not work for tricoplanar facets.  Use option 'Q11'\n");
-      qh_errexit2 (qh_ERRqhull, facet1, facet2);
-    }
-    if (facet2->tricoplanar) {
-      facet2->tricoplanar= False;
-      facet2->keepcentrum= False;
-    }
-  }
-  zzinc_(Ztotmerge);
-  if (qh REPORTfreq2 && qh POSTmerging) {
-    if (zzval_(Ztotmerge) > qh mergereport + qh REPORTfreq2)
-      qh_tracemerging();
-  }
-#ifndef qh_NOtrace
-  if (qh build_cnt >= qh RERUN) {
-    if (mindist && (-*mindist > qh TRACEdist || *maxdist > qh TRACEdist)) {
-      tracerestore= 0;
-      qh IStracing= qh TRACElevel;
-      traceonce= True;
-      fprintf (qh ferr, "qh_mergefacet: ========= trace wide merge #%d (%2.2g) for f%d into f%d, last point was p%d\n", zzval_(Ztotmerge),
-	     fmax_(-*mindist, *maxdist), facet1->id, facet2->id, qh furthest_id);
-    }else if (facet1 == qh tracefacet || facet2 == qh tracefacet) {
-      tracerestore= qh IStracing;
-      qh IStracing= 4;
-      traceonce= True;
-      fprintf (qh ferr, "qh_mergefacet: ========= trace merge #%d involving f%d, furthest is p%d\n",
-		 zzval_(Ztotmerge), qh tracefacet_id,  qh furthest_id);
-    }
-  }
-  if (qh IStracing >= 2) {
-    realT mergemin= -2;
-    realT mergemax= -2;
-    
-    if (mindist) {
-      mergemin= *mindist;
-      mergemax= *maxdist;
-    }
-    fprintf (qh ferr, "qh_mergefacet: #%d merge f%d into f%d, mindist= %2.2g, maxdist= %2.2g\n", 
-    zzval_(Ztotmerge), facet1->id, facet2->id, mergemin, mergemax);
-  }
-#endif /* !qh_NOtrace */
-  if (facet1 == facet2 || facet1->visible || facet2->visible) {
-    fprintf (qh ferr, "qhull internal error (qh_mergefacet): either f%d and f%d are the same or one is a visible facet\n",
-	     facet1->id, facet2->id);
-    qh_errexit2 (qh_ERRqhull, facet1, facet2);
-  }
-  if (qh num_facets - qh num_visible <= qh hull_dim + 1) {
-    fprintf(qh ferr, "\n\
-qhull precision error: Only %d facets remain.  Can not merge another\n\
-pair.  The input is too degenerate or the convexity constraints are\n\
-too strong.\n", qh hull_dim+1);
-    if (qh hull_dim >= 5 && !qh MERGEexact)
-      fprintf(qh ferr, "Option 'Qx' may avoid this problem.\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (!qh VERTEXneighbors)
-    qh_vertexneighbors();
-  qh_makeridges(facet1);
-  qh_makeridges(facet2);
-  if (qh IStracing >=4)
-    qh_errprint ("MERGING", facet1, facet2, NULL, NULL);
-  if (mindist) {
-    maximize_(qh max_outside, *maxdist);
-    maximize_(qh max_vertex, *maxdist);
-#if qh_MAXoutside
-    maximize_(facet2->maxoutside, *maxdist);
-#endif
-    minimize_(qh min_vertex, *mindist);
-    if (!facet2->keepcentrum 
-    && (*maxdist > qh WIDEfacet || *mindist < -qh WIDEfacet)) {
-      facet2->keepcentrum= True;
-      zinc_(Zwidefacet);
-    }
-  }
-  nummerge= facet1->nummerge + facet2->nummerge + 1;
-  if (nummerge >= qh_MAXnummerge) 
-    facet2->nummerge= qh_MAXnummerge;
-  else
-    facet2->nummerge= nummerge;
-  facet2->newmerge= True;
-  facet2->dupridge= False;
-  qh_updatetested  (facet1, facet2);
-  if (qh hull_dim > 2 && qh_setsize (facet1->vertices) == qh hull_dim)
-    qh_mergesimplex (facet1, facet2, mergeapex);
-  else {
-    qh vertex_visit++;
-    FOREACHvertex_(facet2->vertices)
-      vertex->visitid= qh vertex_visit;
-    if (qh hull_dim == 2) 
-      qh_mergefacet2d(facet1, facet2);
-    else {
-      qh_mergeneighbors(facet1, facet2);
-      qh_mergevertices(facet1->vertices, &facet2->vertices);
-    }
-    qh_mergeridges(facet1, facet2);
-    qh_mergevertex_neighbors(facet1, facet2);
-    if (!facet2->newfacet)
-      qh_newvertices (facet2->vertices);
-  }
-  if (!mergeapex)
-    qh_degen_redundant_neighbors (facet2, facet1);
-  if (facet2->coplanar || !facet2->newfacet) {
-    zinc_(Zmergeintohorizon);
-  }else if (!facet1->newfacet && facet2->newfacet) {
-    zinc_(Zmergehorizon);
-  }else {
-    zinc_(Zmergenew);
-  }
-  qh_willdelete (facet1, facet2);
-  qh_removefacet(facet2);  /* append as a newfacet to end of qh facet_list */
-  qh_appendfacet(facet2);
-  facet2->newfacet= True;
-  facet2->tested= False;
-  qh_tracemerge (facet1, facet2);
-  if (traceonce) {
-    fprintf (qh ferr, "qh_mergefacet: end of wide tracing\n");
-    qh IStracing= tracerestore;
-  }
-} /* mergefacet */
-
-
-/*---------------------------------
-  
-  qh_mergefacet2d( facet1, facet2 )
-    in 2d, merges neighbors and vertices of facet1 into facet2
-    
-  returns:
-    build ridges for neighbors if necessary
-    facet2 looks like a simplicial facet except for centrum, ridges
-      neighbors are opposite the corresponding vertex
-      maintains orientation of facet2
-
-  notes:
-    qh_mergefacet() retains non-simplicial structures
-      they are not needed in 2d, but later routines may use them
-    preserves qh.vertex_visit for qh_mergevertex_neighbors()
-  
-  design:
-    get vertices and neighbors
-    determine new vertices and neighbors
-    set new vertices and neighbors and adjust orientation
-    make ridges for new neighbor if needed
-*/
-void qh_mergefacet2d (facetT *facet1, facetT *facet2) {
-  vertexT *vertex1A, *vertex1B, *vertex2A, *vertex2B, *vertexA, *vertexB;
-  facetT *neighbor1A, *neighbor1B, *neighbor2A, *neighbor2B, *neighborA, *neighborB;
-
-  vertex1A= SETfirstt_(facet1->vertices, vertexT);
-  vertex1B= SETsecondt_(facet1->vertices, vertexT);
-  vertex2A= SETfirstt_(facet2->vertices, vertexT);
-  vertex2B= SETsecondt_(facet2->vertices, vertexT);
-  neighbor1A= SETfirstt_(facet1->neighbors, facetT);
-  neighbor1B= SETsecondt_(facet1->neighbors, facetT);
-  neighbor2A= SETfirstt_(facet2->neighbors, facetT);
-  neighbor2B= SETsecondt_(facet2->neighbors, facetT);
-  if (vertex1A == vertex2A) {
-    vertexA= vertex1B;
-    vertexB= vertex2B;
-    neighborA= neighbor2A;
-    neighborB= neighbor1A;
-  }else if (vertex1A == vertex2B) {
-    vertexA= vertex1B;
-    vertexB= vertex2A;
-    neighborA= neighbor2B;
-    neighborB= neighbor1A;
-  }else if (vertex1B == vertex2A) {
-    vertexA= vertex1A;
-    vertexB= vertex2B;
-    neighborA= neighbor2A;
-    neighborB= neighbor1B;
-  }else { /* 1B == 2B */
-    vertexA= vertex1A;
-    vertexB= vertex2A;
-    neighborA= neighbor2B;
-    neighborB= neighbor1B;
-  }
-  /* vertexB always from facet2, neighborB always from facet1 */
-  if (vertexA->id > vertexB->id) {
-    SETfirst_(facet2->vertices)= vertexA;
-    SETsecond_(facet2->vertices)= vertexB;
-    if (vertexB == vertex2A)
-      facet2->toporient= !facet2->toporient;
-    SETfirst_(facet2->neighbors)= neighborA;
-    SETsecond_(facet2->neighbors)= neighborB;
-  }else {
-    SETfirst_(facet2->vertices)= vertexB;
-    SETsecond_(facet2->vertices)= vertexA;
-    if (vertexB == vertex2B)
-      facet2->toporient= !facet2->toporient;
-    SETfirst_(facet2->neighbors)= neighborB;
-    SETsecond_(facet2->neighbors)= neighborA;
-  }
-  qh_makeridges (neighborB);
-  qh_setreplace(neighborB->neighbors, facet1, facet2);
-  trace4((qh ferr, "qh_mergefacet2d: merged v%d and neighbor f%d of f%d into f%d\n",
-       vertexA->id, neighborB->id, facet1->id, facet2->id));
-} /* mergefacet2d */
-
-
-/*---------------------------------
-  
-  qh_mergeneighbors( facet1, facet2 )
-    merges the neighbors of facet1 into facet2
-
-  see: 
-    qh_mergecycle_neighbors()
-
-  design:
-    for each neighbor of facet1
-      if neighbor is also a neighbor of facet2
-        if neighbor is simpilicial
-          make ridges for later deletion as a degenerate facet
-        update its neighbor set
-      else
-        move the neighbor relation to facet2
-    remove the neighbor relation for facet1 and facet2
-*/
-void qh_mergeneighbors(facetT *facet1, facetT *facet2) {
-  facetT *neighbor, **neighborp;
-
-  trace4((qh ferr, "qh_mergeneighbors: merge neighbors of f%d and f%d\n",
-	  facet1->id, facet2->id));
-  qh visit_id++;
-  FOREACHneighbor_(facet2) {
-    neighbor->visitid= qh visit_id;
-  }
-  FOREACHneighbor_(facet1) {
-    if (neighbor->visitid == qh visit_id) {
-      if (neighbor->simplicial)    /* is degen, needs ridges */
-	qh_makeridges (neighbor);
-      if (SETfirstt_(neighbor->neighbors, facetT) != facet1) /*keep newfacet->horizon*/
-	qh_setdel (neighbor->neighbors, facet1);
-      else {
-        qh_setdel(neighbor->neighbors, facet2);
-        qh_setreplace(neighbor->neighbors, facet1, facet2);
-      }
-    }else if (neighbor != facet2) {
-      qh_setappend(&(facet2->neighbors), neighbor);
-      qh_setreplace(neighbor->neighbors, facet1, facet2);
-    }
-  }
-  qh_setdel(facet1->neighbors, facet2);  /* here for makeridges */
-  qh_setdel(facet2->neighbors, facet1);
-} /* mergeneighbors */
-
-
-/*---------------------------------
-  
-  qh_mergeridges( facet1, facet2 )
-    merges the ridge set of facet1 into facet2
-
-  returns:
-    may delete all ridges for a vertex
-    sets vertex->delridge on deleted ridges
-
-  see:
-    qh_mergecycle_ridges()
-
-  design:
-    delete ridges between facet1 and facet2
-      mark (delridge) vertices on these ridges for later testing   
-    for each remaining ridge
-      rename facet1 to facet2  
-*/
-void qh_mergeridges(facetT *facet1, facetT *facet2) {
-  ridgeT *ridge, **ridgep;
-  vertexT *vertex, **vertexp;
-
-  trace4((qh ferr, "qh_mergeridges: merge ridges of f%d and f%d\n",
-	  facet1->id, facet2->id));
-  FOREACHridge_(facet2->ridges) {
-    if ((ridge->top == facet1) || (ridge->bottom == facet1)) {
-      FOREACHvertex_(ridge->vertices)
-        vertex->delridge= True;
-      qh_delridge(ridge);  /* expensive in high-d, could rebuild */
-      ridgep--; /*repeat*/
-    }
-  }
-  FOREACHridge_(facet1->ridges) {
-    if (ridge->top == facet1)
-      ridge->top= facet2;
-    else
-      ridge->bottom= facet2;
-    qh_setappend(&(facet2->ridges), ridge);
-  }
-} /* mergeridges */
-
-
-/*---------------------------------
-  
-  qh_mergesimplex( facet1, facet2, mergeapex )
-    merge simplicial facet1 into facet2
-    mergeapex==qh_MERGEapex if merging samecycle into horizon facet
-      vertex id is latest (most recently created)
-    facet1 may be contained in facet2
-    ridges exist for both facets
-
-  returns:
-    facet2 with updated vertices, ridges, neighbors
-    updated neighbors for facet1's vertices
-    facet1 not deleted
-    sets vertex->delridge on deleted ridges
-  
-  notes:
-    special case code since this is the most common merge
-    called from qh_mergefacet()
-
-  design:
-    if qh_MERGEapex
-      add vertices of facet2 to qh.new_vertexlist if necessary
-      add apex to facet2
-    else
-      for each ridge between facet1 and facet2
-        set vertex->delridge
-      determine the apex for facet1 (i.e., vertex to be merged)
-      unless apex already in facet2
-        insert apex into vertices for facet2
-      add vertices of facet2 to qh.new_vertexlist if necessary
-      add apex to qh.new_vertexlist if necessary
-      for each vertex of facet1
-        if apex
-          rename facet1 to facet2 in its vertex neighbors
-        else
-          delete facet1 from vertex neighors
-          if only in facet2
-            add vertex to qh.del_vertices for later deletion
-      for each ridge of facet1
-        delete ridges between facet1 and facet2
-        append other ridges to facet2 after renaming facet to facet2
-*/
-void qh_mergesimplex(facetT *facet1, facetT *facet2, boolT mergeapex) {
-  vertexT *vertex, **vertexp, *apex;
-  ridgeT *ridge, **ridgep;
-  boolT issubset= False;
-  int vertex_i= -1, vertex_n;
-  facetT *neighbor, **neighborp, *otherfacet;
-
-  if (mergeapex) {
-    if (!facet2->newfacet)
-      qh_newvertices (facet2->vertices);  /* apex is new */
-    apex= SETfirstt_(facet1->vertices, vertexT);
-    if (SETfirstt_(facet2->vertices, vertexT) != apex) 
-      qh_setaddnth (&facet2->vertices, 0, apex);  /* apex has last id */
-    else
-      issubset= True;
-  }else {
-    zinc_(Zmergesimplex);
-    FOREACHvertex_(facet1->vertices)
-      vertex->seen= False;
-    FOREACHridge_(facet1->ridges) {
-      if (otherfacet_(ridge, facet1) == facet2) {
-	FOREACHvertex_(ridge->vertices) {
-	  vertex->seen= True;
-	  vertex->delridge= True;
-	}
-	break;
-      }
-    }
-    FOREACHvertex_(facet1->vertices) {
-      if (!vertex->seen)
-	break;  /* must occur */
-    }
-    apex= vertex;
-    trace4((qh ferr, "qh_mergesimplex: merge apex v%d of f%d into facet f%d\n",
-	  apex->id, facet1->id, facet2->id));
-    FOREACHvertex_i_(facet2->vertices) {
-      if (vertex->id < apex->id) {
-	break;
-      }else if (vertex->id == apex->id) {
-	issubset= True;
-	break;
-      }
-    }
-    if (!issubset)
-      qh_setaddnth (&facet2->vertices, vertex_i, apex);
-    if (!facet2->newfacet)
-      qh_newvertices (facet2->vertices);
-    else if (!apex->newlist) {
-      qh_removevertex (apex);
-      qh_appendvertex (apex);
-    }
-  }
-  trace4((qh ferr, "qh_mergesimplex: update vertex neighbors of f%d\n",
-	  facet1->id));
-  FOREACHvertex_(facet1->vertices) {
-    if (vertex == apex && !issubset)
-      qh_setreplace (vertex->neighbors, facet1, facet2);
-    else {
-      qh_setdel (vertex->neighbors, facet1);
-      if (!SETsecond_(vertex->neighbors))
-	qh_mergevertex_del (vertex, facet1, facet2);
-    }
-  }
-  trace4((qh ferr, "qh_mergesimplex: merge ridges and neighbors of f%d into f%d\n",
-	  facet1->id, facet2->id));
-  qh visit_id++;
-  FOREACHneighbor_(facet2)
-    neighbor->visitid= qh visit_id;
-  FOREACHridge_(facet1->ridges) {
-    otherfacet= otherfacet_(ridge, facet1);
-    if (otherfacet == facet2) {
-      qh_setdel (facet2->ridges, ridge);
-      qh_setfree(&(ridge->vertices)); 
-      qh_memfree (ridge, sizeof(ridgeT));
-      qh_setdel (facet2->neighbors, facet1);
-    }else {
-      qh_setappend (&facet2->ridges, ridge);
-      if (otherfacet->visitid != qh visit_id) {
-	qh_setappend (&facet2->neighbors, otherfacet);
-	qh_setreplace (otherfacet->neighbors, facet1, facet2);
-	otherfacet->visitid= qh visit_id;
-      }else {
-	if (otherfacet->simplicial)    /* is degen, needs ridges */
-	  qh_makeridges (otherfacet);
-	if (SETfirstt_(otherfacet->neighbors, facetT) != facet1)
-	  qh_setdel (otherfacet->neighbors, facet1);
-	else {   /*keep newfacet->neighbors->horizon*/
-	  qh_setdel(otherfacet->neighbors, facet2);
-	  qh_setreplace(otherfacet->neighbors, facet1, facet2);
-	}
-      }
-      if (ridge->top == facet1) /* wait until after qh_makeridges */
-	ridge->top= facet2;
-      else 
-	ridge->bottom= facet2;
-    }
-  }
-  SETfirst_(facet1->ridges)= NULL; /* it will be deleted */
-  trace3((qh ferr, "qh_mergesimplex: merged simplex f%d apex v%d into facet f%d\n",
-	  facet1->id, getid_(apex), facet2->id));
-} /* mergesimplex */
-
-/*---------------------------------
-  
-  qh_mergevertex_del( vertex, facet1, facet2 )
-    delete a vertex because of merging facet1 into facet2
-
-  returns:
-    deletes vertex from facet2
-    adds vertex to qh.del_vertices for later deletion 
-*/
-void qh_mergevertex_del (vertexT *vertex, facetT *facet1, facetT *facet2) {
-
-  zinc_(Zmergevertex);
-  trace2((qh ferr, "qh_mergevertex_del: deleted v%d when merging f%d into f%d\n",
-          vertex->id, facet1->id, facet2->id));
-  qh_setdelsorted (facet2->vertices, vertex);
-  vertex->deleted= True;
-  qh_setappend (&qh del_vertices, vertex);
-} /* mergevertex_del */
-
-/*---------------------------------
-  
-  qh_mergevertex_neighbors( facet1, facet2 )
-    merge the vertex neighbors of facet1 to facet2
-
-  returns:
-    if vertex is current qh.vertex_visit
-      deletes facet1 from vertex->neighbors
-    else
-      renames facet1 to facet2 in vertex->neighbors 
-    deletes vertices if only one neighbor
-  
-  notes:
-    assumes vertex neighbor sets are good
-*/
-void qh_mergevertex_neighbors(facetT *facet1, facetT *facet2) {
-  vertexT *vertex, **vertexp;
-
-  trace4((qh ferr, "qh_mergevertex_neighbors: merge vertex neighbors of f%d and f%d\n",
-	  facet1->id, facet2->id));
-  if (qh tracevertex) {
-    fprintf (qh ferr, "qh_mergevertex_neighbors: of f%d and f%d at furthest p%d f0= %p\n",
-	     facet1->id, facet2->id, qh furthest_id, qh tracevertex->neighbors->e[0].p);
-    qh_errprint ("TRACE", NULL, NULL, NULL, qh tracevertex);
-  }
-  FOREACHvertex_(facet1->vertices) {
-    if (vertex->visitid != qh vertex_visit) 
-      qh_setreplace(vertex->neighbors, facet1, facet2);
-    else {
-      qh_setdel(vertex->neighbors, facet1);
-      if (!SETsecond_(vertex->neighbors))
-	qh_mergevertex_del (vertex, facet1, facet2);
-    }
-  }
-  if (qh tracevertex) 
-    qh_errprint ("TRACE", NULL, NULL, NULL, qh tracevertex);
-} /* mergevertex_neighbors */
-
-
-/*---------------------------------
-  
-  qh_mergevertices( vertices1, vertices2 )
-    merges the vertex set of facet1 into facet2
-
-  returns:
-    replaces vertices2 with merged set
-    preserves vertex_visit for qh_mergevertex_neighbors
-    updates qh.newvertex_list
-
-  design:
-    create a merged set of both vertices (in inverse id order)
-*/
-void qh_mergevertices(setT *vertices1, setT **vertices2) {
-  int newsize= qh_setsize(vertices1)+qh_setsize(*vertices2) - qh hull_dim + 1;
-  setT *mergedvertices;
-  vertexT *vertex, **vertexp, **vertex2= SETaddr_(*vertices2, vertexT);
-
-  mergedvertices= qh_settemp (newsize);
-  FOREACHvertex_(vertices1) {
-    if (!*vertex2 || vertex->id > (*vertex2)->id)
-      qh_setappend (&mergedvertices, vertex);
-    else {
-      while (*vertex2 && (*vertex2)->id > vertex->id)
-	qh_setappend (&mergedvertices, *vertex2++);
-      if (!*vertex2 || (*vertex2)->id < vertex->id)
-	qh_setappend (&mergedvertices, vertex);
-      else
-	qh_setappend (&mergedvertices, *vertex2++);
-    }
-  }
-  while (*vertex2)
-    qh_setappend (&mergedvertices, *vertex2++);
-  if (newsize < qh_setsize (mergedvertices)) {
-    fprintf (qh ferr, "qhull internal error (qh_mergevertices): facets did not share a ridge\n");
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-  qh_setfree(vertices2);
-  *vertices2= mergedvertices;
-  qh_settemppop ();
-} /* mergevertices */
-
-
-/*---------------------------------
-  
-  qh_neighbor_intersections( vertex )
-    return intersection of all vertices in vertex->neighbors except for vertex
-
-  returns:
-    returns temporary set of vertices
-    does not include vertex
-    NULL if a neighbor is simplicial
-    NULL if empty set
-    
-  notes:
-    used for renaming vertices
-
-  design:
-    initialize the intersection set with vertices of the first two neighbors
-    delete vertex from the intersection
-    for each remaining neighbor
-      intersect its vertex set with the intersection set
-      return NULL if empty
-    return the intersection set  
-*/
-setT *qh_neighbor_intersections (vertexT *vertex) {
-  facetT *neighbor, **neighborp, *neighborA, *neighborB;
-  setT *intersect;
-  int neighbor_i, neighbor_n;
-
-  FOREACHneighbor_(vertex) {
-    if (neighbor->simplicial)
-      return NULL;
-  }
-  neighborA= SETfirstt_(vertex->neighbors, facetT);
-  neighborB= SETsecondt_(vertex->neighbors, facetT);
-  zinc_(Zintersectnum);
-  if (!neighborA)
-    return NULL;
-  if (!neighborB)
-    intersect= qh_setcopy (neighborA->vertices, 0);
-  else
-    intersect= qh_vertexintersect_new (neighborA->vertices, neighborB->vertices);
-  qh_settemppush (intersect);
-  qh_setdelsorted (intersect, vertex);
-  FOREACHneighbor_i_(vertex) {
-    if (neighbor_i >= 2) {
-      zinc_(Zintersectnum);
-      qh_vertexintersect (&intersect, neighbor->vertices);
-      if (!SETfirst_(intersect)) {
-        zinc_(Zintersectfail);
-        qh_settempfree (&intersect);
-        return NULL;
-      }
-    }
-  }
-  trace3((qh ferr, "qh_neighbor_intersections: %d vertices in neighbor intersection of v%d\n", 
-          qh_setsize (intersect), vertex->id));
-  return intersect;
-} /* neighbor_intersections */
-
-/*---------------------------------
-  
-  qh_newvertices( vertices )
-    add vertices to end of qh.vertex_list (marks as new vertices)
-
-  returns:
-    vertices on qh.newvertex_list
-    vertex->newlist set
-*/
-void qh_newvertices (setT *vertices) {
-  vertexT *vertex, **vertexp;
-
-  FOREACHvertex_(vertices) {
-    if (!vertex->newlist) {
-      qh_removevertex (vertex);
-      qh_appendvertex (vertex);
-    }
-  }
-} /* newvertices */
-
-/*---------------------------------
-  
-  qh_reducevertices()
-    reduce extra vertices, shared vertices, and redundant vertices
-    facet->newmerge is set if merged since last call
-    if !qh.MERGEvertices, only removes extra vertices
-
-  returns:
-    True if also merged degen_redundant facets
-    vertices are renamed if possible
-    clears facet->newmerge and vertex->delridge
-
-  notes:
-    ignored if 2-d
-
-  design:
-    merge any degenerate or redundant facets
-    for each newly merged facet
-      remove extra vertices
-    if qh.MERGEvertices
-      for each newly merged facet
-        for each vertex
-          if vertex was on a deleted ridge
-            rename vertex if it is shared
-      remove delridge flag from new vertices
-*/
-boolT qh_reducevertices (void) {
-  int numshare=0, numrename= 0;
-  boolT degenredun= False;
-  facetT *newfacet;
-  vertexT *vertex, **vertexp;
-
-  if (qh hull_dim == 2) 
-    return False;
-  if (qh_merge_degenredundant())
-    degenredun= True;
- LABELrestart:
-  FORALLnew_facets {
-    if (newfacet->newmerge) { 
-      if (!qh MERGEvertices)
-        newfacet->newmerge= False;
-      qh_remove_extravertices (newfacet);
-    }
-  }
-  if (!qh MERGEvertices)
-    return False;
-  FORALLnew_facets {
-    if (newfacet->newmerge) {
-      newfacet->newmerge= False;
-      FOREACHvertex_(newfacet->vertices) {
-	if (vertex->delridge) {
-	  if (qh_rename_sharedvertex (vertex, newfacet)) {
-	    numshare++;
-	    vertexp--; /* repeat since deleted vertex */
-	  }
-        }
-      }
-    }
-  }
-  FORALLvertex_(qh newvertex_list) {
-    if (vertex->delridge && !vertex->deleted) {
-      vertex->delridge= False;
-      if (qh hull_dim >= 4 && qh_redundant_vertex (vertex)) {
-	numrename++;
-	if (qh_merge_degenredundant()) {
-	  degenredun= True;
-	  goto LABELrestart;
-	}
-      }
-    }
-  }
-  trace1((qh ferr, "qh_reducevertices: renamed %d shared vertices and %d redundant vertices. Degen? %d\n",
-	  numshare, numrename, degenredun));
-  return degenredun;
-} /* reducevertices */
-      
-/*---------------------------------
-  
-  qh_redundant_vertex( vertex )
-    detect and rename a redundant vertex
-    vertices have full vertex->neighbors 
-
-  returns:
-    returns true if find a redundant vertex
-      deletes vertex (vertex->deleted)
-  
-  notes:
-    only needed if vertex->delridge and hull_dim >= 4
-    may add degenerate facets to qh.facet_mergeset
-    doesn't change vertex->neighbors or create redundant facets
-
-  design:
-    intersect vertices of all facet neighbors of vertex
-    determine ridges for these vertices
-    if find a new vertex for vertex amoung these ridges and vertices
-      rename vertex to the new vertex
-*/
-vertexT *qh_redundant_vertex (vertexT *vertex) {
-  vertexT *newvertex= NULL;
-  setT *vertices, *ridges;
-
-  trace3((qh ferr, "qh_redundant_vertex: check if v%d can be renamed\n", vertex->id));  
-  if ((vertices= qh_neighbor_intersections (vertex))) {
-    ridges= qh_vertexridges (vertex);
-    if ((newvertex= qh_find_newvertex (vertex, vertices, ridges)))
-      qh_renamevertex (vertex, newvertex, ridges, NULL, NULL);
-    qh_settempfree (&ridges);
-    qh_settempfree (&vertices);
-  }
-  return newvertex;
-} /* redundant_vertex */
-
-/*---------------------------------
-  
-  qh_remove_extravertices( facet )
-    remove extra vertices from non-simplicial facets
-
-  returns:
-    returns True if it finds them
-
-  design:
-    for each vertex in facet
-      if vertex not in a ridge (i.e., no longer used)
-        delete vertex from facet
-        delete facet from vertice's neighbors
-        unless vertex in another facet
-          add vertex to qh.del_vertices for later deletion
-*/
-boolT qh_remove_extravertices (facetT *facet) {
-  ridgeT *ridge, **ridgep;
-  vertexT *vertex, **vertexp;
-  boolT foundrem= False;
-
-  trace4((qh ferr, "qh_remove_extravertices: test f%d for extra vertices\n",
-	  facet->id));
-  FOREACHvertex_(facet->vertices)
-    vertex->seen= False;
-  FOREACHridge_(facet->ridges) { 
-    FOREACHvertex_(ridge->vertices)
-      vertex->seen= True;
-  }
-  FOREACHvertex_(facet->vertices) {
-    if (!vertex->seen) {
-      foundrem= True;
-      zinc_(Zremvertex);
-      qh_setdelsorted (facet->vertices, vertex);
-      qh_setdel (vertex->neighbors, facet);
-      if (!qh_setsize (vertex->neighbors)) {
-	vertex->deleted= True;
-	qh_setappend (&qh del_vertices, vertex);
-	zinc_(Zremvertexdel);
-	trace2((qh ferr, "qh_remove_extravertices: v%d deleted because it's lost all ridges\n", vertex->id));
-      }else
-	trace3((qh ferr, "qh_remove_extravertices: v%d removed from f%d because it's lost all ridges\n", vertex->id, facet->id));
-      vertexp--; /*repeat*/
-    }
-  }
-  return foundrem;
-} /* remove_extravertices */
-
-/*---------------------------------
-  
-  qh_rename_sharedvertex( vertex, facet )
-    detect and rename if shared vertex in facet
-    vertices have full ->neighbors
-
-  returns:
-    newvertex or NULL
-    the vertex may still exist in other facets (i.e., a neighbor was pinched)
-    does not change facet->neighbors
-    updates vertex->neighbors
-  
-  notes:
-    a shared vertex for a facet is only in ridges to one neighbor
-    this may undo a pinched facet
- 
-    it does not catch pinches involving multiple facets.  These appear
-      to be difficult to detect, since an exhaustive search is too expensive.
-
-  design:
-    if vertex only has two neighbors
-      determine the ridges that contain the vertex
-      determine the vertices shared by both neighbors
-      if can find a new vertex in this set
-        rename the vertex to the new vertex
-*/
-vertexT *qh_rename_sharedvertex (vertexT *vertex, facetT *facet) {
-  facetT *neighbor, **neighborp, *neighborA= NULL;
-  setT *vertices, *ridges;
-  vertexT *newvertex;
-
-  if (qh_setsize (vertex->neighbors) == 2) {
-    neighborA= SETfirstt_(vertex->neighbors, facetT);
-    if (neighborA == facet)
-      neighborA= SETsecondt_(vertex->neighbors, facetT);
-  }else if (qh hull_dim == 3)
-    return NULL;
-  else {
-    qh visit_id++;
-    FOREACHneighbor_(facet)
-      neighbor->visitid= qh visit_id;
-    FOREACHneighbor_(vertex) {
-      if (neighbor->visitid == qh visit_id) {
-        if (neighborA)
-          return NULL;
-        neighborA= neighbor;
-      }
-    }
-    if (!neighborA) {
-      fprintf (qh ferr, "qhull internal error (qh_rename_sharedvertex): v%d's neighbors not in f%d\n",
-        vertex->id, facet->id);
-      qh_errprint ("ERRONEOUS", facet, NULL, NULL, vertex);
-      qh_errexit (qh_ERRqhull, NULL, NULL);
-    }
-  }
-  /* the vertex is shared by facet and neighborA */
-  ridges= qh_settemp (qh TEMPsize);
-  neighborA->visitid= ++qh visit_id;
-  qh_vertexridges_facet (vertex, facet, &ridges);
-  trace2((qh ferr, "qh_rename_sharedvertex: p%d (v%d) is shared by f%d (%d ridges) and f%d\n",
-    qh_pointid(vertex->point), vertex->id, facet->id, qh_setsize (ridges), neighborA->id));
-  zinc_(Zintersectnum);
-  vertices= qh_vertexintersect_new (facet->vertices, neighborA->vertices);
-  qh_setdel (vertices, vertex);
-  qh_settemppush (vertices);
-  if ((newvertex= qh_find_newvertex (vertex, vertices, ridges))) 
-    qh_renamevertex (vertex, newvertex, ridges, facet, neighborA);
-  qh_settempfree (&vertices);
-  qh_settempfree (&ridges);
-  return newvertex;
-} /* rename_sharedvertex */
-
-/*---------------------------------
-  
-  qh_renameridgevertex( ridge, oldvertex, newvertex )
-    renames oldvertex as newvertex in ridge
-
-  returns:
-  
-  design:
-    delete oldvertex from ridge
-    if newvertex already in ridge
-      copy ridge->noconvex to another ridge if possible
-      delete the ridge
-    else
-      insert newvertex into the ridge
-      adjust the ridge's orientation
-*/
-void qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex) {
-  int nth= 0, oldnth;
-  facetT *temp;
-  vertexT *vertex, **vertexp;
-
-  oldnth= qh_setindex (ridge->vertices, oldvertex);
-  qh_setdelnthsorted (ridge->vertices, oldnth);
-  FOREACHvertex_(ridge->vertices) {
-    if (vertex == newvertex) {
-      zinc_(Zdelridge);
-      if (ridge->nonconvex) /* only one ridge has nonconvex set */
-	qh_copynonconvex (ridge);
-      qh_delridge (ridge);
-      trace2((qh ferr, "qh_renameridgevertex: ridge r%d deleted.  It contained both v%d and v%d\n",
-        ridge->id, oldvertex->id, newvertex->id));
-      return;
-    }
-    if (vertex->id < newvertex->id)
-      break;
-    nth++;
-  }
-  qh_setaddnth(&ridge->vertices, nth, newvertex);
-  if (abs(oldnth - nth)%2) {
-    trace3((qh ferr, "qh_renameridgevertex: swapped the top and bottom of ridge r%d\n", 
-	    ridge->id));
-    temp= ridge->top;
-    ridge->top= ridge->bottom;
-    ridge->bottom= temp;
-  }
-} /* renameridgevertex */
-
-
-/*---------------------------------
-  
-  qh_renamevertex( oldvertex, newvertex, ridges, oldfacet, neighborA )
-    renames oldvertex as newvertex in ridges 
-    gives oldfacet/neighborA if oldvertex is shared between two facets
-
-  returns:
-    oldvertex may still exist afterwards
-    
-
-  notes:
-    can not change neighbors of newvertex (since it's a subset)
-
-  design:
-    for each ridge in ridges
-      rename oldvertex to newvertex and delete degenerate ridges
-    if oldfacet not defined
-      for each neighbor of oldvertex
-        delete oldvertex from neighbor's vertices
-        remove extra vertices from neighbor
-      add oldvertex to qh.del_vertices
-    else if oldvertex only between oldfacet and neighborA
-      delete oldvertex from oldfacet and neighborA
-      add oldvertex to qh.del_vertices
-    else oldvertex is in oldfacet and neighborA and other facets (i.e., pinched)
-      delete oldvertex from oldfacet
-      delete oldfacet from oldvertice's neighbors
-      remove extra vertices (e.g., oldvertex) from neighborA
-*/
-void qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges, facetT *oldfacet, facetT *neighborA) {
-  facetT *neighbor, **neighborp;
-  ridgeT *ridge, **ridgep;
-  boolT istrace= False;
-
-  if (qh IStracing >= 2 || oldvertex->id == qh tracevertex_id ||
-	newvertex->id == qh tracevertex_id)
-    istrace= True;
-  FOREACHridge_(ridges) 
-    qh_renameridgevertex (ridge, oldvertex, newvertex);
-  if (!oldfacet) {
-    zinc_(Zrenameall);
-    if (istrace)
-      fprintf (qh ferr, "qh_renamevertex: renamed v%d to v%d in several facets\n",
-               oldvertex->id, newvertex->id);
-    FOREACHneighbor_(oldvertex) {
-      qh_maydropneighbor (neighbor);
-      qh_setdelsorted (neighbor->vertices, oldvertex);
-      if (qh_remove_extravertices (neighbor))
-        neighborp--; /* neighbor may be deleted */
-    }
-    if (!oldvertex->deleted) {
-      oldvertex->deleted= True;
-      qh_setappend (&qh del_vertices, oldvertex);
-    }
-  }else if (qh_setsize (oldvertex->neighbors) == 2) {
-    zinc_(Zrenameshare);
-    if (istrace)
-      fprintf (qh ferr, "qh_renamevertex: renamed v%d to v%d in oldfacet f%d\n", 
-               oldvertex->id, newvertex->id, oldfacet->id);
-    FOREACHneighbor_(oldvertex)
-      qh_setdelsorted (neighbor->vertices, oldvertex);
-    oldvertex->deleted= True;
-    qh_setappend (&qh del_vertices, oldvertex);
-  }else {
-    zinc_(Zrenamepinch);
-    if (istrace || qh IStracing)
-      fprintf (qh ferr, "qh_renamevertex: renamed pinched v%d to v%d between f%d and f%d\n", 
-               oldvertex->id, newvertex->id, oldfacet->id, neighborA->id);
-    qh_setdelsorted (oldfacet->vertices, oldvertex);
-    qh_setdel (oldvertex->neighbors, oldfacet);
-    qh_remove_extravertices (neighborA);
-  }
-} /* renamevertex */
-
-
-/*---------------------------------
-  
-  qh_test_appendmerge( facet, neighbor )
-    tests facet/neighbor for convexity
-    appends to mergeset if non-convex
-    if pre-merging, 
-      nop if qh.SKIPconvex, or qh.MERGEexact and coplanar
-
-  returns:
-    true if appends facet/neighbor to mergeset
-    sets facet->center as needed
-    does not change facet->seen
-
-  design:
-    if qh.cos_max is defined
-      if the angle between facet normals is too shallow
-        append an angle-coplanar merge to qh.mergeset
-        return True
-    make facet's centrum if needed
-    if facet's centrum is above the neighbor
-      set isconcave
-    else
-      if facet's centrum is not below the neighbor
-        set iscoplanar
-      make neighbor's centrum if needed
-      if neighbor's centrum is above the facet
-        set isconcave
-      else if neighbor's centrum is not below the facet
-        set iscoplanar
-   if isconcave or iscoplanar
-     get angle if needed
-     append concave or coplanar merge to qh.mergeset
-*/
-boolT qh_test_appendmerge (facetT *facet, facetT *neighbor) {
-  realT dist, dist2= -REALmax, angle= -REALmax;
-  boolT isconcave= False, iscoplanar= False, okangle= False;
-
-  if (qh SKIPconvex && !qh POSTmerging)
-    return False;
-  if ((!qh MERGEexact || qh POSTmerging) && qh cos_max < REALmax/2) {
-    angle= qh_getangle(facet->normal, neighbor->normal);
-    zinc_(Zangletests);
-    if (angle > qh cos_max) {
-      zinc_(Zcoplanarangle);
-      qh_appendmergeset(facet, neighbor, MRGanglecoplanar, &angle);
-      trace2((qh ferr, "qh_test_appendmerge: coplanar angle %4.4g between f%d and f%d\n",
-         angle, facet->id, neighbor->id));
-      return True;
-    }else
-      okangle= True;
-  }
-  if (!facet->center)
-    facet->center= qh_getcentrum (facet);
-  zzinc_(Zcentrumtests);
-  qh_distplane(facet->center, neighbor, &dist);
-  if (dist > qh centrum_radius)
-    isconcave= True;
-  else {
-    if (dist > -qh centrum_radius)
-      iscoplanar= True;
-    if (!neighbor->center)
-      neighbor->center= qh_getcentrum (neighbor);
-    zzinc_(Zcentrumtests);
-    qh_distplane(neighbor->center, facet, &dist2);
-    if (dist2 > qh centrum_radius)
-      isconcave= True;
-    else if (!iscoplanar && dist2 > -qh centrum_radius)
-      iscoplanar= True;
-  }
-  if (!isconcave && (!iscoplanar || (qh MERGEexact && !qh POSTmerging)))
-    return False;
-  if (!okangle && qh ANGLEmerge) {
-    angle= qh_getangle(facet->normal, neighbor->normal);
-    zinc_(Zangletests);
-  }
-  if (isconcave) {
-    zinc_(Zconcaveridge);
-    if (qh ANGLEmerge)
-      angle += qh_ANGLEconcave + 0.5;
-    qh_appendmergeset(facet, neighbor, MRGconcave, &angle);
-    trace0((qh ferr, "qh_test_appendmerge: concave f%d to f%d dist %4.4g and reverse dist %4.4g angle %4.4g during p%d\n",
-	   facet->id, neighbor->id, dist, dist2, angle, qh furthest_id));
-  }else /* iscoplanar */ {
-    zinc_(Zcoplanarcentrum);
-    qh_appendmergeset(facet, neighbor, MRGcoplanar, &angle);
-    trace2((qh ferr, "qh_test_appendmerge: coplanar f%d to f%d dist %4.4g, reverse dist %4.4g angle %4.4g\n",
-	      facet->id, neighbor->id, dist, dist2, angle));
-  }
-  return True;
-} /* test_appendmerge */
-
-/*---------------------------------
-  
-  qh_test_vneighbors()
-    test vertex neighbors for convexity
-    tests all facets on qh.newfacet_list
-
-  returns:
-    true if non-convex vneighbors appended to qh.facet_mergeset
-    initializes vertex neighbors if needed
-
-  notes:
-    assumes all facet neighbors have been tested
-    this can be expensive
-    this does not guarantee that a centrum is below all facets
-      but it is unlikely
-    uses qh.visit_id
-
-  design:
-    build vertex neighbors if necessary
-    for all new facets
-      for all vertices
-        for each unvisited facet neighbor of the vertex
-          test new facet and neighbor for convexity
-*/
-boolT qh_test_vneighbors (void /* qh newfacet_list */) {
-  facetT *newfacet, *neighbor, **neighborp;
-  vertexT *vertex, **vertexp;
-  int nummerges= 0;
-
-  trace1((qh ferr, "qh_test_vneighbors: testing vertex neighbors for convexity\n"));
-  if (!qh VERTEXneighbors)
-    qh_vertexneighbors();
-  FORALLnew_facets 
-    newfacet->seen= False;
-  FORALLnew_facets {
-    newfacet->seen= True;
-    newfacet->visitid= qh visit_id++;
-    FOREACHneighbor_(newfacet)
-      newfacet->visitid= qh visit_id;
-    FOREACHvertex_(newfacet->vertices) {
-      FOREACHneighbor_(vertex) {
-      	if (neighbor->seen || neighbor->visitid == qh visit_id)
-      	  continue;
-      	if (qh_test_appendmerge (newfacet, neighbor))
-          nummerges++;
-      }
-    }
-  }
-  zadd_(Ztestvneighbor, nummerges);
-  trace1((qh ferr, "qh_test_vneighbors: found %d non-convex, vertex neighbors\n",
-           nummerges));
-  return (nummerges > 0);    
-} /* test_vneighbors */
-
-/*---------------------------------
-  
-  qh_tracemerge( facet1, facet2 )
-    print trace message after merge
-*/
-void qh_tracemerge (facetT *facet1, facetT *facet2) {
-  boolT waserror= False;
-
-#ifndef qh_NOtrace
-  if (qh IStracing >= 4) 
-    qh_errprint ("MERGED", facet2, NULL, NULL, NULL);
-  if (facet2 == qh tracefacet || (qh tracevertex && qh tracevertex->newlist)) {
-    fprintf (qh ferr, "qh_tracemerge: trace facet and vertex after merge of f%d and f%d, furthest p%d\n", facet1->id, facet2->id, qh furthest_id);
-    if (facet2 != qh tracefacet)
-      qh_errprint ("TRACE", qh tracefacet, 
-        (qh tracevertex && qh tracevertex->neighbors) ? 
-           SETfirstt_(qh tracevertex->neighbors, facetT) : NULL,
-        NULL, qh tracevertex);      
-  }
-  if (qh tracevertex) {
-    if (qh tracevertex->deleted)
-      fprintf (qh ferr, "qh_tracemerge: trace vertex deleted at furthest p%d\n",
-	    qh furthest_id);
-    else
-      qh_checkvertex (qh tracevertex);
-  }
-  if (qh tracefacet) {
-    qh_checkfacet (qh tracefacet, True, &waserror);
-    if (waserror)
-      qh_errexit (qh_ERRqhull, qh tracefacet, NULL);
-  }
-#endif /* !qh_NOtrace */
-  if (qh CHECKfrequently || qh IStracing >= 4) { /* can't check polygon here */
-    qh_checkfacet (facet2, True, &waserror);
-    if (waserror)
-      qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-} /* tracemerge */
-
-/*---------------------------------
-  
-  qh_tracemerging()
-    print trace message during POSTmerging
-
-  returns:
-    updates qh.mergereport
-  
-  notes:
-    called from qh_mergecycle() and qh_mergefacet()
-  
-  see:
-    qh_buildtracing()
-*/
-void qh_tracemerging (void) {
-  realT cpu;
-  int total;
-  time_t timedata;
-  struct tm *tp;
-
-  qh mergereport= zzval_(Ztotmerge);
-  time (&timedata);
-  tp= localtime (&timedata);
-  cpu= qh_CPUclock;
-  cpu /= qh_SECticks;
-  total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
-  fprintf (qh ferr, "\n\
-At %d:%d:%d & %2.5g CPU secs, qhull has merged %d facets.  The hull\n\
-  contains %d facets and %d vertices.\n",
-      tp->tm_hour, tp->tm_min, tp->tm_sec, cpu,
-      total, qh num_facets - qh num_visible,
-      qh num_vertices-qh_setsize (qh del_vertices));
-} /* tracemerging */
-
-/*---------------------------------
-  
-  qh_updatetested( facet1, facet2 )
-    clear facet2->tested and facet1->ridge->tested for merge
-
-  returns:
-    deletes facet2->center unless it's already large
-      if so, clears facet2->ridge->tested
-
-  design:
-    clear facet2->tested
-    clear ridge->tested for facet1's ridges
-    if facet2 has a centrum
-      if facet2 is large
-        set facet2->keepcentrum 
-      else if facet2 has 3 vertices due to many merges, or not large and post merging
-        clear facet2->keepcentrum
-      unless facet2->keepcentrum
-        clear facet2->center to recompute centrum later
-        clear ridge->tested for facet2's ridges
-*/
-void qh_updatetested (facetT *facet1, facetT *facet2) {
-  ridgeT *ridge, **ridgep;
-  int size;
-  
-  facet2->tested= False;
-  FOREACHridge_(facet1->ridges)
-    ridge->tested= False;
-  if (!facet2->center)
-    return;
-  size= qh_setsize (facet2->vertices);
-  if (!facet2->keepcentrum) {
-    if (size > qh hull_dim + qh_MAXnewcentrum) {
-      facet2->keepcentrum= True;
-      zinc_(Zwidevertices);
-    }
-  }else if (size <= qh hull_dim + qh_MAXnewcentrum) {
-    /* center and keepcentrum was set */
-    if (size == qh hull_dim || qh POSTmerging)
-      facet2->keepcentrum= False; /* if many merges need to recompute centrum */
-  }
-  if (!facet2->keepcentrum) {
-    qh_memfree (facet2->center, qh normal_size);
-    facet2->center= NULL;
-    FOREACHridge_(facet2->ridges)
-      ridge->tested= False;
-  }
-} /* updatetested */
-
-/*---------------------------------
-  
-  qh_vertexridges( vertex )
-    return temporary set of ridges adjacent to a vertex
-    vertex->neighbors defined
-
-  ntoes:
-    uses qh.visit_id
-    does not include implicit ridges for simplicial facets
-
-  design:
-    for each neighbor of vertex
-      add ridges that include the vertex to ridges  
-*/
-setT *qh_vertexridges (vertexT *vertex) {
-  facetT *neighbor, **neighborp;
-  setT *ridges= qh_settemp (qh TEMPsize);
-  int size;
-
-  qh visit_id++;
-  FOREACHneighbor_(vertex)
-    neighbor->visitid= qh visit_id;
-  FOREACHneighbor_(vertex) {
-    if (*neighborp)   /* no new ridges in last neighbor */
-      qh_vertexridges_facet (vertex, neighbor, &ridges);
-  }
-  if (qh PRINTstatistics || qh IStracing) {
-    size= qh_setsize (ridges);
-    zinc_(Zvertexridge);
-    zadd_(Zvertexridgetot, size);
-    zmax_(Zvertexridgemax, size);
-    trace3((qh ferr, "qh_vertexridges: found %d ridges for v%d\n",
-             size, vertex->id));
-  }
-  return ridges;
-} /* vertexridges */
-
-/*---------------------------------
-  
-  qh_vertexridges_facet( vertex, facet, ridges )
-    add adjacent ridges for vertex in facet
-    neighbor->visitid==qh.visit_id if it hasn't been visited
-
-  returns:
-    ridges updated
-    sets facet->visitid to qh.visit_id-1
-
-  design:
-    for each ridge of facet
-      if ridge of visited neighbor (i.e., unprocessed)
-        if vertex in ridge
-          append ridge to vertex
-    mark facet processed
-*/
-void qh_vertexridges_facet (vertexT *vertex, facetT *facet, setT **ridges) {
-  ridgeT *ridge, **ridgep;
-  facetT *neighbor;
-
-  FOREACHridge_(facet->ridges) {
-    neighbor= otherfacet_(ridge, facet);
-    if (neighbor->visitid == qh visit_id 
-    && qh_setin (ridge->vertices, vertex))
-      qh_setappend (ridges, ridge);
-  }
-  facet->visitid= qh visit_id-1;
-} /* vertexridges_facet */
-
-/*---------------------------------
-  
-  qh_willdelete( facet, replace )
-    moves facet to visible list
-    sets facet->f.replace to replace (may be NULL)
-
-  returns:
-    bumps qh.num_visible
-*/
-void qh_willdelete (facetT *facet, facetT *replace) {
-
-  qh_removefacet(facet);
-  qh_prependfacet (facet, &qh visible_list);
-  qh num_visible++;
-  facet->visible= True;
-  facet->f.replace= replace;
-} /* willdelete */
-
-#else /* qh_NOmerge */
-void qh_premerge (vertexT *apex, realT maxcentrum, realT maxangle) {
-}
-void qh_postmerge (char *reason, realT maxcentrum, realT maxangle, 
-                      boolT vneighbors) {
-}
-boolT qh_checkzero (boolT testall) {
-   }
-#endif /* qh_NOmerge */
-
diff --git a/extern/qhull/src/merge.h b/extern/qhull/src/merge.h
deleted file mode 100644
index 7fc2afa5967..00000000000
--- a/extern/qhull/src/merge.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
  ---------------------------------
-
-   merge.h 
-   header file for merge.c
-
-   see qh-merge.htm and merge.c
-
-   copyright (c) 1993-2002, The Geometry Center
-*/
-
-#ifndef qhDEFmerge
-#define qhDEFmerge 1
-
-
-/*============ -constants- ==============*/
-
-/*----------------------------------
-
-  qh_ANGLEredundant
-    indicates redundant merge in mergeT->angle
-*/
-#define qh_ANGLEredundant 6.0
-
-/*----------------------------------
-  
-  qh_ANGLEdegen
-    indicates degenerate facet in mergeT->angle
-*/
-#define qh_ANGLEdegen     5.0
-
-/*----------------------------------
-  
-  qh_ANGLEconcave
-    offset to indicate concave facets in mergeT->angle
-  
-  notes:
-    concave facets are assigned the range of [2,4] in mergeT->angle
-    roundoff error may make the angle less than 2
-*/
-#define qh_ANGLEconcave  1.5
-
-/*----------------------------------
-  
-  MRG... (mergeType)
-    indicates the type of a merge (mergeT->type)
-*/
-typedef enum {	/* in sort order for facet_mergeset */
-  MRGnone= 0,
-  MRGcoplanar,		/* centrum coplanar */
-  MRGanglecoplanar,	/* angle coplanar */
-  			/* could detect half concave ridges */
-  MRGconcave,		/* concave ridge */
-  MRGflip,		/* flipped facet. facet1 == facet2 */
-  MRGridge,		/* duplicate ridge (qh_MERGEridge) */
-                        /* degen and redundant go onto degen_mergeset */
-  MRGdegen,		/* degenerate facet (not enough neighbors) facet1 == facet2 */
-  MRGredundant,		/* redundant facet (vertex subset) */
-  			/* merge_degenredundant assumes degen < redundant */
-  MRGmirror,	        /* mirror facet from qh_triangulate */
-  ENDmrg
-} mergeType;
-
-/*----------------------------------
-  
-  qh_MERGEapex
-    flag for qh_mergefacet() to indicate an apex merge  
-*/
-#define qh_MERGEapex     True
-
-/*============ -structures- ====================*/
-
-/*----------------------------------
-     
-  mergeT
-    structure used to merge facets
-*/
-
-typedef struct mergeT mergeT;
-struct mergeT {		/* initialize in qh_appendmergeset */
-  realT   angle;        /* angle between normals of facet1 and facet2 */
-  facetT *facet1; 	/* will merge facet1 into facet2 */
-  facetT *facet2;
-  mergeType type;
-};
-
-
-/*=========== -macros- =========================*/
-
-/*----------------------------------
-     
-  FOREACHmerge_( merges ) {...}
-    assign 'merge' to each merge in merges
-       
-  notes:
-    uses 'mergeT *merge, **mergep;'
-    if qh_mergefacet(),
-      restart since qh.facet_mergeset may change
-    see FOREACHsetelement_
-*/
-#define FOREACHmerge_( merges ) FOREACHsetelement_(mergeT, merges, merge)
-
-/*============ prototypes in alphabetical order after pre/postmerge =======*/
-
-void    qh_premerge (vertexT *apex, realT maxcentrum, realT maxangle);
-void    qh_postmerge (char *reason, realT maxcentrum, realT maxangle, 
-             boolT vneighbors);
-void    qh_all_merges (boolT othermerge, boolT vneighbors);
-void    qh_appendmergeset(facetT *facet, facetT *neighbor, mergeType mergetype, realT *angle);
-setT   *qh_basevertices( facetT *samecycle);
-void    qh_checkconnect (void /* qh new_facets */);
-boolT   qh_checkzero (boolT testall);
-void    qh_copynonconvex (ridgeT *atridge);
-void    qh_degen_redundant_facet (facetT *facet);
-void   	qh_degen_redundant_neighbors (facetT *facet, facetT *delfacet);
-vertexT *qh_find_newvertex (vertexT *oldvertex, setT *vertices, setT *ridges);
-void    qh_findbest_test (boolT testcentrum, facetT *facet, facetT *neighbor,
-           facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp);
-facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp);
-void 	qh_flippedmerges(facetT *facetlist, boolT *wasmerge);
-void 	qh_forcedmerges( boolT *wasmerge);
-void	qh_getmergeset(facetT *facetlist);
-void 	qh_getmergeset_initial (facetT *facetlist);
-void    qh_hashridge (setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex);
-ridgeT *qh_hashridge_find (setT *hashtable, int hashsize, ridgeT *ridge, 
-              vertexT *vertex, vertexT *oldvertex, int *hashslot);
-void 	qh_makeridges(facetT *facet);
-void    qh_mark_dupridges(facetT *facetlist);
-void    qh_maydropneighbor (facetT *facet);
-int     qh_merge_degenredundant (void);
-void    qh_merge_nonconvex( facetT *facet1, facetT *facet2, mergeType mergetype);
-void    qh_mergecycle (facetT *samecycle, facetT *newfacet);
-void    qh_mergecycle_all (facetT *facetlist, boolT *wasmerge);
-void    qh_mergecycle_facets( facetT *samecycle, facetT *newfacet);
-void    qh_mergecycle_neighbors(facetT *samecycle, facetT *newfacet);
-void    qh_mergecycle_ridges(facetT *samecycle, facetT *newfacet);
-void    qh_mergecycle_vneighbors( facetT *samecycle, facetT *newfacet);
-void 	qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, boolT mergeapex);
-void    qh_mergefacet2d (facetT *facet1, facetT *facet2);
-void 	qh_mergeneighbors(facetT *facet1, facetT *facet2);
-void 	qh_mergeridges(facetT *facet1, facetT *facet2);
-void    qh_mergesimplex(facetT *facet1, facetT *facet2, boolT mergeapex);
-void    qh_mergevertex_del (vertexT *vertex, facetT *facet1, facetT *facet2);
-void    qh_mergevertex_neighbors(facetT *facet1, facetT *facet2);
-void	qh_mergevertices(setT *vertices1, setT **vertices);
-setT   *qh_neighbor_intersections (vertexT *vertex);
-void    qh_newvertices (setT *vertices);
-boolT   qh_reducevertices (void);
-vertexT *qh_redundant_vertex (vertexT *vertex);
-boolT   qh_remove_extravertices (facetT *facet);
-vertexT *qh_rename_sharedvertex (vertexT *vertex, facetT *facet);
-void	qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex);
-void    qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges,
-			facetT *oldfacet, facetT *neighborA);
-boolT 	qh_test_appendmerge (facetT *facet, facetT *neighbor);
-boolT   qh_test_vneighbors (void /* qh newfacet_list */);
-void    qh_tracemerge (facetT *facet1, facetT *facet2);
-void    qh_tracemerging (void);
-void    qh_updatetested( facetT *facet1, facetT *facet2);
-setT   *qh_vertexridges (vertexT *vertex);
-void    qh_vertexridges_facet (vertexT *vertex, facetT *facet, setT **ridges);
-void    qh_willdelete (facetT *facet, facetT *replace);
-
-#endif /* qhDEFmerge */
diff --git a/extern/qhull/src/poly.c b/extern/qhull/src/poly.c
deleted file mode 100644
index 6319e43d66a..00000000000
--- a/extern/qhull/src/poly.c
+++ /dev/null
@@ -1,1180 +0,0 @@
-/*
  ---------------------------------
-
-   poly.c 
-   implements polygons and simplices
-
-   see qh-poly.htm, poly.h and qhull.h
-
-   infrequent code is in poly2.c 
-   (all but top 50 and their callers 12/3/95)
-
-   copyright (c) 1993-2002, The Geometry Center
-*/
-
-#include "qhull_a.h"
-
-/*======== functions in alphabetical order ==========*/
-
-/*---------------------------------
-  
-  qh_appendfacet( facet )
-    appends facet to end of qh.facet_list,
-
-  returns:
-    updates qh.newfacet_list, facet_next, facet_list
-    increments qh.numfacets
-  
-  notes:
-    assumes qh.facet_list/facet_tail is defined (createsimplex)
-
-  see:
-    qh_removefacet()
-
-*/
-void qh_appendfacet(facetT *facet) {
-  facetT *tail= qh facet_tail;
-
-  if (tail == qh newfacet_list)
-    qh newfacet_list= facet;
-  if (tail == qh facet_next)
-    qh facet_next= facet;
-  facet->previous= tail->previous;
-  facet->next= tail;
-  if (tail->previous)
-    tail->previous->next= facet;
-  else
-    qh facet_list= facet;
-  tail->previous= facet;
-  qh num_facets++;
-  trace4((qh ferr, "qh_appendfacet: append f%d to facet_list\n", facet->id));
-} /* appendfacet */
-
-
-/*---------------------------------
-  
-  qh_appendvertex( vertex )
-    appends vertex to end of qh.vertex_list,
-
-  returns:
-    sets vertex->newlist
-    updates qh.vertex_list, newvertex_list
-    increments qh.num_vertices
-
-  notes:
-    assumes qh.vertex_list/vertex_tail is defined (createsimplex)
-
-*/
-void qh_appendvertex (vertexT *vertex) {
-  vertexT *tail= qh vertex_tail;
-
-  if (tail == qh newvertex_list)
-    qh newvertex_list= vertex;
-  vertex->newlist= True;
-  vertex->previous= tail->previous;
-  vertex->next= tail;
-  if (tail->previous)
-    tail->previous->next= vertex;
-  else
-    qh vertex_list= vertex;
-  tail->previous= vertex;
-  qh num_vertices++;
-  trace4((qh ferr, "qh_appendvertex: append v%d to vertex_list\n", vertex->id));
-} /* appendvertex */
-
-
-/*---------------------------------
-  
-  qh_attachnewfacets( )
-    attach horizon facets to new facets in qh.newfacet_list
-    newfacets have neighbor and ridge links to horizon but not vice versa
-    only needed for qh.ONLYgood
-
-  returns:
-    set qh.NEWfacets
-    horizon facets linked to new facets 
-      ridges changed from visible facets to new facets
-      simplicial ridges deleted
-    qh.visible_list, no ridges valid
-    facet->f.replace is a newfacet (if any)
-
-  design:
-    delete interior ridges and neighbor sets by
-      for each visible, non-simplicial facet
-        for each ridge
-          if last visit or if neighbor is simplicial
-            if horizon neighbor
-              delete ridge for horizon's ridge set
-            delete ridge
-        erase neighbor set
-    attach horizon facets and new facets by
-      for all new facets
-        if corresponding horizon facet is simplicial
-          locate corresponding visible facet {may be more than one}
-          link visible facet to new facet
-          replace visible facet with new facet in horizon
-        else it's non-simplicial
-          for all visible neighbors of the horizon facet
-            link visible neighbor to new facet
-            delete visible neighbor from horizon facet
-          append new facet to horizon's neighbors
-          the first ridge of the new facet is the horizon ridge
-          link the new facet into the horizon ridge
-*/
-void qh_attachnewfacets (void ) {
-  facetT *newfacet= NULL, *neighbor, **neighborp, *horizon, *visible;
-  ridgeT *ridge, **ridgep;
-
-  qh NEWfacets= True;
-  trace3((qh ferr, "qh_attachnewfacets: delete interior ridges\n"));
-  qh visit_id++;
-  FORALLvisible_facets {
-    visible->visitid= qh visit_id;
-    if (visible->ridges) {
-      FOREACHridge_(visible->ridges) {
-	neighbor= otherfacet_(ridge, visible);
-	if (neighbor->visitid == qh visit_id
-	    || (!neighbor->visible && neighbor->simplicial)) {
-	  if (!neighbor->visible)  /* delete ridge for simplicial horizon */
-	    qh_setdel (neighbor->ridges, ridge);
-	  qh_setfree (&(ridge->vertices)); /* delete on 2nd visit */
-	  qh_memfree (ridge, sizeof(ridgeT));
-	}
-      }
-      SETfirst_(visible->ridges)= NULL;
-    }
-    SETfirst_(visible->neighbors)= NULL;
-  }
-  trace1((qh ferr, "qh_attachnewfacets: attach horizon facets to new facets\n"));
-  FORALLnew_facets {
-    horizon= SETfirstt_(newfacet->neighbors, facetT);
-    if (horizon->simplicial) {
-      visible= NULL;
-      FOREACHneighbor_(horizon) {   /* may have more than one horizon ridge */
-	if (neighbor->visible) {
-	  if (visible) {
-	    if (qh_setequal_skip (newfacet->vertices, 0, horizon->vertices,
-				  SETindex_(horizon->neighbors, neighbor))) {
-	      visible= neighbor;
-	      break;
-	    }
-	  }else
-	    visible= neighbor;
-	}
-      }
-      if (visible) {
-	visible->f.replace= newfacet;
-	qh_setreplace (horizon->neighbors, visible, newfacet);
-      }else {
-	fprintf (qh ferr, "qhull internal error (qh_attachnewfacets): couldn't find visible facet for horizon f%d of newfacet f%d\n",
-		 horizon->id, newfacet->id);
-	qh_errexit2 (qh_ERRqhull, horizon, newfacet);
-      }
-    }else { /* non-simplicial, with a ridge for newfacet */
-      FOREACHneighbor_(horizon) {    /* may hold for many new facets */
-	if (neighbor->visible) {
-	  neighbor->f.replace= newfacet;
-	  qh_setdelnth (horizon->neighbors,
-			SETindex_(horizon->neighbors, neighbor));
-	  neighborp--; /* repeat */
-	}
-      }
-      qh_setappend (&horizon->neighbors, newfacet);
-      ridge= SETfirstt_(newfacet->ridges, ridgeT);
-      if (ridge->top == horizon)
-	ridge->bottom= newfacet;
-      else
-	ridge->top= newfacet;
-      }
-  } /* newfacets */
-  if (qh PRINTstatistics) {
-    FORALLvisible_facets {
-      if (!visible->f.replace) 
-	zinc_(Zinsidevisible);
-    }
-  }
-} /* attachnewfacets */
-
-/*---------------------------------
-  
-  qh_checkflipped( facet, dist, allerror )
-    checks facet orientation to interior point
-
-    if allerror set,
-      tests against qh.DISTround
-    else
-      tests against 0 since tested against DISTround before
-
-  returns:
-    False if it flipped orientation (sets facet->flipped)
-    distance if non-NULL
-*/
-boolT qh_checkflipped (facetT *facet, realT *distp, boolT allerror) {
-  realT dist;
-
-  if (facet->flipped && !distp)
-    return False;
-  zzinc_(Zdistcheck);
-  qh_distplane(qh interior_point, facet, &dist);
-  if (distp)
-    *distp= dist;
-  if ((allerror && dist > -qh DISTround)|| (!allerror && dist >= 0.0)) {
-    facet->flipped= True;
-    zzinc_(Zflippedfacets);
-    trace0((qh ferr, "qh_checkflipped: facet f%d is flipped, distance= %6.12g during p%d\n",
-              facet->id, dist, qh furthest_id));
-    qh_precision ("flipped facet");
-    return False;
-  }
-  return True;
-} /* checkflipped */
-
-/*---------------------------------
-  
-  qh_delfacet( facet )
-    removes facet from facet_list and frees up its memory
-
-  notes:
-    assumes vertices and ridges already freed
-*/
-void qh_delfacet(facetT *facet) {
-  void **freelistp; /* used !qh_NOmem */
-
-  trace4((qh ferr, "qh_delfacet: delete f%d\n", facet->id));
-  if (facet == qh tracefacet)
-    qh tracefacet= NULL;
-  if (facet == qh GOODclosest)
-    qh GOODclosest= NULL;
-  qh_removefacet(facet);
-  if (!facet->tricoplanar || facet->keepcentrum) {
-    qh_memfree_(facet->normal, qh normal_size, freelistp);
-    if (qh CENTERtype == qh_ASvoronoi) {   /* uses macro calls */
-      qh_memfree_(facet->center, qh center_size, freelistp);
-    }else /* AScentrum */ {
-      qh_memfree_(facet->center, qh normal_size, freelistp);
-    }
-  }
-  qh_setfree(&(facet->neighbors));
-  if (facet->ridges)
-    qh_setfree(&(facet->ridges));
-  qh_setfree(&(facet->vertices));
-  if (facet->outsideset)
-    qh_setfree(&(facet->outsideset));
-  if (facet->coplanarset)
-    qh_setfree(&(facet->coplanarset));
-  qh_memfree_(facet, sizeof(facetT), freelistp);
-} /* delfacet */
-
-
-/*---------------------------------
-  
-  qh_deletevisible()
-    delete visible facets and vertices
-
-  returns:
-    deletes each facet and removes from facetlist
-    at exit, qh.visible_list empty (== qh.newfacet_list)
-
-  notes:
-    ridges already deleted
-    horizon facets do not reference facets on qh.visible_list
-    new facets in qh.newfacet_list
-    uses   qh.visit_id;
-*/
-void qh_deletevisible (void /*qh visible_list*/) {
-  facetT *visible, *nextfacet;
-  vertexT *vertex, **vertexp;
-  int numvisible= 0, numdel= qh_setsize(qh del_vertices);
-
-  trace1((qh ferr, "qh_deletevisible: delete %d visible facets and %d vertices\n",
-         qh num_visible, numdel));
-  for (visible= qh visible_list; visible && visible->visible; 
-                visible= nextfacet) { /* deleting current */
-    nextfacet= visible->next;        
-    numvisible++;
-    qh_delfacet(visible);
-  }
-  if (numvisible != qh num_visible) {
-    fprintf (qh ferr, "qhull internal error (qh_deletevisible): qh num_visible %d is not number of visible facets %d\n",
-             qh num_visible, numvisible);
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-  qh num_visible= 0;
-  zadd_(Zvisfacettot, numvisible);
-  zmax_(Zvisfacetmax, numvisible);
-  zzadd_(Zdelvertextot, numdel);
-  zmax_(Zdelvertexmax, numdel);
-  FOREACHvertex_(qh del_vertices) 
-    qh_delvertex (vertex);
-  qh_settruncate (qh del_vertices, 0);
-} /* deletevisible */
-
-/*---------------------------------
-  
-  qh_facetintersect( facetA, facetB, skipa, skipB, prepend )
-    return vertices for intersection of two simplicial facets
-    may include 1 prepended entry (if more, need to settemppush)
-    
-  returns:
-    returns set of qh.hull_dim-1 + prepend vertices
-    returns skipped index for each test and checks for exactly one
-
-  notes:
-    does not need settemp since set in quick memory
-  
-  see also:
-    qh_vertexintersect and qh_vertexintersect_new
-    use qh_setnew_delnthsorted to get nth ridge (no skip information)
-
-  design:
-    locate skipped vertex by scanning facet A's neighbors
-    locate skipped vertex by scanning facet B's neighbors
-    intersect the vertex sets
-*/
-setT *qh_facetintersect (facetT *facetA, facetT *facetB,
-			 int *skipA,int *skipB, int prepend) {
-  setT *intersect;
-  int dim= qh hull_dim, i, j;
-  facetT **neighborsA, **neighborsB;
-
-  neighborsA= SETaddr_(facetA->neighbors, facetT);
-  neighborsB= SETaddr_(facetB->neighbors, facetT);
-  i= j= 0;
-  if (facetB == *neighborsA++)
-    *skipA= 0;
-  else if (facetB == *neighborsA++)
-    *skipA= 1;
-  else if (facetB == *neighborsA++)
-    *skipA= 2;
-  else {
-    for (i= 3; i < dim; i++) {
-      if (facetB == *neighborsA++) {
-        *skipA= i;
-        break;
-      }
-    }
-  }
-  if (facetA == *neighborsB++)
-    *skipB= 0;
-  else if (facetA == *neighborsB++)
-    *skipB= 1;
-  else if (facetA == *neighborsB++)
-    *skipB= 2;
-  else {
-    for (j= 3; j < dim; j++) {
-      if (facetA == *neighborsB++) {
-        *skipB= j;
-        break;
-      }
-    }
-  }
-  if (i >= dim || j >= dim) {
-    fprintf (qh ferr, "qhull internal error (qh_facetintersect): f%d or f%d not in others neighbors\n",
-            facetA->id, facetB->id);
-    qh_errexit2 (qh_ERRqhull, facetA, facetB);
-  }
-  intersect= qh_setnew_delnthsorted (facetA->vertices, qh hull_dim, *skipA, prepend);
-  trace4((qh ferr, "qh_facetintersect: f%d skip %d matches f%d skip %d\n",
-	  facetA->id, *skipA, facetB->id, *skipB));
-  return(intersect);
-} /* facetintersect */
-
-/*---------------------------------
-  
-  qh_gethash( hashsize, set, size, firstindex, skipelem )
-    return hashvalue for a set with firstindex and skipelem
-
-  notes:
-    assumes at least firstindex+1 elements
-    assumes skipelem is NULL, in set, or part of hash
-    
-    hashes memory addresses which may change over different runs of the same data
-    using sum for hash does badly in high d
-*/
-unsigned qh_gethash (int hashsize, setT *set, int size, int firstindex, void *skipelem) {
-  void **elemp= SETelemaddr_(set, firstindex, void);
-  ptr_intT hash = 0, elem;
-  int i;
-
-  switch (size-firstindex) {
-  case 1:
-    hash= (ptr_intT)(*elemp) - (ptr_intT) skipelem;
-    break;
-  case 2:
-    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] - (ptr_intT) skipelem;
-    break;
-  case 3:
-    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
-      - (ptr_intT) skipelem;
-    break;
-  case 4:
-    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
-      + (ptr_intT)elemp[3] - (ptr_intT) skipelem;
-    break;
-  case 5:
-    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
-      + (ptr_intT)elemp[3] + (ptr_intT)elemp[4] - (ptr_intT) skipelem;
-    break;
-  case 6:
-    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
-      + (ptr_intT)elemp[3] + (ptr_intT)elemp[4]+ (ptr_intT)elemp[5]
-      - (ptr_intT) skipelem;
-    break;
-  default:
-    hash= 0;
-    i= 3;
-    do {     /* this is about 10% in 10-d */
-      if ((elem= (ptr_intT)*elemp++) != (ptr_intT)skipelem) {
-        hash ^= (elem << i) + (elem >> (32-i));
-	i += 3;
-	if (i >= 32)
-	  i -= 32;
-      }
-    }while(*elemp);
-    break;
-  }
-  hash %= (ptr_intT) hashsize;
-  /* hash= 0; for debugging purposes */
-  return hash;
-} /* gethash */
-
-/*---------------------------------
-  
-  qh_makenewfacet( vertices, toporient, horizon )
-    creates a toporient? facet from vertices
-
-  returns:
-    returns newfacet
-      adds newfacet to qh.facet_list
-      newfacet->vertices= vertices
-      if horizon
-        newfacet->neighbor= horizon, but not vice versa
-    newvertex_list updated with vertices
-*/
-facetT *qh_makenewfacet(setT *vertices, boolT toporient,facetT *horizon) {
-  facetT *newfacet;
-  vertexT *vertex, **vertexp;
-
-  FOREACHvertex_(vertices) {
-    if (!vertex->newlist) {
-      qh_removevertex (vertex);
-      qh_appendvertex (vertex);
-    }
-  }
-  newfacet= qh_newfacet();
-  newfacet->vertices= vertices;
-  newfacet->toporient= toporient;
-  if (horizon)
-    qh_setappend(&(newfacet->neighbors), horizon);
-  qh_appendfacet(newfacet);
-  return(newfacet);
-} /* makenewfacet */
-
-
-/*---------------------------------
-  
-  qh_makenewplanes()
-    make new hyperplanes for facets on qh.newfacet_list
-
-  returns:
-    all facets have hyperplanes or are marked for   merging
-    doesn't create hyperplane if horizon is coplanar (will merge)
-    updates qh.min_vertex if qh.JOGGLEmax
-
-  notes:
-    facet->f.samecycle is defined for facet->mergehorizon facets
-*/
-void qh_makenewplanes (void /* newfacet_list */) {
-  facetT *newfacet;
-
-  FORALLnew_facets {
-    if (!newfacet->mergehorizon)
-      qh_setfacetplane (newfacet);  
-  }
-  if (qh JOGGLEmax < REALmax/2)  
-    minimize_(qh min_vertex, -wwval_(Wnewvertexmax));
-} /* makenewplanes */
-
-/*---------------------------------
-  
-  qh_makenew_nonsimplicial( visible, apex, numnew )
-    make new facets for ridges of a visible facet
-    
-  returns:
-    first newfacet, bumps numnew as needed
-    attaches new facets if !qh.ONLYgood
-    marks ridge neighbors for simplicial visible
-    if (qh.ONLYgood)
-      ridges on newfacet, horizon, and visible
-    else
-      ridge and neighbors between newfacet and   horizon
-      visible facet's ridges are deleted    
-
-  notes:
-    qh.visit_id if visible has already been processed
-    sets neighbor->seen for building f.samecycle
-      assumes all 'seen' flags initially false
-    
-  design:
-    for each ridge of visible facet
-      get neighbor of visible facet
-      if neighbor was already processed
-        delete the ridge (will delete all visible facets later)
-      if neighbor is a horizon facet
-        create a new facet
-        if neighbor coplanar
-          adds newfacet to f.samecycle for later merging
-        else 
-          updates neighbor's neighbor set
-          (checks for non-simplicial facet with multiple ridges to visible facet)
-        updates neighbor's ridge set
-        (checks for simplicial neighbor to non-simplicial visible facet)
-	(deletes ridge if neighbor is simplicial)
-          
-*/
-#ifndef qh_NOmerge
-facetT *qh_makenew_nonsimplicial (facetT *visible, vertexT *apex, int *numnew) {
-  void **freelistp; /* used !qh_NOmem */
-  ridgeT *ridge, **ridgep;
-  facetT *neighbor, *newfacet= NULL, *samecycle;
-  setT *vertices;
-  boolT toporient;
-  int ridgeid;
-
-  FOREACHridge_(visible->ridges) {
-    ridgeid= ridge->id;
-    neighbor= otherfacet_(ridge, visible);
-    if (neighbor->visible) {
-      if (!qh ONLYgood) {
-        if (neighbor->visitid == qh visit_id) {
-          qh_setfree (&(ridge->vertices));  /* delete on 2nd visit */
-	  qh_memfree_(ridge, sizeof(ridgeT), freelistp);
-	}
-      }
-    }else {  /* neighbor is an horizon facet */
-      toporient= (ridge->top == visible);
-      vertices= qh_setnew (qh hull_dim); /* makes sure this is quick */
-      qh_setappend (&vertices, apex);
-      qh_setappend_set (&vertices, ridge->vertices);
-      newfacet= qh_makenewfacet(vertices, toporient, neighbor);
-      (*numnew)++;
-      if (neighbor->coplanar) {
-	newfacet->mergehorizon= True;
-        if (!neighbor->seen) {
-          newfacet->f.samecycle= newfacet;
-          neighbor->f.newcycle= newfacet;
-        }else {
-          samecycle= neighbor->f.newcycle;
-          newfacet->f.samecycle= samecycle->f.samecycle;
-          samecycle->f.samecycle= newfacet;
-	}
-      }
-      if (qh ONLYgood) {
-        if (!neighbor->simplicial)
- 	  qh_setappend(&(newfacet->ridges), ridge);
-      }else {  /* qh_attachnewfacets */
-        if (neighbor->seen) {
-	  if (neighbor->simplicial) {
-	    fprintf (qh ferr, "qhull internal error (qh_makenew_nonsimplicial): simplicial f%d sharing two ridges with f%d\n", 
-	           neighbor->id, visible->id);
-	    qh_errexit2 (qh_ERRqhull, neighbor, visible);
-	  }
-	  qh_setappend (&(neighbor->neighbors), newfacet);
-	}else
-          qh_setreplace (neighbor->neighbors, visible, newfacet);
-        if (neighbor->simplicial) {
-          qh_setdel (neighbor->ridges, ridge);
-          qh_setfree (&(ridge->vertices)); 
-	  qh_memfree (ridge, sizeof(ridgeT));
-	}else {
- 	  qh_setappend(&(newfacet->ridges), ridge);
- 	  if (toporient)
- 	    ridge->top= newfacet;
- 	  else
- 	    ridge->bottom= newfacet;
- 	}
-      trace4((qh ferr, "qh_makenew_nonsimplicial: created facet f%d from v%d and r%d of horizon f%d\n",
-	    newfacet->id, apex->id, ridgeid, neighbor->id));
-      }
-    }
-    neighbor->seen= True;        
-  } /* for each ridge */
-  if (!qh ONLYgood)
-    SETfirst_(visible->ridges)= NULL;
-  return newfacet;
-} /* makenew_nonsimplicial */
-#else /* qh_NOmerge */
-facetT *qh_makenew_nonsimplicial (facetT *visible, vertexT *apex, int *numnew) {
-  return NULL;
-}
-#endif /* qh_NOmerge */
-
-/*---------------------------------
-  
-  qh_makenew_simplicial( visible, apex, numnew )
-    make new facets for simplicial visible facet and apex
-
-  returns:
-    attaches new facets if (!qh.ONLYgood)
-      neighbors between newfacet and horizon
-
-  notes:
-    nop if neighbor->seen or neighbor->visible (see qh_makenew_nonsimplicial)
-
-  design:
-    locate neighboring horizon facet for visible facet
-    determine vertices and orientation
-    create new facet
-    if coplanar,
-      add new facet to f.samecycle
-    update horizon facet's neighbor list        
-*/
-facetT *qh_makenew_simplicial (facetT *visible, vertexT *apex, int *numnew) {
-  facetT *neighbor, **neighborp, *newfacet= NULL;
-  setT *vertices;
-  boolT flip, toporient;
-  int horizonskip, visibleskip;
-
-  FOREACHneighbor_(visible) {
-    if (!neighbor->seen && !neighbor->visible) {
-      vertices= qh_facetintersect(neighbor,visible, &horizonskip, &visibleskip, 1);
-      SETfirst_(vertices)= apex;
-      flip= ((horizonskip & 0x1) ^ (visibleskip & 0x1));
-      if (neighbor->toporient)         
-	toporient= horizonskip & 0x1;
-      else
-	toporient= (horizonskip & 0x1) ^ 0x1;
-      newfacet= qh_makenewfacet(vertices, toporient, neighbor);
-      (*numnew)++;
-      if (neighbor->coplanar && (qh PREmerge || qh MERGEexact)) {
-#ifndef qh_NOmerge
-	newfacet->f.samecycle= newfacet;
-	newfacet->mergehorizon= True;
-#endif
-      }
-      if (!qh ONLYgood)
-        SETelem_(neighbor->neighbors, horizonskip)= newfacet;
-      trace4((qh ferr, "qh_makenew_simplicial: create facet f%d top %d from v%d and horizon f%d skip %d top %d and visible f%d skip %d, flip? %d\n",
-	    newfacet->id, toporient, apex->id, neighbor->id, horizonskip,
-	      neighbor->toporient, visible->id, visibleskip, flip));
-    }
-  }
-  return newfacet;
-} /* makenew_simplicial */
-
-/*---------------------------------
-  
-  qh_matchneighbor( newfacet, newskip, hashsize, hashcount )
-    either match subridge of newfacet with neighbor or add to hash_table
-
-  returns:
-    duplicate ridges are unmatched and marked by qh_DUPLICATEridge
-
-  notes:
-    ridge is newfacet->vertices w/o newskip vertex
-    do not allocate memory (need to free hash_table cleanly)
-    uses linear hash chains
-  
-  see also:
-    qh_matchduplicates
-
-  design:
-    for each possible matching facet in qh.hash_table
-      if vertices match
-        set ismatch, if facets have opposite orientation
-        if ismatch and matching facet doesn't have a match
-          match the facets by updating their neighbor sets
-        else
-          indicate a duplicate ridge
-          set facet hyperplane for later testing
-          add facet to hashtable
-          unless the other facet was already a duplicate ridge
-            mark both facets with a duplicate ridge
-            add other facet (if defined) to hash table
-*/
-void qh_matchneighbor (facetT *newfacet, int newskip, int hashsize, int *hashcount) {
-  boolT newfound= False;   /* True, if new facet is already in hash chain */
-  boolT same, ismatch;
-  int hash, scan;
-  facetT *facet, *matchfacet;
-  int skip, matchskip;
-
-  hash= (int)qh_gethash (hashsize, newfacet->vertices, qh hull_dim, 1, 
-                     SETelem_(newfacet->vertices, newskip));
-  trace4((qh ferr, "qh_matchneighbor: newfacet f%d skip %d hash %d hashcount %d\n",
-	  newfacet->id, newskip, hash, *hashcount));
-  zinc_(Zhashlookup);
-  for (scan= hash; (facet= SETelemt_(qh hash_table, scan, facetT)); 
-       scan= (++scan >= hashsize ? 0 : scan)) {
-    if (facet == newfacet) {
-      newfound= True;
-      continue;
-    }
-    zinc_(Zhashtests);
-    if (qh_matchvertices (1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
-      if (SETelem_(newfacet->vertices, newskip) == 
-          SETelem_(facet->vertices, skip)) {
-        qh_precision ("two facets with the same vertices");
-        fprintf (qh ferr, "qhull precision error: Vertex sets are the same for f%d and f%d.  Can not force output.\n",
-          facet->id, newfacet->id);
-        qh_errexit2 (qh_ERRprec, facet, newfacet);
-      }
-      ismatch= (same == (newfacet->toporient ^ facet->toporient));
-      matchfacet= SETelemt_(facet->neighbors, skip, facetT);
-      if (ismatch && !matchfacet) {
-        SETelem_(facet->neighbors, skip)= newfacet;
-        SETelem_(newfacet->neighbors, newskip)= facet;
-        (*hashcount)--;
-        trace4((qh ferr, "qh_matchneighbor: f%d skip %d matched with new f%d skip %d\n",
-           facet->id, skip, newfacet->id, newskip));
-        return;
-      }
-      if (!qh PREmerge && !qh MERGEexact) {
-        qh_precision ("a ridge with more than two neighbors");
-	fprintf (qh ferr, "qhull precision error: facets f%d, f%d and f%d meet at a ridge with more than 2 neighbors.  Can not continue.\n",
-		 facet->id, newfacet->id, getid_(matchfacet));
-	qh_errexit2 (qh_ERRprec, facet, newfacet);
-      }
-      SETelem_(newfacet->neighbors, newskip)= qh_DUPLICATEridge;
-      newfacet->dupridge= True;
-      if (!newfacet->normal)
-	qh_setfacetplane (newfacet);
-      qh_addhash (newfacet, qh hash_table, hashsize, hash);
-      (*hashcount)++;
-      if (!facet->normal)
-	qh_setfacetplane (facet);
-      if (matchfacet != qh_DUPLICATEridge) {
-	SETelem_(facet->neighbors, skip)= qh_DUPLICATEridge;
-	facet->dupridge= True;
-	if (!facet->normal)
-	  qh_setfacetplane (facet);
-	if (matchfacet) {
-	  matchskip= qh_setindex (matchfacet->neighbors, facet);
-	  SETelem_(matchfacet->neighbors, matchskip)= qh_DUPLICATEridge;
-	  matchfacet->dupridge= True;
-	  if (!matchfacet->normal)
-	    qh_setfacetplane (matchfacet);
-	  qh_addhash (matchfacet, qh hash_table, hashsize, hash);
-	  *hashcount += 2;
-	}
-      }
-      trace4((qh ferr, "qh_matchneighbor: new f%d skip %d duplicates ridge for f%d skip %d matching f%d ismatch %d at hash %d\n",
-	   newfacet->id, newskip, facet->id, skip, 
-	   (matchfacet == qh_DUPLICATEridge ? -2 : getid_(matchfacet)), 
-	   ismatch, hash));
-      return; /* end of duplicate ridge */
-    }
-  }
-  if (!newfound) 
-    SETelem_(qh hash_table, scan)= newfacet;  /* same as qh_addhash */
-  (*hashcount)++;
-  trace4((qh ferr, "qh_matchneighbor: no match for f%d skip %d at hash %d\n",
-           newfacet->id, newskip, hash));
-} /* matchneighbor */
-
-
-/*---------------------------------
-  
-  qh_matchnewfacets()
-    match newfacets in qh.newfacet_list to their newfacet neighbors
-
-  returns:
-    qh.newfacet_list with full neighbor sets
-      get vertices with nth neighbor by deleting nth vertex
-    if qh.PREmerge/MERGEexact or qh.FORCEoutput 
-      sets facet->flippped if flipped normal (also prevents point partitioning)
-    if duplicate ridges and qh.PREmerge/MERGEexact
-      sets facet->dupridge
-      missing neighbor links identifies extra ridges to be merging (qh_MERGEridge)
-
-  notes:
-    newfacets already have neighbor[0] (horizon facet)
-    assumes qh.hash_table is NULL
-    vertex->neighbors has not been updated yet
-    do not allocate memory after qh.hash_table (need to free it cleanly)
-
-  design:
-    delete neighbor sets for all new facets
-    initialize a hash table
-    for all new facets
-      match facet with neighbors
-    if unmatched facets (due to duplicate ridges)
-      for each new facet with a duplicate ridge
-        match it with a facet
-    check for flipped facets
-*/
-void qh_matchnewfacets (void /* qh newfacet_list */) {
-  int numnew=0, hashcount=0, newskip;
-  facetT *newfacet, *neighbor;
-  int dim= qh hull_dim, hashsize, neighbor_i, neighbor_n;
-  setT *neighbors;
-#ifndef qh_NOtrace
-  int facet_i, facet_n, numfree= 0;
-  facetT *facet;
-#endif
-  
-  trace1((qh ferr, "qh_matchnewfacets: match neighbors for new facets.\n"));
-  FORALLnew_facets {
-    numnew++;
-    {  /* inline qh_setzero (newfacet->neighbors, 1, qh hull_dim); */
-      neighbors= newfacet->neighbors;
-      neighbors->e[neighbors->maxsize].i= dim+1; /*may be overwritten*/
-      memset ((char *)SETelemaddr_(neighbors, 1, void), 0, dim * SETelemsize);
-    }    
-  }
-  qh_newhashtable (numnew*(qh hull_dim-1)); /* twice what is normally needed,
-                                     but every ridge could be DUPLICATEridge */
-  hashsize= qh_setsize (qh hash_table);
-  FORALLnew_facets {
-    for (newskip=1; newskipneighbors, k, facetT);
-	  if (!neighbor || neighbor == qh_DUPLICATEridge)
-	    count++;
-	}
-	if (facet == newfacet)
-	  break;
-      }
-      if (count != hashcount) {
-	fprintf (qh ferr, "qh_matchnewfacets: after adding facet %d, hashcount %d != count %d\n",
-		 newfacet->id, hashcount, count);
-	qh_errexit (qh_ERRqhull, newfacet, NULL);
-      }
-    }
-#endif  /* end of trap code */
-  }
-  if (hashcount) {
-    FORALLnew_facets {
-      if (newfacet->dupridge) {
-        FOREACHneighbor_i_(newfacet) {
-          if (neighbor == qh_DUPLICATEridge) {
-            qh_matchduplicates (newfacet, neighbor_i, hashsize, &hashcount);
-         	    /* this may report MERGEfacet */
-	  }
-        }
-      }
-    }
-  }
-  if (hashcount) {
-    fprintf (qh ferr, "qhull internal error (qh_matchnewfacets): %d neighbors did not match up\n",
-        hashcount);
-    qh_printhashtable (qh ferr);
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-#ifndef qh_NOtrace
-  if (qh IStracing >= 2) {
-    FOREACHfacet_i_(qh hash_table) {
-      if (!facet)
-        numfree++;
-    }
-    fprintf (qh ferr, "qh_matchnewfacets: %d new facets, %d unused hash entries .  hashsize %d\n",
-	     numnew, numfree, qh_setsize (qh hash_table));
-  }
-#endif /* !qh_NOtrace */
-  qh_setfree (&qh hash_table);
-  if (qh PREmerge || qh MERGEexact) {
-    if (qh IStracing >= 4)
-      qh_printfacetlist (qh newfacet_list, NULL, qh_ALL);
-    FORALLnew_facets {
-      if (newfacet->normal)
-	qh_checkflipped (newfacet, NULL, qh_ALL);
-    }
-  }else if (qh FORCEoutput)
-    qh_checkflipped_all (qh newfacet_list);  /* prints warnings for flipped */
-} /* matchnewfacets */
-
-    
-/*---------------------------------
-  
-  qh_matchvertices( firstindex, verticesA, skipA, verticesB, skipB, same )
-    tests whether vertices match with a single skip
-    starts match at firstindex since all new facets have a common vertex
-
-  returns:
-    true if matched vertices
-    skip index for each set
-    sets same iff vertices have the same orientation
-
-  notes:
-    assumes skipA is in A and both sets are the same size
-
-  design:
-    set up pointers
-    scan both sets checking for a match
-    test orientation
-*/
-boolT qh_matchvertices (int firstindex, setT *verticesA, int skipA, 
-       setT *verticesB, int *skipB, boolT *same) {
-  vertexT **elemAp, **elemBp, **skipBp=NULL, **skipAp;
-
-  elemAp= SETelemaddr_(verticesA, firstindex, vertexT);
-  elemBp= SETelemaddr_(verticesB, firstindex, vertexT);
-  skipAp= SETelemaddr_(verticesA, skipA, vertexT);
-  do if (elemAp != skipAp) {
-    while (*elemAp != *elemBp++) {
-      if (skipBp)
-        return False;
-      skipBp= elemBp;  /* one extra like FOREACH */
-    }
-  }while(*(++elemAp));
-  if (!skipBp)
-    skipBp= ++elemBp;
-  *skipB= SETindex_(verticesB, skipB);
-  *same= !(((ptr_intT)skipA & 0x1) ^ ((ptr_intT)*skipB & 0x1));
-  trace4((qh ferr, "qh_matchvertices: matched by skip %d (v%d) and skip %d (v%d) same? %d\n",
-	  skipA, (*skipAp)->id, *skipB, (*(skipBp-1))->id, *same));
-  return (True);
-} /* matchvertices */
-
-/*---------------------------------
-  
-  qh_newfacet()
-    return a new facet 
-
-  returns:
-    all fields initialized or cleared   (NULL)
-    preallocates neighbors set
-*/
-facetT *qh_newfacet(void) {
-  facetT *facet;
-  void **freelistp; /* used !qh_NOmem */
-  
-  qh_memalloc_(sizeof(facetT), freelistp, facet, facetT);
-  memset ((char *)facet, 0, sizeof(facetT));
-  if (qh facet_id == qh tracefacet_id)
-    qh tracefacet= facet;
-  facet->id= qh facet_id++;
-  facet->neighbors= qh_setnew(qh hull_dim);
-#if !qh_COMPUTEfurthest
-  facet->furthestdist= 0.0;
-#endif
-#if qh_MAXoutside
-  if (qh FORCEoutput && qh APPROXhull)
-    facet->maxoutside= qh MINoutside;
-  else
-    facet->maxoutside= qh DISTround;
-#endif
-  facet->simplicial= True;
-  facet->good= True;
-  facet->newfacet= True;
-  trace4((qh ferr, "qh_newfacet: created facet f%d\n", facet->id));
-  return (facet);
-} /* newfacet */
-
-
-/*---------------------------------
-  
-  qh_newridge()
-    return a new ridge
-*/
-ridgeT *qh_newridge(void) {
-  ridgeT *ridge;
-  void **freelistp;   /* used !qh_NOmem */
-
-  qh_memalloc_(sizeof(ridgeT), freelistp, ridge, ridgeT);
-  memset ((char *)ridge, 0, sizeof(ridgeT));
-  zinc_(Ztotridges);
-  if (qh ridge_id == 0xFFFFFF) {
-    fprintf(qh ferr, "\
-qhull warning: more than %d ridges.  ID field overflows and two ridges\n\
-may have the same identifier.  Otherwise output ok.\n", 0xFFFFFF);
-  }
-  ridge->id= qh ridge_id++;     
-  trace4((qh ferr, "qh_newridge: created ridge r%d\n", ridge->id));
-  return (ridge);
-} /* newridge */
-
-
-/*---------------------------------
-  
-  qh_pointid(  )
-    return id for a point, 
-    returns -3 if null, -2 if interior, or -1 if not known
-
-  alternative code:
-    unsigned long id;
-    id= ((unsigned long)point - (unsigned long)qh.first_point)/qh.normal_size;
-
-  notes:
-    if point not in point array
-      the code does a comparison of unrelated pointers.
-*/
-int qh_pointid (pointT *point) {
-  long offset, id;
-
-  if (!point)
-    id= -3;
-  else if (point == qh interior_point)
-    id= -2;
-  else if (point >= qh first_point
-  && point < qh first_point + qh num_points * qh hull_dim) {
-    offset= point - qh first_point;
-    id= offset / qh hull_dim;
-  }else if ((id= qh_setindex (qh other_points, point)) != -1)
-    id += qh num_points;
-  else
-    id= -1;
-  return (int) id;
-} /* pointid */
-  
-/*---------------------------------
-  
-  qh_removefacet( facet )
-    unlinks facet from qh.facet_list,
-
-  returns:
-    updates qh.facet_list .newfacet_list .facet_next visible_list
-    decrements qh.num_facets
-
-  see:
-    qh_appendfacet
-*/
-void qh_removefacet(facetT *facet) {
-  facetT *next= facet->next, *previous= facet->previous;
-  
-  if (facet == qh newfacet_list)
-    qh newfacet_list= next;
-  if (facet == qh facet_next)
-    qh facet_next= next;
-  if (facet == qh visible_list)
-    qh visible_list= next; 
-  if (previous) {
-    previous->next= next;
-    next->previous= previous;
-  }else {  /* 1st facet in qh facet_list */
-    qh facet_list= next;
-    qh facet_list->previous= NULL;
-  }
-  qh num_facets--;
-  trace4((qh ferr, "qh_removefacet: remove f%d from facet_list\n", facet->id));
-} /* removefacet */
-
-
-/*---------------------------------
-  
-  qh_removevertex( vertex )
-    unlinks vertex from qh.vertex_list,
-
-  returns:
-    updates qh.vertex_list .newvertex_list 
-    decrements qh.num_vertices
-*/
-void qh_removevertex(vertexT *vertex) {
-  vertexT *next= vertex->next, *previous= vertex->previous;
-  
-  if (vertex == qh newvertex_list)
-    qh newvertex_list= next;
-  if (previous) {
-    previous->next= next;
-    next->previous= previous;
-  }else {  /* 1st vertex in qh vertex_list */
-    qh vertex_list= vertex->next;
-    qh vertex_list->previous= NULL;
-  }
-  qh num_vertices--;
-  trace4((qh ferr, "qh_removevertex: remove v%d from vertex_list\n", vertex->id));
-} /* removevertex */
-
-
-/*---------------------------------
-  
-  qh_updatevertices()
-    update vertex neighbors and delete interior vertices
-
-  returns:
-    if qh.VERTEXneighbors, updates neighbors for each vertex
-      if qh.newvertex_list, 
-         removes visible neighbors  from vertex neighbors
-      if qh.newfacet_list
-         adds new facets to vertex neighbors
-    if qh.visible_list
-       interior vertices added to qh.del_vertices for later partitioning
-
-  design:
-    if qh.VERTEXneighbors
-      deletes references to visible facets from vertex neighbors
-      appends new facets to the neighbor list for each vertex
-      checks all vertices of visible facets
-        removes visible facets from neighbor lists
-        marks unused vertices for deletion
-*/
-void qh_updatevertices (void /*qh newvertex_list, newfacet_list, visible_list*/) {
-  facetT *newfacet= NULL, *neighbor, **neighborp, *visible;
-  vertexT *vertex, **vertexp;
-
-  trace3((qh ferr, "qh_updatevertices: delete interior vertices and update vertex->neighbors\n"));
-  if (qh VERTEXneighbors) {
-    FORALLvertex_(qh newvertex_list) {
-      FOREACHneighbor_(vertex) {
-	if (neighbor->visible) 
-	  SETref_(neighbor)= NULL;
-      }
-      qh_setcompact (vertex->neighbors);
-    }
-    FORALLnew_facets {
-      FOREACHvertex_(newfacet->vertices)
-        qh_setappend (&vertex->neighbors, newfacet);
-    }
-    FORALLvisible_facets {
-      FOREACHvertex_(visible->vertices) {
-        if (!vertex->newlist && !vertex->deleted) {
-  	  FOREACHneighbor_(vertex) { /* this can happen under merging */
-	    if (!neighbor->visible)
-	      break;
-	  }
-	  if (neighbor)
-	    qh_setdel (vertex->neighbors, visible);
-	  else {
-	    vertex->deleted= True;
-	    qh_setappend (&qh del_vertices, vertex);
-	    trace2((qh ferr, "qh_updatevertices: delete vertex p%d (v%d) in f%d\n",
-		  qh_pointid(vertex->point), vertex->id, visible->id));
-  	  }
-        }
-      }
-    }
-  }else {  /* !VERTEXneighbors */
-    FORALLvisible_facets {
-      FOREACHvertex_(visible->vertices) {
-        if (!vertex->newlist && !vertex->deleted) {
-          vertex->deleted= True;
-	  qh_setappend (&qh del_vertices, vertex);
-	  trace2((qh ferr, "qh_updatevertices: delete vertex p%d (v%d) in f%d\n",
-		  qh_pointid(vertex->point), vertex->id, visible->id));
-  	}
-      }
-    }
-  }
-} /* updatevertices */
-
-
-
diff --git a/extern/qhull/src/poly.h b/extern/qhull/src/poly.h
deleted file mode 100644
index 294ec9527fc..00000000000
--- a/extern/qhull/src/poly.h
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
  ---------------------------------
-
-   poly.h 
-   header file for poly.c and poly2.c
-
-   see qh-poly.htm, qhull.h and poly.c
-
-   copyright (c) 1993-2002, The Geometry Center
-*/
-
-#ifndef qhDEFpoly
-#define qhDEFpoly 1
-
-/*===============   constants ========================== */
-
-/*----------------------------------
-  
-  ALGORITHMfault   
-    use as argument to checkconvex() to report errors during buildhull
-*/
-#define qh_ALGORITHMfault 0
-
-/*----------------------------------
-  
-  DATAfault        
-    use as argument to checkconvex() to report errors during initialhull
-*/
-#define qh_DATAfault 1
-
-/*----------------------------------
-  
-  DUPLICATEridge
-    special value for facet->neighbor to indicate a duplicate ridge
-  
-  notes:
-    set by matchneighbor, used by matchmatch and mark_dupridge
-*/
-#define qh_DUPLICATEridge ( facetT * ) 1L
-
-/*----------------------------------
-  
-  MERGEridge       flag in facet
-    special value for facet->neighbor to indicate a merged ridge
-  
-  notes:
-    set by matchneighbor, used by matchmatch and mark_dupridge
-*/
-#define qh_MERGEridge ( facetT * ) 2L
-
-
-/*============ -structures- ====================*/
-
-/*=========== -macros- =========================*/
-
-/*----------------------------------
-  
-  FORALLfacet_( facetlist ) { ... }
-    assign 'facet' to each facet in facetlist
-    
-  notes:
-    uses 'facetT *facet;'
-    assumes last facet is a sentinel
-    
-  see:
-    FORALLfacets
-*/
-#define FORALLfacet_( facetlist ) if ( facetlist ) for( facet=( facetlist );facet && facet->next;facet=facet->next )
-
-/*----------------------------------
-  
-  FORALLnew_facets { ... } 
-    assign 'newfacet' to each facet in qh.newfacet_list
-    
-  notes:
-    uses 'facetT *newfacet;'
-    at exit, newfacet==NULL
-*/
-#define FORALLnew_facets for( newfacet=qh newfacet_list;newfacet && newfacet->next;newfacet=newfacet->next )
-
-/*----------------------------------
-  
-  FORALLvertex_( vertexlist ) { ... }
-    assign 'vertex' to each vertex in vertexlist
-    
-  notes:
-    uses 'vertexT *vertex;'
-    at exit, vertex==NULL
-*/
-#define FORALLvertex_( vertexlist ) for ( vertex=( vertexlist );vertex && vertex->next;vertex= vertex->next )
-
-/*----------------------------------
-  
-  FORALLvisible_facets { ... }
-    assign 'visible' to each visible facet in qh.visible_list
-    
-  notes:
-    uses 'vacetT *visible;'
-    at exit, visible==NULL
-*/
-#define FORALLvisible_facets for (visible=qh visible_list; visible && visible->visible; visible= visible->next)
-
-/*----------------------------------
-  
-  FORALLsame_( newfacet ) { ... } 
-    assign 'same' to each facet in newfacet->f.samecycle
-    
-  notes:
-    uses 'facetT *same;'
-    stops when it returns to newfacet
-*/
-#define FORALLsame_(newfacet) for (same= newfacet->f.samecycle; same != newfacet; same= same->f.samecycle)
-
-/*----------------------------------
-  
-  FORALLsame_cycle_( newfacet ) { ... } 
-    assign 'same' to each facet in newfacet->f.samecycle
-    
-  notes:
-    uses 'facetT *same;'
-    at exit, same == NULL
-*/
-#define FORALLsame_cycle_(newfacet) \
-     for (same= newfacet->f.samecycle; \
-         same; same= (same == newfacet ?  NULL : same->f.samecycle))
-
-/*----------------------------------
-  
-  FOREACHneighborA_( facet ) { ... }
-    assign 'neighborA' to each neighbor in facet->neighbors
-  
-  FOREACHneighborA_( vertex ) { ... }
-    assign 'neighborA' to each neighbor in vertex->neighbors
-  
-  declare:
-    facetT *neighborA, **neighborAp;
-
-  see:
-    FOREACHsetelement_
-*/
-#define FOREACHneighborA_(facet)  FOREACHsetelement_(facetT, facet->neighbors, neighborA)
-
-/*----------------------------------
-  
-  FOREACHvisible_( facets ) { ... } 
-    assign 'visible' to each facet in facets
-    
-  notes:
-    uses 'facetT *facet, *facetp;'
-    see FOREACHsetelement_
-*/
-#define FOREACHvisible_(facets) FOREACHsetelement_(facetT, facets, visible)
-
-/*----------------------------------
-  
-  FOREACHnewfacet_( facets ) { ... } 
-    assign 'newfacet' to each facet in facets
-    
-  notes:
-    uses 'facetT *newfacet, *newfacetp;'
-    see FOREACHsetelement_
-*/
-#define FOREACHnewfacet_(facets) FOREACHsetelement_(facetT, facets, newfacet)
-
-/*----------------------------------
-  
-  FOREACHvertexA_( vertices ) { ... } 
-    assign 'vertexA' to each vertex in vertices
-    
-  notes:
-    uses 'vertexT *vertexA, *vertexAp;'
-    see FOREACHsetelement_
-*/
-#define FOREACHvertexA_(vertices) FOREACHsetelement_(vertexT, vertices, vertexA)
-
-/*----------------------------------
-  
-  FOREACHvertexreverse12_( vertices ) { ... } 
-    assign 'vertex' to each vertex in vertices
-    reverse order of first two vertices
-    
-  notes:
-    uses 'vertexT *vertex, *vertexp;'
-    see FOREACHsetelement_
-*/
-#define FOREACHvertexreverse12_(vertices) FOREACHsetelementreverse12_(vertexT, vertices, vertex)
-
-
-/*=============== prototypes poly.c in alphabetical order ================*/
-
-void    qh_appendfacet(facetT *facet);
-void    qh_appendvertex(vertexT *vertex);
-void 	qh_attachnewfacets (void);
-boolT   qh_checkflipped (facetT *facet, realT *dist, boolT allerror);
-void	qh_delfacet(facetT *facet);
-void 	qh_deletevisible(void /*qh visible_list, qh horizon_list*/);
-setT   *qh_facetintersect (facetT *facetA, facetT *facetB, int *skipAp,int *skipBp, int extra);
-unsigned qh_gethash (int hashsize, setT *set, int size, int firstindex, void *skipelem);
-facetT *qh_makenewfacet(setT *vertices, boolT toporient, facetT *facet);
-void    qh_makenewplanes ( void /* newfacet_list */);
-facetT *qh_makenew_nonsimplicial (facetT *visible, vertexT *apex, int *numnew);
-facetT *qh_makenew_simplicial (facetT *visible, vertexT *apex, int *numnew);
-void    qh_matchneighbor (facetT *newfacet, int newskip, int hashsize,
-			  int *hashcount);
-void	qh_matchnewfacets (void);
-boolT   qh_matchvertices (int firstindex, setT *verticesA, int skipA, 
-			  setT *verticesB, int *skipB, boolT *same);
-facetT *qh_newfacet(void);
-ridgeT *qh_newridge(void);
-int     qh_pointid (pointT *point);
-void 	qh_removefacet(facetT *facet);
-void 	qh_removevertex(vertexT *vertex);
-void    qh_updatevertices (void);
-
-
-/*========== -prototypes poly2.c in alphabetical order ===========*/
-
-void    qh_addhash (void* newelem, setT *hashtable, int hashsize, unsigned hash);
-void 	qh_check_bestdist (void);
-void    qh_check_maxout (void);
-void    qh_check_output (void);
-void    qh_check_point (pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2);
-void   	qh_check_points(void);
-void 	qh_checkconvex(facetT *facetlist, int fault);
-void    qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp);
-void 	qh_checkflipped_all (facetT *facetlist);
-void 	qh_checkpolygon(facetT *facetlist);
-void    qh_checkvertex (vertexT *vertex);
-void 	qh_clearcenters (qh_CENTER type);
-void 	qh_createsimplex(setT *vertices);
-void 	qh_delridge(ridgeT *ridge);
-void    qh_delvertex (vertexT *vertex);
-setT   *qh_facet3vertex (facetT *facet);
-facetT *qh_findbestfacet (pointT *point, boolT bestoutside,
-           realT *bestdist, boolT *isoutside);
-facetT *qh_findfacet_all (pointT *point, realT *bestdist, boolT *isoutside,
-			  int *numpart);
-int 	qh_findgood (facetT *facetlist, int goodhorizon);
-void 	qh_findgood_all (facetT *facetlist);
-void    qh_furthestnext (void /* qh facet_list */);
-void    qh_furthestout (facetT *facet);
-void    qh_infiniteloop (facetT *facet);
-void 	qh_initbuild(void);
-void 	qh_initialhull(setT *vertices);
-setT   *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints);
-vertexT *qh_isvertex (pointT *point, setT *vertices);
-vertexT *qh_makenewfacets (pointT *point /*horizon_list, visible_list*/);
-void    qh_matchduplicates (facetT *atfacet, int atskip, int hashsize, int *hashcount);
-void    qh_nearcoplanar ( void /* qh.facet_list */);
-vertexT *qh_nearvertex (facetT *facet, pointT *point, realT *bestdistp);
-int 	qh_newhashtable(int newsize);
-vertexT *qh_newvertex(pointT *point);
-ridgeT *qh_nextridge3d (ridgeT *atridge, facetT *facet, vertexT **vertexp);
-void    qh_outcoplanar (void /* facet_list */);
-pointT *qh_point (int id);
-void 	qh_point_add (setT *set, pointT *point, void *elem);
-setT   *qh_pointfacet (void /*qh facet_list*/);
-setT   *qh_pointvertex (void /*qh facet_list*/);
-void 	qh_prependfacet(facetT *facet, facetT **facetlist);
-void	qh_printhashtable(FILE *fp);
-void    qh_printlists (void);
-void    qh_resetlists (boolT stats, boolT resetVisible /*qh newvertex_list newfacet_list visible_list*/);
-void    qh_setvoronoi_all (void);
-void	qh_triangulate (void /*qh facet_list*/);
-void    qh_triangulate_facet (facetT *facetA, vertexT **first_vertex);
-void    qh_triangulate_link (facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB);
-void	qh_triangulate_mirror (facetT *facetA, facetT *facetB);
-void    qh_triangulate_null (facetT *facetA);
-void    qh_vertexintersect(setT **vertexsetA,setT *vertexsetB);
-setT   *qh_vertexintersect_new(setT *vertexsetA,setT *vertexsetB);
-void    qh_vertexneighbors (void /*qh facet_list*/);
-boolT 	qh_vertexsubset(setT *vertexsetA, setT *vertexsetB);
-
-
-#endif /* qhDEFpoly */
diff --git a/extern/qhull/src/poly2.c b/extern/qhull/src/poly2.c
deleted file mode 100644
index 713faab8bed..00000000000
--- a/extern/qhull/src/poly2.c
+++ /dev/null
@@ -1,3070 +0,0 @@
-/*
  ---------------------------------
-
-   poly2.c 
-   implements polygons and simplices
-
-   see qh-poly.htm, poly.h and qhull.h
-
-   frequently used code is in poly.c
-
-   copyright (c) 1993-2002, The Geometry Center
-*/
-
-#include "qhull_a.h"
-
-/*======== functions in alphabetical order ==========*/
-
-/*---------------------------------
-  
-  qh_addhash( newelem, hashtable, hashsize, hash )
-    add newelem to linear hash table at hash if not already there
-*/
-void qh_addhash (void* newelem, setT *hashtable, int hashsize, unsigned hash) {
-  int scan;
-  void *elem;
-
-  for (scan= (int)hash; (elem= SETelem_(hashtable, scan)); 
-       scan= (++scan >= hashsize ? 0 : scan)) {
-    if (elem == newelem)
-      break;
-  }
-  /* loop terminates because qh_HASHfactor >= 1.1 by qh_initbuffers */
-  if (!elem)
-    SETelem_(hashtable, scan)= newelem;
-} /* addhash */
-
-/*---------------------------------
-  
-  qh_check_bestdist()
-    check that all points are within max_outside of the nearest facet
-    if qh.ONLYgood,
-      ignores !good facets
-
-  see: 
-    qh_check_maxout(), qh_outerinner()
-
-  notes:
-    only called from qh_check_points()
-      seldom used since qh.MERGING is almost always set
-    if notverified>0 at end of routine
-      some points were well inside the hull.  If the hull contains
-      a lens-shaped component, these points were not verified.  Use
-      options 'Qi Tv' to verify all points.  (Exhaustive check also verifies)
-
-  design:
-    determine facet for each point (if any)
-    for each point
-      start with the assigned facet or with the first facet
-      find the best facet for the point and check all coplanar facets
-      error if point is outside of facet
-*/
-void qh_check_bestdist (void) {
-  boolT waserror= False, unassigned;
-  facetT *facet, *bestfacet, *errfacet1= NULL, *errfacet2= NULL;
-  facetT *facetlist; 
-  realT dist, maxoutside, maxdist= -REALmax;
-  pointT *point;
-  int numpart= 0, facet_i, facet_n, notgood= 0, notverified= 0;
-  setT *facets;
-
-  trace1((qh ferr, "qh_check_bestdist: check points below nearest facet.  Facet_list f%d\n",
-      qh facet_list->id));
-  maxoutside= qh_maxouter();
-  maxoutside += qh DISTround;
-  /* one more qh.DISTround for check computation */
-  trace1((qh ferr, "qh_check_bestdist: check that all points are within %2.2g of best facet\n", maxoutside));
-  facets= qh_pointfacet (/*qh facet_list*/);
-  if (!qh_QUICKhelp && qh PRINTprecision)
-    fprintf (qh ferr, "\n\
-qhull output completed.  Verifying that %d points are\n\
-below %2.2g of the nearest %sfacet.\n",
-	     qh_setsize(facets), maxoutside, (qh ONLYgood ?  "good " : ""));
-  FOREACHfacet_i_(facets) {  /* for each point with facet assignment */
-    if (facet)
-      unassigned= False;
-    else {
-      unassigned= True;
-      facet= qh facet_list;
-    }
-    point= qh_point(facet_i);
-    if (point == qh GOODpointp)
-      continue;
-    qh_distplane(point, facet, &dist);
-    numpart++;
-    bestfacet= qh_findbesthorizon (!qh_IScheckmax, point, facet, qh_NOupper, &dist, &numpart);
-    /* occurs after statistics reported */
-    maximize_(maxdist, dist);
-    if (dist > maxoutside) {
-      if (qh ONLYgood && !bestfacet->good 
-	  && !((bestfacet= qh_findgooddist (point, bestfacet, &dist, &facetlist))
-	       && dist > maxoutside))
-	notgood++;
-      else {
-	waserror= True;
-	fprintf(qh ferr, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n", 
-		facet_i, bestfacet->id, dist, maxoutside);
-	if (errfacet1 != bestfacet) {
-	  errfacet2= errfacet1;
-	  errfacet1= bestfacet;
-	}
-      }
-    }else if (unassigned && dist < -qh MAXcoplanar)
-      notverified++;
-  }
-  qh_settempfree (&facets);
-  if (notverified && !qh DELAUNAY && !qh_QUICKhelp && qh PRINTprecision) 
-    fprintf(qh ferr, "\n%d points were well inside the hull.  If the hull contains\n\
-a lens-shaped component, these points were not verified.  Use\n\
-options 'Qci Tv' to verify all points.\n", notverified); 
-  if (maxdist > qh outside_err) {
-    fprintf( qh ferr, "qhull precision error (qh_check_bestdist): a coplanar point is %6.2g from convex hull.  The maximum value (qh.outside_err) is %6.2g\n",
-              maxdist, qh outside_err);
-    qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
-  }else if (waserror && qh outside_err > REALmax/2)
-    qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
-  else if (waserror)
-    ;                       /* the error was logged to qh.ferr but does not effect the output */
-  trace0((qh ferr, "qh_check_bestdist: max distance outside %2.2g\n", maxdist));
-} /* check_bestdist */
-
-/*---------------------------------
-  
-  qh_check_maxout()
-    updates qh.max_outside by checking all points against bestfacet
-    if qh.ONLYgood, ignores !good facets
-
-  returns:
-    updates facet->maxoutside via qh_findbesthorizon()
-    sets qh.maxoutdone
-    if printing qh.min_vertex (qh_outerinner), 
-      it is updated to the current vertices
-    removes inside/coplanar points from coplanarset as needed
-
-  notes:
-    defines coplanar as min_vertex instead of MAXcoplanar 
-    may not need to check near-inside points because of qh.MAXcoplanar 
-      and qh.KEEPnearinside (before it was -DISTround)
-
-  see also:
-    qh_check_bestdist()
-
-  design:
-    if qh.min_vertex is needed
-      for all neighbors of all vertices
-        test distance from vertex to neighbor
-    determine facet for each point (if any)
-    for each point with an assigned facet
-      find the best facet for the point and check all coplanar facets
-        (updates outer planes)
-    remove near-inside points from coplanar sets
-*/
-#ifndef qh_NOmerge
-void qh_check_maxout (void) {
-  facetT *facet, *bestfacet, *neighbor, **neighborp, *facetlist;
-  realT dist, maxoutside, minvertex, old_maxoutside;
-  pointT *point;
-  int numpart= 0, facet_i, facet_n, notgood= 0;
-  setT *facets, *vertices;
-  vertexT *vertex;
-
-  trace1((qh ferr, "qh_check_maxout: check and update maxoutside for each facet.\n"));
-  maxoutside= minvertex= 0;
-  if (qh VERTEXneighbors 
-  && (qh PRINTsummary || qh KEEPinside || qh KEEPcoplanar 
-	|| qh TRACElevel || qh PRINTstatistics
-	|| qh PRINTout[0] == qh_PRINTsummary || qh PRINTout[0] == qh_PRINTnone)) { 
-    trace1((qh ferr, "qh_check_maxout: determine actual maxoutside and minvertex\n"));
-    vertices= qh_pointvertex (/*qh facet_list*/);
-    FORALLvertices {
-      FOREACHneighbor_(vertex) {
-        zinc_(Zdistvertex);  /* distance also computed by main loop below */
-	qh_distplane (vertex->point, neighbor, &dist);
-	minimize_(minvertex, dist);
-	if (-dist > qh TRACEdist || dist > qh TRACEdist 
-	|| neighbor == qh tracefacet || vertex == qh tracevertex)
-	  fprintf (qh ferr, "qh_check_maxout: p%d (v%d) is %.2g from f%d\n",
-		    qh_pointid (vertex->point), vertex->id, dist, neighbor->id);
-      }
-    }
-    if (qh MERGING) {
-      wmin_(Wminvertex, qh min_vertex);
-    }
-    qh min_vertex= minvertex;
-    qh_settempfree (&vertices);  
-  }
-  facets= qh_pointfacet (/*qh facet_list*/);
-  do {
-    old_maxoutside= fmax_(qh max_outside, maxoutside);
-    FOREACHfacet_i_(facets) {     /* for each point with facet assignment */
-      if (facet) { 
-	point= qh_point(facet_i);
-	if (point == qh GOODpointp)
-	  continue;
-	zinc_(Ztotcheck);
-	qh_distplane(point, facet, &dist);
-	numpart++;
-	bestfacet= qh_findbesthorizon (qh_IScheckmax, point, facet, !qh_NOupper, &dist, &numpart);
-	if (bestfacet && dist > maxoutside) {
-	  if (qh ONLYgood && !bestfacet->good 
-	  && !((bestfacet= qh_findgooddist (point, bestfacet, &dist, &facetlist))
-	       && dist > maxoutside))
-	    notgood++;
-	  else
-	    maxoutside= dist;
-	}
-	if (dist > qh TRACEdist || (bestfacet && bestfacet == qh tracefacet))
-	  fprintf (qh ferr, "qh_check_maxout: p%d is %.2g above f%d\n",
-		     qh_pointid (point), dist, bestfacet->id);
-      }
-    }
-  }while 
-    (maxoutside > 2*old_maxoutside);
-    /* if qh.maxoutside increases substantially, qh_SEARCHdist is not valid 
-          e.g., RBOX 5000 s Z1 G1e-13 t1001200614 | qhull */
-  zzadd_(Zcheckpart, numpart);
-  qh_settempfree (&facets);
-  wval_(Wmaxout)= maxoutside - qh max_outside;
-  wmax_(Wmaxoutside, qh max_outside);
-  qh max_outside= maxoutside;
-  qh_nearcoplanar (/*qh.facet_list*/);
-  qh maxoutdone= True;
-  trace1((qh ferr, "qh_check_maxout: maxoutside %2.2g, min_vertex %2.2g, outside of not good %d\n",
-       maxoutside, qh min_vertex, notgood));
-} /* check_maxout */
-#else /* qh_NOmerge */
-void qh_check_maxout (void) {
-}
-#endif
-
-/*---------------------------------
-  
-  qh_check_output()
-    performs the checks at the end of qhull algorithm
-    Maybe called after voronoi output.  Will recompute otherwise centrums are Voronoi centers instead
-*/
-void qh_check_output (void) {
-  int i;
-
-  if (qh STOPcone)
-    return;
-  if (qh VERIFYoutput | qh IStracing | qh CHECKfrequently) {
-    qh_checkpolygon (qh facet_list);
-    qh_checkflipped_all (qh facet_list);
-    qh_checkconvex (qh facet_list, qh_ALGORITHMfault);
-  }else if (!qh MERGING && qh_newstats (qhstat precision, &i)) {
-    qh_checkflipped_all (qh facet_list);
-    qh_checkconvex (qh facet_list, qh_ALGORITHMfault);
-  }
-} /* check_output */
-
-
-
-/*---------------------------------
-  
-  qh_check_point( point, facet, maxoutside, maxdist, errfacet1, errfacet2 )
-    check that point is less than maxoutside from facet
-*/
-void qh_check_point (pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2) {
-  realT dist;
-
-  /* occurs after statistics reported */
-  qh_distplane(point, facet, &dist);
-  if (dist > *maxoutside) {
-    if (*errfacet1 != facet) {
-      *errfacet2= *errfacet1;
-      *errfacet1= facet;
-    }
-    fprintf(qh ferr, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n", 
-	      qh_pointid(point), facet->id, dist, *maxoutside);
-  }
-  maximize_(*maxdist, dist);
-} /* qh_check_point */
-
-
-/*---------------------------------
-  
-  qh_check_points()
-    checks that all points are inside all facets
-
-  notes:
-    if many points and qh_check_maxout not called (i.e., !qh.MERGING), 
-       calls qh_findbesthorizon (seldom done).
-    ignores flipped facets
-    maxoutside includes 2 qh.DISTrounds
-      one qh.DISTround for the computed distances in qh_check_points
-    qh_printafacet and qh_printsummary needs only one qh.DISTround
-    the computation for qh.VERIFYdirect does not account for qh.other_points
-
-  design:
-    if many points
-      use qh_check_bestdist()
-    else
-      for all facets
-        for all points
-          check that point is inside facet
-*/
-void qh_check_points (void) {
-  facetT *facet, *errfacet1= NULL, *errfacet2= NULL;
-  realT total, maxoutside, maxdist= -REALmax;
-  pointT *point, **pointp, *pointtemp;
-  boolT testouter;
-
-  maxoutside= qh_maxouter();
-  maxoutside += qh DISTround;
-  /* one more qh.DISTround for check computation */
-  trace1((qh ferr, "qh_check_points: check all points below %2.2g of all facet planes\n",
-	  maxoutside));
-  if (qh num_good)   /* miss counts other_points and !good facets */
-     total= (float) qh num_good * qh num_points;
-  else
-     total= (float) qh num_facets * qh num_points;
-  if (total >= qh_VERIFYdirect && !qh maxoutdone) {
-    if (!qh_QUICKhelp && qh SKIPcheckmax && qh MERGING)
-      fprintf (qh ferr, "\n\
-qhull input warning: merging without checking outer planes ('Q5' or 'Po').\n\
-Verify may report that a point is outside of a facet.\n");
-    qh_check_bestdist();
-  }else {
-    if (qh_MAXoutside && qh maxoutdone)
-      testouter= True;
-    else
-      testouter= False;
-    if (!qh_QUICKhelp) {
-      if (qh MERGEexact)
-	fprintf (qh ferr, "\n\
-qhull input warning: exact merge ('Qx').  Verify may report that a point\n\
-is outside of a facet.  See qh-optq.htm#Qx\n");
-      else if (qh SKIPcheckmax || qh NOnearinside)
-	fprintf (qh ferr, "\n\
-qhull input warning: no outer plane check ('Q5') or no processing of\n\
-near-inside points ('Q8').  Verify may report that a point is outside\n\
-of a facet.\n");
-    }
-    if (qh PRINTprecision) {
-      if (testouter)
-	fprintf (qh ferr, "\n\
-Output completed.  Verifying that all points are below outer planes of\n\
-all %sfacets.  Will make %2.0f distance computations.\n", 
-	      (qh ONLYgood ?  "good " : ""), total);
-      else
-	fprintf (qh ferr, "\n\
-Output completed.  Verifying that all points are below %2.2g of\n\
-all %sfacets.  Will make %2.0f distance computations.\n", 
-	      maxoutside, (qh ONLYgood ?  "good " : ""), total);
-    }
-    FORALLfacets {
-      if (!facet->good && qh ONLYgood)
-        continue;
-      if (facet->flipped)
-        continue;
-      if (!facet->normal) {
-	fprintf( qh ferr, "qhull warning (qh_check_points): missing normal for facet f%d\n", facet->id);
-        continue;
-      }
-      if (testouter) {
-#if qh_MAXoutside
-	maxoutside= facet->maxoutside + 2* qh DISTround;
-	/* one DISTround to actual point and another to computed point */
-#endif
-      }
-      FORALLpoints {
-	if (point != qh GOODpointp)
-	  qh_check_point (point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2);
-      }
-      FOREACHpoint_(qh other_points) {
-	if (point != qh GOODpointp)
-	  qh_check_point (point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2);
-      }
-    }
-    if (maxdist > qh outside_err) {
-      fprintf( qh ferr, "qhull precision error (qh_check_points): a coplanar point is %6.2g from convex hull.  The maximum value (qh.outside_err) is %6.2g\n",
-                maxdist, qh outside_err );
-      qh_errexit2( qh_ERRprec, errfacet1, errfacet2 );
-    }else if (errfacet1 && qh outside_err > REALmax/2)
-        qh_errexit2( qh_ERRprec, errfacet1, errfacet2 );
-    else if (errfacet1)
-        ;  /* the error was logged to qh.ferr but does not effect the output */
-    trace0((qh ferr, "qh_check_points: max distance outside %2.2g\n", maxdist));
-  }
-} /* check_points */
-
-
-/*---------------------------------
-  
-  qh_checkconvex( facetlist, fault )
-    check that each ridge in facetlist is convex
-    fault = qh_DATAfault if reporting errors
-          = qh_ALGORITHMfault otherwise
-
-  returns:
-    counts Zconcaveridges and Zcoplanarridges
-    errors if concaveridge or if merging an coplanar ridge
-
-  note:
-    if not merging, 
-      tests vertices for neighboring simplicial facets
-    else if ZEROcentrum, 
-      tests vertices for neighboring simplicial   facets
-    else 
-      tests centrums of neighboring facets
-
-  design:
-    for all facets
-      report flipped facets
-      if ZEROcentrum and simplicial neighbors
-        test vertices for neighboring simplicial facets
-      else
-        test centrum against all neighbors 
-*/
-void qh_checkconvex(facetT *facetlist, int fault) {
-  facetT *facet, *neighbor, **neighborp, *errfacet1=NULL, *errfacet2=NULL;
-  vertexT *vertex;
-  realT dist;
-  pointT *centrum;
-  boolT waserror= False, centrum_warning= False, tempcentrum= False, allsimplicial;
-  int neighbor_i;
-
-  trace1((qh ferr, "qh_checkconvex: check all ridges are convex\n"));
-  if (!qh RERUN) {
-    zzval_(Zconcaveridges)= 0;
-    zzval_(Zcoplanarridges)= 0;
-  }
-  FORALLfacet_(facetlist) {
-    if (facet->flipped) {
-      qh_precision ("flipped facet");
-      fprintf (qh ferr, "qhull precision error: f%d is flipped (interior point is outside)\n",
-	       facet->id);
-      errfacet1= facet;
-      waserror= True;
-      continue;
-    }
-    if (qh MERGING && (!qh ZEROcentrum || !facet->simplicial || facet->tricoplanar))
-      allsimplicial= False;
-    else {
-      allsimplicial= True;
-      neighbor_i= 0;
-      FOREACHneighbor_(facet) {
-        vertex= SETelemt_(facet->vertices, neighbor_i++, vertexT);
-	if (!neighbor->simplicial || neighbor->tricoplanar) {
-	  allsimplicial= False;
-	  continue;
-	}
-        qh_distplane (vertex->point, neighbor, &dist);
-        if (dist > -qh DISTround) {
-	  if (fault == qh_DATAfault) {
-            qh_precision ("coplanar or concave ridge");
-	    fprintf (qh ferr, "qhull precision error: initial simplex is not convex. Distance=%.2g\n", dist);
-	    qh_errexit(qh_ERRsingular, NULL, NULL);
-	  }
-          if (dist > qh DISTround) {
-            zzinc_(Zconcaveridges);
-            qh_precision ("concave ridge");
-            fprintf (qh ferr, "qhull precision error: f%d is concave to f%d, since p%d (v%d) is %6.4g above\n",
-              facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
-            errfacet1= facet;
-            errfacet2= neighbor;
-            waserror= True;
-          }else if (qh ZEROcentrum) {
-            if (dist > 0) {     /* qh_checkzero checks that dist < - qh DISTround */
-              zzinc_(Zcoplanarridges); 
-              qh_precision ("coplanar ridge");
-              fprintf (qh ferr, "qhull precision error: f%d is clearly not convex to f%d, since p%d (v%d) is %6.4g above\n",
-                facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
-              errfacet1= facet;
-              errfacet2= neighbor;
-              waserror= True;
-	    }
-	  }else {              
-            zzinc_(Zcoplanarridges);
-            qh_precision ("coplanar ridge");
-            trace0((qh ferr, "qhull precision error: f%d may be coplanar to f%d, since p%d (v%d) is within %6.4g during p%d\n",
-              facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist, qh furthest_id));
-          }
-        }
-      }
-    }
-    if (!allsimplicial) {
-      if (qh CENTERtype == qh_AScentrum) {
-        if (!facet->center)
-          facet->center= qh_getcentrum (facet);
-        centrum= facet->center;
-      }else {
-	if (!centrum_warning && (!facet->simplicial || facet->tricoplanar)) {
-	   centrum_warning= True;
-	   fprintf (qh ferr, "qhull note: recomputing centrums for convexity test.  This may lead to false, precision errors.\n");
-	}
-        centrum= qh_getcentrum(facet);
-        tempcentrum= True;
-      }
-      FOREACHneighbor_(facet) {
-	if (qh ZEROcentrum && facet->simplicial && neighbor->simplicial)
-	  continue;
-	if (facet->tricoplanar || neighbor->tricoplanar)
-	  continue;
-        zzinc_(Zdistconvex);
-        qh_distplane (centrum, neighbor, &dist);
-        if (dist > qh DISTround) {
-          zzinc_(Zconcaveridges);
-          qh_precision ("concave ridge");
-          fprintf (qh ferr, "qhull precision error: f%d is concave to f%d.  Centrum of f%d is %6.4g above f%d\n",
-            facet->id, neighbor->id, facet->id, dist, neighbor->id);
-          errfacet1= facet;
-          errfacet2= neighbor;
-          waserror= True;
-	}else if (dist >= 0.0) {   /* if arithmetic always rounds the same,
-				     can test against centrum radius instead */
-          zzinc_(Zcoplanarridges);
-          qh_precision ("coplanar ridge");
-          fprintf (qh ferr, "qhull precision error: f%d is coplanar or concave to f%d.  Centrum of f%d is %6.4g above f%d\n",
-            facet->id, neighbor->id, facet->id, dist, neighbor->id);
-	  errfacet1= facet;
-	  errfacet2= neighbor;
-	  waserror= True;
-        }
-      }
-      if (tempcentrum)
-        qh_memfree(centrum, qh normal_size);
-    }
-  }
-  if (waserror && !qh FORCEoutput)
-    qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
-} /* checkconvex */
-
-
-/*---------------------------------
-  
-  qh_checkfacet( facet, newmerge, waserror )
-    checks for consistency errors in facet
-    newmerge set if from merge.c
-
-  returns:
-    sets waserror if any error occurs
-
-  checks:
-    vertex ids are inverse sorted
-    unless newmerge, at least hull_dim neighbors and vertices (exactly if simplicial)
-    if non-simplicial, at least as many ridges as neighbors
-    neighbors are not duplicated
-    ridges are not duplicated
-    in 3-d, ridges=verticies
-    (qh.hull_dim-1) ridge vertices
-    neighbors are reciprocated
-    ridge neighbors are facet neighbors and a ridge for every neighbor
-    simplicial neighbors match facetintersect
-    vertex intersection matches vertices of common ridges 
-    vertex neighbors and facet vertices agree
-    all ridges have distinct vertex sets
-
-  notes:  
-    uses neighbor->seen
-
-  design:
-    check sets
-    check vertices
-    check sizes of neighbors and vertices
-    check for qh_MERGEridge and qh_DUPLICATEridge flags
-    check neighbor set
-    check ridge set
-    check ridges, neighbors, and vertices
-*/
-void qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp) {
-  facetT *neighbor, **neighborp, *errother=NULL;
-  ridgeT *ridge, **ridgep, *errridge= NULL, *ridge2;
-  vertexT *vertex, **vertexp;
-  unsigned previousid= INT_MAX;
-  int numneighbors, numvertices, numridges=0, numRvertices=0;
-  boolT waserror= False;
-  int skipA, skipB, ridge_i, ridge_n, i;
-  setT *intersection;
-
-  if (facet->visible) {
-    fprintf (qh ferr, "qhull internal error (qh_checkfacet): facet f%d is on the visible_list\n",
-      facet->id);
-    qh_errexit (qh_ERRqhull, facet, NULL);
-  }
-  if (!facet->normal) {
-    fprintf (qh ferr, "qhull internal error (qh_checkfacet): facet f%d does not have  a normal\n",
-      facet->id);
-    waserror= True;
-  }
-  qh_setcheck (facet->vertices, "vertices for f", facet->id);
-  qh_setcheck (facet->ridges, "ridges for f", facet->id);
-  qh_setcheck (facet->outsideset, "outsideset for f", facet->id);
-  qh_setcheck (facet->coplanarset, "coplanarset for f", facet->id);
-  qh_setcheck (facet->neighbors, "neighbors for f", facet->id);
-  FOREACHvertex_(facet->vertices) {
-    if (vertex->deleted) {
-      fprintf(qh ferr, "qhull internal error (qh_checkfacet): deleted vertex v%d in f%d\n", vertex->id, facet->id);
-      qh_errprint ("ERRONEOUS", NULL, NULL, NULL, vertex);
-      waserror= True;
-    }
-    if (vertex->id >= previousid) {
-      fprintf(qh ferr, "qhull internal error (qh_checkfacet): vertices of f%d are not in descending id order at v%d\n", facet->id, vertex->id);
-      waserror= True;
-      break;
-    }
-    previousid= vertex->id;
-  }
-  numneighbors= qh_setsize(facet->neighbors);
-  numvertices= qh_setsize(facet->vertices);
-  numridges= qh_setsize(facet->ridges);
-  if (facet->simplicial) {
-    if (numvertices+numneighbors != 2*qh hull_dim 
-    && !facet->degenerate && !facet->redundant) {
-      fprintf(qh ferr, "qhull internal error (qh_checkfacet): for simplicial facet f%d, #vertices %d + #neighbors %d != 2*qh hull_dim\n", 
-                facet->id, numvertices, numneighbors);
-      qh_setprint (qh ferr, "", facet->neighbors);
-      waserror= True;
-    }
-  }else { /* non-simplicial */
-    if (!newmerge 
-    &&(numvertices < qh hull_dim || numneighbors < qh hull_dim)
-    && !facet->degenerate && !facet->redundant) {
-      fprintf(qh ferr, "qhull internal error (qh_checkfacet): for facet f%d, #vertices %d or #neighbors %d < qh hull_dim\n",
-         facet->id, numvertices, numneighbors);
-       waserror= True;
-    }
-    /* in 3-d, can get a vertex twice in an edge list, e.g., RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv TP624 TW1e-13 T4 */
-    if (numridges < numneighbors
-    ||(qh hull_dim == 3 && numvertices > numridges && !qh NEWfacets)
-    ||(qh hull_dim == 2 && numridges + numvertices + numneighbors != 6)) {
-      if (!facet->degenerate && !facet->redundant) {
-	fprintf(qh ferr, "qhull internal error (qh_checkfacet): for facet f%d, #ridges %d < #neighbors %d or (3-d) > #vertices %d or (2-d) not all 2\n",
-	    facet->id, numridges, numneighbors, numvertices);
-	waserror= True;
-      }
-    }
-  }
-  FOREACHneighbor_(facet) {
-    if (neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge) {
-      fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d still has a MERGE or DUP neighbor\n", facet->id);
-      qh_errexit (qh_ERRqhull, facet, NULL);
-    }
-    neighbor->seen= True;
-  }
-  FOREACHneighbor_(facet) {
-    if (!qh_setin(neighbor->neighbors, facet)) {
-      fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d has neighbor f%d, but f%d does not have neighbor f%d\n",
-	      facet->id, neighbor->id, neighbor->id, facet->id);
-      errother= neighbor;
-      waserror= True;
-    }
-    if (!neighbor->seen) {
-      fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d has a duplicate neighbor f%d\n",
-	      facet->id, neighbor->id);
-      errother= neighbor;
-      waserror= True;
-    }    
-    neighbor->seen= False;
-  }
-  FOREACHridge_(facet->ridges) {
-    qh_setcheck (ridge->vertices, "vertices for r", ridge->id);
-    ridge->seen= False;
-  }
-  FOREACHridge_(facet->ridges) {
-    if (ridge->seen) {
-      fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d has a duplicate ridge r%d\n",
-	      facet->id, ridge->id);
-      errridge= ridge;
-      waserror= True;
-    }    
-    ridge->seen= True;
-    numRvertices= qh_setsize(ridge->vertices);
-    if (numRvertices != qh hull_dim - 1) {
-      fprintf(qh ferr, "qhull internal error (qh_checkfacet): ridge between f%d and f%d has %d vertices\n", 
-                ridge->top->id, ridge->bottom->id, numRvertices);
-      errridge= ridge;
-      waserror= True;
-    }
-    neighbor= otherfacet_(ridge, facet);
-    neighbor->seen= True;
-    if (!qh_setin(facet->neighbors, neighbor)) {
-      fprintf(qh ferr, "qhull internal error (qh_checkfacet): for facet f%d, neighbor f%d of ridge r%d not in facet\n",
-           facet->id, neighbor->id, ridge->id);
-      errridge= ridge;
-      waserror= True;
-    }
-  }
-  if (!facet->simplicial) {
-    FOREACHneighbor_(facet) {
-      if (!neighbor->seen) {
-        fprintf(qh ferr, "qhull internal error (qh_checkfacet): facet f%d does not have a ridge for neighbor f%d\n",
-	      facet->id, neighbor->id);
-	errother= neighbor;
-        waserror= True;
-      }
-      intersection= qh_vertexintersect_new(facet->vertices, neighbor->vertices);
-      qh_settemppush (intersection);
-      FOREACHvertex_(facet->vertices) {
-	vertex->seen= False;
-	vertex->seen2= False;
-      }
-      FOREACHvertex_(intersection)
-	vertex->seen= True;
-      FOREACHridge_(facet->ridges) {
-	if (neighbor != otherfacet_(ridge, facet))
-	    continue;
-	FOREACHvertex_(ridge->vertices) {
-	  if (!vertex->seen) {
-	    fprintf (qh ferr, "qhull internal error (qh_checkfacet): vertex v%d in r%d not in f%d intersect f%d\n",
-  	          vertex->id, ridge->id, facet->id, neighbor->id);
-	    qh_errexit (qh_ERRqhull, facet, ridge);
-	  }
-	  vertex->seen2= True;
-	}
-      }
-      if (!newmerge) {
-	FOREACHvertex_(intersection) {
-	  if (!vertex->seen2) {
-	    if (qh IStracing >=3 || !qh MERGING) {
-	      fprintf (qh ferr, "qhull precision error (qh_checkfacet): vertex v%d in f%d intersect f%d but\n\
- not in a ridge.  This is ok under merging.  Last point was p%d\n",
-		     vertex->id, facet->id, neighbor->id, qh furthest_id);
-	      if (!qh FORCEoutput && !qh MERGING) {
-		qh_errprint ("ERRONEOUS", facet, neighbor, NULL, vertex);
-		if (!qh MERGING)
-		  qh_errexit (qh_ERRqhull, NULL, NULL);
-	      }
-	    }
-	  }
-	}
-      }      
-      qh_settempfree (&intersection);
-    }
-  }else { /* simplicial */
-    FOREACHneighbor_(facet) {
-      if (neighbor->simplicial) {    
-	skipA= SETindex_(facet->neighbors, neighbor);
-	skipB= qh_setindex (neighbor->neighbors, facet);
-	if (!qh_setequal_skip (facet->vertices, skipA, neighbor->vertices, skipB)) {
-	  fprintf (qh ferr, "qhull internal error (qh_checkfacet): facet f%d skip %d and neighbor f%d skip %d do not match \n",
-		   facet->id, skipA, neighbor->id, skipB);
-	  errother= neighbor;
-	  waserror= True;
-	}
-      }
-    }
-  }
-  if (qh hull_dim < 5 && (qh IStracing > 2 || qh CHECKfrequently)) {
-    FOREACHridge_i_(facet->ridges) {           /* expensive */
-      for (i= ridge_i+1; i < ridge_n; i++) {
-	ridge2= SETelemt_(facet->ridges, i, ridgeT);
-	if (qh_setequal (ridge->vertices, ridge2->vertices)) {
-	  fprintf (qh ferr, "qh_checkfacet: ridges r%d and r%d have the same vertices\n",
-		  ridge->id, ridge2->id);
-	  errridge= ridge;
-	  waserror= True;
-	}
-      }
-    }
-  }
-  if (waserror) {
-    qh_errprint("ERRONEOUS", facet, errother, errridge, NULL);
-    *waserrorp= True;
-  }
-} /* checkfacet */
-
-
-/*---------------------------------
-  
-  qh_checkflipped_all( facetlist )
-    checks orientation of facets in list against interior point
-*/
-void qh_checkflipped_all (facetT *facetlist) {
-  facetT *facet;
-  boolT waserror= False;
-  realT dist;
-
-  if (facetlist == qh facet_list)
-    zzval_(Zflippedfacets)= 0;
-  FORALLfacet_(facetlist) {
-    if (facet->normal && !qh_checkflipped (facet, &dist, !qh_ALL)) {
-      fprintf(qh ferr, "qhull precision error: facet f%d is flipped, distance= %6.12g\n",
-	      facet->id, dist);
-      if (!qh FORCEoutput) {
-	qh_errprint("ERRONEOUS", facet, NULL, NULL, NULL);
-	waserror= True;
-      }
-    }
-  }
-  if (waserror) {
-    fprintf (qh ferr, "\n\
-A flipped facet occurs when its distance to the interior point is\n\
-greater than %2.2g, the maximum roundoff error.\n", -qh DISTround);
-    qh_errexit(qh_ERRprec, NULL, NULL);
-  }
-} /* checkflipped_all */
-
-/*---------------------------------
-  
-  qh_checkpolygon( facetlist )
-    checks the correctness of the structure
-
-  notes:
-    call with either qh.facet_list or qh.newfacet_list
-    checks num_facets and num_vertices if qh.facet_list
-
-  design:
-    for each facet
-      checks facet and outside set
-    initializes vertexlist
-    for each facet
-      checks vertex set
-    if checking all facets (qh.facetlist)
-      check facet count
-      if qh.VERTEXneighbors
-        check vertex neighbors and count
-      check vertex count
-*/
-void qh_checkpolygon(facetT *facetlist) {
-  facetT *facet;
-  vertexT *vertex, **vertexp, *vertexlist;
-  int numfacets= 0, numvertices= 0, numridges= 0;
-  int totvneighbors= 0, totvertices= 0;
-  boolT waserror= False, nextseen= False, visibleseen= False;
-  
-  trace1((qh ferr, "qh_checkpolygon: check all facets from f%d\n", facetlist->id));
-  if (facetlist != qh facet_list || qh ONLYgood)
-    nextseen= True;
-  FORALLfacet_(facetlist) {
-    if (facet == qh visible_list)
-      visibleseen= True;
-    if (!facet->visible) {
-      if (!nextseen) {
-	if (facet == qh facet_next)
-	  nextseen= True;
-	else if (qh_setsize (facet->outsideset)) {
-	  if (!qh NARROWhull
-#if !qh_COMPUTEfurthest
-	       || facet->furthestdist >= qh MINoutside
-#endif
-			) {
-	    fprintf (qh ferr, "qhull internal error (qh_checkpolygon): f%d has outside points before qh facet_next\n",
-		     facet->id);
-	    qh_errexit (qh_ERRqhull, facet, NULL);
-	  }
-	}
-      }
-      numfacets++;
-      qh_checkfacet(facet, False, &waserror);
-    }
-  }
-  if (qh visible_list && !visibleseen && facetlist == qh facet_list) {
-    fprintf (qh ferr, "qhull internal error (qh_checkpolygon): visible list f%d no longer on facet list\n", qh visible_list->id);
-    qh_printlists();
-    qh_errexit (qh_ERRqhull, qh visible_list, NULL);
-  }
-  if (facetlist == qh facet_list)
-    vertexlist= qh vertex_list;
-  else if (facetlist == qh newfacet_list)
-    vertexlist= qh newvertex_list;
-  else
-    vertexlist= NULL;
-  FORALLvertex_(vertexlist) {
-    vertex->seen= False;
-    vertex->visitid= 0;
-  }  
-  FORALLfacet_(facetlist) {
-    if (facet->visible)
-      continue;
-    if (facet->simplicial)
-      numridges += qh hull_dim;
-    else
-      numridges += qh_setsize (facet->ridges);
-    FOREACHvertex_(facet->vertices) {
-      vertex->visitid++;
-      if (!vertex->seen) {
-	vertex->seen= True;
-	numvertices++;
-	if (qh_pointid (vertex->point) == -1) {
-	  fprintf (qh ferr, "qhull internal error (qh_checkpolygon): unknown point %p for vertex v%d first_point %p\n",
-		   vertex->point, vertex->id, qh first_point);
-	  waserror= True;
-	}
-      }
-    }
-  }
-  qh vertex_visit += numfacets;
-  if (facetlist == qh facet_list) {
-    if (numfacets != qh num_facets - qh num_visible) {
-      fprintf(qh ferr, "qhull internal error (qh_checkpolygon): actual number of facets is %d, cumulative facet count is %d - %d visible facets\n",
-	      numfacets, qh num_facets, qh num_visible);
-      waserror= True;
-    }
-    qh vertex_visit++;
-    if (qh VERTEXneighbors) {
-      FORALLvertices {
-	qh_setcheck (vertex->neighbors, "neighbors for v", vertex->id);
-	if (vertex->deleted)
-	  continue;
-	totvneighbors += qh_setsize (vertex->neighbors);
-      }
-      FORALLfacet_(facetlist)
-	totvertices += qh_setsize (facet->vertices);
-      if (totvneighbors != totvertices) {
-	fprintf(qh ferr, "qhull internal error (qh_checkpolygon): vertex neighbors inconsistent.  Totvneighbors %d, totvertices %d\n",
-		totvneighbors, totvertices);
-	waserror= True;
-      }
-    }
-    if (numvertices != qh num_vertices - qh_setsize(qh del_vertices)) {
-      fprintf(qh ferr, "qhull internal error (qh_checkpolygon): actual number of vertices is %d, cumulative vertex count is %d\n",
-	      numvertices, qh num_vertices - qh_setsize(qh del_vertices));
-      waserror= True;
-    }
-    if (qh hull_dim == 2 && numvertices != numfacets) {
-      fprintf (qh ferr, "qhull internal error (qh_checkpolygon): #vertices %d != #facets %d\n",
-        numvertices, numfacets);
-      waserror= True;
-    }
-    if (qh hull_dim == 3 && numvertices + numfacets - numridges/2 != 2) {
-      fprintf (qh ferr, "qhull warning: #vertices %d + #facets %d - #edges %d != 2\n\
-	A vertex appears twice in a edge list.  May occur during merging.",
-        numvertices, numfacets, numridges/2);
-      /* occurs if lots of merging and a vertex ends up twice in an edge list.  e.g., RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv */
-    }
-  }
-  if (waserror) 
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-} /* checkpolygon */
-
-
-/*---------------------------------
-  
-  qh_checkvertex( vertex )
-    check vertex for consistency
-    checks vertex->neighbors
-
-  notes:
-    neighbors checked efficiently in checkpolygon
-*/
-void qh_checkvertex (vertexT *vertex) {
-  boolT waserror= False;
-  facetT *neighbor, **neighborp, *errfacet=NULL;
-
-  if (qh_pointid (vertex->point) == -1) {
-    fprintf (qh ferr, "qhull internal error (qh_checkvertex): unknown point id %p\n", vertex->point);
-    waserror= True;
-  }
-  if (vertex->id >= qh vertex_id) {
-    fprintf (qh ferr, "qhull internal error (qh_checkvertex): unknown vertex id %d\n", vertex->id);
-    waserror= True;
-  }
-  if (!waserror && !vertex->deleted) {
-    if (qh_setsize (vertex->neighbors)) {
-      FOREACHneighbor_(vertex) {
-        if (!qh_setin (neighbor->vertices, vertex)) {
-          fprintf (qh ferr, "qhull internal error (qh_checkvertex): neighbor f%d does not contain v%d\n", neighbor->id, vertex->id);
-	  errfacet= neighbor;
-	  waserror= True;
-	}
-      }
-    }
-  }
-  if (waserror) {
-    qh_errprint ("ERRONEOUS", NULL, NULL, NULL, vertex);
-    qh_errexit (qh_ERRqhull, errfacet, NULL);
-  }
-} /* checkvertex */
-  
-/*---------------------------------
-  
-  qh_clearcenters( type )
-    clear old data from facet->center
-
-  notes:
-    sets new centertype
-    nop if CENTERtype is the same
-*/
-void qh_clearcenters (qh_CENTER type) {
-  facetT *facet;
-  
-  if (qh CENTERtype != type) {
-    FORALLfacets {
-      if (qh CENTERtype == qh_ASvoronoi){
-        if (facet->center) {
-          qh_memfree (facet->center, qh center_size);
-          facet->center= NULL;
-        }
-      }else /* qh CENTERtype == qh_AScentrum */ {
-        if (facet->center) {
-          qh_memfree (facet->center, qh normal_size);
-	  facet->center= NULL;
-        }
-      }
-    }
-    qh CENTERtype= type;
-  }
-  trace2((qh ferr, "qh_clearcenters: switched to center type %d\n", type));
-} /* clearcenters */
-
-/*---------------------------------
-  
-  qh_createsimplex( vertices )
-    creates a simplex from a set of vertices
-
-  returns:
-    initializes qh.facet_list to the simplex
-    initializes qh.newfacet_list, .facet_tail
-    initializes qh.vertex_list, .newvertex_list, .vertex_tail
-
-  design:
-    initializes lists
-    for each vertex
-      create a new facet
-    for each new facet
-      create its neighbor set
-*/
-void qh_createsimplex(setT *vertices) {
-  facetT *facet= NULL, *newfacet;
-  boolT toporient= True;
-  int vertex_i, vertex_n, nth;
-  setT *newfacets= qh_settemp (qh hull_dim+1);
-  vertexT *vertex;
-  
-  qh facet_list= qh newfacet_list= qh facet_tail= qh_newfacet();
-  qh num_facets= qh num_vertices= qh num_visible= 0;
-  qh vertex_list= qh newvertex_list= qh vertex_tail= qh_newvertex(NULL);
-  FOREACHvertex_i_(vertices) {
-    newfacet= qh_newfacet();
-    newfacet->vertices= qh_setnew_delnthsorted (vertices, vertex_n,
-						vertex_i, 0);
-    newfacet->toporient= toporient;
-    qh_appendfacet(newfacet);
-    newfacet->newfacet= True;
-    qh_appendvertex (vertex);
-    qh_setappend (&newfacets, newfacet);
-    toporient ^= True;
-  }
-  FORALLnew_facets {
-    nth= 0;
-    FORALLfacet_(qh newfacet_list) {
-      if (facet != newfacet) 
-        SETelem_(newfacet->neighbors, nth++)= facet;
-    }
-    qh_settruncate (newfacet->neighbors, qh hull_dim);
-  }
-  qh_settempfree (&newfacets);
-  trace1((qh ferr, "qh_createsimplex: created simplex\n"));
-} /* createsimplex */
-
-/*---------------------------------
-  
-  qh_delridge( ridge )
-    deletes ridge from data structures it belongs to
-    frees up its memory
-
-  notes:
-    in merge.c, caller sets vertex->delridge for each vertex
-    ridges also freed in qh_freeqhull
-*/
-void qh_delridge(ridgeT *ridge) {
-  void **freelistp; /* used !qh_NOmem */
-  
-  qh_setdel(ridge->top->ridges, ridge);
-  qh_setdel(ridge->bottom->ridges, ridge);
-  qh_setfree(&(ridge->vertices));
-  qh_memfree_(ridge, sizeof(ridgeT), freelistp);
-} /* delridge */
-
-
-/*---------------------------------
-  
-  qh_delvertex( vertex )
-    deletes a vertex and frees its memory
-
-  notes:
-    assumes vertex->adjacencies have been updated if needed
-    unlinks from vertex_list
-*/
-void qh_delvertex (vertexT *vertex) {
-
-  if (vertex == qh tracevertex)
-    qh tracevertex= NULL;
-  qh_removevertex (vertex);
-  qh_setfree (&vertex->neighbors);
-  qh_memfree(vertex, sizeof(vertexT));
-} /* delvertex */
-
-
-/*---------------------------------
-  
-  qh_facet3vertex(  )
-    return temporary set of 3-d vertices in qh_ORIENTclock order
-
-  design:
-    if simplicial facet
-      build set from facet->vertices with facet->toporient
-    else
-      for each ridge in order
-        build set from ridge's vertices
-*/
-setT *qh_facet3vertex (facetT *facet) {
-  ridgeT *ridge, *firstridge;
-  vertexT *vertex;
-  int cntvertices, cntprojected=0;
-  setT *vertices;
-
-  cntvertices= qh_setsize(facet->vertices);
-  vertices= qh_settemp (cntvertices);
-  if (facet->simplicial) {
-    if (cntvertices != 3) {
-      fprintf (qh ferr, "qhull internal error (qh_facet3vertex): only %d vertices for simplicial facet f%d\n", 
-                  cntvertices, facet->id);
-      qh_errexit(qh_ERRqhull, facet, NULL);
-    }
-    qh_setappend (&vertices, SETfirst_(facet->vertices));
-    if (facet->toporient ^ qh_ORIENTclock)
-      qh_setappend (&vertices, SETsecond_(facet->vertices));
-    else
-      qh_setaddnth (&vertices, 0, SETsecond_(facet->vertices));
-    qh_setappend (&vertices, SETelem_(facet->vertices, 2));
-  }else {
-    ridge= firstridge= SETfirstt_(facet->ridges, ridgeT);   /* no infinite */
-    while ((ridge= qh_nextridge3d (ridge, facet, &vertex))) {
-      qh_setappend (&vertices, vertex);
-      if (++cntprojected > cntvertices || ridge == firstridge)
-        break;
-    }
-    if (!ridge || cntprojected != cntvertices) {
-      fprintf (qh ferr, "qhull internal error (qh_facet3vertex): ridges for facet %d don't match up.  got at least %d\n", 
-                  facet->id, cntprojected);
-      qh_errexit(qh_ERRqhull, facet, ridge);
-    }
-  }
-  return vertices;
-} /* facet3vertex */
-
-/*---------------------------------
-  
-  qh_findbestfacet( point, bestoutside, bestdist, isoutside )
-    find facet that is furthest below a point 
-
-    for Delaunay triangulations, 
-      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
-      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates. 
-
-  returns:
-    if bestoutside is set (e.g., qh_ALL)
-      returns best facet that is not upperdelaunay
-      if Delaunay and inside, point is outside circumsphere of bestfacet
-    else
-      returns first facet below point
-      if point is inside, returns nearest, !upperdelaunay facet
-    distance to facet
-    isoutside set if outside of facet
-    
-  notes:
-    this works for all distributions
-    if inside, qh_findbestfacet performs an exhaustive search
-       this may be too conservative.  Sometimes it is clearly required.
-    qh_findbestfacet is not used by qhull.
-    uses qh.visit_id and qh.coplanarset
-    
-  see:
-    qh_findbest
-*/
-facetT *qh_findbestfacet (pointT *point, boolT bestoutside,
-           realT *bestdist, boolT *isoutside) {
-  facetT *bestfacet= NULL;
-  int numpart, totpart= 0;
-  
-  bestfacet= qh_findbest (point, qh facet_list, 
-			    bestoutside, !qh_ISnewfacets, bestoutside /* qh_NOupper */,
-			    bestdist, isoutside, &totpart);
-  if (*bestdist < -qh DISTround) {
-    bestfacet= qh_findfacet_all (point, bestdist, isoutside, &numpart);
-    totpart += numpart;
-    if ((isoutside && bestoutside)
-    || (!isoutside && bestfacet->upperdelaunay)) {
-      bestfacet= qh_findbest (point, bestfacet, 
-			    bestoutside, False, bestoutside,
-			    bestdist, isoutside, &totpart);
-      totpart += numpart;
-    }
-  }
-  trace3((qh ferr, "qh_findbestfacet: f%d dist %2.2g isoutside %d totpart %d\n",
-	  bestfacet->id, *bestdist, *isoutside, totpart));
-  return bestfacet;
-} /* findbestfacet */ 
- 
-/*---------------------------------
-  
-  qh_findfacet_all( point, bestdist, isoutside, numpart )
-    exhaustive search for facet below a point 
-
-    for Delaunay triangulations, 
-      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
-      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates. 
-
-  returns:
-    returns first facet below point
-    if point is inside, 
-      returns nearest facet
-    distance to facet
-    isoutside if point is outside of the hull
-    number of distance tests
-*/
-facetT *qh_findfacet_all (pointT *point, realT *bestdist, boolT *isoutside,
-			  int *numpart) {
-  facetT *bestfacet= NULL, *facet;
-  realT dist;
-  int totpart= 0;
-  
-  *bestdist= REALmin;
-  *isoutside= False;
-  FORALLfacets {
-    if (facet->flipped || !facet->normal)
-      continue;
-    totpart++;
-    qh_distplane (point, facet, &dist);
-    if (dist > *bestdist) {
-      *bestdist= dist;
-      bestfacet= facet;
-      if (dist > qh MINoutside) {
-        *isoutside= True;
-        break;
-      }
-    }
-  }
-  *numpart= totpart;
-  trace3((qh ferr, "qh_findfacet_all: f%d dist %2.2g isoutside %d totpart %d\n",
-	  getid_(bestfacet), *bestdist, *isoutside, totpart));
-  return bestfacet;
-} /* findfacet_all */ 
- 
-/*---------------------------------
-  
-  qh_findgood( facetlist, goodhorizon )
-    identify good facets for qh.PRINTgood
-    if qh.GOODvertex>0
-      facet includes point as vertex
-      if !match, returns goodhorizon
-      inactive if qh.MERGING
-    if qh.GOODpoint
-      facet is visible or coplanar (>0) or not visible (<0) 
-    if qh.GOODthreshold
-      facet->normal matches threshold
-    if !goodhorizon and !match, 
-      selects facet with closest angle
-      sets GOODclosest
-      
-  returns:
-    number of new, good facets found
-    determines facet->good
-    may update qh.GOODclosest
-    
-  notes:
-    qh_findgood_all further reduces the good region
-
-  design:
-    count good facets
-    mark good facets for qh.GOODpoint  
-    mark good facets for qh.GOODthreshold
-    if necessary
-      update qh.GOODclosest  
-*/
-int qh_findgood (facetT *facetlist, int goodhorizon) {
-  facetT *facet, *bestfacet= NULL;
-  realT angle, bestangle= REALmax, dist;
-  int  numgood=0;
-
-  FORALLfacet_(facetlist) {
-    if (facet->good)
-      numgood++;
-  }
-  if (qh GOODvertex>0 && !qh MERGING) {
-    FORALLfacet_(facetlist) {
-      if (!qh_isvertex (qh GOODvertexp, facet->vertices)) {
-        facet->good= False;
-        numgood--;
-      }
-    }
-  }
-  if (qh GOODpoint && numgood) {
-    FORALLfacet_(facetlist) {
-      if (facet->good && facet->normal) {
-        zinc_(Zdistgood);
-        qh_distplane (qh GOODpointp, facet, &dist);
-        if ((qh GOODpoint > 0) ^ (dist > 0.0)) {
-          facet->good= False;
-          numgood--;
-        }
-      }
-    }
-  }
-  if (qh GOODthreshold && (numgood || goodhorizon || qh GOODclosest)) {
-    FORALLfacet_(facetlist) {
-      if (facet->good && facet->normal) {
-        if (!qh_inthresholds (facet->normal, &angle)) {
-          facet->good= False;
-          numgood--;
-          if (angle < bestangle) {
-            bestangle= angle;
-            bestfacet= facet;
-          }
-        }
-      }
-    }
-    if (!numgood && (!goodhorizon || qh GOODclosest)) {
-      if (qh GOODclosest) {
-	if (qh GOODclosest->visible)
-	  qh GOODclosest= NULL;
-	else {
-	  qh_inthresholds (qh GOODclosest->normal, &angle);
-	  if (angle < bestangle)
-	    bestfacet= qh GOODclosest;
-	}
-      }
-      if (bestfacet && bestfacet != qh GOODclosest) {
-	if (qh GOODclosest)
-	  qh GOODclosest->good= False;
-	qh GOODclosest= bestfacet;
-	bestfacet->good= True;
-	numgood++;
-	trace2((qh ferr, "qh_findgood: f%d is closest (%2.2g) to thresholds\n", 
-           bestfacet->id, bestangle));
-	return numgood;
-      }
-    }else if (qh GOODclosest) { /* numgood > 0 */
-      qh GOODclosest->good= False;
-      qh GOODclosest= NULL;
-    }
-  }
-  zadd_(Zgoodfacet, numgood);
-  trace2((qh ferr, "qh_findgood: found %d good facets with %d good horizon\n",
-               numgood, goodhorizon));
-  if (!numgood && qh GOODvertex>0 && !qh MERGING) 
-    return goodhorizon;
-  return numgood;
-} /* findgood */
-
-/*---------------------------------
-  
-  qh_findgood_all( facetlist )
-    apply other constraints for good facets (used by qh.PRINTgood)
-    if qh.GOODvertex 
-      facet includes (>0) or doesn't include (<0) point as vertex
-      if last good facet and ONLYgood, prints warning and continues
-    if qh.SPLITthresholds
-      facet->normal matches threshold, or if none, the closest one
-    calls qh_findgood
-    nop if good not used
-
-  returns:
-    clears facet->good if not good
-    sets qh.num_good
-
-  notes:
-    this is like qh_findgood but more restrictive
-
-  design:
-    uses qh_findgood to mark good facets
-    marks facets for qh.GOODvertex
-    marks facets for qh.SPLITthreholds  
-*/
-void qh_findgood_all (facetT *facetlist) {
-  facetT *facet, *bestfacet=NULL;
-  realT angle, bestangle= REALmax;
-  int  numgood=0, startgood;
-
-  if (!qh GOODvertex && !qh GOODthreshold && !qh GOODpoint 
-  && !qh SPLITthresholds)
-    return;
-  if (!qh ONLYgood)
-    qh_findgood (qh facet_list, 0);
-  FORALLfacet_(facetlist) {
-    if (facet->good)
-      numgood++;
-  }
-  if (qh GOODvertex <0 || (qh GOODvertex > 0 && qh MERGING)) {
-    FORALLfacet_(facetlist) {
-      if (facet->good && ((qh GOODvertex > 0) ^ !!qh_isvertex (qh GOODvertexp, facet->vertices))) {
-        if (!--numgood) {
-	  if (qh ONLYgood) {
-            fprintf (qh ferr, "qhull warning: good vertex p%d does not match last good facet f%d.  Ignored.\n",
-               qh_pointid(qh GOODvertexp), facet->id);
-	    return;
-	  }else if (qh GOODvertex > 0)
-            fprintf (qh ferr, "qhull warning: point p%d is not a vertex ('QV%d').\n",
-		qh GOODvertex-1, qh GOODvertex-1);
-	  else
-            fprintf (qh ferr, "qhull warning: point p%d is a vertex for every facet ('QV-%d').\n",
-	        -qh GOODvertex - 1, -qh GOODvertex - 1);
-        }
-        facet->good= False;
-      }
-    }
-  }
-  startgood= numgood;
-  if (qh SPLITthresholds) {
-    FORALLfacet_(facetlist) {
-      if (facet->good) {
-        if (!qh_inthresholds (facet->normal, &angle)) {
-          facet->good= False;
-          numgood--;
-          if (angle < bestangle) {
-            bestangle= angle;
-            bestfacet= facet;
-          }
-        }
-      }
-    }
-    if (!numgood && bestfacet) {
-      bestfacet->good= True;
-      numgood++;
-      trace0((qh ferr, "qh_findgood_all: f%d is closest (%2.2g) to thresholds\n", 
-           bestfacet->id, bestangle));
-      return;
-    }
-  }
-  qh num_good= numgood;
-  trace0((qh ferr, "qh_findgood_all: %d good facets remain out of %d facets\n",
-        numgood, startgood));
-} /* findgood_all */
-
-/*---------------------------------
-  
-  qh_furthestnext()
-    set qh.facet_next to facet with furthest of all furthest points
-    searches all facets on qh.facet_list
-
-  notes:
-    this may help avoid precision problems
-*/
-void qh_furthestnext (void /* qh facet_list */) {
-  facetT *facet, *bestfacet= NULL;
-  realT dist, bestdist= -REALmax;
-
-  FORALLfacets {
-    if (facet->outsideset) {
-#if qh_COMPUTEfurthest
-      pointT *furthest;
-      furthest= (pointT*)qh_setlast (facet->outsideset);
-      zinc_(Zcomputefurthest);
-      qh_distplane (furthest, facet, &dist);
-#else
-      dist= facet->furthestdist;
-#endif
-      if (dist > bestdist) {
-	bestfacet= facet;
-	bestdist= dist;
-      }
-    }
-  }
-  if (bestfacet) {
-    qh_removefacet (bestfacet);
-    qh_prependfacet (bestfacet, &qh facet_next);
-    trace1((qh ferr, "qh_furthestnext: made f%d next facet (dist %.2g)\n",
-	    bestfacet->id, bestdist));
-  }
-} /* furthestnext */
-
-/*---------------------------------
-  
-  qh_furthestout( facet )
-    make furthest outside point the last point of outsideset
-
-  returns:
-    updates facet->outsideset
-    clears facet->notfurthest
-    sets facet->furthestdist
-
-  design:
-    determine best point of outsideset
-    make it the last point of outsideset
-*/
-void qh_furthestout (facetT *facet) {
-  pointT *point, **pointp, *bestpoint= NULL;
-  realT dist, bestdist= -REALmax;
-
-  FOREACHpoint_(facet->outsideset) {
-    qh_distplane (point, facet, &dist);
-    zinc_(Zcomputefurthest);
-    if (dist > bestdist) {
-      bestpoint= point;
-      bestdist= dist;
-    }
-  }
-  if (bestpoint) {
-    qh_setdel (facet->outsideset, point);
-    qh_setappend (&facet->outsideset, point);
-#if !qh_COMPUTEfurthest
-    facet->furthestdist= bestdist;
-#endif
-  }
-  facet->notfurthest= False;
-  trace3((qh ferr, "qh_furthestout: p%d is furthest outside point of f%d\n",
-	  qh_pointid (point), facet->id));
-} /* furthestout */
-
-
-/*---------------------------------
-  
-  qh_infiniteloop( facet )
-    report infinite loop error due to facet
-*/
-void qh_infiniteloop (facetT *facet) {
-
-  fprintf (qh ferr, "qhull internal error (qh_infiniteloop): potential infinite loop detected\n");
-  qh_errexit (qh_ERRqhull, facet, NULL);
-} /* qh_infiniteloop */
-
-/*---------------------------------
-  
-  qh_initbuild()
-    initialize hull and outside sets with point array
-    qh.FIRSTpoint/qh.NUMpoints is point array
-    if qh.GOODpoint
-      adds qh.GOODpoint to initial hull
-
-  returns:
-    qh_facetlist with initial hull
-    points partioned into outside sets, coplanar sets, or inside
-    initializes qh.GOODpointp, qh.GOODvertexp,
-
-  design:
-    initialize global variables used during qh_buildhull
-    determine precision constants and points with max/min coordinate values
-      if qh.SCALElast, scale last coordinate (for 'd')
-    build initial simplex
-    partition input points into facets of initial simplex
-    set up lists
-    if qh.ONLYgood
-      check consistency  
-      add qh.GOODvertex if defined
-*/
-void qh_initbuild( void) {
-  setT *maxpoints, *vertices;
-  facetT *facet;
-  int i, numpart;
-  realT dist;
-  boolT isoutside;
-
-  qh furthest_id= -1;
-  qh lastreport= 0;
-  qh facet_id= qh vertex_id= qh ridge_id= 0;
-  qh visit_id= qh vertex_visit= 0;
-  qh maxoutdone= False;
-
-  if (qh GOODpoint > 0) 
-    qh GOODpointp= qh_point (qh GOODpoint-1);
-  else if (qh GOODpoint < 0) 
-    qh GOODpointp= qh_point (-qh GOODpoint-1);
-  if (qh GOODvertex > 0)
-    qh GOODvertexp= qh_point (qh GOODvertex-1);
-  else if (qh GOODvertex < 0) 
-    qh GOODvertexp= qh_point (-qh GOODvertex-1);
-  if ((qh GOODpoint  
-       && (qh GOODpointp < qh first_point  /* also catches !GOODpointp */
-	   || qh GOODpointp > qh_point (qh num_points-1)))
-    || (qh GOODvertex
-	&& (qh GOODvertexp < qh first_point  /* also catches !GOODvertexp */
-	    || qh GOODvertexp > qh_point (qh num_points-1)))) {
-    fprintf (qh ferr, "qhull input error: either QGn or QVn point is > p%d\n",
-	     qh num_points-1);
-    qh_errexit (qh_ERRinput, NULL, NULL);
-  }
-  maxpoints= qh_maxmin(qh first_point, qh num_points, qh hull_dim);
-  if (qh SCALElast)
-    qh_scalelast (qh first_point, qh num_points, qh hull_dim,
-               qh MINlastcoord, qh MAXlastcoord, qh MAXwidth);
-  qh_detroundoff();
-  if (qh DELAUNAY && qh upper_threshold[qh hull_dim-1] > REALmax/2
-                  && qh lower_threshold[qh hull_dim-1] < -REALmax/2) {
-    for (i= qh_PRINTEND; i--; ) {
-      if (qh PRINTout[i] == qh_PRINTgeom && qh DROPdim < 0 
- 	  && !qh GOODthreshold && !qh SPLITthresholds)
-	break;  /* in this case, don't set upper_threshold */
-    }
-    if (i < 0) {
-      if (qh UPPERdelaunay) { /* matches qh.upperdelaunay in qh_setfacetplane */
-	qh lower_threshold[qh hull_dim-1]= qh ANGLEround * qh_ZEROdelaunay;
-	qh GOODthreshold= True;
-      }else { 
-	qh upper_threshold[qh hull_dim-1]= -qh ANGLEround * qh_ZEROdelaunay;
-        if (!qh GOODthreshold) 
-	  qh SPLITthresholds= True; /* build upper-convex hull even if Qg */
-          /* qh_initqhull_globals errors if Qg without Pdk/etc. */
-      }
-    }
-  }
-  vertices= qh_initialvertices(qh hull_dim, maxpoints, qh first_point, qh num_points); 
-  qh_initialhull (vertices);  /* initial qh facet_list */
-  qh_partitionall (vertices, qh first_point, qh num_points);
-  if (qh PRINToptions1st || qh TRACElevel || qh IStracing) {
-    if (qh TRACElevel || qh IStracing)
-      fprintf (qh ferr, "\nTrace level %d for %s | %s\n", 
-         qh IStracing ? qh IStracing : qh TRACElevel, qh rbox_command, qh qhull_command);
-    fprintf (qh ferr, "Options selected for Qhull %s:\n%s\n", qh_VERSION, qh qhull_options);
-  }
-  qh_resetlists (False, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
-  qh facet_next= qh facet_list;
-  qh_furthestnext (/* qh facet_list */);
-  if (qh PREmerge) {
-    qh cos_max= qh premerge_cos;
-    qh centrum_radius= qh premerge_centrum;
-  }
-  if (qh ONLYgood) {
-    if (qh GOODvertex > 0 && qh MERGING) {
-      fprintf (qh ferr, "qhull input error: 'Qg QVn' (only good vertex) does not work with merging.\nUse 'QJ' to joggle the input or 'Q0' to turn off merging.\n");
-      qh_errexit (qh_ERRinput, NULL, NULL);
-    }
-    if (!(qh GOODthreshold || qh GOODpoint
-         || (!qh MERGEexact && !qh PREmerge && qh GOODvertexp))) {
-      fprintf (qh ferr, "qhull input error: 'Qg' (ONLYgood) needs a good threshold ('Pd0D0'), a\n\
-good point (QGn or QG-n), or a good vertex with 'QJ' or 'Q0' (QVn).\n");
-      qh_errexit (qh_ERRinput, NULL, NULL);
-    }
-    if (qh GOODvertex > 0  && !qh MERGING  /* matches qh_partitionall */
-	&& !qh_isvertex (qh GOODvertexp, vertices)) {
-      facet= qh_findbestnew (qh GOODvertexp, qh facet_list, 
-			  &dist, !qh_ALL, &isoutside, &numpart);
-      zadd_(Zdistgood, numpart);
-      if (!isoutside) {
-        fprintf (qh ferr, "qhull input error: point for QV%d is inside initial simplex.  It can not be made a vertex.\n",
-	       qh_pointid(qh GOODvertexp));
-        qh_errexit (qh_ERRinput, NULL, NULL);
-      }
-      if (!qh_addpoint (qh GOODvertexp, facet, False)) {
-	qh_settempfree(&vertices);
-	qh_settempfree(&maxpoints);
-	return;
-      }
-    }
-    qh_findgood (qh facet_list, 0);
-  }
-  qh_settempfree(&vertices);
-  qh_settempfree(&maxpoints);
-  trace1((qh ferr, "qh_initbuild: initial hull created and points partitioned\n"));
-} /* initbuild */
-
-/*---------------------------------
-  
-  qh_initialhull( vertices )
-    constructs the initial hull as a DIM3 simplex of vertices
-
-  design:
-    creates a simplex (initializes lists)
-    determines orientation of simplex
-    sets hyperplanes for facets
-    doubles checks orientation (in case of axis-parallel facets with Gaussian elimination)
-    checks for flipped facets and qh.NARROWhull
-    checks the result   
-*/
-void qh_initialhull(setT *vertices) {
-  facetT *facet, *firstfacet, *neighbor, **neighborp;
-  realT dist, angle, minangle= REALmax;
-#ifndef qh_NOtrace
-  int k;
-#endif
-
-  qh_createsimplex(vertices);  /* qh facet_list */
-  qh_resetlists (False, qh_RESETvisible);
-  qh facet_next= qh facet_list;      /* advance facet when processed */
-  qh interior_point= qh_getcenter(vertices);
-  firstfacet= qh facet_list;
-  qh_setfacetplane(firstfacet);
-  zinc_(Znumvisibility); /* needs to be in printsummary */
-  qh_distplane(qh interior_point, firstfacet, &dist);
-  if (dist > 0) {  
-    FORALLfacets
-      facet->toporient ^= True;
-  }
-  FORALLfacets
-    qh_setfacetplane(facet);
-  FORALLfacets {
-    if (!qh_checkflipped (facet, NULL, qh_ALL)) {/* due to axis-parallel facet */
-      trace1((qh ferr, "qh_initialhull: initial orientation incorrect.  Correct all facets\n"));
-      facet->flipped= False;
-      FORALLfacets {
-	facet->toporient ^= True;
-	qh_orientoutside (facet);
-      }
-      break;
-    }
-  }
-  FORALLfacets {
-    if (!qh_checkflipped (facet, NULL, !qh_ALL)) {  /* can happen with 'R0.1' */
-      qh_precision ("initial facet is coplanar with interior point");
-      fprintf (qh ferr, "qhull precision error: initial facet %d is coplanar with the interior point\n",
-                   facet->id);
-      qh_errexit (qh_ERRsingular, facet, NULL);
-    }
-    FOREACHneighbor_(facet) {
-      angle= qh_getangle (facet->normal, neighbor->normal);
-      minimize_( minangle, angle);
-    }
-  }
-  if (minangle < qh_MAXnarrow && !qh NOnarrow) { 
-    realT diff= 1.0 + minangle;
-
-    qh NARROWhull= True;
-    qh_option ("_narrow-hull", NULL, &diff);
-    if (minangle < qh_WARNnarrow && !qh RERUN && qh PRINTprecision)
-      fprintf (qh ferr, "qhull precision warning: \n\
-The initial hull is narrow (cosine of min. angle is %.16f).\n\
-A coplanar point may lead to a wide facet.  Options 'QbB' (scale to unit box)\n\
-or 'Qbb' (scale last coordinate) may remove this warning.  Use 'Pp' to skip\n\
-this warning.  See 'Limitations' in qh-impre.htm.\n",
-          -minangle);   /* convert from angle between normals to angle between facets */
-  }
-  zzval_(Zprocessed)= qh hull_dim+1;
-  qh_checkpolygon (qh facet_list);
-  qh_checkconvex(qh facet_list,   qh_DATAfault);
-#ifndef qh_NOtrace
-  if (qh IStracing >= 1) {
-    fprintf(qh ferr, "qh_initialhull: simplex constructed, interior point:");
-    for (k=0; k < qh hull_dim; k++) 
-      fprintf (qh ferr, " %6.4g", qh interior_point[k]);
-    fprintf (qh ferr, "\n");
-  }
-#endif
-} /* initialhull */
-
-/*---------------------------------
-  
-  qh_initialvertices( dim, maxpoints, points, numpoints )
-    determines a non-singular set of initial vertices
-    maxpoints may include duplicate points
-
-  returns:
-    temporary set of dim+1 vertices in descending order by vertex id
-    if qh.RANDOMoutside && !qh.ALLpoints
-      picks random points
-    if dim >= qh_INITIALmax, 
-      uses min/max x and max points with non-zero determinants
-
-  notes:
-    unless qh.ALLpoints, 
-      uses maxpoints as long as determinate is non-zero
-*/
-setT *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints) {
-  pointT *point, **pointp;
-  setT *vertices, *simplex, *tested;
-  realT randr;
-  int index, point_i, point_n, k;
-  boolT nearzero= False;
-  
-  vertices= qh_settemp (dim + 1);
-  simplex= qh_settemp (dim+1);
-  if (qh ALLpoints) 
-    qh_maxsimplex (dim, NULL, points, numpoints, &simplex);
-  else if (qh RANDOMoutside) {
-    while (qh_setsize (simplex) != dim+1) {
-      randr= qh_RANDOMint;
-      randr= randr/(qh_RANDOMmax+1);
-      index= (int)floor(qh num_points * randr);
-      while (qh_setin (simplex, qh_point (index))) {
-	index++; /* in case qh_RANDOMint always returns the same value */
-        index= index < qh num_points ? index : 0;
-      }
-      qh_setappend (&simplex, qh_point (index));
-    }
-  }else if (qh hull_dim >= qh_INITIALmax) {
-    tested= qh_settemp (dim+1);
-    qh_setappend (&simplex, SETfirst_(maxpoints));   /* max and min X coord */
-    qh_setappend (&simplex, SETsecond_(maxpoints));
-    qh_maxsimplex (fmin_(qh_INITIALsearch, dim), maxpoints, points, numpoints, &simplex);
-    k= qh_setsize (simplex);
-    FOREACHpoint_i_(maxpoints) { 
-      if (point_i & 0x1) {     /* first pick up max. coord. points */
-      	if (!qh_setin (simplex, point) && !qh_setin (tested, point)){
-	  qh_detsimplex(point, simplex, k, &nearzero);
-          if (nearzero)
-            qh_setappend (&tested, point);
-          else {
-            qh_setappend (&simplex, point);
-            if (++k == dim)  /* use search for last point */
-	      break;
-	  }
-	}
-      }
-    }
-    while (k != dim && (point= (pointT*)qh_setdellast (maxpoints))) {
-      if (!qh_setin (simplex, point) && !qh_setin (tested, point)){
-        qh_detsimplex (point, simplex, k, &nearzero);
-        if (nearzero)
-          qh_setappend (&tested, point);
-        else {
-          qh_setappend (&simplex, point);
-          k++;
-	}
-      }
-    }
-    index= 0;
-    while (k != dim && (point= qh_point (index++))) {
-      if (!qh_setin (simplex, point) && !qh_setin (tested, point)){
-        qh_detsimplex (point, simplex, k, &nearzero);
-        if (!nearzero){
-          qh_setappend (&simplex, point);
-          k++;
-	}
-      }
-    }
-    qh_settempfree (&tested);
-    qh_maxsimplex (dim, maxpoints, points, numpoints, &simplex);
-  }else
-    qh_maxsimplex (dim, maxpoints, points, numpoints, &simplex);
-  FOREACHpoint_(simplex) 
-    qh_setaddnth (&vertices, 0, qh_newvertex(point)); /* descending order */
-  qh_settempfree (&simplex);
-  return vertices;
-} /* initialvertices */
-
-
-/*---------------------------------
-  
-  qh_isvertex(  )
-    returns vertex if point is in vertex set, else returns NULL
-
-  notes:
-    for qh.GOODvertex
-*/
-vertexT *qh_isvertex (pointT *point, setT *vertices) {
-  vertexT *vertex, **vertexp;
-
-  FOREACHvertex_(vertices) {
-    if (vertex->point == point)
-      return vertex;
-  }
-  return NULL;
-} /* isvertex */
-
-/*---------------------------------
-  
-  qh_makenewfacets( point )
-    make new facets from point and qh.visible_list
-
-  returns:
-    qh.newfacet_list= list of new facets with hyperplanes and ->newfacet
-    qh.newvertex_list= list of vertices in new facets with ->newlist set
-    
-    if (qh.ONLYgood)
-      newfacets reference horizon facets, but not vice versa
-      ridges reference non-simplicial horizon ridges, but not vice versa
-      does not change existing facets
-    else
-      sets qh.NEWfacets
-      new facets attached to horizon facets and ridges
-      for visible facets, 
-        visible->r.replace is corresponding new facet
-
-  see also: 
-    qh_makenewplanes() -- make hyperplanes for facets
-    qh_attachnewfacets() -- attachnewfacets if not done here (qh ONLYgood)
-    qh_matchnewfacets() -- match up neighbors
-    qh_updatevertices() -- update vertex neighbors and delvertices
-    qh_deletevisible() -- delete visible facets
-    qh_checkpolygon() --check the result
-    qh_triangulate() -- triangulate a non-simplicial facet
-
-  design:
-    for each visible facet
-      make new facets to its horizon facets
-      update its f.replace 
-      clear its neighbor set
-*/
-vertexT *qh_makenewfacets (pointT *point /*visible_list*/) {
-  facetT *visible, *newfacet= NULL, *newfacet2= NULL, *neighbor, **neighborp;
-  vertexT *apex;
-  int numnew=0;
-
-  qh newfacet_list= qh facet_tail;
-  qh newvertex_list= qh vertex_tail;
-  apex= qh_newvertex(point);
-  qh_appendvertex (apex);  
-  qh visit_id++;
-  if (!qh ONLYgood)
-    qh NEWfacets= True;
-  FORALLvisible_facets {
-    FOREACHneighbor_(visible) 
-      neighbor->seen= False;
-    if (visible->ridges) {
-      visible->visitid= qh visit_id;
-      newfacet2= qh_makenew_nonsimplicial (visible, apex, &numnew);
-    }
-    if (visible->simplicial)
-      newfacet= qh_makenew_simplicial (visible, apex, &numnew);
-    if (!qh ONLYgood) {
-      if (newfacet2)  /* newfacet is null if all ridges defined */
-        newfacet= newfacet2;
-      if (newfacet)
-      	visible->f.replace= newfacet;
-      else
-        zinc_(Zinsidevisible);
-      SETfirst_(visible->neighbors)= NULL;
-    }
-  }
-  trace1((qh ferr, "qh_makenewfacets: created %d new facets from point p%d to horizon\n",
-	  numnew, qh_pointid(point)));
-  if (qh IStracing >= 4)
-    qh_printfacetlist (qh newfacet_list, NULL, qh_ALL);
-  return apex;
-} /* makenewfacets */
-
-/*---------------------------------
-  
-  qh_matchduplicates( atfacet, atskip, hashsize, hashcount )
-    match duplicate ridges in qh.hash_table for atfacet/atskip
-    duplicates marked with ->dupridge and qh_DUPLICATEridge
-
-  returns:
-    picks match with worst merge (min distance apart)
-    updates hashcount
-  
-  see also:
-    qh_matchneighbor
-
-  notes:
-
-  design:
-    compute hash value for atfacet and atskip
-    repeat twice -- once to make best matches, once to match the rest
-      for each possible facet in qh.hash_table
-        if it is a matching facet and pass 2
-          make match 
-	  unless tricoplanar, mark match for merging (qh_MERGEridge)
-          [e.g., tricoplanar RBOX s 1000 t993602376 | QHULL C-1e-3 d Qbb FA Qt]
-        if it is a matching facet and pass 1
-          test if this is a better match
-      if pass 1,
-        make best match (it will not be merged)
-*/
-#ifndef qh_NOmerge
-void qh_matchduplicates (facetT *atfacet, int atskip, int hashsize, int *hashcount) {
-  boolT same, ismatch;
-  int hash, scan;
-  facetT *facet, *newfacet, *maxmatch= NULL, *maxmatch2= NULL, *nextfacet;
-  int skip, newskip, nextskip= 0, maxskip= 0, maxskip2= 0, makematch;
-  realT maxdist= -REALmax, mindist, dist2, low, high;
-
-  hash= (int)qh_gethash (hashsize, atfacet->vertices, qh hull_dim, 1, 
-                     SETelem_(atfacet->vertices, atskip));
-  trace2((qh ferr, "qh_matchduplicates: find duplicate matches for f%d skip %d hash %d hashcount %d\n",
-	  atfacet->id, atskip, hash, *hashcount));
-  for (makematch= 0; makematch < 2; makematch++) {
-    qh visit_id++;
-    for (newfacet= atfacet, newskip= atskip; newfacet; newfacet= nextfacet, newskip= nextskip) {
-      zinc_(Zhashlookup);
-      nextfacet= NULL;
-      newfacet->visitid= qh visit_id;
-      for (scan= hash; (facet= SETelemt_(qh hash_table, scan, facetT)); 
-	   scan= (++scan >= hashsize ? 0 : scan)) {
-	if (!facet->dupridge || facet->visitid == qh visit_id)
-	  continue;
-	zinc_(Zhashtests);
-	if (qh_matchvertices (1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
-	  ismatch= (same == (newfacet->toporient ^ facet->toporient));
-	  if (SETelemt_(facet->neighbors, skip, facetT) != qh_DUPLICATEridge) {
-	    if (!makematch) {
-	      fprintf (qh ferr, "qhull internal error (qh_matchduplicates): missing dupridge at f%d skip %d for new f%d skip %d hash %d\n",
-		     facet->id, skip, newfacet->id, newskip, hash);
-	      qh_errexit2 (qh_ERRqhull, facet, newfacet);
-	    }
-	  }else if (ismatch && makematch) {
-	    if (SETelemt_(newfacet->neighbors, newskip, facetT) == qh_DUPLICATEridge) {
-	      SETelem_(facet->neighbors, skip)= newfacet;
-	      if (newfacet->tricoplanar)
-  		SETelem_(newfacet->neighbors, newskip)= facet;
-	      else
-		SETelem_(newfacet->neighbors, newskip)= qh_MERGEridge;
-	      *hashcount -= 2; /* removed two unmatched facets */
-	      trace4((qh ferr, "qh_matchduplicates: duplicate f%d skip %d matched with new f%d skip %d merge\n",
-		    facet->id, skip, newfacet->id, newskip));
-	    }
-	  }else if (ismatch) {
-	    mindist= qh_getdistance (facet, newfacet, &low, &high);
-	    dist2= qh_getdistance (newfacet, facet, &low, &high);
-	    minimize_(mindist, dist2);
-	    if (mindist > maxdist) {
-	      maxdist= mindist;
-	      maxmatch= facet;
-	      maxskip= skip;
-	      maxmatch2= newfacet;
-	      maxskip2= newskip;
-	    }
-	    trace3((qh ferr, "qh_matchduplicates: duplicate f%d skip %d new f%d skip %d at dist %2.2g, max is now f%d f%d\n",
-		    facet->id, skip, newfacet->id, newskip, mindist, 
-		    maxmatch->id, maxmatch2->id));
-	  }else { /* !ismatch */
-	    nextfacet= facet;
-	    nextskip= skip;
-	  }
-	}
-	if (makematch && !facet 
-        && SETelemt_(facet->neighbors, skip, facetT) == qh_DUPLICATEridge) {
-	  fprintf (qh ferr, "qhull internal error (qh_matchduplicates): no MERGEridge match for duplicate f%d skip %d at hash %d\n",
-		     newfacet->id, newskip, hash);
-	  qh_errexit (qh_ERRqhull, newfacet, NULL);
-	}
-      }
-    } /* end of for each new facet at hash */
-    if (!makematch) {
-      if (!maxmatch) {
-	fprintf (qh ferr, "qhull internal error (qh_matchduplicates): no maximum match at duplicate f%d skip %d at hash %d\n",
-		     atfacet->id, atskip, hash);
-	qh_errexit (qh_ERRqhull, atfacet, NULL);
-      }
-      SETelem_(maxmatch->neighbors, maxskip)= maxmatch2;
-      SETelem_(maxmatch2->neighbors, maxskip2)= maxmatch;
-      *hashcount -= 2; /* removed two unmatched facets */
-      zzinc_(Zmultiridge);
-      trace0((qh ferr, "qh_matchduplicates: duplicate f%d skip %d matched with new f%d skip %d keep\n",
-	      maxmatch->id, maxskip, maxmatch2->id, maxskip2));
-      qh_precision ("ridge with multiple neighbors");
-      if (qh IStracing >= 4)
-	qh_errprint ("DUPLICATED/MATCH", maxmatch, maxmatch2, NULL, NULL);
-    }
-  }
-} /* matchduplicates */
-
-/*---------------------------------
-  
-  qh_nearcoplanar()
-    for all facets, remove near-inside points from facet->coplanarset
-    coplanar points defined by innerplane from qh_outerinner()
-
-  returns:
-    if qh KEEPcoplanar && !qh KEEPinside
-      facet->coplanarset only contains coplanar points
-    if qh.JOGGLEmax
-      drops inner plane by another qh.JOGGLEmax diagonal since a
-        vertex could shift out while a coplanar point shifts in
-  
-  notes:
-    used for qh.PREmerge and qh.JOGGLEmax
-    must agree with computation of qh.NEARcoplanar in qh_detroundoff()
-  design:
-    if not keeping coplanar or inside points
-      free all coplanar sets
-    else if not keeping both coplanar and inside points
-      remove !coplanar or !inside points from coplanar sets
-*/
-void qh_nearcoplanar ( void /* qh.facet_list */) {
-  facetT *facet;
-  pointT *point, **pointp;
-  int numpart;
-  realT dist, innerplane;
-
-  if (!qh KEEPcoplanar && !qh KEEPinside) {
-    FORALLfacets {
-      if (facet->coplanarset) 
-        qh_setfree( &facet->coplanarset);
-    }
-  }else if (!qh KEEPcoplanar || !qh KEEPinside) {
-    qh_outerinner (NULL, NULL, &innerplane);
-    if (qh JOGGLEmax < REALmax/2)
-      innerplane -= qh JOGGLEmax * sqrt (qh hull_dim);
-    numpart= 0;
-    FORALLfacets { 
-      if (facet->coplanarset) {
-        FOREACHpoint_(facet->coplanarset) {
-          numpart++;
-	  qh_distplane (point, facet, &dist); 
-  	  if (dist < innerplane) {
-	    if (!qh KEEPinside)
-              SETref_(point)= NULL;
-          }else if (!qh KEEPcoplanar)
-            SETref_(point)= NULL;
-        }
-	qh_setcompact (facet->coplanarset);
-      }
-    }
-    zzadd_(Zcheckpart, numpart);
-  }
-} /* nearcoplanar */
-
-/*---------------------------------
-  
-  qh_nearvertex( facet, point, bestdist )
-    return nearest vertex in facet to point
-
-  returns:
-    vertex and its distance
-    
-  notes:
-    if qh.DELAUNAY
-      distance is measured in the input set
-    searches neighboring tricoplanar facets (requires vertexneighbors)
-      Slow implementation.  Recomputes vertex set for each point.
-    The vertex set could be stored in the qh.keepcentrum facet.
-*/
-vertexT *qh_nearvertex (facetT *facet, pointT *point, realT *bestdistp) {
-  realT bestdist= REALmax, dist;
-  vertexT *bestvertex= NULL, *vertex, **vertexp, *apex;
-  coordT *center;
-  facetT *neighbor, **neighborp;
-  setT *vertices;
-  int dim= qh hull_dim;
-
-  if (qh DELAUNAY)
-    dim--;
-  if (facet->tricoplanar) {
-    if (!qh VERTEXneighbors || !facet->center) {
-      fprintf(qh ferr, "qhull internal error (qh_nearvertex): qh.VERTEXneighbors and facet->center required for tricoplanar facets\n");
-      qh_errexit(qh_ERRqhull, NULL, NULL);
-    }
-    vertices= qh_settemp (qh TEMPsize);
-    apex= SETfirst_(facet->vertices);
-    center= facet->center;
-    FOREACHneighbor_(apex) {
-      if (neighbor->center == center) {
-	FOREACHvertex_(neighbor->vertices) 
-	  qh_setappend(&vertices, vertex);
-      }
-    }
-  }else 
-    vertices= facet->vertices;
-  FOREACHvertex_(vertices) {
-    dist= qh_pointdist (vertex->point, point, -dim);
-    if (dist < bestdist) {
-      bestdist= dist;
-      bestvertex= vertex;
-    }
-  }
-  if (facet->tricoplanar)
-    qh_settempfree (&vertices);
-  *bestdistp= sqrt (bestdist);
-  return bestvertex;
-} /* nearvertex */
-
-/*---------------------------------
-  
-  qh_newhashtable( newsize )
-    returns size of qh.hash_table of at least newsize slots
-
-  notes:
-    assumes qh.hash_table is NULL
-    qh_HASHfactor determines the number of extra slots
-    size is not divisible by 2, 3, or 5
-*/
-int qh_newhashtable(int newsize) {
-  int size;
-
-  size= ((newsize+1)*qh_HASHfactor) | 0x1;  /* odd number */
-  while (True) { 
-    if ((size%3) && (size%5))
-      break;
-    size += 2;
-    /* loop terminates because there is an infinite number of primes */
-  }
-  qh hash_table= qh_setnew (size);
-  qh_setzero (qh hash_table, 0, size);
-  return size;
-} /* newhashtable */
-
-/*---------------------------------
-  
-  qh_newvertex( point )
-    returns a new vertex for point
-*/
-vertexT *qh_newvertex(pointT *point) {
-  vertexT *vertex;
-
-  zinc_(Ztotvertices);
-  vertex= (vertexT *)qh_memalloc(sizeof(vertexT));
-  memset ((char *) vertex, 0, sizeof (vertexT));
-  if (qh vertex_id == 0xFFFFFF) {
-    fprintf(qh ferr, "qhull input error: more than %d vertices.  ID field overflows and two vertices\n\
-may have the same identifier.  Vertices not sorted correctly.\n", 0xFFFFFF);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (qh vertex_id == qh tracevertex_id)
-    qh tracevertex= vertex;
-  vertex->id= qh vertex_id++;
-  vertex->point= point;
-  trace4((qh ferr, "qh_newvertex: vertex p%d (v%d) created\n", qh_pointid(vertex->point), 
-	  vertex->id));
-  return (vertex);
-} /* newvertex */
-
-/*---------------------------------
-  
-  qh_nextridge3d( atridge, facet, vertex )
-    return next ridge and vertex for a 3d facet
-
-  notes:
-    in qh_ORIENTclock order
-    this is a O(n^2) implementation to trace all ridges
-    be sure to stop on any 2nd visit
-  
-  design:
-    for each ridge
-      exit if it is the ridge after atridge
-*/
-ridgeT *qh_nextridge3d (ridgeT *atridge, facetT *facet, vertexT **vertexp) {
-  vertexT *atvertex, *vertex, *othervertex;
-  ridgeT *ridge, **ridgep;
-
-  if ((atridge->top == facet) ^ qh_ORIENTclock)
-    atvertex= SETsecondt_(atridge->vertices, vertexT);
-  else
-    atvertex= SETfirstt_(atridge->vertices, vertexT);
-  FOREACHridge_(facet->ridges) {
-    if (ridge == atridge)
-      continue;
-    if ((ridge->top == facet) ^ qh_ORIENTclock) {
-      othervertex= SETsecondt_(ridge->vertices, vertexT);
-      vertex= SETfirstt_(ridge->vertices, vertexT);
-    }else {
-      vertex= SETsecondt_(ridge->vertices, vertexT);
-      othervertex= SETfirstt_(ridge->vertices, vertexT);
-    }
-    if (vertex == atvertex) {
-      if (vertexp)
-        *vertexp= othervertex;
-      return ridge;
-    }
-  }
-  return NULL;
-} /* nextridge3d */
-#else /* qh_NOmerge */
-void qh_matchduplicates (facetT *atfacet, int atskip, int hashsize, int *hashcount) {
-}
-ridgeT *qh_nextridge3d (ridgeT *atridge, facetT *facet, vertexT **vertexp) {
-
-  return NULL;
-}
-#endif /* qh_NOmerge */
-  
-/*---------------------------------
-  
-  qh_outcoplanar()
-    move points from all facets' outsidesets to their coplanarsets
-
-  notes:
-    for post-processing under qh.NARROWhull
-
-  design:
-    for each facet
-      for each outside point for facet
-        partition point into coplanar set
-*/
-void qh_outcoplanar (void /* facet_list */) {
-  pointT *point, **pointp;
-  facetT *facet;
-  realT dist;
-
-  trace1((qh ferr, "qh_outcoplanar: move outsideset to coplanarset for qh NARROWhull\n"));
-  FORALLfacets {
-    FOREACHpoint_(facet->outsideset) {
-      qh num_outside--;
-      if (qh KEEPcoplanar || qh KEEPnearinside) {
-	qh_distplane (point, facet, &dist);
-        zinc_(Zpartition);
-	qh_partitioncoplanar (point, facet, &dist);
-      }
-    }
-    qh_setfree (&facet->outsideset);
-  }
-} /* outcoplanar */
-
-/*---------------------------------
-  
-  qh_point( id )
-    return point for a point id, or NULL if unknown
-
-  alternative code:
-    return ((pointT *)((unsigned   long)qh.first_point
-           + (unsigned long)((id)*qh.normal_size)));
-*/
-pointT *qh_point (int id) {
-
-  if (id < 0)
-    return NULL;
-  if (id < qh num_points)
-    return qh first_point + id * qh hull_dim;
-  id -= qh num_points;
-  if (id < qh_setsize (qh other_points))
-    return SETelemt_(qh other_points, id, pointT);
-  return NULL;
-} /* point */
-  
-/*---------------------------------
-  
-  qh_point_add( set, point, elem )
-    stores elem at set[point.id]
-  
-  returns:
-    access function for qh_pointfacet and qh_pointvertex
-
-  notes:
-    checks point.id
-*/
-void qh_point_add (setT *set, pointT *point, void *elem) {
-  int id, size;
-
-  SETreturnsize_(set, size);
-  if ((id= qh_pointid(point)) < 0)
-    fprintf (qh ferr, "qhull internal warning (point_add): unknown point %p id %d\n", 
-      point, id);
-  else if (id >= size) {
-    fprintf (qh ferr, "qhull internal errror (point_add): point p%d is out of bounds (%d)\n",
-	     id, size);
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }else
-    SETelem_(set, id)= elem;
-} /* point_add */
-
-
-/*---------------------------------
-  
-  qh_pointfacet()
-    return temporary set of facet for each point
-    the set is indexed by point id
-
-  notes:
-    vertices assigned to one of the facets
-    coplanarset assigned to the facet
-    outside set assigned to the facet
-    NULL if no facet for point (inside)
-      includes qh.GOODpointp
-
-  access:
-    FOREACHfacet_i_(facets) { ... }
-    SETelem_(facets, i)
-  
-  design:
-    for each facet
-      add each vertex
-      add each coplanar point
-      add each outside point
-*/
-setT *qh_pointfacet (void /*qh facet_list*/) {
-  int numpoints= qh num_points + qh_setsize (qh other_points);
-  setT *facets;
-  facetT *facet;
-  vertexT *vertex, **vertexp;
-  pointT *point, **pointp;
-  
-  facets= qh_settemp (numpoints);
-  qh_setzero (facets, 0, numpoints);
-  qh vertex_visit++;
-  FORALLfacets {
-    FOREACHvertex_(facet->vertices) {
-      if (vertex->visitid != qh vertex_visit) {
-        vertex->visitid= qh vertex_visit;
-        qh_point_add (facets, vertex->point, facet);
-      }
-    }
-    FOREACHpoint_(facet->coplanarset) 
-      qh_point_add (facets, point, facet);
-    FOREACHpoint_(facet->outsideset) 
-      qh_point_add (facets, point, facet);
-  }
-  return facets;
-} /* pointfacet */
-
-/*---------------------------------
-  
-  qh_pointvertex(  )
-    return temporary set of vertices indexed by point id
-    entry is NULL if no vertex for a point
-      this will include qh.GOODpointp
-
-  access:
-    FOREACHvertex_i_(vertices) { ... }
-    SETelem_(vertices, i)
-*/
-setT *qh_pointvertex (void /*qh facet_list*/) {
-  int numpoints= qh num_points + qh_setsize (qh other_points);
-  setT *vertices;
-  vertexT *vertex;
-  
-  vertices= qh_settemp (numpoints);
-  qh_setzero (vertices, 0, numpoints);
-  FORALLvertices 
-    qh_point_add (vertices, vertex->point, vertex);
-  return vertices;
-} /* pointvertex */
-
-
-/*---------------------------------
-  
-  qh_prependfacet( facet, facetlist )
-    prepend facet to the start of a facetlist
-
-  returns:
-    increments qh.numfacets
-    updates facetlist, qh.facet_list, facet_next
-  
-  notes:
-    be careful of prepending since it can lose a pointer.
-      e.g., can lose _next by deleting and then prepending before _next
-*/
-void qh_prependfacet(facetT *facet, facetT **facetlist) {
-  facetT *prevfacet, *list;
-  
-
-  trace4((qh ferr, "qh_prependfacet: prepend f%d before f%d\n",
-	  facet->id, getid_(*facetlist)));
-  if (!*facetlist)
-    (*facetlist)= qh facet_tail;
-  list= *facetlist;
-  prevfacet= list->previous;
-  facet->previous= prevfacet;
-  if (prevfacet)
-    prevfacet->next= facet;
-  list->previous= facet;
-  facet->next= *facetlist;
-  if (qh facet_list == list)  /* this may change *facetlist */
-    qh facet_list= facet;
-  if (qh facet_next == list)
-    qh facet_next= facet;
-  *facetlist= facet;
-  qh num_facets++;
-} /* prependfacet */
-
-
-/*---------------------------------
-  
-  qh_printhashtable( fp )
-    print hash table to fp
-
-  notes:
-    not in I/O to avoid bringing io.c in
-  
-  design:
-    for each hash entry
-      if defined
-        if unmatched or will merge (NULL, qh_MERGEridge, qh_DUPLICATEridge)
-          print entry and neighbors
-*/
-void qh_printhashtable(FILE *fp) {
-  facetT *facet, *neighbor;
-  int id, facet_i, facet_n, neighbor_i= 0, neighbor_n= 0;
-  vertexT *vertex, **vertexp;
-
-  FOREACHfacet_i_(qh hash_table) {
-    if (facet) {
-      FOREACHneighbor_i_(facet) {
-        if (!neighbor || neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge) 
-          break;
-      }
-      if (neighbor_i == neighbor_n)
-        continue;
-      fprintf (fp, "hash %d f%d ", facet_i, facet->id);
-      FOREACHvertex_(facet->vertices)
-        fprintf (fp, "v%d ", vertex->id);
-      fprintf (fp, "\n neighbors:");
-      FOREACHneighbor_i_(facet) {
-	if (neighbor == qh_MERGEridge)
-	  id= -3;
-	else if (neighbor == qh_DUPLICATEridge)
-	  id= -2;
-	else
-	  id= getid_(neighbor);
-        fprintf (fp, " %d", id);
-      }
-      fprintf (fp, "\n");
-    }
-  }
-} /* printhashtable */
-     
-
-/*---------------------------------
-  
-  qh_printlists( fp )
-    print out facet and vertex list for debugging (without 'f/v' tags)
-*/
-void qh_printlists (void) {
-  facetT *facet;
-  vertexT *vertex;
-  int count= 0;
-  
-  fprintf (qh ferr, "qh_printlists: facets:");
-  FORALLfacets {
-    if (++count % 100 == 0)
-      fprintf (qh ferr, "\n     ");
-    fprintf (qh ferr, " %d", facet->id);
-  }
-  fprintf (qh ferr, "\n  new facets %d visible facets %d next facet for qh_addpoint %d\n  vertices (new %d):",
-     getid_(qh newfacet_list), getid_(qh visible_list), getid_(qh facet_next),
-     getid_(qh newvertex_list));
-  count = 0;
-  FORALLvertices {
-    if (++count % 100 == 0)
-      fprintf (qh ferr, "\n     ");
-    fprintf (qh ferr, " %d", vertex->id);
-  }
-  fprintf (qh ferr, "\n");
-} /* printlists */
-  
-/*---------------------------------
-  
-  qh_resetlists( stats, qh_RESETvisible )
-    reset newvertex_list, newfacet_list, visible_list
-    if stats, 
-      maintains statistics
-
-  returns:
-    visible_list is empty if qh_deletevisible was called
-*/
-void qh_resetlists (boolT stats, boolT resetVisible /*qh newvertex_list newfacet_list visible_list*/) {
-  vertexT *vertex;
-  facetT *newfacet, *visible;
-  int totnew=0, totver=0;
-  
-  if (stats) {
-    FORALLvertex_(qh newvertex_list)
-      totver++;
-    FORALLnew_facets 
-      totnew++;
-    zadd_(Zvisvertextot, totver);
-    zmax_(Zvisvertexmax, totver);
-    zadd_(Znewfacettot, totnew);
-    zmax_(Znewfacetmax, totnew);
-  }
-  FORALLvertex_(qh newvertex_list)
-    vertex->newlist= False;
-  qh newvertex_list= NULL;
-  FORALLnew_facets
-    newfacet->newfacet= False;
-  qh newfacet_list= NULL;
-  if (resetVisible) {
-    FORALLvisible_facets {
-      visible->f.replace= NULL;
-      visible->visible= False;
-    }
-    qh num_visible= 0;
-  }
-  qh visible_list= NULL; /* may still have visible facets via qh_triangulate */
-  qh NEWfacets= False;
-} /* resetlists */
-
-/*---------------------------------
-  
-  qh_setvoronoi_all()
-    compute Voronoi centers for all facets
-    includes upperDelaunay facets if qh.UPPERdelaunay ('Qu')
-
-  returns:
-    facet->center is the Voronoi center
-    
-  notes:
-    this is unused/untested code
-      please email bradb@shore.net if this works ok for you
-  
-  use:
-    FORALLvertices {...} to locate the vertex for a point.  
-    FOREACHneighbor_(vertex) {...} to visit the Voronoi centers for a Voronoi cell.
-*/
-void qh_setvoronoi_all (void) {
-  facetT *facet;
-
-  qh_clearcenters (qh_ASvoronoi);
-  qh_vertexneighbors();
-  
-  FORALLfacets {
-    if (!facet->normal || !facet->upperdelaunay || qh UPPERdelaunay) {
-      if (!facet->center)
-        facet->center= qh_facetcenter (facet->vertices);
-    }
-  }
-} /* setvoronoi_all */
-
-#ifndef qh_NOmerge
-
-/*---------------------------------
-  
-  qh_triangulate()
-    triangulate non-simplicial facets on qh.facet_list, 
-    if qh.CENTERtype=qh_ASvoronoi, sets Voronoi centers of non-simplicial facets
-
-  returns:
-    all facets simplicial
-    each tricoplanar facet has ->f.triowner == owner of ->center,normal,etc.
-
-  notes:
-    call after qh_check_output since may switch to Voronoi centers
-    Output may overwrite ->f.triowner with ->f.area
-*/
-void qh_triangulate (void /*qh facet_list*/) {
-  facetT *facet, *nextfacet, *owner;
-  int onlygood= qh ONLYgood;
-  facetT *neighbor, *visible= NULL, *facet1, *facet2, *new_facet_list= NULL;
-  facetT *orig_neighbor= NULL, *otherfacet;
-  vertexT *new_vertex_list= NULL;
-  mergeT *merge; 
-  mergeType mergetype;
-  int neighbor_i, neighbor_n;
-
-  trace1((qh ferr, "qh_triangulate: triangulate non-simplicial facets\n"));
-  if (qh hull_dim == 2)
-    return;
-  if (qh VORONOI) {  /* otherwise lose Voronoi centers [could rebuild vertex set from tricoplanar] */
-    qh_clearcenters (qh_ASvoronoi);
-    qh_vertexneighbors();
-  }
-  qh ONLYgood= False; /* for makenew_nonsimplicial */
-  qh visit_id++;
-  qh NEWfacets= True;
-  qh degen_mergeset= qh_settemp (qh TEMPsize);
-  qh newvertex_list= qh vertex_tail;
-  for (facet= qh facet_list; facet && facet->next; facet= nextfacet) { /* non-simplicial facets moved to end */
-    nextfacet= facet->next;
-    if (facet->visible || facet->simplicial)
-      continue;
-    /* triangulate all non-simplicial facets, otherwise merging does not work, e.g., RBOX c P-0.1 P+0.1 P+0.1 D3 | QHULL d Qt Tv */
-    if (!new_facet_list)
-      new_facet_list= facet;  /* will be moved to end */
-    qh_triangulate_facet (facet, &new_vertex_list);
-  }
-  trace2((qh ferr, "qh_triangulate: delete null facets from f%d -- apex same as second vertex\n", getid_(new_facet_list)));
-  for (facet= new_facet_list; facet && facet->next; facet= nextfacet) { /* null facets moved to end */
-    nextfacet= facet->next;
-    if (facet->visible) 
-      continue;
-    if (facet->ridges) {
-      if (qh_setsize(facet->ridges) > 0) {
-	fprintf( qh ferr, "qhull error (qh_triangulate): ridges still defined for f%d\n", facet->id);
-	qh_errexit (qh_ERRqhull, facet, NULL);
-      }
-      qh_setfree (&facet->ridges);
-    }
-    if (SETfirst_(facet->vertices) == SETsecond_(facet->vertices)) {
-      zinc_(Ztrinull);
-      qh_triangulate_null (facet);
-    }
-  }
-  trace2((qh ferr, "qh_triangulate: delete %d or more mirror facets -- same vertices and neighbors\n", qh_setsize(qh degen_mergeset)));
-  qh visible_list= qh facet_tail;
-  while ((merge= (mergeT*)qh_setdellast (qh degen_mergeset))) {
-    facet1= merge->facet1;
-    facet2= merge->facet2;
-    mergetype= merge->type;
-    qh_memfree (merge, sizeof(mergeT));
-    if (mergetype == MRGmirror) {
-      zinc_(Ztrimirror);
-      qh_triangulate_mirror (facet1, facet2);
-    }
-  }
-  qh_settempfree(&qh degen_mergeset);
-  trace2((qh ferr, "qh_triangulate: update neighbor lists for vertices from v%d\n", getid_(new_vertex_list)));
-  qh newvertex_list= new_vertex_list;  /* all vertices of new facets */
-  qh visible_list= NULL;
-  qh_updatevertices(/*qh newvertex_list, empty newfacet_list and visible_list*/);
-  qh_resetlists (False, !qh_RESETvisible /*qh newvertex_list, empty newfacet_list and visible_list*/);
-
-  trace2((qh ferr, "qh_triangulate: identify degenerate tricoplanar facets from f%d\n", getid_(new_facet_list)));
-  trace2((qh ferr, "qh_triangulate: and replace facet->f.triowner with tricoplanar facets that own center, normal, etc.\n"));
-  FORALLfacet_(new_facet_list) {
-    if (facet->tricoplanar && !facet->visible) {
-      FOREACHneighbor_i_(facet) {
-	if (neighbor_i == 0) {  /* first iteration */
-	  if (neighbor->tricoplanar)
-            orig_neighbor= neighbor->f.triowner;
-	  else
-	    orig_neighbor= neighbor;
-	}else {
-	  if (neighbor->tricoplanar)
-  	    otherfacet= neighbor->f.triowner;
-	  else
-	    otherfacet= neighbor;
-	  if (orig_neighbor == otherfacet) {
-	    zinc_(Ztridegen);
-	    facet->degenerate= True;
-	    break;
-	  }
-	}
-      }
-    }
-  }
-
-  trace2((qh ferr, "qh_triangulate: delete visible facets -- non-simplicial, null, and mirrored facets\n"));
-  owner= NULL;
-  visible= NULL;
-  for (facet= new_facet_list; facet && facet->next; facet= nextfacet) { /* may delete facet */
-    nextfacet= facet->next;
-    if (facet->visible) {
-      if (facet->tricoplanar) { /* a null or mirrored facet */
-	qh_delfacet(facet);
-	qh num_visible--;
-      }else {  /* a non-simplicial facet followed by its tricoplanars */
-	if (visible && !owner) {
-	  /*  RBOX 200 s D5 t1001471447 | QHULL Qt C-0.01 Qx Qc Tv Qt -- f4483 had 6 vertices/neighbors and 8 ridges */
-	  trace2((qh ferr, "qh_triangulate: all tricoplanar facets degenerate for non-simplicial facet f%d\n",
-		       visible->id));
-	  qh_delfacet(visible);
-	  qh num_visible--;
-	}
-	visible= facet;
-	owner= NULL;
-      }
-    }else if (facet->tricoplanar) {
-      if (facet->f.triowner != visible) { 
-	fprintf( qh ferr, "qhull error (qh_triangulate): tricoplanar facet f%d not owned by its visible, non-simplicial facet f%d\n", facet->id, getid_(visible));
-	qh_errexit2 (qh_ERRqhull, facet, visible);
-      }
-      if (owner) 
-	facet->f.triowner= owner;
-      else if (!facet->degenerate) {
-	owner= facet;
-	nextfacet= visible->next; /* rescan tricoplanar facets with owner */
-	facet->keepcentrum= True;  /* one facet owns ->normal, etc. */
-	facet->coplanarset= visible->coplanarset;
-	facet->outsideset= visible->outsideset;
-  	visible->coplanarset= NULL;
-	visible->outsideset= NULL;
-        if (!qh TRInormals) { /* center and normal copied to tricoplanar facets */
-	  visible->center= NULL;
-	  visible->normal= NULL;
-	}
-	qh_delfacet(visible);
-	qh num_visible--;
-      }
-    }
-  }
-  if (visible && !owner) {
-    trace2((qh ferr, "qh_triangulate: all tricoplanar facets degenerate for last non-simplicial facet f%d\n",
-	         visible->id));
-    qh_delfacet(visible);
-    qh num_visible--;
-  }
-  qh NEWfacets= False;
-  qh ONLYgood= onlygood; /* restore value */
-  if (qh CHECKfrequently) 
-    qh_checkpolygon (qh facet_list);
-} /* triangulate */
-
-
-/*---------------------------------
-  
-  qh_triangulate_facet (facetA)
-    triangulate a non-simplicial facet
-      if qh.CENTERtype=qh_ASvoronoi, sets its Voronoi center
-  returns:
-    qh.newfacet_list == simplicial facets
-      facet->tricoplanar set and ->keepcentrum false
-      facet->degenerate set if duplicated apex
-      facet->f.trivisible set to facetA
-      facet->center copied from facetA (created if qh_ASvoronoi)
-	qh_eachvoronoi, qh_detvridge, qh_detvridge3 assume centers copied
-      facet->normal,offset,maxoutside copied from facetA
-
-  notes:
-      qh_makenew_nonsimplicial uses neighbor->seen for the same
-
-  see also:
-      qh_addpoint() -- add a point
-      qh_makenewfacets() -- construct a cone of facets for a new vertex
-
-  design:
-      if qh_ASvoronoi, 
-	 compute Voronoi center (facet->center)
-      select first vertex (highest ID to preserve ID ordering of ->vertices)
-      triangulate from vertex to ridges
-      copy facet->center, normal, offset
-      update vertex neighbors
-*/
-void qh_triangulate_facet (facetT *facetA, vertexT **first_vertex) {
-  facetT *newfacet;
-  facetT *neighbor, **neighborp;
-  vertexT *apex;
-  int numnew=0;
-
-  trace3((qh ferr, "qh_triangulate_facet: triangulate facet f%d\n", facetA->id));
-
-  if (qh IStracing >= 4)
-    qh_printfacet (qh ferr, facetA);
-  FOREACHneighbor_(facetA) {
-    neighbor->seen= False;
-    neighbor->coplanar= False;
-  }
-  if (qh CENTERtype == qh_ASvoronoi && !facetA->center  /* matches upperdelaunay in qh_setfacetplane() */
-        && fabs_(facetA->normal[qh hull_dim -1]) >= qh ANGLEround * qh_ZEROdelaunay) {
-    facetA->center= qh_facetcenter (facetA->vertices);
-  }
-  qh_willdelete (facetA, NULL);
-  qh newfacet_list= qh facet_tail;
-  facetA->visitid= qh visit_id;
-  apex= SETfirst_(facetA->vertices);
-  qh_makenew_nonsimplicial (facetA, apex, &numnew);
-  SETfirst_(facetA->neighbors)= NULL;
-  FORALLnew_facets {
-    newfacet->tricoplanar= True;
-    newfacet->f.trivisible= facetA;
-    newfacet->degenerate= False;
-    newfacet->upperdelaunay= facetA->upperdelaunay;
-    newfacet->good= facetA->good;
-    if (qh TRInormals) { 
-      newfacet->keepcentrum= True;
-      newfacet->normal= qh_copypoints (facetA->normal, 1, qh hull_dim);
-      if (qh CENTERtype == qh_AScentrum) 
-	newfacet->center= qh_getcentrum (newfacet);
-      else
-	newfacet->center= qh_copypoints (facetA->center, 1, qh hull_dim);
-    }else {
-      newfacet->keepcentrum= False;
-      newfacet->normal= facetA->normal;
-      newfacet->center= facetA->center;
-    }
-    newfacet->offset= facetA->offset;
-#if qh_MAXoutside
-    newfacet->maxoutside= facetA->maxoutside;
-#endif
-  }
-  qh_matchnewfacets(/*qh newfacet_list*/);
-  zinc_(Ztricoplanar);
-  zadd_(Ztricoplanartot, numnew);
-  zmax_(Ztricoplanarmax, numnew);
-  qh visible_list= NULL;
-  if (!(*first_vertex))
-    (*first_vertex)= qh newvertex_list;
-  qh newvertex_list= NULL;
-  qh_updatevertices(/*qh newfacet_list, empty visible_list and newvertex_list*/);
-  qh_resetlists (False, !qh_RESETvisible /*qh newfacet_list, empty visible_list and newvertex_list*/);
-} /* triangulate_facet */
-
-/*---------------------------------
-  
-  qh_triangulate_link (oldfacetA, facetA, oldfacetB, facetB)
-    relink facetA to facetB via oldfacets
-  returns:
-    adds mirror facets to qh degen_mergeset (4-d and up only)
-  design:
-    if they are already neighbors, the opposing neighbors become MRGmirror facets
-*/
-void qh_triangulate_link (facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB) {
-  int errmirror= False;
-
-  trace3((qh ferr, "qh_triangulate_link: relink old facets f%d and f%d between neighbors f%d and f%d\n", 
-         oldfacetA->id, oldfacetB->id, facetA->id, facetB->id));
-  if (qh_setin (facetA->neighbors, facetB)) {
-    if (!qh_setin (facetB->neighbors, facetA)) 
-      errmirror= True;
-    else
-      qh_appendmergeset (facetA, facetB, MRGmirror, NULL);
-  }else if (qh_setin (facetB->neighbors, facetA)) 
-    errmirror= True;
-  if (errmirror) {
-    fprintf( qh ferr, "qhull error (qh_triangulate_link): mirror facets f%d and f%d do not match for old facets f%d and f%d\n",
-       facetA->id, facetB->id, oldfacetA->id, oldfacetB->id);
-    qh_errexit2 (qh_ERRqhull, facetA, facetB);
-  }
-  qh_setreplace (facetB->neighbors, oldfacetB, facetA);
-  qh_setreplace (facetA->neighbors, oldfacetA, facetB);
-} /* triangulate_link */
-
-/*---------------------------------
-  
-  qh_triangulate_mirror (facetA, facetB)
-    delete mirrored facets from qh_triangulate_null() and qh_triangulate_mirror
-      a mirrored facet shares the same vertices of a logical ridge
-  design:
-    since a null facet duplicates the first two vertices, the opposing neighbors absorb the null facet
-    if they are already neighbors, the opposing neighbors become MRGmirror facets
-*/
-void qh_triangulate_mirror (facetT *facetA, facetT *facetB) {
-  facetT *neighbor, *neighborB;
-  int neighbor_i, neighbor_n;
-
-  trace3((qh ferr, "qh_triangulate_mirror: delete mirrored facets f%d and f%d\n", 
-         facetA->id, facetB->id));
-  FOREACHneighbor_i_(facetA) {
-    neighborB= SETelemt_(facetB->neighbors, neighbor_i, facetT);
-    if (neighbor == neighborB)
-      continue; /* occurs twice */
-    qh_triangulate_link (facetA, neighbor, facetB, neighborB);
-  }
-  qh_willdelete (facetA, NULL);
-  qh_willdelete (facetB, NULL);
-} /* triangulate_mirror */
-
-/*---------------------------------
-  
-  qh_triangulate_null (facetA)
-    remove null facetA from qh_triangulate_facet()
-      a null facet has vertex #1 (apex) == vertex #2
-  returns:
-    adds facetA to ->visible for deletion after qh_updatevertices
-    qh degen_mergeset contains mirror facets (4-d and up only)
-  design:
-    since a null facet duplicates the first two vertices, the opposing neighbors absorb the null facet
-    if they are already neighbors, the opposing neighbors become MRGmirror facets
-*/
-void qh_triangulate_null (facetT *facetA) {
-  facetT *neighbor, *otherfacet;
-
-  trace3((qh ferr, "qh_triangulate_null: delete null facet f%d\n", facetA->id));
-  neighbor= SETfirst_(facetA->neighbors);
-  otherfacet= SETsecond_(facetA->neighbors);
-  qh_triangulate_link (facetA, neighbor, facetA, otherfacet);
-  qh_willdelete (facetA, NULL);
-} /* triangulate_null */
-
-#else /* qh_NOmerge */
-void qh_triangulate (void) {
-}
-#endif /* qh_NOmerge */
-
-   /*---------------------------------
-  
-  qh_vertexintersect( vertexsetA, vertexsetB )
-    intersects two vertex sets (inverse id ordered)
-    vertexsetA is a temporary set at the top of qhmem.tempstack
-
-  returns:
-    replaces vertexsetA with the intersection
-  
-  notes:
-    could overwrite vertexsetA if currently too slow
-*/
-void qh_vertexintersect(setT **vertexsetA,setT *vertexsetB) {
-  setT *intersection;
-
-  intersection= qh_vertexintersect_new (*vertexsetA, vertexsetB);
-  qh_settempfree (vertexsetA);
-  *vertexsetA= intersection;
-  qh_settemppush (intersection);
-} /* vertexintersect */
-
-/*---------------------------------
-  
-  qh_vertexintersect_new(  )
-    intersects two vertex sets (inverse id ordered)
-
-  returns:
-    a new set
-*/
-setT *qh_vertexintersect_new (setT *vertexsetA,setT *vertexsetB) {
-  setT *intersection= qh_setnew (qh hull_dim - 1);
-  vertexT **vertexA= SETaddr_(vertexsetA, vertexT); 
-  vertexT **vertexB= SETaddr_(vertexsetB, vertexT); 
-
-  while (*vertexA && *vertexB) {
-    if (*vertexA  == *vertexB) {
-      qh_setappend(&intersection, *vertexA);
-      vertexA++; vertexB++;
-    }else {
-      if ((*vertexA)->id > (*vertexB)->id)
-        vertexA++;
-      else
-        vertexB++;
-    }
-  }
-  return intersection;
-} /* vertexintersect_new */
-
-/*---------------------------------
-  
-  qh_vertexneighbors()
-    for each vertex in qh.facet_list, 
-      determine its neighboring facets 
-
-  returns:
-    sets qh.VERTEXneighbors
-      nop if qh.VERTEXneighbors already set
-      qh_addpoint() will maintain them
-
-  notes:
-    assumes all vertex->neighbors are NULL
-
-  design:
-    for each facet
-      for each vertex
-        append facet to vertex->neighbors
-*/
-void qh_vertexneighbors (void /*qh facet_list*/) {
-  facetT *facet;
-  vertexT *vertex, **vertexp;
-
-  if (qh VERTEXneighbors)
-    return;
-  trace1((qh ferr, "qh_vertexneighbors: determing neighboring facets for each vertex\n"));
-  qh vertex_visit++;
-  FORALLfacets {
-    if (facet->visible)
-      continue;
-    FOREACHvertex_(facet->vertices) {
-      if (vertex->visitid != qh vertex_visit) {
-        vertex->visitid= qh vertex_visit;
-        vertex->neighbors= qh_setnew (qh hull_dim);
-      }
-      qh_setappend (&vertex->neighbors, facet);
-    }
-  }
-  qh VERTEXneighbors= True;
-} /* vertexneighbors */
-
-/*---------------------------------
-  
-  qh_vertexsubset( vertexsetA, vertexsetB )
-    returns True if vertexsetA is a subset of vertexsetB
-    assumes vertexsets are sorted
-
-  note:    
-    empty set is a subset of any other set
-*/
-boolT qh_vertexsubset(setT *vertexsetA, setT *vertexsetB) {
-  vertexT **vertexA= (vertexT **) SETaddr_(vertexsetA, vertexT);
-  vertexT **vertexB= (vertexT **) SETaddr_(vertexsetB, vertexT);
-
-  while (True) {
-    if (!*vertexA)
-      return True;
-    if (!*vertexB)
-      return False;
-    if ((*vertexA)->id > (*vertexB)->id)
-      return False;
-    if (*vertexA  == *vertexB)
-      vertexA++;
-    vertexB++; 
-  }
-  return False; /* avoid warnings */
-} /* vertexsubset */
diff --git a/extern/qhull/src/qconvex.c b/extern/qhull/src/qconvex.c
deleted file mode 100644
index 67b78646e50..00000000000
--- a/extern/qhull/src/qconvex.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
  ---------------------------------
-
-   qconvex.c
-      compute convex hulls using qhull
-
-   see unix.c for full interface
-
-   copyright (c) 1993-2002, The Geometry Center
-*/
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include "qhull.h"
-#include "mem.h"
-#include "qset.h"
-
-#if __MWERKS__ && __POWERPC__
-#include 
-#include 
-#include 
-#include 
-
-#elif __cplusplus
-extern "C" {
-  int isatty (int);
-}
-
-#elif _MSC_VER
-#include 
-#define isatty _isatty
-
-#else
-int isatty (int);  /* returns 1 if stdin is a tty
-		   if "Undefined symbol" this can be deleted along with call in main() */
-#endif
-
-/*---------------------------------
-
-  qh_prompt
-    long prompt for qconvex
-    
-  notes:
-    restricted version of qhull.c
-
-  see:
-    concise prompt below
-*/  
-
-/* duplicated in qconvex.htm */
-char hidden_options[]=" d v H Qbb Qf Qg Qm Qr Qu Qv Qx Qz TR E V Fp Gt Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 ";
-	       
-char qh_prompta[]= "\n\
-qconvex- compute the convex hull\n\
-    http://www.geom.umn.edu/software/qhull  %s\n\
-\n\
-input (stdin):\n\
-    first lines: dimension and number of points (or vice-versa).\n\
-    other lines: point coordinates, best if one point per line\n\
-    comments:    start with a non-numeric character\n\
-\n\
-options:\n\
-    Qt   - triangulated output\n\
-    QJ   - joggled input instead of merged facets\n\
-    Qc   - keep coplanar points with nearest facet\n\
-    Qi   - keep interior points with nearest facet\n\
-\n\
-Qhull control options:\n\
-    Qbk:n   - scale coord k so that low bound is n\n\
-      QBk:n - scale coord k so that upper bound is n (QBk is %2.2g)\n\
-    QbB  - scale input to unit cube centered at the origin\n\
-    Qbk:0Bk:0 - remove k-th coordinate from input\n\
-    QJn  - randomly joggle input in range [-n,n]\n\
-    QRn  - random rotation (n=seed, n=0 time, n=-1 time/no rotate)\n\
-%s%s%s%s";  /* split up qh_prompt for Visual C++ */
-char qh_promptb[]= "\
-    Qs   - search all points for the initial simplex\n\
-    QGn  - good facet if visible from point n, -n for not visible\n\
-    QVn  - good facet if it includes point n, -n if not\n\
-\n\
-";
-char qh_promptc[]= "\
-Trace options:\n\
-    T4   - trace at level n, 4=all, 5=mem/gauss, -1= events\n\
-    Tc   - check frequently during execution\n\
-    Ts   - print statistics\n\
-    Tv   - verify result: structure, convexity, and point inclusion\n\
-    Tz   - send all output to stdout\n\
-    TFn  - report summary when n or more facets created\n\
-    TI file - input data from file, no spaces or single quotes\n\
-    TO file - output results to file, may be enclosed in single quotes\n\
-    TPn  - turn on tracing when point n added to hull\n\
-     TMn - turn on tracing at merge n\n\
-     TWn - trace merge facets when width > n\n\
-    TVn  - stop qhull after adding point n, -n for before (see TCn)\n\
-     TCn - stop qhull after building cone for point n (see TVn)\n\
-\n\
-Precision options:\n\
-    Cn   - radius of centrum (roundoff added).  Merge facets if non-convex\n\
-     An  - cosine of maximum angle.  Merge facets if cosine > n or non-convex\n\
-           C-0 roundoff, A-0.99/C-0.01 pre-merge, A0.99/C0.01 post-merge\n\
-    Rn   - randomly perturb computations by a factor of [1-n,1+n]\n\
-    Un   - max distance below plane for a new, coplanar point\n\
-    Wn   - min facet width for outside point (before roundoff)\n\
-\n\
-Output formats (may be combined; if none, produces a summary to stdout):\n\
-    f    - facet dump\n\
-    G    - Geomview output (see below)\n\
-    i    - vertices incident to each facet\n\
-    m    - Mathematica output (2-d and 3-d)\n\
-    n    - normals with offsets\n\
-    o    - OFF file format (dim, points and facets; Voronoi regions)\n\
-    p    - point coordinates \n\
-    s    - summary (stderr)\n\
-\n\
-";
-char qh_promptd[]= "\
-More formats:\n\
-    Fa   - area for each facet\n\
-    FA   - compute total area and volume for option 's'\n\
-    Fc   - count plus coplanar points for each facet\n\
-           use 'Qc' (default) for coplanar and 'Qi' for interior\n\
-    FC   - centrum for each facet\n\
-    Fd   - use cdd format for input (homogeneous with offset first)\n\
-    FD   - use cdd format for numeric output (offset first)\n\
-    FF   - facet dump without ridges\n\
-    Fi   - inner plane for each facet\n\
-    FI   - ID for each facet\n\
-    Fm   - merge count for each facet (511 max)\n\
-    Fn   - count plus neighboring facets for each facet\n\
-    FN   - count plus neighboring facets for each point\n\
-    Fo   - outer plane (or max_outside) for each facet\n\
-    FO   - options and precision constants\n\
-    FP   - nearest vertex for each coplanar point\n\
-    FQ   - command used for qconvex\n\
-    Fs   - summary: #int (8), dimension, #points, tot vertices, tot facets,\n\
-                      for output: #vertices, #facets,\n\
-                                  #coplanar points, #non-simplicial facets\n\
-                    #real (2), max outer plane, min vertex\n\
-    FS   - sizes:   #int (0) \n\
-                    #real(2) tot area, tot volume\n\
-    Ft   - triangulation with centrums for non-simplicial facets (OFF format)\n\
-    Fv   - count plus vertices for each facet\n\
-    FV   - average of vertices (a feasible point for 'H')\n\
-    Fx   - extreme points (in order for 2-d)\n\
-\n\
-";
-char qh_prompte[]= "\
-Geomview output (2-d, 3-d, and 4-d)\n\
-    Ga   - all points as dots\n\
-     Gp  -  coplanar points and vertices as radii\n\
-     Gv  -  vertices as spheres\n\
-    Gi   - inner planes only\n\
-     Gn  -  no planes\n\
-     Go  -  outer planes only\n\
-    Gc   - centrums\n\
-    Gh   - hyperplane intersections\n\
-    Gr   - ridges\n\
-    GDn  - drop dimension n in 3-d and 4-d output\n\
-\n\
-Print options:\n\
-    PAn  - keep n largest facets by area\n\
-    Pdk:n - drop facet if normal[k] <= n (default 0.0)\n\
-    PDk:n - drop facet if normal[k] >= n\n\
-    Pg   - print good facets (needs 'QGn' or 'QVn')\n\
-    PFn  - keep facets whose area is at least n\n\
-    PG   - print neighbors of good facets\n\
-    PMn  - keep n facets with most merges\n\
-    Po   - force output.  If error, output neighborhood of facet\n\
-    Pp   - do not report precision problems\n\
-\n\
-    .    - list of all options\n\
-    -    - one line descriptions of all options\n\
-";
-/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
-
-/*---------------------------------
-
-  qh_prompt2
-    synopsis for qhull 
-*/  
-char qh_prompt2[]= "\n\
-qconvex- compute the convex hull.  Qhull %s\n\
-    input (stdin): dimension, number of points, point coordinates\n\
-    comments start with a non-numeric character\n\
-\n\
-options (qconvex.htm):\n\
-    Qt   - triangulated output\n\
-    QJ   - joggled input instead of merged facets\n\
-    Tv   - verify result: structure, convexity, and point inclusion\n\
-    .    - concise list of all options\n\
-    -    - one-line description of all options\n\
-\n\
-output options (subset):\n\
-    s    - summary of results (default)\n\
-    i    - vertices incident to each facet\n\
-    n    - normals with offsets\n\
-    p    - vertex coordinates (includes coplanar points if 'Qc')\n\
-    Fx   - extreme points (convex hull vertices)\n\
-    FA   - compute total area and volume\n\
-    o    - OFF format (dim, n, points, facets)\n\
-    G    - Geomview output (2-d, 3-d, and 4-d)\n\
-    m    - Mathematica output (2-d and 3-d)\n\
-    QVn  - print facets that include point n, -n if not\n\
-    TO file- output results to file, may be enclosed in single quotes\n\
-\n\
-examples:\n\
-    rbox c D2 | qconvex s n                    rbox c D2 | qconvex i\n\
-    rbox c D2 | qconvex o                      rbox 1000 s | qconvex s Tv FA\n\
-    rbox c d D2 | qconvex s Qc Fx              rbox y 1000 W0 | qconvex s n\n\
-    rbox y 1000 W0 | qconvex s QJ              rbox d G1 D12 | qconvex QR0 FA Pp\n\
-    rbox c D7 | qconvex FA TF1000\n\
-\n\
-";
-/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
-
-/*---------------------------------
-
-  qh_prompt3
-    concise prompt for qhull 
-*/  
-char qh_prompt3[]= "\n\
-Qhull %s.\n\
-Except for 'F.' and 'PG', upper-case options take an argument.\n\
-\n\
- incidences     mathematica    normals        OFF_format     points\n\
- summary        facet_dump\n\
-\n\
- Farea          FArea_total    Fcoplanars     FCentrums      Fd_cdd_in\n\
- FD_cdd_out     FFacet_xridge  Finner         FIDs           Fmerges\n\
- Fneighbors     FNeigh_vertex  Fouter         FOptions       FPoint_near\n\
- FQhull         Fsummary       FSize          Fvertices      FVertex_ave\n\
- Fxtremes\n\
-\n\
- Gvertices      Gpoints        Gall_points    Gno_planes     Ginner\n\
- Gcentrums      Ghyperplanes   Gridges        Gouter         GDrop_dim\n\
-\n\
- PArea_keep     Pdrop d0:0D0   PFacet_area_keep Pgood        PGood_neighbors\n\
- PMerge_keep    Poutput_forced Pprecision_not\n\
-\n\
- QbBound 0:0.5  QbB_scale_box  Qcoplanar      QGood_point    Qinterior\n\
- QJoggle        Qrandom        QRotate        Qsearch_1st    Qtriangulate\n\
- QVertex_good\n\
-\n\
- T4_trace       Tcheck_often   Tstatistics    Tverify        Tz_stdout\n\
- TFacet_log     TInput_file    TPoint_trace   TMerge_trace   TOutput_file\n\
- TWide_trace    TVertex_stop   TCone_stop\n\
-\n\
- Angle_max      Centrum_size   Random_dist    Ucoplanar_max  Wide_outside\n\
-";
-
-/*---------------------------------
-  
-  main( argc, argv )
-    processes the command line, calls qhull() to do the work, and exits
-  
-  design:
-    initializes data structures
-    reads points
-    finishes initialization
-    computes convex hull and other structures
-    checks the result
-    writes the output
-    frees memory
-*/
-int main(int argc, char *argv[]) {
-  int curlong, totlong; /* used !qh_NOmem */
-  int exitcode, numpoints, dim;
-  coordT *points;
-  boolT ismalloc;
-
-#if __MWERKS__ && __POWERPC__
-  char inBuf[BUFSIZ], outBuf[BUFSIZ], errBuf[BUFSIZ];
-  SIOUXSettings.showstatusline= false;
-  SIOUXSettings.tabspaces= 1;
-  SIOUXSettings.rows= 40;
-  if (setvbuf (stdin, inBuf, _IOFBF, sizeof(inBuf)) < 0   /* w/o, SIOUX I/O is slow*/
-  || setvbuf (stdout, outBuf, _IOFBF, sizeof(outBuf)) < 0
-  || (stdout != stderr && setvbuf (stderr, errBuf, _IOFBF, sizeof(errBuf)) < 0)) 
-    fprintf (stderr, "qhull internal warning (main): could not change stdio to fully buffered.\n");
-  argc= ccommand(&argv);
-#endif
-
-  if ((argc == 1) && isatty( 0 /*stdin*/)) {      
-    fprintf(stdout, qh_prompt2, qh_VERSION);
-    exit(qh_ERRnone);
-  }
-  if (argc > 1 && *argv[1] == '-' && !*(argv[1]+1)) {
-    fprintf(stdout, qh_prompta, qh_VERSION, qh_DEFAULTbox, 
-		qh_promptb, qh_promptc, qh_promptd, qh_prompte);
-    exit(qh_ERRnone);
-  }
-  if (argc >1 && *argv[1] == '.' && !*(argv[1]+1)) {
-    fprintf(stdout, qh_prompt3, qh_VERSION);
-    exit(qh_ERRnone);
-  }
-  qh_init_A (stdin, stdout, stderr, argc, argv);  /* sets qh qhull_command */
-  exitcode= setjmp (qh errexit); /* simple statement for CRAY J916 */
-  if (!exitcode) {
-    qh_checkflags (qh qhull_command, hidden_options);
-    qh_initflags (qh qhull_command);
-    points= qh_readpoints (&numpoints, &dim, &ismalloc);
-    if (dim >= 5) {
-      qh_option ("Qxact_merge", NULL, NULL);
-      qh MERGEexact= True; /* 'Qx' always */
-    }
-    qh_init_B (points, numpoints, dim, ismalloc);
-    qh_qhull();
-    qh_check_output();
-    qh_produce_output();
-    if (qh VERIFYoutput && !qh FORCEoutput && !qh STOPpoint && !qh STOPcone)
-      qh_check_points();
-    exitcode= qh_ERRnone;
-  }
-  qh NOerrexit= True;  /* no more setjmp */
-#ifdef qh_NOmem
-  qh_freeqhull( True);
-#else
-  qh_freeqhull( False);
-  qh_memfreeshort (&curlong, &totlong);
-  if (curlong || totlong) 
-    fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
-       totlong, curlong);
-#endif
-  return exitcode;
-} /* main */
-
diff --git a/extern/qhull/src/qdelaun.c b/extern/qhull/src/qdelaun.c
deleted file mode 100644
index 0e49d9c381e..00000000000
--- a/extern/qhull/src/qdelaun.c
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
  ---------------------------------
-
-   qdelaun.c
-     compute Delaunay triangulations and furthest-point Delaunay
-     triangulations using qhull
-
-   see unix.c for full interface
-
-   copyright (c) 1993-2002, The Geometry Center
-*/
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include "qhull.h"
-#include "mem.h"
-#include "qset.h"
-
-#if __MWERKS__ && __POWERPC__
-#include 
-#include 
-#include 
-#include 
-
-#elif __cplusplus
-extern "C" {
-  int isatty (int);
-}
-
-#elif _MSC_VER
-#include 
-#define isatty _isatty
-
-#else
-int isatty (int);  /* returns 1 if stdin is a tty
-		   if "Undefined symbol" this can be deleted along with call in main() */
-#endif
-
-/*---------------------------------
-
-  qh_prompt 
-    long prompt for qhull
-    
-  notes:
-    restricted version of qhull.c
- 
-  see:
-    concise prompt below
-*/  
-
-/* duplicated in qdelau_f.htm and qdelaun.htm */
-char hidden_options[]=" d n v H U Qb QB Qc Qf Qg Qi Qm Qr QR Qv Qx TR E V FC Fi Fo Ft Fp FV Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 ";
-
-char qh_prompta[]= "\n\
-qdelaunay- compute the Delaunay triangulation\n\
-    http://www.geom.umn.edu/software/qhull  %s\n\
-\n\
-input (stdin):\n\
-    first lines: dimension and number of points (or vice-versa).\n\
-    other lines: point coordinates, best if one point per line\n\
-    comments:    start with a non-numeric character\n\
-\n\
-options:\n\
-    Qu   - compute furthest-site Delaunay triangulation\n\
-    Qt   - triangulated output\n\
-    QJ   - joggled input instead of merged facets\n\
-\n\
-Qhull control options:\n\
-    QJn  - randomly joggle input in range [-n,n]\n\
-%s%s%s%s";  /* split up qh_prompt for Visual C++ */
-char qh_promptb[]= "\
-    Qs   - search all points for the initial simplex\n\
-    Qz   - add point-at-infinity to Delaunay triangulation\n\
-    QGn  - print Delaunay region if visible from point n, -n if not\n\
-    QVn  - print Delaunay regions that include point n, -n if not\n\
-\n\
-";
-char qh_promptc[]= "\
-Trace options:\n\
-    T4   - trace at level n, 4=all, 5=mem/gauss, -1= events\n\
-    Tc   - check frequently during execution\n\
-    Ts   - print statistics\n\
-    Tv   - verify result: structure, convexity, and in-circle test\n\
-    Tz   - send all output to stdout\n\
-    TFn  - report summary when n or more facets created\n\
-    TI file - input data from file, no spaces or single quotes\n\
-    TO file - output results to file, may be enclosed in single quotes\n\
-    TPn  - turn on tracing when point n added to hull\n\
-     TMn - turn on tracing at merge n\n\
-     TWn - trace merge facets when width > n\n\
-    TVn  - stop qhull after adding point n, -n for before (see TCn)\n\
-     TCn - stop qhull after building cone for point n (see TVn)\n\
-\n\
-Precision options:\n\
-    Cn   - radius of centrum (roundoff added).  Merge facets if non-convex\n\
-     An  - cosine of maximum angle.  Merge facets if cosine > n or non-convex\n\
-           C-0 roundoff, A-0.99/C-0.01 pre-merge, A0.99/C0.01 post-merge\n\
-    Rn   - randomly perturb computations by a factor of [1-n,1+n]\n\
-    Wn   - min facet width for outside point (before roundoff)\n\
-\n\
-Output formats (may be combined; if none, produces a summary to stdout):\n\
-    f    - facet dump\n\
-    G    - Geomview output (see below)\n\
-    i    - vertices incident to each Delaunay region\n\
-    m    - Mathematica output (2-d only, lifted to a paraboloid)\n\
-    o    - OFF format (dim, points, and facets as a paraboloid)\n\
-    p    - point coordinates (lifted to a paraboloid)\n\
-    s    - summary (stderr)\n\
-\n\
-";
-char qh_promptd[]= "\
-More formats:\n\
-    Fa   - area for each Delaunay region\n\
-    FA   - compute total area for option 's'\n\
-    Fc   - count plus coincident points for each Delaunay region\n\
-    Fd   - use cdd format for input (homogeneous with offset first)\n\
-    FD   - use cdd format for numeric output (offset first)\n\
-    FF   - facet dump without ridges\n\
-    FI   - ID of each Delaunay region\n\
-    Fm   - merge count for each Delaunay region (511 max)\n\
-    Fn   - count plus neighboring region for each Delaunay region\n\
-    FN   - count plus neighboring region for each point\n\
-    FO   - options and precision constants\n\
-    FP   - nearest point and distance for each coincident point\n\
-    FQ   - command used for qdelaunay\n\
-    Fs   - summary: #int (8), dimension, #points, tot vertices, tot facets,\n\
-                    for output: #vertices, #Delaunay regions,\n\
-                                #coincident points, #non-simplicial regions\n\
-                    #real (2), max outer plane, min vertex\n\
-    FS   - sizes:   #int (0)\n\
-                    #real(2) tot area, 0\n\
-    Fv   - count plus vertices for each Delaunay region\n\
-    Fx   - extreme points of Delaunay triangulation (on convex hull)\n\
-\n\
-";
-char qh_prompte[]= "\
-Geomview options (2-d and 3-d)\n\
-    Ga   - all points as dots\n\
-     Gp  -  coplanar points and vertices as radii\n\
-     Gv  -  vertices as spheres\n\
-    Gi   - inner planes only\n\
-     Gn  -  no planes\n\
-     Go  -  outer planes only\n\
-    Gc	   - centrums\n\
-    Gh   - hyperplane intersections\n\
-    Gr   - ridges\n\
-    GDn  - drop dimension n in 3-d and 4-d output\n\
-    Gt   - transparent outer ridges to view 3-d Delaunay\n\
-\n\
-Print options:\n\
-    PAn  - keep n largest Delaunay regions by area\n\
-    Pdk:n - drop facet if normal[k] <= n (default 0.0)\n\
-    PDk:n - drop facet if normal[k] >= n\n\
-    Pg   - print good Delaunay regions (needs 'QGn' or 'QVn')\n\
-    PFn  - keep Delaunay regions whose area is at least n\n\
-    PG   - print neighbors of good regions (needs 'QGn' or 'QVn')\n\
-    PMn  - keep n Delaunay regions with most merges\n\
-    Po   - force output.  If error, output neighborhood of facet\n\
-    Pp   - do not report precision problems\n\
-\n\
-    .    - list of all options\n\
-    -    - one line descriptions of all options\n\
-";
-/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
-
-/*---------------------------------
-
-  qh_prompt2
-    synopsis for qhull 
-*/  
-char qh_prompt2[]= "\n\
-qdelaunay- compute the Delaunay triangulation. Qhull %s\n\
-    input (stdin): dimension, number of points, point coordinates\n\
-    comments start with a non-numeric character\n\
-\n\
-options (qdelaun.htm):\n\
-    Qu   - furthest-site Delaunay triangulation\n\
-    Qt   - triangulated output\n\
-    QJ   - joggled input instead of merged facets\n\
-    Tv   - verify result: structure, convexity, and in-circle test\n\
-    .    - concise list of all options\n\
-    -    - one-line description of all options\n\
-\n\
-output options (subset):\n\
-    s    - summary of results (default)\n\
-    i    - vertices incident to each Delaunay region\n\
-    Fx   - extreme points (vertices of the convex hull)\n\
-    o    - OFF format (shows the points lifted to a paraboloid)\n\
-    G    - Geomview output (2-d and 3-d points lifted to a paraboloid)\n\
-    m    - Mathematica output (2-d inputs lifted to a paraboloid)\n\
-    QVn  - print Delaunay regions that include point n, -n if not\n\
-    TO file- output results to file, may be enclosed in single quotes\n\
-\n\
-examples:\n\
-    rbox c P0 D2 | qdelaunay s o          rbox c P0 D2 | qdelaunay i\n\
-    rbox c P0 D2 | qdelaunay Fv           rbox c P0 D2 | qdelaunay s Qu Fv\n\
-    rbox c G1 d D2 | qdelaunay s i        rbox c G1 d D2 | qdelaunay Qt\n\
-    rbox M3,4 z 100 D2 | qdelaunay s      rbox M3,4 z 100 D2 | qdelaunay s Qt\n\
-\n\
-";
-/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
-
-/*---------------------------------
-
-  qh_prompt3
-    concise prompt for qhull 
-*/  
-char qh_prompt3[]= "\n\
-Qhull %s.\n\
-Except for 'F.' and 'PG', upper-case options take an argument.\n\
-\n\
- incidences     mathematica    OFF_format     points_lifted  summary\n\
- facet_dump\n\
-\n\
- Farea          FArea_total    Fcoincident    Fd_cdd_in      FD_cdd_out\n\
- FF_dump_xridge FIDs           Fmerges        Fneighbors     FNeigh_vertex\n\
- FOptions       FPoint_near    FQdelaun       Fsummary       FSize\n\
- Fvertices      Fxtremes\n\
-\n\
- Gvertices      Gpoints        Gall_points    Gno_planes     Ginner\n\
- Gcentrums      Ghyperplanes   Gridges        Gouter         GDrop_dim\n\
- Gtransparent\n\
-\n\
- PArea_keep     Pdrop d0:0D0   Pgood          PFacet_area_keep\n\
- PGood_neighbors PMerge_keep   Poutput_forced Pprecision_not\n\
-\n\
- QGood_point    QJoggle        Qsearch_1st    Qtriangulate   QupperDelaunay\n\
- QVertex_good   Qzinfinite\n\
-\n\
- T4_trace       Tcheck_often   Tstatistics    Tverify        Tz_stdout\n\
- TFacet_log     TInput_file    TPoint_trace   TMerge_trace   TOutput_file\n\
- TWide_trace    TVertex_stop   TCone_stop\n\
-\n\
- Angle_max      Centrum_size   Random_dist    Wide_outside\n\
-";
-
-/*---------------------------------
-  
-  main( argc, argv )
-    processes the command line, calls qhull() to do the work, and exits
-  
-  design:
-    initializes data structures
-    reads points
-    finishes initialization
-    computes convex hull and other structures
-    checks the result
-    writes the output
-    frees memory
-*/
-int main(int argc, char *argv[]) {
-  int curlong, totlong; /* used !qh_NOmem */
-  int exitcode, numpoints, dim;
-  coordT *points;
-  boolT ismalloc;
-
-#if __MWERKS__ && __POWERPC__
-  char inBuf[BUFSIZ], outBuf[BUFSIZ], errBuf[BUFSIZ];
-  SIOUXSettings.showstatusline= false;
-  SIOUXSettings.tabspaces= 1;
-  SIOUXSettings.rows= 40;
-  if (setvbuf (stdin, inBuf, _IOFBF, sizeof(inBuf)) < 0   /* w/o, SIOUX I/O is slow*/
-  || setvbuf (stdout, outBuf, _IOFBF, sizeof(outBuf)) < 0
-  || (stdout != stderr && setvbuf (stderr, errBuf, _IOFBF, sizeof(errBuf)) < 0)) 
-    fprintf (stderr, "qhull internal warning (main): could not change stdio to fully buffered.\n");
-  argc= ccommand(&argv);
-#endif
-
-  if ((argc == 1) && isatty( 0 /*stdin*/)) {      
-    fprintf(stdout, qh_prompt2, qh_VERSION);
-    exit(qh_ERRnone);
-  }
-  if (argc > 1 && *argv[1] == '-' && !*(argv[1]+1)) {
-    fprintf(stdout, qh_prompta, qh_VERSION,  
-		qh_promptb, qh_promptc, qh_promptd, qh_prompte);
-    exit(qh_ERRnone);
-  }
-  if (argc >1 && *argv[1] == '.' && !*(argv[1]+1)) {
-    fprintf(stdout, qh_prompt3, qh_VERSION);
-    exit(qh_ERRnone);
-  }
-  qh_init_A (stdin, stdout, stderr, argc, argv);  /* sets qh qhull_command */
-  exitcode= setjmp (qh errexit); /* simple statement for CRAY J916 */
-  if (!exitcode) {
-    qh_option ("delaunay  Qbbound-last", NULL, NULL);
-    qh DELAUNAY= True;     /* 'd'   */
-    qh SCALElast= True;    /* 'Qbb' */
-    qh KEEPcoplanar= True; /* 'Qc', to keep coplanars in 'p' */
-    qh_checkflags (qh qhull_command, hidden_options);
-    qh_initflags (qh qhull_command);
-    points= qh_readpoints (&numpoints, &dim, &ismalloc);
-    if (dim >= 5) {
-      qh_option ("Qxact_merge", NULL, NULL);
-      qh MERGEexact= True; /* 'Qx' always */
-    }
-    qh_init_B (points, numpoints, dim, ismalloc);
-    qh_qhull();
-    qh_check_output();
-    qh_produce_output();
-    if (qh VERIFYoutput && !qh FORCEoutput && !qh STOPpoint && !qh STOPcone)
-      qh_check_points();
-    exitcode= qh_ERRnone;
-  }
-  qh NOerrexit= True;  /* no more setjmp */
-#ifdef qh_NOmem
-  qh_freeqhull( True);
-#else
-  qh_freeqhull( False);
-  qh_memfreeshort (&curlong, &totlong);
-  if (curlong || totlong) 
-    fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
-       totlong, curlong);
-#endif
-  return exitcode;
-} /* main */
-
diff --git a/extern/qhull/src/qhalf.c b/extern/qhull/src/qhalf.c
deleted file mode 100644
index a2b3875dd7f..00000000000
--- a/extern/qhull/src/qhalf.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
  ---------------------------------
-
-   qhalf.c
-     compute the intersection of halfspaces about a point
-
-   see unix.c for full interface
-
-   copyright (c) 1993-2002, The Geometry Center
-*/
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include "qhull.h"
-#include "mem.h"
-#include "qset.h"
-
-#if __MWERKS__ && __POWERPC__
-#include 
-#include 
-#include 
-#include 
-
-#elif __cplusplus
-extern "C" {
-  int isatty (int);
-}
-
-#elif _MSC_VER
-#include 
-#define isatty _isatty
-
-#else
-int isatty (int);  /* returns 1 if stdin is a tty
-		   if "Undefined symbol" this can be deleted along with call in main() */
-#endif
-
-/*---------------------------------
-
-  qh_prompt 
-    long prompt for qhull
-    
-  notes:
-    restricted version of qhull.c
- 
-  see:
-    concise prompt below
-*/  
-
-/* duplicated in qhalf.htm */
-char hidden_options[]=" d n v Qbb QbB Qf Qg Qm Qr QR Qv Qx Qz TR E V Fa FA FC FD FS Ft FV Gt Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 ";
-
-char qh_prompta[]= "\n\
-qhalf- compute the intersection of halfspaces about a point\n\
-    http://www.geom.umn.edu/software/qhull  %s\n\
-\n\
-input (stdin):\n\
-    optional interior point: dimension, 1, coordinates\n\
-    first lines: dimension+1 and number of halfspaces\n\
-    other lines: halfspace coefficients followed by offset\n\
-    comments:    start with a non-numeric character\n\
-\n\
-options:\n\
-    Hn,n - specify coordinates of interior point\n\
-    Qt   - triangulated output\n\
-    QJ   - joggled input instead of merged facets\n\
-    Qc   - keep coplanar halfspaces\n\
-    Qi   - keep other redundant halfspaces\n\
-\n\
-Qhull control options:\n\
-    QJn  - randomly joggle input in range [-n,n]\n\
-%s%s%s%s";  /* split up qh_prompt for Visual C++ */
-char qh_promptb[]= "\
-    Qbk:0Bk:0 - remove k-th coordinate from input\n\
-    Qs   - search all halfspaces for the initial simplex\n\
-    QGn  - print intersection if visible to halfspace n, -n for not\n\
-    QVn  - print intersections for halfspace n, -n if not\n\
-\n\
-";
-char qh_promptc[]= "\
-Trace options:\n\
-    T4   - trace at level n, 4=all, 5=mem/gauss, -1= events\n\
-    Tc   - check frequently during execution\n\
-    Ts   - print statistics\n\
-    Tv   - verify result: structure, convexity, and redundancy\n\
-    Tz   - send all output to stdout\n\
-    TFn  - report summary when n or more facets created\n\
-    TI file - input data from file, no spaces or single quotes\n\
-    TO file - output results to file, may be enclosed in single quotes\n\
-    TPn  - turn on tracing when halfspace n added to intersection\n\
-    TMn  - turn on tracing at merge n\n\
-    TWn  - trace merge facets when width > n\n\
-    TVn  - stop qhull after adding halfspace n, -n for before (see TCn)\n\
-    TCn  - stop qhull after building cone for halfspace n (see TVn)\n\
-\n\
-Precision options:\n\
-    Cn   - radius of centrum (roundoff added).  Merge facets if non-convex\n\
-     An  - cosine of maximum angle.  Merge facets if cosine > n or non-convex\n\
-           C-0 roundoff, A-0.99/C-0.01 pre-merge, A0.99/C0.01 post-merge\n\
-    Rn   - randomly perturb computations by a factor of [1-n,1+n]\n\
-    Un   - max distance below plane for a new, coplanar halfspace\n\
-    Wn   - min facet width for outside halfspace (before roundoff)\n\
-\n\
-Output formats (may be combined; if none, produces a summary to stdout):\n\
-    f    - facet dump\n\
-    G    - Geomview output (dual convex hull)\n\
-    i    - non-redundant halfspaces incident to each intersection\n\
-    m    - Mathematica output (dual convex hull)\n\
-    o    - OFF format (dual convex hull: dimension, points, and facets)\n\
-    p    - vertex coordinates of dual convex hull (coplanars if 'Qc' or 'Qi')\n\
-    s    - summary (stderr)\n\
-\n\
-";
-char qh_promptd[]= "\
-More formats:\n\
-    Fc   - count plus redundant halfspaces for each intersection\n\
-         -   Qc (default) for coplanar and Qi for other redundant\n\
-    Fd   - use cdd format for input (homogeneous with offset first)\n\
-    FF   - facet dump without ridges\n\
-    FI   - ID of each intersection\n\
-    Fm   - merge count for each intersection (511 max)\n\
-    Fn   - count plus neighboring intersections for each intersection\n\
-    FN   - count plus intersections for each non-redundant halfspace\n\
-    FO   - options and precision constants\n\
-    Fp   - dim, count, and intersection coordinates\n\
-    FP   - nearest halfspace and distance for each redundant halfspace\n\
-    FQ   - command used for qhalf\n\
-    Fs   - summary: #int (8), dim, #halfspaces, #non-redundant, #intersections\n\
-                      for output: #non-redundant, #intersections, #coplanar\n\
-                                  halfspaces, #non-simplicial intersections\n\
-                    #real (2), max outer plane, min vertex\n\
-    Fv   - count plus non-redundant halfspaces for each intersection\n\
-    Fx   - non-redundant halfspaces\n\
-\n\
-";
-char qh_prompte[]= "\
-Geomview output (2-d, 3-d and 4-d; dual convex hull)\n\
-    Ga   - all points (i.e., transformed halfspaces) as dots\n\
-     Gp  -  coplanar points and vertices as radii\n\
-     Gv  -  vertices (i.e., non-redundant halfspaces) as spheres\n\
-    Gi   - inner planes (i.e., halfspace intersections) only\n\
-     Gn  -  no planes\n\
-     Go  -  outer planes only\n\
-    Gc	 - centrums\n\
-    Gh   - hyperplane intersections\n\
-    Gr   - ridges\n\
-    GDn  - drop dimension n in 3-d and 4-d output\n\
-\n\
-Print options:\n\
-    PAn  - keep n largest facets (i.e., intersections) by area\n\
-    Pdk:n- drop facet if normal[k] <= n (default 0.0)\n\
-    PDk:n- drop facet if normal[k] >= n\n\
-    Pg   - print good facets (needs 'QGn' or 'QVn')\n\
-    PFn  - keep facets whose area is at least n\n\
-    PG   - print neighbors of good facets\n\
-    PMn  - keep n facets with most merges\n\
-    Po   - force output.  If error, output neighborhood of facet\n\
-    Pp   - do not report precision problems\n\
-\n\
-    .    - list of all options\n\
-    -    - one line descriptions of all options\n\
-";
-/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
-
-/*---------------------------------
-
-  qh_prompt2
-    synopsis for qhull 
-*/  
-char qh_prompt2[]= "\n\
-qhalf- halfspace intersection about a point. Qhull %s\n\
-    input (stdin): [dim, 1, interior point], dim+1, n, coefficients+offset\n\
-    comments start with a non-numeric character\n\
-\n\
-options (qhalf.htm):\n\
-    Hn,n - specify coordinates of interior point\n\
-    Qt   - triangulated output\n\
-    QJ   - joggled input instead of merged facets\n\
-    Tv   - verify result: structure, convexity, and redundancy\n\
-    .    - concise list of all options\n\
-    -    - one-line description of all options\n\
-\n\
-output options (subset):\n\
-    s    - summary of results (default)\n\
-    Fp   - intersection coordinates\n\
-    Fv   - non-redundant halfspaces incident to each intersection\n\
-    Fx   - non-redundant halfspaces\n\
-    o    - OFF file format (dual convex hull)\n\
-    G    - Geomview output (dual convex hull)\n\
-    m    - Mathematica output (dual convex hull)\n\
-    QVn  - print intersections for halfspace n, -n if not\n\
-    TO file - output results to file, may be enclosed in single quotes\n\
-\n\
-examples:\n\
-    rbox d | qconvex FQ n | qhalf s H0,0,0 Fp\n\
-    rbox c | qconvex FQ FV n | qhalf s i\n\
-    rbox c | qconvex FQ FV n | qhalf s o\n\
-\n\
-";
-/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
-
-/*---------------------------------
-
-  qh_prompt3
-    concise prompt for qhull 
-*/  
-char qh_prompt3[]= "\n\
-Qhull %s.\n\
-Except for 'F.' and 'PG', upper_case options take an argument.\n\
-\n\
- incidences     Geomview       mathematica    OFF_format     point_dual\n\
- summary        facet_dump\n\
-\n\
- Fc_redundant   Fd_cdd_in      FF_dump_xridge FIDs           Fmerges\n\
- Fneighbors     FN_intersect   FOptions       Fp_coordinates FP_nearest\n\
- FQhalf         Fsummary       Fv_halfspace   Fx_non_redundant\n\
-\n\
- Gvertices      Gpoints        Gall_points    Gno_planes     Ginner\n\
- Gcentrums      Ghyperplanes   Gridges        Gouter         GDrop_dim\n\
-\n\
- PArea_keep     Pdrop d0:0D0   Pgood          PFacet_area_keep\n\
- PGood_neighbors PMerge_keep   Poutput_forced Pprecision_not\n\
-\n\
- Qbk:0Bk:0_drop Qcoplanar      QG_half_good   Qi_redundant   QJoggle\n\
- Qsearch_1st    Qtriangulate   QVertex_good\n\
-\n\
- T4_trace       Tcheck_often   Tstatistics    Tverify        Tz_stdout\n\
- TFacet_log     TInput_file    TPoint_trace   TMerge_trace   TOutput_file\n\
- TWide_trace    TVertex_stop   TCone_stop\n\
-\n\
- Angle_max      Centrum_size   Random_dist    Ucoplanar_max  Wide_outside\n\
-";
-
-/*---------------------------------
-  
-  main( argc, argv )
-    processes the command line, calls qhull() to do the work, and exits
-  
-  design:
-    initializes data structures
-    reads points
-    finishes initialization
-    computes convex hull and other structures
-    checks the result
-    writes the output
-    frees memory
-*/
-int main(int argc, char *argv[]) {
-  int curlong, totlong; /* used !qh_NOmem */
-  int exitcode, numpoints, dim;
-  coordT *points;
-  boolT ismalloc;
-
-#if __MWERKS__ && __POWERPC__
-  char inBuf[BUFSIZ], outBuf[BUFSIZ], errBuf[BUFSIZ];
-  SIOUXSettings.showstatusline= false;
-  SIOUXSettings.tabspaces= 1;
-  SIOUXSettings.rows= 40;
-  if (setvbuf (stdin, inBuf, _IOFBF, sizeof(inBuf)) < 0   /* w/o, SIOUX I/O is slow*/
-  || setvbuf (stdout, outBuf, _IOFBF, sizeof(outBuf)) < 0
-  || (stdout != stderr && setvbuf (stderr, errBuf, _IOFBF, sizeof(errBuf)) < 0)) 
-    fprintf (stderr, "qhull internal warning (main): could not change stdio to fully buffered.\n");
-  argc= ccommand(&argv);
-#endif
-
-  if ((argc == 1) && isatty( 0 /*stdin*/)) {      
-    fprintf(stdout, qh_prompt2, qh_VERSION);
-    exit(qh_ERRnone);
-  }
-  if (argc > 1 && *argv[1] == '-' && !*(argv[1]+1)) {
-    fprintf(stdout, qh_prompta, qh_VERSION, 
-        qh_promptb, qh_promptc, qh_promptd, qh_prompte);
-    exit(qh_ERRnone);
-  }
-  if (argc >1 && *argv[1] == '.' && !*(argv[1]+1)) {
-    fprintf(stdout, qh_prompt3, qh_VERSION);
-    exit(qh_ERRnone);
-  }
-  qh_init_A (stdin, stdout, stderr, argc, argv);  /* sets qh qhull_command */
-  exitcode= setjmp (qh errexit); /* simple statement for CRAY J916 */
-  if (!exitcode) {
-    qh_option ("Halfspace", NULL, NULL);
-    qh HALFspace= True;    /* 'H'   */
-    qh_checkflags (qh qhull_command, hidden_options);
-    qh_initflags (qh qhull_command);
-    if (qh SCALEinput) {
-      fprintf(qh ferr, "\
-qhull error: options 'Qbk:n' and 'QBk:n' are not used with qhalf.\n\
-             Use 'Qbk:0Bk:0 to drop dimension k.\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    points= qh_readpoints (&numpoints, &dim, &ismalloc);
-    if (dim >= 5) {
-      qh_option ("Qxact_merge", NULL, NULL);
-      qh MERGEexact= True; /* 'Qx' always */
-    }
-    qh_init_B (points, numpoints, dim, ismalloc);
-    qh_qhull();
-    qh_check_output();
-    qh_produce_output();
-    if (qh VERIFYoutput && !qh FORCEoutput && !qh STOPpoint && !qh STOPcone)
-      qh_check_points();
-    exitcode= qh_ERRnone;
-  }
-  qh NOerrexit= True;  /* no more setjmp */
-#ifdef qh_NOmem
-  qh_freeqhull( True);
-#else
-  qh_freeqhull( False);
-  qh_memfreeshort (&curlong, &totlong);
-  if (curlong || totlong) 
-    fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
-       totlong, curlong);
-#endif
-  return exitcode;
-} /* main */
-
diff --git a/extern/qhull/src/qhull.c b/extern/qhull/src/qhull.c
deleted file mode 100644
index dc835bb4f28..00000000000
--- a/extern/qhull/src/qhull.c
+++ /dev/null
@@ -1,1395 +0,0 @@
-/*
  ---------------------------------
-
-   qhull.c
-   Quickhull algorithm for convex hulls
-
-   qhull() and top-level routines
-
-   see qh-qhull.htm, qhull.h, unix.c
-
-   see qhull_a.h for internal functions
-
-   copyright (c) 1993-2002 The Geometry Center        
-*/
-
-#include "qhull_a.h" 
-
-/*============= functions in alphabetic order after qhull() =======*/
-
-/*---------------------------------
-  
-  qh_qhull()
-    compute DIM3 convex hull of qh.num_points starting at qh.first_point
-    qh contains all global options and variables
-
-  returns:
-    returns polyhedron
-      qh.facet_list, qh.num_facets, qh.vertex_list, qh.num_vertices,
-    
-    returns global variables
-      qh.hulltime, qh.max_outside, qh.interior_point, qh.max_vertex, qh.min_vertex
-    
-    returns precision constants
-      qh.ANGLEround, centrum_radius, cos_max, DISTround, MAXabs_coord, ONEmerge
-
-  notes:
-    unless needed for output
-      qh.max_vertex and qh.min_vertex are max/min due to merges
-      
-  see:
-    to add individual points to either qh.num_points
-      use qh_addpoint()
-      
-    if qh.GETarea
-      qh_produceoutput() returns qh.totarea and qh.totvol via qh_getarea()
-
-  design:
-    record starting time
-    initialize hull and partition points
-    build convex hull
-    unless early termination
-      update facet->maxoutside for vertices, coplanar, and near-inside points
-    error if temporary sets exist
-    record end time
-*/
-void qh_qhull (void) {
-  int numoutside;
-
-  qh hulltime= qh_CPUclock;
-  if (qh RERUN || qh JOGGLEmax < REALmax/2) 
-    qh_build_withrestart();
-  else {
-    qh_initbuild();
-    qh_buildhull();
-  }
-  if (!qh STOPpoint && !qh STOPcone) {
-    if (qh ZEROall_ok && !qh TESTvneighbors && qh MERGEexact)
-      qh_checkzero( qh_ALL);
-    if (qh ZEROall_ok && !qh TESTvneighbors && !qh WAScoplanar) {
-      trace2((qh ferr, "qh_qhull: all facets are clearly convex and no coplanar points.  Post-merging and check of maxout not needed.\n"));
-      qh DOcheckmax= False;
-    }else {
-      if (qh MERGEexact || (qh hull_dim > qh_DIMreduceBuild && qh PREmerge))
-        qh_postmerge ("First post-merge", qh premerge_centrum, qh premerge_cos, 
-             (qh POSTmerge ? False : qh TESTvneighbors));
-      else if (!qh POSTmerge && qh TESTvneighbors) 
-        qh_postmerge ("For testing vertex neighbors", qh premerge_centrum,
-             qh premerge_cos, True); 
-      if (qh POSTmerge)
-        qh_postmerge ("For post-merging", qh postmerge_centrum, 
-             qh postmerge_cos, qh TESTvneighbors);
-      if (qh visible_list == qh facet_list) { /* i.e., merging done */
-        qh findbestnew= True;
-        qh_partitionvisible (/*visible_list, newfacet_list*/ !qh_ALL, &numoutside);
-        qh findbestnew= False;
-        qh_deletevisible (/*qh visible_list*/);
-        qh_resetlists (False, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
-      }
-    }
-    if (qh DOcheckmax){
-      if (qh REPORTfreq) {
-	qh_buildtracing (NULL, NULL); 
-	fprintf (qh ferr, "\nTesting all coplanar points.\n");
-      }
-      qh_check_maxout();
-    }
-    if (qh KEEPnearinside && !qh maxoutdone)  
-      qh_nearcoplanar();
-  }
-  if (qh_setsize ((setT*)qhmem.tempstack) != 0) {
-    fprintf (qh ferr, "qhull internal error (qh_qhull): temporary sets not empty (%d)\n",
-	     qh_setsize ((setT*)qhmem.tempstack));
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-  qh hulltime= qh_CPUclock - qh hulltime;
-  qh QHULLfinished= True;
-  trace1((qh ferr, "qh_qhull: algorithm completed\n"));
-} /* qhull */
-
-/*---------------------------------
-  
-  qh_addpoint( furthest, facet, checkdist )
-    add point (usually furthest point) above facet to hull 
-    if checkdist, 
-      check that point is above facet.
-      if point is not outside of the hull, uses qh_partitioncoplanar()
-      assumes that facet is defined by qh_findbestfacet()
-    else if facet specified,
-      assumes that point is above facet (major damage if below)
-    for Delaunay triangulations, 
-      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
-      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates. 
-
-  returns:
-    returns False if user requested an early termination
-     qh.visible_list, newfacet_list, delvertex_list, NEWfacets may be defined
-    updates qh.facet_list, qh.num_facets, qh.vertex_list, qh.num_vertices
-    clear qh.maxoutdone (will need to call qh_check_maxout() for facet->maxoutside)
-    if unknown point, adds a pointer to qh.other_points
-      do not deallocate the point's coordinates
-  
-  notes:
-    assumes point is near its best facet and not at a local minimum of a lens
-      distributions.  Use qh_findbestfacet to avoid this case.
-    uses qh.visible_list, qh.newfacet_list, qh.delvertex_list, qh.NEWfacets
-
-  see also:
-    qh_triangulate() -- triangulate non-simplicial facets
-
-  design:
-    check point in qh.first_point/.num_points
-    if checkdist
-      if point not above facet
-        partition coplanar point 
-        exit
-    exit if pre STOPpoint requested
-    find horizon and visible facets for point
-    make new facets for point to horizon
-    make hyperplanes for point
-    compute balance statistics
-    match neighboring new facets
-    update vertex neighbors and delete interior vertices
-    exit if STOPcone requested
-    merge non-convex new facets
-    if merge found, many merges, or 'Qf'
-       use qh_findbestnew() instead of qh_findbest()
-    partition outside points from visible facets
-    delete visible facets
-    check polyhedron if requested
-    exit if post STOPpoint requested
-    reset working lists of facets and vertices
-*/
-boolT qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist) {
-  int goodvisible, goodhorizon;
-  vertexT *vertex;
-  facetT *newfacet;
-  realT dist, newbalance, pbalance;
-  boolT isoutside= False;
-  int numpart, numpoints, numnew, firstnew;
-
-  qh maxoutdone= False;
-  if (qh_pointid (furthest) == -1)
-    qh_setappend (&qh other_points, furthest);
-  if (!facet) {
-    fprintf (qh ferr, "qh_addpoint: NULL facet.  Need to call qh_findbestfacet first\n");
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-  if (checkdist) {
-    facet= qh_findbest (furthest, facet, !qh_ALL, !qh_ISnewfacets, !qh_NOupper,
-			&dist, &isoutside, &numpart);
-    zzadd_(Zpartition, numpart);
-    if (!isoutside) {
-      zinc_(Znotmax);  /* last point of outsideset is no longer furthest. */
-      facet->notfurthest= True;
-      qh_partitioncoplanar (furthest, facet, &dist);
-      return True;
-    }
-  }
-  qh_buildtracing (furthest, facet);
-  if (qh STOPpoint < 0 && qh furthest_id == -qh STOPpoint-1) {
-    facet->notfurthest= True;
-    return False;
-  }
-  qh_findhorizon (furthest, facet, &goodvisible, &goodhorizon); 
-  if (qh ONLYgood && !(goodvisible+goodhorizon) && !qh GOODclosest) {
-    zinc_(Znotgood);  
-    facet->notfurthest= True;
-    /* last point of outsideset is no longer furthest.  This is ok
-       since all points of the outside are likely to be bad */
-    qh_resetlists (False, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
-    return True;
-  }
-  zzinc_(Zprocessed);
-  firstnew= qh facet_id;
-  vertex= qh_makenewfacets (furthest /*visible_list, attaches if !ONLYgood */);
-  qh_makenewplanes (/* newfacet_list */);
-  numnew= qh facet_id - firstnew;
-  newbalance= numnew - (realT) (qh num_facets-qh num_visible)
-                         * qh hull_dim/qh num_vertices;
-  wadd_(Wnewbalance, newbalance);
-  wadd_(Wnewbalance2, newbalance * newbalance);
-  if (qh ONLYgood 
-  && !qh_findgood (qh newfacet_list, goodhorizon) && !qh GOODclosest) {
-    FORALLnew_facets 
-      qh_delfacet (newfacet);
-    qh_delvertex (vertex);
-    qh_resetlists (True, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
-    zinc_(Znotgoodnew);
-    facet->notfurthest= True;
-    return True;
-  }
-  if (qh ONLYgood)
-    qh_attachnewfacets(/*visible_list*/);
-  qh_matchnewfacets();
-  qh_updatevertices();
-  if (qh STOPcone && qh furthest_id == qh STOPcone-1) {
-    facet->notfurthest= True;
-    return False;  /* visible_list etc. still defined */
-  }
-  qh findbestnew= False;
-  if (qh PREmerge || qh MERGEexact) {
-    qh_premerge (vertex, qh premerge_centrum, qh premerge_cos);
-    if (qh_USEfindbestnew)
-      qh findbestnew= True;
-    else {
-      FORALLnew_facets {
-	if (!newfacet->simplicial) {
-	  qh findbestnew= True;  /* use qh_findbestnew instead of qh_findbest*/
-	  break;
-	}
-      }
-    }
-  }else if (qh BESToutside)
-    qh findbestnew= True;
-  qh_partitionvisible (/*visible_list, newfacet_list*/ !qh_ALL, &numpoints);
-  qh findbestnew= False;
-  qh findbest_notsharp= False;
-  zinc_(Zpbalance);
-  pbalance= numpoints - (realT) qh hull_dim /* assumes all points extreme */
-                * (qh num_points - qh num_vertices)/qh num_vertices;
-  wadd_(Wpbalance, pbalance);
-  wadd_(Wpbalance2, pbalance * pbalance);
-  qh_deletevisible (/*qh visible_list*/);
-  zmax_(Zmaxvertex, qh num_vertices);
-  qh NEWfacets= False;
-  if (qh IStracing >= 4) {
-    if (qh num_facets < 2000)
-      qh_printlists();
-    qh_printfacetlist (qh newfacet_list, NULL, True);
-    qh_checkpolygon (qh facet_list);
-  }else if (qh CHECKfrequently) {
-    if (qh num_facets < 50)
-      qh_checkpolygon (qh facet_list);
-    else
-      qh_checkpolygon (qh newfacet_list);
-  }
-  if (qh STOPpoint > 0 && qh furthest_id == qh STOPpoint-1) 
-    return False; 
-  qh_resetlists (True, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
-  /* qh_triangulate(); to test qh.TRInormals */
-  trace2((qh ferr, "qh_addpoint: added p%d new facets %d new balance %2.2g point balance %2.2g\n",
-    qh_pointid (furthest), numnew, newbalance, pbalance));
-  return True;
-} /* addpoint */
-
-/*---------------------------------
-  
-  qh_build_withrestart()
-    allow restarts due to qh.JOGGLEmax while calling qh_buildhull()
-    qh.FIRSTpoint/qh.NUMpoints is point array
-        it may be moved by qh_joggleinput()
-*/
-void qh_build_withrestart (void) {
-  int restart;
-
-  qh ALLOWrestart= True;
-  while (True) {
-    restart= setjmp (qh restartexit); /* simple statement for CRAY J916 */
-    if (restart) {       /* only from qh_precision() */
-      zzinc_(Zretry);
-      wmax_(Wretrymax, qh JOGGLEmax);
-      qh ERREXITcalled= False;
-      qh STOPcone= True; /* if break, prevents normal output */
-    }
-    if (!qh RERUN && qh JOGGLEmax < REALmax/2) {
-      if (qh build_cnt > qh_JOGGLEmaxretry) {
-	fprintf(qh ferr, "\n\
-qhull precision error: %d attempts to construct a convex hull\n\
-        with joggled input.  Increase joggle above 'QJ%2.2g'\n\
-	or modify qh_JOGGLE... parameters in user.h\n",
-	   qh build_cnt, qh JOGGLEmax);
-	qh_errexit (qh_ERRqhull, NULL, NULL);
-      }
-      if (qh build_cnt && !restart)
-	break;
-    }else if (qh build_cnt && qh build_cnt >= qh RERUN)
-      break;
-    qh STOPcone= False;
-    qh_freebuild (True);  /* first call is a nop */
-    qh build_cnt++;
-    if (!qh qhull_optionsiz)
-      qh qhull_optionsiz= strlen (qh qhull_options);
-    else { 
-      qh qhull_options [qh qhull_optionsiz]= '\0';
-      qh qhull_optionlen= 80;
-    }
-    qh_option("_run", &qh build_cnt, NULL);
-    if (qh build_cnt == qh RERUN) {
-      qh IStracing= qh TRACElastrun;  /* duplicated from qh_initqhull_globals */
-      if (qh TRACEpoint != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) {
-        qh TRACElevel= (qh IStracing? qh IStracing : 3);
-        qh IStracing= 0;
-      }
-      qhmem.IStracing= qh IStracing;
-    }
-    if (qh JOGGLEmax < REALmax/2)
-      qh_joggleinput();
-    qh_initbuild();
-    qh_buildhull();
-    if (qh JOGGLEmax < REALmax/2 && !qh MERGING)
-      qh_checkconvex (qh facet_list, qh_ALGORITHMfault);
-  }
-  qh ALLOWrestart= False;
-} /* qh_build_withrestart */
-
-/*---------------------------------
-  
-  qh_buildhull()
-    construct a convex hull by adding outside points one at a time
-
-  returns:
-  
-  notes:
-    may be called multiple times
-    checks facet and vertex lists for incorrect flags
-    to recover from STOPcone, call qh_deletevisible and qh_resetlists
-
-  design:
-    check visible facet and newfacet flags
-    check newlist vertex flags and qh.STOPcone/STOPpoint
-    for each facet with a furthest outside point
-      add point to facet
-      exit if qh.STOPcone or qh.STOPpoint requested
-    if qh.NARROWhull for initial simplex
-      partition remaining outside points to coplanar sets
-*/
-void qh_buildhull(void) {
-  facetT *facet;
-  pointT *furthest;
-  vertexT *vertex;
-  int id;
-  
-  trace1((qh ferr, "qh_buildhull: start build hull\n"));
-  FORALLfacets {
-    if (facet->visible || facet->newfacet) {
-      fprintf (qh ferr, "qhull internal error (qh_buildhull): visible or new facet f%d in facet list\n",
-                   facet->id);    
-      qh_errexit (qh_ERRqhull, facet, NULL);
-    }
-  }
-  FORALLvertices {
-    if (vertex->newlist) {
-      fprintf (qh ferr, "qhull internal error (qh_buildhull): new vertex f%d in vertex list\n",
-                   vertex->id);
-      qh_errprint ("ERRONEOUS", NULL, NULL, NULL, vertex);
-      qh_errexit (qh_ERRqhull, NULL, NULL);
-    }
-    id= qh_pointid (vertex->point);
-    if ((qh STOPpoint>0 && id == qh STOPpoint-1) ||
-	(qh STOPpoint<0 && id == -qh STOPpoint-1) ||
-	(qh STOPcone>0 && id == qh STOPcone-1)) {
-      trace1((qh ferr,"qh_buildhull: stop point or cone P%d in initial hull\n", id));
-      return;
-    }
-  }
-  qh facet_next= qh facet_list;      /* advance facet when processed */
-  while ((furthest= qh_nextfurthest (&facet))) {
-    qh num_outside--;  /* if ONLYmax, furthest may not be outside */
-    if (!qh_addpoint (furthest, facet, qh ONLYmax))
-      break;
-  }
-  if (qh NARROWhull) /* move points from outsideset to coplanarset */
-    qh_outcoplanar( /* facet_list */ );
-  if (qh num_outside && !furthest) {
-    fprintf (qh ferr, "qhull internal error (qh_buildhull): %d outside points were never processed.\n", qh num_outside);
-    qh_errexit (qh_ERRqhull, NULL, NULL);
-  }
-  trace1((qh ferr, "qh_buildhull: completed the hull construction\n"));
-} /* buildhull */
-  
-
-/*---------------------------------
-  
-  qh_buildtracing( furthest, facet )
-    trace an iteration of qh_buildhull() for furthest point and facet
-    if !furthest, prints progress message
-
-  returns:
-    tracks progress with qh.lastreport
-    updates qh.furthest_id (-3 if furthest is NULL)
-    also resets visit_id, vertext_visit on wrap around
-
-  see:
-    qh_tracemerging()
-
-  design:
-    if !furthest
-      print progress message
-      exit
-    if 'TFn' iteration
-      print progress message
-    else if tracing
-      trace furthest point and facet
-    reset qh.visit_id and qh.vertex_visit if overflow may occur
-    set qh.furthest_id for tracing
-*/
-void qh_buildtracing (pointT *furthest, facetT *facet) {
-  realT dist= 0;
-  float cpu;
-  int total, furthestid;
-  time_t timedata;
-  struct tm *tp;
-  vertexT *vertex;
-
-  qh old_randomdist= qh RANDOMdist;
-  qh RANDOMdist= False;
-  if (!furthest) {
-    time (&timedata);
-    tp= localtime (&timedata);
-    cpu= qh_CPUclock - qh hulltime;
-    cpu /= qh_SECticks;
-    total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
-    fprintf (qh ferr, "\n\
-At %02d:%02d:%02d & %2.5g CPU secs, qhull has created %d facets and merged %d.\n\
- The current hull contains %d facets and %d vertices.  Last point was p%d\n",
-      tp->tm_hour, tp->tm_min, tp->tm_sec, cpu, qh facet_id -1,
-      total, qh num_facets, qh num_vertices, qh furthest_id);
-    return;
-  }
-  furthestid= qh_pointid (furthest);
-  if (qh TRACEpoint == furthestid) {
-    qh IStracing= qh TRACElevel;
-    qhmem.IStracing= qh TRACElevel;
-  }else if (qh TRACEpoint != -1 && qh TRACEdist < REALmax/2) {
-    qh IStracing= 0;
-    qhmem.IStracing= 0;
-  }
-  if (qh REPORTfreq && (qh facet_id-1 > qh lastreport+qh REPORTfreq)) {
-    qh lastreport= qh facet_id-1;
-    time (&timedata);
-    tp= localtime (&timedata);
-    cpu= qh_CPUclock - qh hulltime;
-    cpu /= qh_SECticks;
-    total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
-    zinc_(Zdistio);
-    qh_distplane (furthest, facet, &dist);
-    fprintf (qh ferr, "\n\
-At %02d:%02d:%02d & %2.5g CPU secs, qhull has created %d facets and merged %d.\n\
- The current hull contains %d facets and %d vertices.  There are %d\n\
- outside points.  Next is point p%d (v%d), %2.2g above f%d.\n",
-      tp->tm_hour, tp->tm_min, tp->tm_sec, cpu, qh facet_id -1,
-      total, qh num_facets, qh num_vertices, qh num_outside+1,
-      furthestid, qh vertex_id, dist, getid_(facet));
-  }else if (qh IStracing >=1) {
-    cpu= qh_CPUclock - qh hulltime;
-    cpu /= qh_SECticks;
-    qh_distplane (furthest, facet, &dist);
-    fprintf (qh ferr, "qh_addpoint: add p%d (v%d) to hull of %d facets (%2.2g above f%d) and %d outside at %4.4g CPU secs.  Previous was p%d.\n",
-      furthestid, qh vertex_id, qh num_facets, dist,
-      getid_(facet), qh num_outside+1, cpu, qh furthest_id);
-  }
-  if (qh visit_id > (unsigned) INT_MAX) {
-    qh visit_id= 0;
-    FORALLfacets
-      facet->visitid= qh visit_id;
-  }
-  if (qh vertex_visit > (unsigned) INT_MAX) {
-    qh vertex_visit= 0;
-    FORALLvertices
-      vertex->visitid= qh vertex_visit;
-  }
-  qh furthest_id= furthestid;
-  qh RANDOMdist= qh old_randomdist;
-} /* buildtracing */
-
-/*---------------------------------
-  
-  qh_errexit2( exitcode, facet, otherfacet )
-    return exitcode to system after an error
-    report two facets
-
-  returns:
-    assumes exitcode non-zero
-
-  see:
-    normally use qh_errexit() in user.c (reports a facet and a ridge)
-*/
-void qh_errexit2(int exitcode, facetT *facet, facetT *otherfacet) {
-  
-  qh_errprint("ERRONEOUS", facet, otherfacet, NULL, NULL);
-  qh_errexit (exitcode, NULL, NULL);
-} /* errexit2 */
-
-
-/*---------------------------------
-  
-  qh_findhorizon( point, facet, goodvisible, goodhorizon )
-    given a visible facet, find the point's horizon and visible facets
-    for all facets, !facet-visible
-
-  returns:
-    returns qh.visible_list/num_visible with all visible facets 
-      marks visible facets with ->visible 
-    updates count of good visible and good horizon facets
-    updates qh.max_outside, qh.max_vertex, facet->maxoutside
-
-  see:
-    similar to qh_delpoint()
-
-  design:
-    move facet to qh.visible_list at end of qh.facet_list
-    for all visible facets
-     for each unvisited neighbor of a visible facet
-       compute distance of point to neighbor
-       if point above neighbor
-         move neighbor to end of qh.visible_list
-       else if point is coplanar with neighbor
-         update qh.max_outside, qh.max_vertex, neighbor->maxoutside
-         mark neighbor coplanar (will create a samecycle later)
-         update horizon statistics         
-*/
-void qh_findhorizon(pointT *point, facetT *facet, int *goodvisible, int *goodhorizon) {
-  facetT *neighbor, **neighborp, *visible;
-  int numhorizon= 0, coplanar= 0;
-  realT dist;
-  
-  trace1((qh ferr,"qh_findhorizon: find horizon for point p%d facet f%d\n",qh_pointid(point),facet->id));
-  *goodvisible= *goodhorizon= 0;
-  zinc_(Ztotvisible);
-  qh_removefacet(facet);  /* visible_list at end of qh facet_list */
-  qh_appendfacet(facet);
-  qh num_visible= 1;
-  if (facet->good)
-    (*goodvisible)++;
-  qh visible_list= facet;
-  facet->visible= True;
-  facet->f.replace= NULL;
-  if (qh IStracing >=4)
-    qh_errprint ("visible", facet, NULL, NULL, NULL);
-  qh visit_id++;
-  FORALLvisible_facets {
-    if (visible->tricoplanar && !qh TRInormals) {
-      fprintf (qh ferr, "qh_findhorizon: does not work for tricoplanar facets.  Use option 'Q11'\n");
-      qh_errexit (qh_ERRqhull, visible, NULL);
-    }
-    visible->visitid= qh visit_id;
-    FOREACHneighbor_(visible) {
-      if (neighbor->visitid == qh visit_id) 
-        continue;
-      neighbor->visitid= qh visit_id;
-      zzinc_(Znumvisibility);
-      qh_distplane(point, neighbor, &dist);
-      if (dist > qh MINvisible) {
-        zinc_(Ztotvisible);
-	qh_removefacet(neighbor);  /* append to end of qh visible_list */
-	qh_appendfacet(neighbor);
-	neighbor->visible= True;
-        neighbor->f.replace= NULL;
-	qh num_visible++;
-	if (neighbor->good)
-	  (*goodvisible)++;
-        if (qh IStracing >=4)
-          qh_errprint ("visible", neighbor, NULL, NULL, NULL);
-      }else {
- 	if (dist > - qh MAXcoplanar) {
-    	  neighbor->coplanar= True;
-          zzinc_(Zcoplanarhorizon);
-          qh_precision ("coplanar horizon");
-	  coplanar++;
-	  if (qh MERGING) {
-	    if (dist > 0) {
-	      maximize_(qh max_outside, dist);
-	      maximize_(qh max_vertex, dist);
-#if qh_MAXoutside
-	      maximize_(neighbor->maxoutside, dist);
-#endif
-	    }else
-	      minimize_(qh min_vertex, dist);  /* due to merge later */
-	  }
-      	  trace2((qh ferr, "qh_findhorizon: point p%d is coplanar to horizon f%d, dist=%2.7g < qh MINvisible (%2.7g)\n",
-	      qh_pointid(point), neighbor->id, dist, qh MINvisible));
-	}else
-    	  neighbor->coplanar= False;
-    	zinc_(Ztothorizon);
-        numhorizon++;
-	if (neighbor->good)
-	  (*goodhorizon)++;
-        if (qh IStracing >=4)
-          qh_errprint ("horizon", neighbor, NULL, NULL, NULL);
-      }
-    }
-  }
-  if (!numhorizon) {
-    qh_precision ("empty horizon");
-    fprintf(qh ferr, "qhull precision error (qh_findhorizon): empty horizon\n\
-Point p%d was above all facets.\n", qh_pointid(point));
-    qh_printfacetlist (qh facet_list, NULL, True);
-    qh_errexit(qh_ERRprec, NULL, NULL);
-  }
-  trace1((qh ferr, "qh_findhorizon: %d horizon facets (good %d), %d visible (good %d), %d coplanar\n", 
-       numhorizon, *goodhorizon, qh num_visible, *goodvisible, coplanar));
-  if (qh IStracing >= 4 && qh num_facets < 50) 
-    qh_printlists ();
-} /* findhorizon */
-
-/*---------------------------------
-  
-  qh_nextfurthest( visible )
-    returns next furthest point and visible facet for qh_addpoint()
-    starts search at qh.facet_next
-
-  returns:
-    removes furthest point from outside set
-    NULL if none available
-    advances qh.facet_next over facets with empty outside sets  
-
-  design:
-    for each facet from qh.facet_next
-      if empty outside set
-        advance qh.facet_next
-      else if qh.NARROWhull
-        determine furthest outside point
-        if furthest point is not outside
-          advance qh.facet_next (point will be coplanar)
-    remove furthest point from outside set
-*/
-pointT *qh_nextfurthest (facetT **visible) {
-  facetT *facet;
-  int size, index;
-  realT randr, dist;
-  pointT *furthest;
-
-  while ((facet= qh facet_next) != qh facet_tail) {
-    if (!facet->outsideset) {
-      qh facet_next= facet->next;
-      continue;
-    }
-    SETreturnsize_(facet->outsideset, size);
-    if (!size) {
-      qh_setfree (&facet->outsideset);
-      qh facet_next= facet->next;
-      continue;
-    }
-    if (qh NARROWhull) {
-      if (facet->notfurthest) 
-	qh_furthestout (facet);
-      furthest= (pointT*)qh_setlast (facet->outsideset);
-#if qh_COMPUTEfurthest
-      qh_distplane (furthest, facet, &dist);
-      zinc_(Zcomputefurthest);
-#else
-      dist= facet->furthestdist;
-#endif
-      if (dist < qh MINoutside) { /* remainder of outside set is coplanar for qh_outcoplanar */
-	qh facet_next= facet->next;
-	continue;
-      }
-    }
-    if (!qh RANDOMoutside && !qh VIRTUALmemory) {
-      if (qh PICKfurthest) {
-	qh_furthestnext (/* qh facet_list */);
-	facet= qh facet_next;
-      }
-      *visible= facet;
-      return ((pointT*)qh_setdellast (facet->outsideset));
-    }
-    if (qh RANDOMoutside) {
-      int outcoplanar = 0;
-      if (qh NARROWhull) {
-        FORALLfacets {
-	  if (facet == qh facet_next)
-	    break;
-	  if (facet->outsideset)
-  	    outcoplanar += qh_setsize( facet->outsideset);
-	}
-      }
-      randr= qh_RANDOMint;
-      randr= randr/(qh_RANDOMmax+1);
-      index= (int)floor((qh num_outside - outcoplanar) * randr);
-      FORALLfacet_(qh facet_next) {
-        if (facet->outsideset) {
-          SETreturnsize_(facet->outsideset, size);
-          if (!size)
-            qh_setfree (&facet->outsideset);
-          else if (size > index) {
-            *visible= facet;
-            return ((pointT*)qh_setdelnth (facet->outsideset, index));
-          }else
-            index -= size;
-        }
-      }
-      fprintf (qh ferr, "qhull internal error (qh_nextfurthest): num_outside %d is too low\nby at least %d, or a random real %g >= 1.0\n",
-              qh num_outside, index+1, randr);
-      qh_errexit (qh_ERRqhull, NULL, NULL);
-    }else { /* VIRTUALmemory */
-      facet= qh facet_tail->previous;
-      if (!(furthest= (pointT*)qh_setdellast(facet->outsideset))) {
-        if (facet->outsideset)
-          qh_setfree (&facet->outsideset);
-        qh_removefacet (facet);
-        qh_prependfacet (facet, &qh facet_list);
-        continue;
-      }
-      *visible= facet;
-      return furthest;
-    }
-  }
-  return NULL;
-} /* nextfurthest */
-
-/*---------------------------------
-  
-  qh_partitionall( vertices, points, numpoints )
-    partitions all points in points/numpoints to the outsidesets of facets
-    vertices= vertices in qh.facet_list (not partitioned)
-
-  returns:
-    builds facet->outsideset
-    does not partition qh.GOODpoint
-    if qh.ONLYgood && !qh.MERGING, 
-      does not partition qh.GOODvertex
-
-  notes:
-    faster if qh.facet_list sorted by anticipated size of outside set
-
-  design:
-    initialize pointset with all points
-    remove vertices from pointset
-    remove qh.GOODpointp from pointset (unless it's qh.STOPcone or qh.STOPpoint)
-    for all facets
-      for all remaining points in pointset
-        compute distance from point to facet
-        if point is outside facet
-          remove point from pointset (by not reappending)
-          update bestpoint
-          append point or old bestpoint to facet's outside set
-      append bestpoint to facet's outside set (furthest)
-    for all points remaining in pointset
-      partition point into facets' outside sets and coplanar sets
-*/
-void qh_partitionall(setT *vertices, pointT *points, int numpoints){
-  setT *pointset;
-  vertexT *vertex, **vertexp;
-  pointT *point, **pointp, *bestpoint;
-  int size, point_i, point_n, point_end, remaining, i, id;
-  facetT *facet;
-  realT bestdist= -REALmax, dist, distoutside;
-    
-  trace1((qh ferr, "qh_partitionall: partition all points into outside sets\n"));
-  pointset= qh_settemp (numpoints);
-  qh num_outside= 0;
-  pointp= SETaddr_(pointset, pointT);
-  for (i=numpoints, point= points; i--; point += qh hull_dim)
-    *(pointp++)= point;
-  qh_settruncate (pointset, numpoints);
-  FOREACHvertex_(vertices) {
-    if ((id= qh_pointid(vertex->point)) >= 0)
-      SETelem_(pointset, id)= NULL;
-  }
-  id= qh_pointid (qh GOODpointp);
-  if (id >=0 && qh STOPcone-1 != id && -qh STOPpoint-1 != id)
-    SETelem_(pointset, id)= NULL;
-  if (qh GOODvertexp && qh ONLYgood && !qh MERGING) { /* matches qhull()*/
-    if ((id= qh_pointid(qh GOODvertexp)) >= 0)
-      SETelem_(pointset, id)= NULL;
-  }
-  if (!qh BESToutside) {  /* matches conditional for qh_partitionpoint below */
-    distoutside= qh_DISToutside; /* multiple of qh.MINoutside & qh.max_outside, see user.h */
-    zval_(Ztotpartition)= qh num_points - qh hull_dim - 1; /*misses GOOD... */
-    remaining= qh num_facets;
-    point_end= numpoints;
-    FORALLfacets {
-      size= point_end/(remaining--) + 100;
-      facet->outsideset= qh_setnew (size);
-      bestpoint= NULL;
-      point_end= 0;
-      FOREACHpoint_i_(pointset) {
-        if (point) {
-          zzinc_(Zpartitionall);
-          qh_distplane (point, facet, &dist);
-          if (dist < distoutside)
-            SETelem_(pointset, point_end++)= point;
-          else {
-	    qh num_outside++;
-            if (!bestpoint) {
-              bestpoint= point;
-              bestdist= dist;
-            }else if (dist > bestdist) {
-              qh_setappend (&facet->outsideset, bestpoint);
-              bestpoint= point;
-              bestdist= dist;
-            }else 
-              qh_setappend (&facet->outsideset, point);
-          }
-        }
-      }
-      if (bestpoint) {
-        qh_setappend (&facet->outsideset, bestpoint);
-#if !qh_COMPUTEfurthest
-	facet->furthestdist= bestdist;
-#endif
-      }else
-        qh_setfree (&facet->outsideset);
-      qh_settruncate (pointset, point_end);
-    }
-  }
-  /* if !qh BESToutside, pointset contains points not assigned to outsideset */
-  if (qh BESToutside || qh MERGING || qh KEEPcoplanar || qh KEEPinside) {
-    qh findbestnew= True;
-    FOREACHpoint_i_(pointset) { 
-      if (point)
-        qh_partitionpoint(point, qh facet_list);
-    }
-    qh findbestnew= False;
-  }
-  zzadd_(Zpartitionall, zzval_(Zpartition));
-  zzval_(Zpartition)= 0;
-  qh_settempfree(&pointset);
-  if (qh IStracing >= 4)
-    qh_printfacetlist (qh facet_list, NULL, True);
-} /* partitionall */
-
-
-/*---------------------------------
-  
-  qh_partitioncoplanar( point, facet, dist )
-    partition coplanar point to a facet
-    dist is distance from point to facet
-    if dist NULL, 
-      searches for bestfacet and does nothing if inside
-    if qh.findbestnew set, 
-      searches new facets instead of using qh_findbest()
-
-  returns:
-    qh.max_ouside updated
-    if qh.KEEPcoplanar or qh.KEEPinside
-      point assigned to best coplanarset
-  
-  notes:
-    facet->maxoutside is updated at end by qh_check_maxout
-
-  design:
-    if dist undefined
-      find best facet for point
-      if point sufficiently below facet (depends on qh.NEARinside and qh.KEEPinside)
-        exit
-    if keeping coplanar/nearinside/inside points
-      if point is above furthest coplanar point
-        append point to coplanar set (it is the new furthest)
-        update qh.max_outside
-      else
-        append point one before end of coplanar set
-    else if point is clearly outside of qh.max_outside and bestfacet->coplanarset
-    and bestfacet is more than perpendicular to facet
-      repartition the point using qh_findbest() -- it may be put on an outsideset
-    else
-      update qh.max_outside
-*/
-void qh_partitioncoplanar (pointT *point, facetT *facet, realT *dist) {
-  facetT *bestfacet;
-  pointT *oldfurthest;
-  realT bestdist, dist2, angle;
-  int numpart= 0, oldfindbest;
-  boolT isoutside;
-
-  qh WAScoplanar= True;
-  if (!dist) {
-    if (qh findbestnew)
-      bestfacet= qh_findbestnew (point, facet, &bestdist, qh_ALL, &isoutside, &numpart);
-    else
-      bestfacet= qh_findbest (point, facet, qh_ALL, !qh_ISnewfacets, qh DELAUNAY, 
-                          &bestdist, &isoutside, &numpart);
-    zinc_(Ztotpartcoplanar);
-    zzadd_(Zpartcoplanar, numpart);
-    if (!qh DELAUNAY && !qh KEEPinside) { /*  for 'd', bestdist skips upperDelaunay facets */
-      if (qh KEEPnearinside) {
-        if (bestdist < -qh NEARinside) { 
-          zinc_(Zcoplanarinside);
-	  trace4((qh ferr, "qh_partitioncoplanar: point p%d is more than near-inside facet f%d dist %2.2g findbestnew %d\n",
-		  qh_pointid(point), bestfacet->id, bestdist, qh findbestnew));
-          return;
-        }
-      }else if (bestdist < -qh MAXcoplanar) {
-	  trace4((qh ferr, "qh_partitioncoplanar: point p%d is inside facet f%d dist %2.2g findbestnew %d\n",
-		  qh_pointid(point), bestfacet->id, bestdist, qh findbestnew));
-        zinc_(Zcoplanarinside);
-        return;
-      }
-    }
-  }else {
-    bestfacet= facet;
-    bestdist= *dist;
-  }
-  if (bestdist > qh max_outside) {
-    if (!dist && facet != bestfacet) { 
-      zinc_(Zpartangle);
-      angle= qh_getangle(facet->normal, bestfacet->normal);
-      if (angle < 0) {
-	/* typically due to deleted vertex and coplanar facets, e.g.,
-	     RBOX 1000 s Z1 G1e-13 t1001185205 | QHULL Tv */
-	zinc_(Zpartflip);
-	trace2((qh ferr, "qh_partitioncoplanar: repartition point p%d from f%d.  It is above flipped facet f%d dist %2.2g\n",
-		qh_pointid(point), facet->id, bestfacet->id, bestdist));
-	oldfindbest= qh findbestnew;
-        qh findbestnew= False;
-	qh_partitionpoint(point, bestfacet);
-        qh findbestnew= oldfindbest;
-	return;
-      }
-    }
-    qh max_outside= bestdist;
-    if (bestdist > qh TRACEdist) {
-      fprintf (qh ferr, "qh_partitioncoplanar: ====== p%d from f%d increases max_outside to %2.2g of f%d last p%d\n",
-		     qh_pointid(point), facet->id, bestdist, bestfacet->id, qh furthest_id);
-      qh_errprint ("DISTANT", facet, bestfacet, NULL, NULL);
-    }
-  }
-  if (qh KEEPcoplanar + qh KEEPinside + qh KEEPnearinside) {
-    oldfurthest= (pointT*)qh_setlast (bestfacet->coplanarset);
-    if (oldfurthest) {
-      zinc_(Zcomputefurthest);
-      qh_distplane (oldfurthest, bestfacet, &dist2);
-    }
-    if (!oldfurthest || dist2 < bestdist) 
-      qh_setappend(&bestfacet->coplanarset, point);
-    else 
-      qh_setappend2ndlast(&bestfacet->coplanarset, point);
-  }
-  trace4((qh ferr, "qh_partitioncoplanar: point p%d is coplanar with facet f%d (or inside) dist %2.2g\n",
-	  qh_pointid(point), bestfacet->id, bestdist));
-} /* partitioncoplanar */
-
-/*---------------------------------
-  
-  qh_partitionpoint( point, facet )
-    assigns point to an outside set, coplanar set, or inside set (i.e., dropt)
-    if qh.findbestnew
-      uses qh_findbestnew() to search all new facets
-    else
-      uses qh_findbest()
-  
-  notes:
-    after qh_distplane(), this and qh_findbest() are most expensive in 3-d
-
-  design:
-    find best facet for point 
-      (either exhaustive search of new facets or directed search from facet)
-    if qh.NARROWhull
-      retain coplanar and nearinside points as outside points
-    if point is outside bestfacet
-      if point above furthest point for bestfacet
-        append point to outside set (it becomes the new furthest)
-        if outside set was empty
-          move bestfacet to end of qh.facet_list (i.e., after qh.facet_next)
-        update bestfacet->furthestdist
-      else
-        append point one before end of outside set
-    else if point is coplanar to bestfacet
-      if keeping coplanar points or need to update qh.max_outside
-        partition coplanar point into bestfacet
-    else if near-inside point        
-      partition as coplanar point into bestfacet
-    else is an inside point
-      if keeping inside points 
-        partition as coplanar point into bestfacet
-*/
-void qh_partitionpoint (pointT *point, facetT *facet) {
-  realT bestdist;
-  boolT isoutside;
-  facetT *bestfacet;
-  int numpart;
-#if qh_COMPUTEfurthest
-  realT dist;
-#endif
-
-  if (qh findbestnew)
-    bestfacet= qh_findbestnew (point, facet, &bestdist, qh BESToutside, &isoutside, &numpart);
-  else
-    bestfacet= qh_findbest (point, facet, qh BESToutside, qh_ISnewfacets, !qh_NOupper,
-			  &bestdist, &isoutside, &numpart);
-  zinc_(Ztotpartition);
-  zzadd_(Zpartition, numpart);
-  if (qh NARROWhull) {
-    if (qh DELAUNAY && !isoutside && bestdist >= -qh MAXcoplanar)
-      qh_precision ("nearly incident point (narrow hull)");
-    if (qh KEEPnearinside) {
-      if (bestdist >= -qh NEARinside)
-	isoutside= True;
-    }else if (bestdist >= -qh MAXcoplanar)
-      isoutside= True;
-  }
-
-  if (isoutside) {
-    if (!bestfacet->outsideset 
-    || !qh_setlast (bestfacet->outsideset)) {
-      qh_setappend(&(bestfacet->outsideset), point);
-      if (!bestfacet->newfacet) {
-        qh_removefacet (bestfacet);  /* make sure it's after qh facet_next */
-        qh_appendfacet (bestfacet);
-      }
-#if !qh_COMPUTEfurthest
-      bestfacet->furthestdist= bestdist;
-#endif
-    }else {
-#if qh_COMPUTEfurthest
-      zinc_(Zcomputefurthest);
-      qh_distplane (oldfurthest, bestfacet, &dist);
-      if (dist < bestdist) 
-	qh_setappend(&(bestfacet->outsideset), point);
-      else
-	qh_setappend2ndlast(&(bestfacet->outsideset), point);
-#else
-      if (bestfacet->furthestdist < bestdist) {
-	qh_setappend(&(bestfacet->outsideset), point);
-	bestfacet->furthestdist= bestdist;
-      }else
-	qh_setappend2ndlast(&(bestfacet->outsideset), point);
-#endif
-    }
-    qh num_outside++;
-    trace4((qh ferr, "qh_partitionpoint: point p%d is outside facet f%d new? %d(or narrowhull)\n",
-	  qh_pointid(point), bestfacet->id, bestfacet->newfacet));
-  }else if (qh DELAUNAY || bestdist >= -qh MAXcoplanar) { /* for 'd', bestdist skips upperDelaunay facets */
-    zzinc_(Zcoplanarpart);
-    if (qh DELAUNAY)
-      qh_precision ("nearly incident point");
-    if ((qh KEEPcoplanar + qh KEEPnearinside) || bestdist > qh max_outside) 
-      qh_partitioncoplanar (point, bestfacet, &bestdist);
-    else {
-      trace4((qh ferr, "qh_partitionpoint: point p%d is coplanar to facet f%d (dropped)\n",
-	  qh_pointid(point), bestfacet->id));
-    }
-  }else if (qh KEEPnearinside && bestdist > -qh NEARinside) {
-    zinc_(Zpartnear);
-    qh_partitioncoplanar (point, bestfacet, &bestdist);
-  }else {
-    zinc_(Zpartinside);
-    trace4((qh ferr, "qh_partitionpoint: point p%d is inside all facets, closest to f%d dist %2.2g\n",
-	  qh_pointid(point), bestfacet->id, bestdist));
-    if (qh KEEPinside)
-      qh_partitioncoplanar (point, bestfacet, &bestdist);
-  }
-} /* partitionpoint */
-
-/*---------------------------------
-  
-  qh_partitionvisible( allpoints, numoutside )
-    partitions points in visible facets to qh.newfacet_list
-    qh.visible_list= visible facets
-    for visible facets
-      1st neighbor (if any) points to a horizon facet or a new facet
-    if allpoints (not used),
-      repartitions coplanar points
-
-  returns:
-    updates outside sets and coplanar sets of qh.newfacet_list
-    updates qh.num_outside (count of outside points)
-  
-  notes:
-    qh.findbest_notsharp should be clear (extra work if set)
-
-  design:
-    for all visible facets with outside set or coplanar set
-      select a newfacet for visible facet
-      if outside set
-        partition outside set into new facets
-      if coplanar set and keeping coplanar/near-inside/inside points
-        if allpoints
-          partition coplanar set into new facets, may be assigned outside
-        else
-          partition coplanar set into coplanar sets of new facets
-    for each deleted vertex
-      if allpoints
-        partition vertex into new facets, may be assigned outside
-      else
-        partition vertex into coplanar sets of new facets
-*/
-void qh_partitionvisible(/*visible_list*/ boolT allpoints, int *numoutside) {
-  facetT *visible, *newfacet;
-  pointT *point, **pointp;
-  int coplanar=0, size;
-  unsigned count;
-  vertexT *vertex, **vertexp;
-  
-  if (qh ONLYmax)
-    maximize_(qh MINoutside, qh max_vertex);
-  *numoutside= 0;
-  FORALLvisible_facets {
-    if (!visible->outsideset && !visible->coplanarset)
-      continue;
-    newfacet= visible->f.replace;
-    count= 0;
-    while (newfacet && newfacet->visible) {
-      newfacet= newfacet->f.replace;
-      if (count++ > qh facet_id)
-	qh_infiniteloop (visible);
-    }
-    if (!newfacet)
-      newfacet= qh newfacet_list;
-    if (newfacet == qh facet_tail) {
-      fprintf (qh ferr, "qhull precision error (qh_partitionvisible): all new facets deleted as\n        degenerate facets. Can not continue.\n");
-      qh_errexit (qh_ERRprec, NULL, NULL);
-    }
-    if (visible->outsideset) {
-      size= qh_setsize (visible->outsideset);
-      *numoutside += size;
-      qh num_outside -= size;
-      FOREACHpoint_(visible->outsideset) 
-        qh_partitionpoint (point, newfacet);
-    }
-    if (visible->coplanarset && (qh KEEPcoplanar + qh KEEPinside + qh KEEPnearinside)) {
-      size= qh_setsize (visible->coplanarset);
-      coplanar += size;
-      FOREACHpoint_(visible->coplanarset) {
-        if (allpoints) /* not used */
-          qh_partitionpoint (point, newfacet);
-        else
-          qh_partitioncoplanar (point, newfacet, NULL);
-      }
-    }
-  }
-  FOREACHvertex_(qh del_vertices) {
-    if (vertex->point) {
-      if (allpoints) /* not used */
-        qh_partitionpoint (vertex->point, qh newfacet_list);
-      else
-        qh_partitioncoplanar (vertex->point, qh newfacet_list, NULL);
-    }
-  }
-  trace1((qh ferr,"qh_partitionvisible: partitioned %d points from outsidesets and %d points from coplanarsets\n", *numoutside, coplanar));
-} /* partitionvisible */
-
-
-
-/*---------------------------------
-  
-  qh_precision( reason )
-    restart on precision errors if not merging and if 'QJn'
-*/
-void qh_precision (char *reason) {
-
-  if (qh ALLOWrestart && !qh PREmerge && !qh MERGEexact) {
-    if (qh JOGGLEmax < REALmax/2) {
-      trace0((qh ferr, "qh_precision: qhull restart because of %s\n", reason));
-      longjmp(qh restartexit, qh_ERRprec);
-    }
-  }
-} /* qh_precision */
-
-/*---------------------------------
-  
-  qh_printsummary( fp )
-    prints summary to fp
-
-  notes:
-    not in io.c so that user_eg.c can prevent io.c from loading
-    qh_printsummary and qh_countfacets must match counts
-
-  design:
-    determine number of points, vertices, and coplanar points
-    print summary
-*/
-void qh_printsummary(FILE *fp) {
-  realT ratio, outerplane, innerplane;
-  float cpu;
-  int size, id, nummerged, numvertices, numcoplanars= 0, nonsimplicial=0;
-  int goodused;
-  facetT *facet;
-  char *s;
-  int numdel= zzval_(Zdelvertextot);
-  int numtricoplanars= 0;
-
-  size= qh num_points + qh_setsize (qh other_points);
-  numvertices= qh num_vertices - qh_setsize (qh del_vertices);
-  id= qh_pointid (qh GOODpointp);
-  FORALLfacets {
-    if (facet->coplanarset)
-      numcoplanars += qh_setsize( facet->coplanarset);
-    if (facet->good) {
-      if (facet->simplicial) {
-	if (facet->keepcentrum && facet->tricoplanar)
-	  numtricoplanars++;
-      }else if (qh_setsize(facet->vertices) != qh hull_dim)
-	nonsimplicial++;
-    }
-  }
-  if (id >=0 && qh STOPcone-1 != id && -qh STOPpoint-1 != id)
-    size--;
-  if (qh STOPcone || qh STOPpoint)
-      fprintf (fp, "\nAt a premature exit due to 'TVn', 'TCn', 'TRn', or precision error.");
-  if (qh UPPERdelaunay)
-    goodused= qh GOODvertex + qh GOODpoint + qh SPLITthresholds;
-  else if (qh DELAUNAY)
-    goodused= qh GOODvertex + qh GOODpoint + qh GOODthreshold;
-  else
-    goodused= qh num_good;
-  nummerged= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
-  if (qh VORONOI) {
-    if (qh UPPERdelaunay)
-      fprintf (fp, "\n\
-Furthest-site Voronoi vertices by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
-    else
-      fprintf (fp, "\n\
-Voronoi diagram by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
-    fprintf(fp, "  Number of Voronoi regions%s: %d\n",
-              qh ATinfinity ? " and at-infinity" : "", numvertices);
-    if (numdel)
-      fprintf(fp, "  Total number of deleted points due to merging: %d\n", numdel); 
-    if (numcoplanars - numdel > 0) 
-      fprintf(fp, "  Number of nearly incident points: %d\n", numcoplanars - numdel); 
-    else if (size - numvertices - numdel > 0) 
-      fprintf(fp, "  Total number of nearly incident points: %d\n", size - numvertices - numdel); 
-    fprintf(fp, "  Number of%s Voronoi vertices: %d\n", 
-              goodused ? " 'good'" : "", qh num_good);
-    if (nonsimplicial) 
-      fprintf(fp, "  Number of%s non-simplicial Voronoi vertices: %d\n", 
-              goodused ? " 'good'" : "", nonsimplicial);
-  }else if (qh DELAUNAY) {
-    if (qh UPPERdelaunay)
-      fprintf (fp, "\n\
-Furthest-site Delaunay triangulation by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
-    else
-      fprintf (fp, "\n\
-Delaunay triangulation by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
-    fprintf(fp, "  Number of input sites%s: %d\n", 
-              qh ATinfinity ? " and at-infinity" : "", numvertices);
-    if (numdel)
-      fprintf(fp, "  Total number of deleted points due to merging: %d\n", numdel); 
-    if (numcoplanars - numdel > 0) 
-      fprintf(fp, "  Number of nearly incident points: %d\n", numcoplanars - numdel); 
-    else if (size - numvertices - numdel > 0)
-      fprintf(fp, "  Total number of nearly incident points: %d\n", size - numvertices - numdel); 
-    fprintf(fp, "  Number of%s Delaunay regions: %d\n", 
-              goodused ? " 'good'" : "", qh num_good);
-    if (nonsimplicial) 
-      fprintf(fp, "  Number of%s non-simplicial Delaunay regions: %d\n", 
-              goodused ? " 'good'" : "", nonsimplicial);
-  }else if (qh HALFspace) {
-    fprintf (fp, "\n\
-Halfspace intersection by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
-    fprintf(fp, "  Number of halfspaces: %d\n", size);
-    fprintf(fp, "  Number of non-redundant halfspaces: %d\n", numvertices);
-    if (numcoplanars) {
-      if (qh KEEPinside && qh KEEPcoplanar)
-      	s= "similar and redundant";
-      else if (qh KEEPinside)
-        s= "redundant";
-      else
-        s= "similar"; 
-      fprintf(fp, "  Number of %s halfspaces: %d\n", s, numcoplanars);
-    } 
-    fprintf(fp, "  Number of intersection points: %d\n", qh num_facets - qh num_visible);
-    if (goodused)
-      fprintf(fp, "  Number of 'good' intersection points: %d\n", qh num_good);
-    if (nonsimplicial) 
-      fprintf(fp, "  Number of%s non-simplicial intersection points: %d\n", 
-              goodused ? " 'good'" : "", nonsimplicial);
-  }else {
-    fprintf (fp, "\n\
-Convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
-    fprintf(fp, "  Number of vertices: %d\n", numvertices);
-    if (numcoplanars) {
-      if (qh KEEPinside && qh KEEPcoplanar)
-      	s= "coplanar and interior";
-      else if (qh KEEPinside)
-        s= "interior";
-      else
-        s= "coplanar"; 
-      fprintf(fp, "  Number of %s points: %d\n", s, numcoplanars);
-    } 
-    fprintf(fp, "  Number of facets: %d\n", qh num_facets - qh num_visible);
-    if (goodused)
-      fprintf(fp, "  Number of 'good' facets: %d\n", qh num_good);
-    if (nonsimplicial) 
-      fprintf(fp, "  Number of%s non-simplicial facets: %d\n", 
-              goodused ? " 'good'" : "", nonsimplicial);
-  }
-  if (numtricoplanars)
-      fprintf(fp, "  Number of triangulated facets: %d\n", numtricoplanars);
-  fprintf(fp, "\nStatistics for: %s | %s", 
-                      qh rbox_command, qh qhull_command);
-  if (qh ROTATErandom != INT_MIN)
-    fprintf(fp, " QR%d\n\n", qh ROTATErandom);
-  else
-    fprintf(fp, "\n\n");
-  fprintf(fp, "  Number of points processed: %d\n", zzval_(Zprocessed));
-  fprintf(fp, "  Number of hyperplanes created: %d\n", zzval_(Zsetplane));
-  if (qh DELAUNAY)
-    fprintf(fp, "  Number of facets in hull: %d\n", qh num_facets - qh num_visible);
-  fprintf(fp, "  Number of distance tests for qhull: %d\n", zzval_(Zpartition)+
-      zzval_(Zpartitionall)+zzval_(Znumvisibility)+zzval_(Zpartcoplanar));
-#if 0  /* NOTE: must print before printstatistics() */
-  {realT stddev, ave;
-  fprintf(fp, "  average new facet balance: %2.2g\n",
-	  wval_(Wnewbalance)/zval_(Zprocessed));
-  stddev= qh_stddev (zval_(Zprocessed), wval_(Wnewbalance), 
-                                 wval_(Wnewbalance2), &ave);
-  fprintf(fp, "  new facet standard deviation: %2.2g\n", stddev);
-  fprintf(fp, "  average partition balance: %2.2g\n",
-	  wval_(Wpbalance)/zval_(Zpbalance));
-  stddev= qh_stddev (zval_(Zpbalance), wval_(Wpbalance), 
-                                 wval_(Wpbalance2), &ave);
-  fprintf(fp, "  partition standard deviation: %2.2g\n", stddev);
-  }
-#endif
-  if (nummerged) {
-    fprintf(fp,"  Number of distance tests for merging: %d\n",zzval_(Zbestdist)+
-          zzval_(Zcentrumtests)+zzval_(Zdistconvex)+zzval_(Zdistcheck)+
-          zzval_(Zdistzero));
-    fprintf(fp,"  Number of distance tests for checking: %d\n",zzval_(Zcheckpart));
-    fprintf(fp,"  Number of merged facets: %d\n", nummerged);
-  }
-  if (!qh RANDOMoutside && qh QHULLfinished) {
-    cpu= qh hulltime;
-    cpu /= qh_SECticks;
-    wval_(Wcpu)= cpu;
-    fprintf (fp, "  CPU seconds to compute hull (after input): %2.4g\n", cpu);
-  }
-  if (qh RERUN) {
-    if (!qh PREmerge && !qh MERGEexact)
-      fprintf(fp, "  Percentage of runs with precision errors: %4.1f\n",
-	   zzval_(Zretry)*100.0/qh build_cnt);  /* careful of order */
-  }else if (qh JOGGLEmax < REALmax/2) {
-    if (zzval_(Zretry))
-      fprintf(fp, "  After %d retries, input joggled by: %2.2g\n",
-         zzval_(Zretry), qh JOGGLEmax);
-    else
-      fprintf(fp, "  Input joggled by: %2.2g\n", qh JOGGLEmax);
-  }
-  if (qh totarea != 0.0) 
-    fprintf(fp, "  %s facet area:   %2.8g\n", 
-	    zzval_(Ztotmerge) ? "Approximate" : "Total", qh totarea);
-  if (qh totvol != 0.0) 
-    fprintf(fp, "  %s volume:       %2.8g\n", 
-	    zzval_(Ztotmerge) ? "Approximate" : "Total", qh totvol);
-  if (qh MERGING) {
-    qh_outerinner (NULL, &outerplane, &innerplane);
-    if (outerplane > 2 * qh DISTround) {
-      fprintf(fp, "  Maximum distance of %spoint above facet: %2.2g", 
-	    (qh QHULLfinished ? "" : "merged "), outerplane);
-      ratio= outerplane/(qh ONEmerge + qh DISTround);
-      /* don't report ratio if MINoutside is large */
-      if (ratio > 0.05 && 2* qh ONEmerge > qh MINoutside && qh JOGGLEmax > REALmax/2)
-        fprintf (fp, " (%.1fx)\n", ratio);
-      else
-        fprintf (fp, "\n");
-    }
-    if (innerplane < -2 * qh DISTround) {
-      fprintf(fp, "  Maximum distance of %svertex below facet: %2.2g", 
-	    (qh QHULLfinished ? "" : "merged "), innerplane);
-      ratio= -innerplane/(qh ONEmerge+qh DISTround);
-      if (ratio > 0.05 && qh JOGGLEmax > REALmax/2)
-        fprintf (fp, " (%.1fx)\n", ratio);
-      else
-        fprintf (fp, "\n");
-    }
-  }
-  fprintf(fp, "\n");
-} /* printsummary */
-
-
diff --git a/extern/qhull/src/qhull.h b/extern/qhull/src/qhull.h
deleted file mode 100644
index 896ec1e9c18..00000000000
--- a/extern/qhull/src/qhull.h
+++ /dev/null
@@ -1,1048 +0,0 @@
-/*
  ---------------------------------
-
-   qhull.h
-   user-level header file for using qhull.a library
-
-   see qh-qhull.htm, qhull_a.h
-
-   copyright (c) 1993-2002, The Geometry Center
-
-   NOTE: access to qh_qh is via the 'qh' macro.  This allows
-   qh_qh to be either a pointer or a structure.  An example
-   of using qh is "qh DROPdim" which accesses the DROPdim
-   field of qh_qh.  Similarly, access to qh_qhstat is via
-   the 'qhstat' macro.
-
-   includes function prototypes for qhull.c, geom.c, global.c, io.c, user.c
-
-   use mem.h for mem.c
-   use qset.h for qset.c
-
-   see unix.c for an example of using qhull.h
-
-   recompile qhull if you change this file
-*/
-
-#ifndef qhDEFqhull
-#define qhDEFqhull 1
-
-/*=========================== -included files ==============*/
-
-#include 
-#include 
-#include 
-
-#if __MWERKS__ && __POWERPC__
-#include  
-#include  
-#include	
-#endif
-
-#ifndef __STDC__
-#ifndef __cplusplus
-#if     !_MSC_VER
-#error  Neither __STDC__ nor __cplusplus is defined.  Please use strict ANSI C or C++ to compile
-#error  Qhull.  You may need to turn off compiler extensions in your project configuration.  If
-#error  your compiler is a standard C compiler, you can delete this warning from qhull.h
-#endif
-#endif
-#endif
-
-#include "user.h"      /* user defineable constants */
-
-/*============ constants and basic types ====================*/
-
-/*----------------------------------
-
-  qh_VERSION
-    version string by year and date
-
-    the revision increases on code changes only
-
-  notes:
-    change date:    Changes.txt, Announce.txt, README.txt, qhull.man
-                    qhull-news.html, Eudora signatures, 
-    change version: README.txt, qhull.html, file_id.diz, Makefile
-    change year:    Copying.txt
-    check download size
-    recompile user_eg.c, rbox.c, qhull.c, qconvex.c, qdelaun.c qvoronoi.c, qhalf.c
-    make copy of qhull-news.html as qh-news.htm
-*/
-
-#define qh_VERSION "2002.1 2002/8/20"
-
-/*----------------------------------
-
-  coordT
-    coordinates and coefficients are stored as realT (i.e., double)
-
-  notes:
-    could use 'float' for data and 'double' for calculations (realT vs. coordT)
-      This requires many type casts, and adjusted error bounds.
-      Also C compilers may do expressions in double anyway.
-*/
-#define coordT realT
-
-/*----------------------------------
-
-  pointT
-    a point is an array of DIM3 coordinates
-*/
-#define pointT coordT
-
-/*----------------------------------
-
-  flagT
-    Boolean flag as a bit
-*/
-#define flagT unsigned int
-
-/*----------------------------------
-
-  boolT
-    boolean value, either True or False
-
-  notes:
-    needed for portability
-*/
-#define boolT unsigned int
-#ifdef False
-#undef False
-#endif
-#ifdef True
-#undef True
-#endif
-#define False 0
-#define True 1
-
-/*----------------------------------
-
-  qh_CENTER
-    to distinguish facet->center
-*/
-typedef enum
-{
-    qh_ASnone = 0, qh_ASvoronoi, qh_AScentrum
-}
-qh_CENTER;
-
-/*----------------------------------
-
-  qh_PRINT
-    output formats for printing (qh.PRINTout).
-    'Fa' 'FV' 'Fc' 'FC' 
-       
-
-   notes:
-   some of these names are similar to qh names.  The similar names are only
-   used in switch statements in qh_printbegin() etc.
-*/
-typedef enum {qh_PRINTnone= 0, 
-  qh_PRINTarea, qh_PRINTaverage,           /* 'Fa' 'FV' 'Fc' 'FC' */
-  qh_PRINTcoplanars, qh_PRINTcentrums, 
-  qh_PRINTfacets, qh_PRINTfacets_xridge,   /* 'f' 'FF' 'G' 'FI' 'Fi' 'Fn' */
-  qh_PRINTgeom, qh_PRINTids, qh_PRINTinner, qh_PRINTneighbors, 
-  qh_PRINTnormals, qh_PRINTouter,          /* 'n' 'Fo' 'i' 'm' 'Fm' 'o' */
-  qh_PRINTincidences, qh_PRINTmathematica, qh_PRINTmerges, qh_PRINToff, 
-  qh_PRINToptions, qh_PRINTpointintersect, /* 'FO' 'Fp' 'FP' 'p' 'FQ' 'FS' */
-  qh_PRINTpointnearest, qh_PRINTpoints, qh_PRINTqhull, qh_PRINTsize, 
-  qh_PRINTsummary, qh_PRINTtriangles,      /* 'Fs' 'Ft' 'Fv' 'FN' 'Fx' */
-  qh_PRINTvertices, qh_PRINTvneighbors, qh_PRINTextremes,
-  qh_PRINTEND} qh_PRINT;
-
-/*----------------------------------
-
-  qh_ALL
-    argument flag for selecting everything
-*/
-#define qh_ALL      True
-#define qh_NOupper  True     /* argument for qh_findbest */
-#define qh_IScheckmax  True     /* argument for qh_findbesthorizon */
-#define qh_ISnewfacets  True     /* argument for qh_findbest */
-#define qh_RESETvisible  True     /* argument for qh_resetlists */
-
-/*----------------------------------
-
-  qh_ERR
-    Qhull exit codes, for indicating errors
-*/
-#define qh_ERRnone  0    /* no error occurred during qhull */
-#define qh_ERRinput 1    /* input inconsistency */
-#define qh_ERRsingular 2 /* singular input data */
-#define qh_ERRprec  3    /* precision error */
-#define qh_ERRmem   4    /* insufficient memory, matches mem.h */
-#define qh_ERRqhull 5    /* internal error detected, matches mem.h */
-
-/* ============ -structures- ====================
-   each of the following structures is defined by a typedef
-   all realT and coordT fields occur at the beginning of a structure
-        (otherwise space may be wasted due to alignment)
-   define all flags together and pack into 32-bit number
-*/
-
-typedef struct vertexT vertexT;
-typedef struct ridgeT ridgeT;
-typedef struct facetT facetT;
-#ifndef DEFsetT
-#define DEFsetT 1
-typedef struct setT setT;          /* defined in qset.h */
-#endif
-
-/*----------------------------------
-
-  facetT
-    defines a facet
-
-  notes:
-   qhull() generates the hull as a list of facets.
-
-  topological information:
-    f.previous,next     doubly-linked list of facets
-    f.vertices          set of vertices
-    f.ridges            set of ridges
-    f.neighbors         set of neighbors
-    f.toporient         True if facet has top-orientation (else bottom)
-
-  geometric information:
-    f.offset,normal     hyperplane equation
-    f.maxoutside        offset to outer plane -- all points inside
-    f.center            centrum for testing convexity
-    f.simplicial        True if facet is simplicial
-    f.flipped           True if facet does not include qh.interior_point
-
-  for constructing hull:
-    f.visible           True if facet on list of visible facets (will be deleted)
-    f.newfacet          True if facet on list of newly created facets
-    f.coplanarset       set of points coplanar with this facet
-                        (includes near-inside points for later testing)
-    f.outsideset        set of points outside of this facet
-    f.furthestdist      distance to furthest point of outside set
-    f.visitid           marks visited facets during a loop
-    f.replace           replacement facet for to-be-deleted, visible facets
-    f.samecycle,newcycle cycle of facets for merging into horizon facet
-
-  see below for other flags and fields
-*/
-struct facetT {
-#if !qh_COMPUTEfurthest
-  coordT   furthestdist;/* distance to furthest point of outsideset */
-#endif
-#if qh_MAXoutside
-  coordT   maxoutside;  /* max computed distance of point to facet
-  			Before QHULLfinished this is an approximation
-  			since maxdist not always set for mergefacet
-			Actual outer plane is +DISTround and
-			computed outer plane is +2*DISTround */
-#endif
-  coordT   offset;      /* exact offset of hyperplane from origin */
-  coordT  *normal;      /* normal of hyperplane, hull_dim coefficients */
-			/*   if tricoplanar, shared with a neighbor */
-  union {               /* in order of testing */
-   realT   area;        /* area of facet, only in io.c if  ->isarea */
-   facetT *replace;	/*  replacement facet if ->visible and NEWfacets
-  			     is NULL only if qh_mergedegen_redundant or interior */
-   facetT *samecycle;   /*  cycle of facets from the same visible/horizon intersection,
-   			     if ->newfacet */
-   facetT *newcycle;    /*  in horizon facet, current samecycle of new facets */ 
-   facetT *trivisible;  /* visible facet for ->tricoplanar facets during qh_triangulate() */
-   facetT *triowner;    /* owner facet for ->tricoplanar, !isarea facets w/ ->keepcentrum */
-  }f;
-  coordT  *center;      /*  centrum for convexity, qh CENTERtype == qh_AScentrum */
-      			/*  Voronoi center, qh CENTERtype == qh_ASvoronoi */
-			/*   if tricoplanar, shared with a neighbor */
-  facetT  *previous;    /* previous facet in the facet_list */
-  facetT  *next;        /* next facet in the facet_list */
-  setT    *vertices;    /* vertices for this facet, inverse sorted by ID 
-                           if simplicial, 1st vertex was apex/furthest */
-  setT    *ridges;      /* explicit ridges for nonsimplicial facets.
-  			   for simplicial facets, neighbors defines ridge */
-  setT    *neighbors;   /* neighbors of the facet.  If simplicial, the kth
-			   neighbor is opposite the kth vertex, and the first
-			   neighbor is the horizon facet for the first vertex*/
-  setT    *outsideset;  /* set of points outside this facet
-		           if non-empty, last point is furthest
-			   if NARROWhull, includes coplanars for partitioning*/
-  setT    *coplanarset; /* set of points coplanar with this facet
-  			   > qh.min_vertex and <= facet->max_outside
-                           a point is assigned to the furthest facet
-		           if non-empty, last point is furthest away */
-  unsigned visitid;     /* visit_id, for visiting all neighbors,
-			   all uses are independent */
-  unsigned id;	        /* unique identifier from qh facet_id */
-  unsigned nummerge:9;  /* number of merges */
-#define qh_MAXnummerge 511 /*     2^9-1, 32 flags total, see "flags:" in io.c */
-  flagT    tricoplanar:1; /* True if TRIangulate and simplicial and coplanar with a neighbor */
-			  /*   all tricoplanars share the same ->center, ->normal, ->offset, ->maxoutside */
-			  /*   all tricoplanars share the same apex */
-                          /*   if ->degenerate, does not span facet (one logical ridge) */
-                          /*   one tricoplanar has ->keepcentrum and ->coplanarset */
-                          /*   during qh_triangulate, f.trivisible points to original facet */
-  flagT	   newfacet:1;  /* True if facet on qh newfacet_list (new or merged) */
-  flagT	   visible:1;   /* True if visible facet (will be deleted) */
-  flagT    toporient:1; /* True if created with top orientation
-			   after merging, use ridge orientation */
-  flagT    simplicial:1;/* True if simplicial facet, ->ridges may be implicit */
-  flagT    seen:1;      /* used to perform operations only once, like visitid */
-  flagT    seen2:1;     /* used to perform operations only once, like visitid */
-  flagT	   flipped:1;   /* True if facet is flipped */
-  flagT    upperdelaunay:1; /* True if facet is upper envelope of Delaunay triangulation */
-  flagT    notfurthest:1; /* True if last point of outsideset is not furthest*/
-
-/*-------- flags primarily for output ---------*/
-  flagT	   good:1;      /* True if a facet marked good for output */
-  flagT    isarea:1;    /* True if facet->f.area is defined */
-
-/*-------- flags for merging ------------------*/
-  flagT    dupridge:1;  /* True if duplicate ridge in facet */
-  flagT    mergeridge:1; /* True if facet or neighbor contains a qh_MERGEridge
-                            ->normal defined (also defined for mergeridge2) */
-  flagT    mergeridge2:1; /* True if neighbor contains a qh_MERGEridge (mark_dupridges */
-  flagT    coplanar:1;  /* True if horizon facet is coplanar at last use */
-  flagT     mergehorizon:1; /* True if will merge into horizon (->coplanar) */
-  flagT	    cycledone:1;/* True if mergecycle_all already done */
-  flagT    tested:1;    /* True if facet convexity has been tested (false after merge */
-  flagT    keepcentrum:1; /* True if keep old centrum after a merge, or marks owner for ->tricoplanar */
-  flagT	   newmerge:1;  /* True if facet is newly merged for reducevertices */
-  flagT	   degenerate:1; /* True if facet is degenerate (degen_mergeset or ->tricoplanar) */
-  flagT	   redundant:1;  /* True if facet is redundant (degen_mergeset) */
-};
-
-
-/*----------------------------------
-
-  ridgeT
-    defines a ridge
-
-  notes:
-  a ridge is DIM3-1 simplex between two neighboring facets.  If the
-  facets are non-simplicial, there may be more than one ridge between
-  two facets.  E.G. a 4-d hypercube has two triangles between each pair
-  of neighboring facets.
-
-  topological information:
-    vertices            a set of vertices
-    top,bottom          neighboring facets with orientation
-
-  geometric information:
-    tested              True if ridge is clearly convex
-    nonconvex           True if ridge is non-convex
-*/
-struct ridgeT {
-  setT    *vertices;    /* vertices belonging to this ridge, inverse sorted by ID 
-                           NULL if a degen ridge (matchsame) */
-  facetT  *top;         /* top facet this ridge is part of */
-  facetT  *bottom;      /* bottom facet this ridge is part of */
-  unsigned id:24;       /* unique identifier, =>room for 8 flags */
-  flagT    seen:1;      /* used to perform operations only once */
-  flagT    tested:1;    /* True when ridge is tested for convexity */
-  flagT    nonconvex:1; /* True if getmergeset detected a non-convex neighbor
-			   only one ridge between neighbors may have nonconvex */
-};
-
-/*----------------------------------
-
-  vertexT
-     defines a vertex
-
-  topological information:
-    next,previous       doubly-linked list of all vertices
-    neighbors           set of adjacent facets (only if qh.VERTEXneighbors)
-
-  geometric information:
-    point               array of DIM3 coordinates
-*/
-struct vertexT {
-  vertexT *next;        /* next vertex in vertex_list */
-  vertexT *previous;    /* previous vertex in vertex_list */
-  pointT  *point;       /* hull_dim coordinates (coordT) */
-  setT    *neighbors;   /* neighboring facets of vertex, qh_vertexneighbors()
-			   inits in io.c or after first merge */
-  unsigned visitid; /* for use with qh vertex_visit */
-  unsigned id:24;   /* unique identifier, =>room for 8 flags */
-  flagT    seen:1;      /* used to perform operations only once */
-  flagT    seen2:1;     /* another seen flag */
-  flagT    delridge:1;  /* vertex was part of a deleted ridge */
-  flagT	   deleted:1;   /* true if vertex on qh del_vertices */
-  flagT    newlist:1;   /* true if vertex on qh newvertex_list */
-};
-
-/*======= -global variables -qh ============================*/
-
-/*----------------------------------
-
-  qh
-   all global variables for qhull are in qh, qhmem, and qhstat
-
-  notes:
-   qhmem is defined in mem.h and qhstat is defined in stat.h
-   access to qh_qh is via the "qh" macro.  See qh_QHpointer in user.h
-*/
-typedef struct qhT qhT;
-#if qh_QHpointer
-#define qh qh_qh->
-extern qhT *qh_qh;     /* allocated in global.c */
-#else
-#define qh qh_qh.
-extern qhT qh_qh;
-#endif
-
-struct qhT {
-
-/*----------------------------------
-
-  qh constants
-    configuration flags and constants for Qhull
-
-  notes:
-    The user configures Qhull by defining flags.  They are
-    copied into qh by qh_setflags().  qh-quick.htm#options defines the flags.
-*/
-  boolT ALLpoints;        /* true 'Qs' if search all points for initial simplex */
-  boolT ANGLEmerge;	  /* true 'Qa' if sort potential merges by angle */
-  boolT APPROXhull;       /* true 'Wn' if MINoutside set */
-  realT MINoutside;       /*   'Wn' min. distance for an outside point */
-  boolT ATinfinity;       /* true 'Qz' if point num_points-1 is "at-infinity"
-                             for improving precision in Delaunay triangulations */
-  boolT AVOIDold;         /* true 'Q4' if avoid old->new merges */
-  boolT BESToutside;      /* true 'Qf' if partition points into best outsideset */
-  boolT CDDinput;         /* true 'Pc' if input uses CDD format (1.0/offset first) */
-  boolT CDDoutput;        /* true 'PC' if print normals in CDD format (offset first) */
-  boolT CHECKfrequently;  /* true 'Tc' if checking frequently */
-  realT premerge_cos;     /*   'A-n'   cos_max when pre merging */
-  realT postmerge_cos;    /*   'An'    cos_max when post merging */
-  boolT DELAUNAY;         /* true 'd' if computing DELAUNAY triangulation */
-  boolT DOintersections;  /* true 'Gh' if print hyperplane intersections */
-  int   DROPdim;          /* drops dim 'GDn' for 4-d -> 3-d output */
-  boolT FORCEoutput;      /* true 'Po' if forcing output despite degeneracies */
-  int   GOODpoint;        /* 1+n for 'QGn', good facet if visible/not(-) from point n*/
-  pointT *GOODpointp;     /*   the actual point */
-  boolT GOODthreshold;    /* true if qh lower_threshold/upper_threshold defined
-  			     false if qh SPLITthreshold */
-  int   GOODvertex;       /* 1+n, good facet if vertex for point n */
-  pointT *GOODvertexp;     /*   the actual point */
-  boolT HALFspace;        /* true 'Hn,n,n' if halfspace intersection */
-  int   IStracing;        /* trace execution, 0=none, 1=least, 4=most, -1=events */
-  int   KEEParea;         /* 'PAn' number of largest facets to keep */
-  boolT KEEPcoplanar;     /* true 'Qc' if keeping nearest facet for coplanar points */
-  boolT KEEPinside;       /* true 'Qi' if keeping nearest facet for inside points
-			      set automatically if 'd Qc' */
-  int   KEEPmerge;        /* 'PMn' number of facets to keep with most merges */
-  realT KEEPminArea;      /* 'PFn' minimum facet area to keep */
-  realT MAXcoplanar;      /* 'Un' max distance below a facet to be coplanar*/
-  boolT MERGEexact;	  /* true 'Qx' if exact merges (coplanar, degen, dupridge, flipped) */
-  boolT MERGEindependent; /* true 'Q2' if merging independent sets */
-  boolT MERGING;          /* true if exact-, pre- or post-merging, with angle and centrum tests */
-  realT   premerge_centrum;  /*   'C-n' centrum_radius when pre merging.  Default is round-off */
-  realT   postmerge_centrum; /*   'Cn' centrum_radius when post merging.  Default is round-off */
-  boolT MERGEvertices;	  /* true 'Q3' if merging redundant vertices */
-  realT MINvisible;       /* 'Vn' min. distance for a facet to be visible */
-  boolT NOnarrow;         /* true 'Q10' if no special processing for narrow distributions */
-  boolT NOnearinside;     /* true 'Q8' if ignore near-inside points when partitioning */
-  boolT NOpremerge;       /* true 'Q0' if no defaults for C-0 or Qx */
-  boolT ONLYgood; 	  /* true 'Qg' if process points with good visible or horizon facets */
-  boolT ONLYmax; 	  /* true 'Qm' if only process points that increase max_outside */
-  boolT PICKfurthest;     /* true 'Q9' if process furthest of furthest points*/
-  boolT POSTmerge;        /* true if merging after buildhull (Cn or An) */
-  boolT PREmerge;         /* true if merging during buildhull (C-n or A-n) */
-  			/* NOTE: some of these names are similar to qh_PRINT names */
-  boolT PRINTcentrums;	  /* true 'Gc' if printing centrums */
-  boolT PRINTcoplanar;    /* true 'Gp' if printing coplanar points */
-  int	PRINTdim;      	  /* print dimension for Geomview output */
-  boolT PRINTdots;        /* true 'Ga' if printing all points as dots */
-  boolT PRINTgood;        /* true 'Pg' if printing good facets */
-  boolT PRINTinner;	  /* true 'Gi' if printing inner planes */
-  boolT PRINTneighbors;	  /* true 'PG' if printing neighbors of good facets */
-  boolT PRINTnoplanes;	  /* true 'Gn' if printing no planes */
-  boolT PRINToptions1st;  /* true 'FO' if printing options to stderr */
-  boolT PRINTouter;	  /* true 'Go' if printing outer planes */
-  boolT PRINTprecision;   /* false 'Pp' if not reporting precision problems */
-  qh_PRINT PRINTout[qh_PRINTEND]; /* list of output formats to print */
-  boolT PRINTridges;      /* true 'Gr' if print ridges */
-  boolT PRINTspheres;     /* true 'Gv' if print vertices as spheres */
-  boolT PRINTstatistics;  /* true 'Ts' if printing statistics to stderr */
-  boolT PRINTsummary;     /* true 's' if printing summary to stderr */
-  boolT PRINTtransparent; /* true 'Gt' if print transparent outer ridges */
-  boolT PROJECTdelaunay;  /* true if DELAUNAY, no readpoints() and
-			     need projectinput() for Delaunay in qh_init_B */
-  int   PROJECTinput;     /* number of projected dimensions 'bn:0Bn:0' */
-  boolT QUICKhelp;	  /* true if quick help message for degen input */
-  boolT RANDOMdist;       /* true if randomly change distplane and setfacetplane */
-  realT RANDOMfactor;     /*    maximum random perturbation */
-  realT RANDOMa;         /*  qh_randomfactor is randr * RANDOMa + RANDOMb */
-  realT RANDOMb;
-  boolT RANDOMoutside;    /* true if select a random outside point */
-  int	REPORTfreq;       /* buildtracing reports every n facets */
-  int   REPORTfreq2;	  /* tracemerging reports every REPORTfreq/2 facets */
-  int	RERUN;            /* 'TRn' rerun qhull n times (qh.build_cnt) */
-  int	ROTATErandom;	  /* 'QRn' seed, 0 time, >= rotate input */
-  boolT SCALEinput;       /* true 'Qbk' if scaling input */
-  boolT SCALElast;        /* true 'Qbb' if scale last coord to max prev coord */
-  boolT SETroundoff;      /* true 'E' if qh DISTround is predefined */
-  boolT SKIPcheckmax;	  /* true 'Q5' if skip qh_check_maxout */
-  boolT SKIPconvex;       /* true 'Q6' if skip convexity testing during pre-merge */
-  boolT SPLITthresholds;  /* true if upper_/lower_threshold defines a region
-                               used only for printing (not for qh ONLYgood) */
-  int	STOPcone;         /* 'TCn' 1+n for stopping after cone for point n*/
-			  /*       also used by qh_build_withresart for err exit*/
-  int	STOPpoint;        /* 'TVn' 'TV-n' 1+n for stopping after/before(-)
-			                adding point n */
-  int	TESTpoints;	  /* 'QTn' num of test points after qh.num_points.  Test points always coplanar. */
-  boolT TESTvneighbors;   /*  true 'Qv' if test vertex neighbors at end */
-  int   TRACElevel;       /* 'Tn' conditional IStracing level */
-  int	TRACElastrun;	  /*  qh.TRACElevel applies to last qh.RERUN */
-  int   TRACEpoint;       /* 'TPn' start tracing when point n is a vertex */
-  realT TRACEdist;        /* 'TWn' start tracing when merge distance too big */
-  int   TRACEmerge;       /* 'TMn' start tracing before this merge */
-  boolT TRIangulate;	  /* true 'Qt' if triangulate non-simplicial facets */
-  boolT TRInormals;	  /* true 'Q11' if triangulate duplicates normals (sets Qt) */
-  boolT UPPERdelaunay;    /* true 'Qu' if computing furthest-site Delaunay */
-  boolT VERIFYoutput;     /* true 'Tv' if verify output at end of qhull */
-  boolT VIRTUALmemory;    /* true 'Q7' if depth-first processing in buildhull */
-  boolT VORONOI;	  /* true 'v' if computing Voronoi diagram */
-
-  /*--------input constants ---------*/
-  realT AREAfactor;       /* 1/(hull_dim-1)! for converting det's to area */
-  boolT DOcheckmax;       /* true if calling qh_check_maxout (qh_initqhull_globals) */
-  char	*feasible_string;  /* feasible point 'Hn,n,n' for halfspace intersection */
-  coordT *feasible_point;  /*    as coordinates, both malloc'd */
-  boolT GETarea;          /* true 'Fa', 'FA', 'FS', 'PAn', 'PFn' if compute facet area/Voronoi volume in io.c */
-  boolT KEEPnearinside;   /* true if near-inside points in coplanarset */
-  int 	hull_dim;         /* dimension of hull, set by initbuffers */
-  int 	input_dim;	  /* dimension of input, set by initbuffers */
-  int 	num_points;       /* number of input points */
-  pointT *first_point;    /* array of input points, see POINTSmalloc */
-  boolT POINTSmalloc;     /*   true if qh first_point/num_points allocated */
-  pointT *input_points;   /* copy of original qh.first_point for input points for qh_joggleinput */
-  boolT input_malloc;     /* true if qh input_points malloc'd */
-  char 	qhull_command[256];/* command line that invoked this program */
-  char 	rbox_command[256]; /* command line that produced the input points */
-  char  qhull_options[512];/* descriptive list of options */
-  int   qhull_optionlen;  /*    length of last line */
-  int   qhull_optionsiz;  /*     size of qhull_options before qh_initbuild */
-  boolT VERTEXneighbors;  /* true if maintaining vertex neighbors */
-  boolT ZEROcentrum;      /* true if 'C-0' or 'C-0 Qx'.  sets ZEROall_ok */
-  realT *upper_threshold; /* don't print if facet->normal[k]>=upper_threshold[k]
-                             must set either GOODthreshold or SPLITthreshold
-  			     if Delaunay, default is 0.0 for upper envelope */
-  realT *lower_threshold; /* don't print if facet->normal[k] <=lower_threshold[k] */
-  realT *upper_bound;     /* scale point[k] to new upper bound */
-  realT *lower_bound;     /* scale point[k] to new lower bound
-  			     project if both upper_ and lower_bound == 0 */
-
-/*----------------------------------
-
-  qh precision constants
-    precision constants for Qhull
-
-  notes:
-    qh_detroundoff() computes the maximum roundoff error for distance
-    and other computations.  It also sets default values for the
-    qh constants above.
-*/
-  realT ANGLEround;       /* max round off error for angles */
-  realT centrum_radius;   /* max centrum radius for convexity (roundoff added) */
-  realT cos_max;	  /* max cosine for convexity (roundoff added) */
-  realT DISTround;        /* max round off error for distances, 'E' overrides */
-  realT MAXabs_coord;     /* max absolute coordinate */
-  realT MAXlastcoord;     /* max last coordinate for qh_scalelast */
-  realT MAXsumcoord;      /* max sum of coordinates */
-  realT MAXwidth;         /* max rectilinear width of point coordinates */
-  realT MINdenom_1;       /* min. abs. value for 1/x */
-  realT MINdenom;         /*    use divzero if denominator < MINdenom */
-  realT MINdenom_1_2;     /* min. abs. val for 1/x that allows normalization */
-  realT MINdenom_2;       /*    use divzero if denominator < MINdenom_2 */
-  realT MINlastcoord;     /* min. last coordinate for qh_scalelast */
-  boolT NARROWhull;       /* set in qh_initialhull if angle < qh_MAXnarrow */
-  realT *NEARzero;        /* hull_dim array for near zero in gausselim */
-  realT NEARinside;       /* keep points for qh_check_maxout if close to facet */
-  realT ONEmerge;         /* max distance for merging simplicial facets */
-  realT outside_err;      /* application's epsilon for coplanar points
-                             qh_check_bestdist() qh_check_points() reports error if point outside */
-  realT WIDEfacet;        /* size of wide facet for skipping ridge in
-			     area computation and locking centrum */
-  
-/*----------------------------------
-
-  qh internal constants
-    internal constants for Qhull
-*/
-  char qhull[sizeof("qhull")]; /* for checking ownership */
-  void *old_stat;         /* pointer to saved qh_qhstat, qh_save_qhull */
-  jmp_buf errexit;        /* exit label for qh_errexit, defined by setjmp() */
-  char jmpXtra[40];       /* extra bytes in case jmp_buf is defined wrong by compiler */
-  jmp_buf restartexit;    /* restart label for qh_errexit, defined by setjmp() */
-  char jmpXtra2[40];      /* extra bytes in case jmp_buf is defined wrong by compiler*/
-  FILE *fin;              /* pointer to input file, init by qh_meminit */
-  FILE *fout;             /* pointer to output file */
-  FILE *ferr;             /* pointer to error file */
-  pointT *interior_point; /* center point of the initial simplex*/
-  int   normal_size;      /* size in bytes for facet normals and point coords*/
-  int   center_size;      /* size in bytes for Voronoi centers */
-  int   TEMPsize;         /* size for small, temporary sets (in quick mem) */
-
-/*----------------------------------
-
-  qh facet and vertex lists
-    defines lists of facets, new facets, visible facets, vertices, and
-    new vertices.  Includes counts, next ids, and trace ids.
-  see:
-    qh_resetlists()
-*/
-  facetT *facet_list;     /* first facet */
-  facetT  *facet_tail;     /* end of facet_list (dummy facet) */
-  facetT *facet_next;     /* next facet for buildhull()
-    			     previous facets do not have outside sets
-                             NARROWhull: previous facets may have coplanar outside sets for qh_outcoplanar */
-  facetT *newfacet_list;  /* list of new facets to end of facet_list */
-  facetT *visible_list;   /* list of visible facets preceeding newfacet_list,
-                             facet->visible set */
-  int       num_visible;  /* current number of visible facets */
-  unsigned tracefacet_id;  /* set at init, then can print whenever */
-  facetT *tracefacet;     /*   set in newfacet/mergefacet, undone in delfacet*/
-  unsigned tracevertex_id;  /* set at buildtracing, can print whenever */
-  vertexT *tracevertex;     /*   set in newvertex, undone in delvertex*/
-  vertexT *vertex_list;     /* list of all vertices, to vertex_tail */
-  vertexT  *vertex_tail;    /*      end of vertex_list (dummy vertex) */
-  vertexT *newvertex_list; /* list of vertices in newfacet_list, to vertex_tail
-                             all vertices have 'newlist' set */
-  int 	num_facets;	  /* number of facets in facet_list
-			     includes visble faces (num_visible) */
-  int 	num_vertices;     /* number of vertices in facet_list */
-  int   num_outside;      /* number of points in outsidesets (for tracing and RANDOMoutside)
-                               includes coplanar outsideset points for NARROWhull/qh_outcoplanar() */
-  int   num_good;         /* number of good facets (after findgood_all) */
-  unsigned facet_id;      /* ID of next, new facet from newfacet() */
-  unsigned ridge_id;      /* ID of next, new ridge from newridge() */
-  unsigned vertex_id;     /* ID of next, new vertex from newvertex() */
-
-/*----------------------------------
-
-  qh global variables
-    defines minimum and maximum distances, next visit ids, several flags,
-    and other global variables.
-    initialize in qh_initbuild or qh_maxmin if used in qh_buildhull
-*/
-  unsigned long hulltime; /* ignore time to set up input and randomize */
-                          /*   use unsigned to avoid wrap-around errors */
-  boolT ALLOWrestart;     /* true if qh_precision can use qh.restartexit */
-  int   build_cnt;        /* number of calls to qh_initbuild */
-  qh_CENTER CENTERtype;   /* current type of facet->center, qh_CENTER */
-  int 	furthest_id;      /* pointid of furthest point, for tracing */
-  facetT *GOODclosest;    /* closest facet to GOODthreshold in qh_findgood */
-  realT JOGGLEmax;        /* set 'QJn' if randomly joggle input */
-  boolT maxoutdone;       /* set qh_check_maxout(), cleared by qh_addpoint() */
-  realT max_outside;      /* maximum distance from a point to a facet,
-			       before roundoff, not simplicial vertices
-			       actual outer plane is +DISTround and
-			       computed outer plane is +2*DISTround */
-  realT max_vertex;       /* maximum distance (>0) from vertex to a facet,
-			       before roundoff, due to a merge */
-  realT min_vertex;       /* minimum distance (<0) from vertex to a facet,
-			       before roundoff, due to a merge
-			       if qh.JOGGLEmax, qh_makenewplanes sets it
-  			       recomputed if qh.DOcheckmax, default -qh.DISTround */
-  boolT NEWfacets;        /* true while visible facets invalid due to new or merge
-			      from makecone/attachnewfacets to deletevisible */
-  boolT findbestnew;	  /* true if partitioning calls qh_findbestnew */
-  boolT findbest_notsharp; /* true if new facets are at least 90 degrees */
-  boolT NOerrexit;        /* true if qh.errexit is not available */
-  realT PRINTcradius;     /* radius for printing centrums */
-  realT PRINTradius;      /* radius for printing vertex spheres and points */
-  boolT POSTmerging;      /* true when post merging */
-  int 	printoutvar;	  /* temporary variable for qh_printbegin, etc. */
-  int 	printoutnum;	  /* number of facets printed */
-  boolT QHULLfinished;    /* True after qhull() is finished */
-  realT totarea;          /* 'FA': total facet area computed by qh_getarea */
-  realT totvol;           /* 'FA': total volume computed by qh_getarea */
-  unsigned int visit_id;  /* unique ID for searching neighborhoods, */
-  unsigned int vertex_visit; /* unique ID for searching vertices */
-  boolT ZEROall_ok;       /* True if qh_checkzero always succeeds */
-  boolT WAScoplanar;      /* True if qh_partitioncoplanar (qh_check_maxout) */
-  
-/*----------------------------------
-
-  qh global sets
-    defines sets for merging, initial simplex, hashing, extra input points,
-    and deleted vertices
-*/
-  setT *facet_mergeset;   /* temporary set of merges to be done */
-  setT *degen_mergeset;   /* temporary set of degenerate and redundant merges */
-  setT *hash_table;	  /* hash table for matching ridges in qh_matchfacets
-                             size is setsize() */
-  setT *other_points;     /* additional points (first is qh interior_point) */
-  setT *del_vertices;     /* vertices to partition and delete with visible
-                             facets.  Have deleted set for checkfacet */
-
-/*----------------------------------
-
-  qh global buffers
-    defines buffers for maxtrix operations, input, and error messages
-*/
-  coordT *gm_matrix;      /* (dim+1)Xdim matrix for geom.c */
-  coordT **gm_row;        /* array of gm_matrix rows */
-  char* line;             /* malloc'd input line of maxline+1 chars */
-  int maxline;
-  coordT *half_space;     /* malloc'd input array for halfspace (qh normal_size+coordT) */
-  coordT *temp_malloc;    /* malloc'd input array for points */
-  
-/*----------------------------------
-
-  qh static variables
-    defines static variables for individual functions
-
-  notes:
-    do not use 'static' within a function.  Multiple instances of qhull
-    may exist.
-
-    do not assume zero initialization, 'QPn' may cause a restart
-*/
-  boolT ERREXITcalled;    /* true during errexit (prevents duplicate calls */
-  boolT firstcentrum; 	  /* for qh_printcentrum */
-  realT last_low;         /* qh_scalelast parameters for qh_setdelaunay */
-  realT last_high;
-  realT last_newhigh;
-  unsigned lastreport;    /* for qh_buildtracing */
-  int mergereport;        /* for qh_tracemerging */
-  boolT old_randomdist;   /* save RANDOMdist when io, tracing, or statistics */
-  int   ridgeoutnum;      /* number of ridges in 4OFF output */
-  void *old_qhstat;       /* for saving qh_qhstat in save_qhull() */
-  setT *old_tempstack;     /* for saving qhmem.tempstack in save_qhull */
-  setT *coplanarset;      /* set of coplanar facets for searching qh_findbesthorizon() */
-};
-
-/*=========== -macros- =========================*/
-
-/*----------------------------------
-
-  otherfacet_(ridge, facet)
-    return neighboring facet for a ridge in facet
-*/
-#define otherfacet_(ridge, facet) \
-                        (((ridge)->top == (facet)) ? (ridge)->bottom : (ridge)->top)
-
-/*----------------------------------
-
-  getid_(p)
-    return ID for facet, ridge, or vertex
-    return MAXINT if NULL (-1 causes type conversion error )
-*/
-#define getid_(p)       ((p) ? (p)->id : -1)
-
-/*============== FORALL macros ===================*/
-
-/*----------------------------------
-
-  FORALLfacets { ... }
-    assign 'facet' to each facet in qh.facet_list
-
-  notes:
-    uses 'facetT *facet;'
-    assumes last facet is a sentinel
-
-  see:
-    FORALLfacet_( facetlist )
-*/
-#define FORALLfacets for (facet=qh facet_list;facet && facet->next;facet=facet->next)
-
-/*----------------------------------
-
-  FORALLpoints { ... }
-    assign 'point' to each point in qh.first_point, qh.num_points
-
-  declare:
-    coordT *point, *pointtemp;
-*/
-#define FORALLpoints FORALLpoint_(qh first_point, qh num_points)
-
-/*----------------------------------
-
-  FORALLpoint_( points, num) { ... }
-    assign 'point' to each point in points array of num points
-
-  declare:
-    coordT *point, *pointtemp;
-*/
-#define FORALLpoint_(points, num) for(point= (points), \
-      pointtemp= (points)+qh hull_dim*(num); point < pointtemp; point += qh hull_dim)
-
-/*----------------------------------
-
-  FORALLvertices { ... }
-    assign 'vertex' to each vertex in qh.vertex_list
-
-  declare:
-    vertexT *vertex;
-
-  notes:
-    assumes qh.vertex_list terminated with a sentinel
-*/
-#define FORALLvertices for (vertex=qh vertex_list;vertex && vertex->next;vertex= vertex->next)
-
-/*----------------------------------
-
-  FOREACHfacet_( facets ) { ... }
-    assign 'facet' to each facet in facets
-
-  declare:
-    facetT *facet, **facetp;
-
-  see:
-    FOREACHsetelement_
-*/
-#define FOREACHfacet_(facets)    FOREACHsetelement_(facetT, facets, facet)
-
-/*----------------------------------
-
-  FOREACHneighbor_( facet ) { ... }
-    assign 'neighbor' to each neighbor in facet->neighbors
-
-  FOREACHneighbor_( vertex ) { ... }
-    assign 'neighbor' to each neighbor in vertex->neighbors
-
-  declare:
-    facetT *neighbor, **neighborp;
-
-  see:
-    FOREACHsetelement_
-*/
-#define FOREACHneighbor_(facet)  FOREACHsetelement_(facetT, facet->neighbors, neighbor)
-
-/*----------------------------------
-
-  FOREACHpoint_( points ) { ... }
-    assign 'point' to each point in points set
-
-  declare:
-    pointT *point, **pointp;
-
-  see:
-    FOREACHsetelement_
-*/
-#define FOREACHpoint_(points)    FOREACHsetelement_(pointT, points, point)
-
-/*----------------------------------
-
-  FOREACHridge_( ridges ) { ... }
-    assign 'ridge' to each ridge in ridges set
-
-  declare:
-    ridgeT *ridge, **ridgep;
-
-  see:
-    FOREACHsetelement_
-*/
-#define FOREACHridge_(ridges)    FOREACHsetelement_(ridgeT, ridges, ridge)
-
-/*----------------------------------
-
-  FOREACHvertex_( vertices ) { ... }
-    assign 'vertex' to each vertex in vertices set
-
-  declare:
-    vertexT *vertex, **vertexp;
-
-  see:
-    FOREACHsetelement_
-*/
-#define FOREACHvertex_(vertices) FOREACHsetelement_(vertexT, vertices,vertex)
-
-/*----------------------------------
-
-  FOREACHfacet_i_( facets ) { ... }
-    assign 'facet' and 'facet_i' for each facet in facets set
-
-  declare:
-    facetT *facet;
-    int     facet_n, facet_i;
-
-  see:
-    FOREACHsetelement_i_
-*/
-#define FOREACHfacet_i_(facets)    FOREACHsetelement_i_(facetT, facets, facet)
-
-/*----------------------------------
-
-  FOREACHneighbor_i_( facet ) { ... }
-    assign 'neighbor' and 'neighbor_i' for each neighbor in facet->neighbors
-
-  FOREACHneighbor_i_( vertex ) { ... }
-    assign 'neighbor' and 'neighbor_i' for each neighbor in vertex->neighbors
-
-  declare:
-    facetT *neighbor;
-    int     neighbor_n, neighbor_i;
-
-  see:
-    FOREACHsetelement_i_
-*/
-#define FOREACHneighbor_i_(facet)  FOREACHsetelement_i_(facetT, facet->neighbors, neighbor)
-
-/*----------------------------------
-
-  FOREACHpoint_i_( points ) { ... }
-    assign 'point' and 'point_i' for each point in points set
-
-  declare:
-    pointT *point;
-    int     point_n, point_i;
-
-  see:
-    FOREACHsetelement_i_
-*/
-#define FOREACHpoint_i_(points)    FOREACHsetelement_i_(pointT, points, point)
-
-/*----------------------------------
-
-  FOREACHridge_i_( ridges ) { ... }
-    assign 'ridge' and 'ridge_i' for each ridge in ridges set
-
-  declare:
-    ridgeT *ridge;
-    int     ridge_n, ridge_i;
-
-  see:
-    FOREACHsetelement_i_
-*/
-#define FOREACHridge_i_(ridges)    FOREACHsetelement_i_(ridgeT, ridges, ridge)
-
-/*----------------------------------
-
-  FOREACHvertex_i_( vertices ) { ... }
-    assign 'vertex' and 'vertex_i' for each vertex in vertices set
-
-  declare:
-    vertexT *vertex;
-    int     vertex_n, vertex_i;
-
-  see:
-    FOREACHsetelement_i_
- */
-#define FOREACHvertex_i_(vertices) FOREACHsetelement_i_(vertexT, vertices,vertex)
-
-/********* -qhull.c prototypes (duplicated from qhull_a.h) **********************/
-
-void    qh_qhull (void);
-boolT   qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist);
-void	qh_printsummary(FILE *fp);
-
-/********* -user.c prototypes (alphabetical) **********************/
-
-void 	qh_errexit(int exitcode, facetT *facet, ridgeT *ridge);
-void 	qh_errprint(char* string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex);
-int     qh_new_qhull (int dim, int numpoints, coordT *points, boolT ismalloc,
-		char *qhull_cmd, FILE *outfile, FILE *errfile);
-void    qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall);
-void 	qh_user_memsizes (void);
-
-/***** -geom.c/geom2.c prototypes (duplicated from geom.h) ****************/
-
-facetT *qh_findbest (pointT *point, facetT *startfacet,
-		     boolT bestoutside, boolT newfacets, boolT noupper,
-		     realT *dist, boolT *isoutside, int *numpart);
-facetT *qh_findbestnew (pointT *point, facetT *startfacet,
-                     realT *dist, boolT bestoutside, boolT *isoutside, int *numpart);
-boolT   qh_gram_schmidt(int dim, realT **rows);
-void    qh_outerinner (facetT *facet, realT *outerplane, realT *innerplane);
-void	qh_printsummary(FILE *fp);
-void    qh_projectinput (void);
-void    qh_randommatrix (realT *buffer, int dim, realT **row);
-void    qh_rotateinput (realT **rows);
-void    qh_scaleinput (void);
-void    qh_setdelaunay (int dim, int count, pointT *points);
-coordT  *qh_sethalfspace_all (int dim, int count, coordT *halfspaces, pointT *feasible);
-
-/***** -global.c prototypes (alphabetical) ***********************/
-
-unsigned long qh_clock (void);
-void 	qh_checkflags (char *command, char *hiddenflags);
-void 	qh_freebuffers (void);
-void    qh_freeqhull (boolT allmem);
-void    qh_init_A (FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]);
-void    qh_init_B (coordT *points, int numpoints, int dim, boolT ismalloc);
-void 	qh_init_qhull_command (int argc, char *argv[]);
-void    qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc);
-void 	qh_initflags (char *command);
-void 	qh_initqhull_buffers (void);
-void 	qh_initqhull_globals (coordT *points, int numpoints, int dim, boolT ismalloc);
-void    qh_initqhull_mem (void);
-void 	qh_initqhull_start (FILE *infile, FILE *outfile, FILE *errfile);
-void 	qh_initthresholds (char *command);
-void    qh_option (char *option, int *i, realT *r);
-#if qh_QHpointer
-void 	qh_restore_qhull (qhT **oldqh);
-qhT    *qh_save_qhull (void);
-#endif
-
-/***** -io.c prototypes (duplicated from io.h) ***********************/
-
-void    dfacet( unsigned id);
-void    dvertex( unsigned id);
-void	qh_printneighborhood (FILE *fp, int format, facetT *facetA, facetT *facetB, boolT printall);
-void	qh_produce_output(void);
-coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
-
-
-/********* -mem.c prototypes (duplicated from mem.h) **********************/
-
-void qh_meminit (FILE *ferr);
-void qh_memfreeshort (int *curlong, int *totlong);
-
-/********* -poly.c/poly2.c prototypes (duplicated from poly.h) **********************/
-
-void    qh_check_output (void);
-void    qh_check_points (void);
-setT   *qh_facetvertices (facetT *facetlist, setT *facets, boolT allfacets);
-facetT *qh_findbestfacet (pointT *point, boolT bestoutside,
-           realT *bestdist, boolT *isoutside);
-vertexT *qh_nearvertex (facetT *facet, pointT *point, realT *bestdistp);
-pointT *qh_point (int id);
-setT   *qh_pointfacet (void /*qh.facet_list*/);
-int     qh_pointid (pointT *point);
-setT   *qh_pointvertex (void /*qh.facet_list*/);
-void    qh_setvoronoi_all (void);
-void	qh_triangulate (void /*qh facet_list*/);
-
-/********* -stat.c prototypes (duplicated from stat.h) **********************/
-
-void    qh_collectstatistics (void);
-void    qh_printallstatistics (FILE *fp, char *string);
-
-#endif /* qhDEFqhull */
diff --git a/extern/qhull/src/qhull_a.h b/extern/qhull/src/qhull_a.h
deleted file mode 100644
index d4e69b071be..00000000000
--- a/extern/qhull/src/qhull_a.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
  ---------------------------------
-
-   qhull_a.h 
-   all header files for compiling qhull
-
-   see qh-qhull.htm
-
-   see qhull.h for user-level definitions
-   
-   see user.h for user-defineable constants
-   
-   defines internal functions for qhull.c global.c
-
-   copyright (c) 1993-2002, The Geometry Center
-
-   Notes:  grep for ((" and (" to catch fprintf("lkasdjf");
-           full parens around (x?y:z)
-	   use '#include qhull/qhull_a.h' to avoid name clashes
-*/
-
-#ifndef qhDEFqhulla
-#define qhDEFqhulla
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include     /* some compilers will not need float.h */
-#include 
-#include 
-#include 
-/*** uncomment here and qset.c
-     if string.h does not define memcpy()
-#include 
-*/
-#include "qhull.h"
-#include "mem.h"
-#include "qset.h"
-#include "geom.h"
-#include "merge.h"
-#include "poly.h"
-#include "io.h"
-#include "stat.h"
-
-#if qh_CLOCKtype == 2  /* defined in user.h from qhull.h */
-#include 
-#include 
-#include 
-#endif
-
-#ifdef _MSC_VER  /* Microsoft Visual C++ */
-#pragma warning( disable : 4056)  /* float constant expression.  Looks like a compiler bug */
-#pragma warning( disable : 4146)  /* unary minus applied to unsigned type */
-#pragma warning( disable : 4244)  /* conversion from 'unsigned long' to 'real' */
-#pragma warning( disable : 4305)  /* conversion from 'const double' to 'float' */
-#endif
-
-/* ======= -macros- =========== */
-
-/*----------------------------------
-  
-  traceN((fp.ferr, "format\n", vars));  
-    calls fprintf if qh.IStracing >= N
-  
-  notes:
-    removing tracing reduces code size but doesn't change execution speed
-*/
-#ifndef qh_NOtrace
-#define trace0(args) {if (qh IStracing) fprintf args;}
-#define trace1(args) {if (qh IStracing >= 1) fprintf args;}
-#define trace2(args) {if (qh IStracing >= 2) fprintf args;}
-#define trace3(args) {if (qh IStracing >= 3) fprintf args;}
-#define trace4(args) {if (qh IStracing >= 4) fprintf args;}
-#define trace5(args) {if (qh IStracing >= 5) fprintf args;}
-#else /* qh_NOtrace */
-#define trace0(args) {}
-#define trace1(args) {}
-#define trace2(args) {}
-#define trace3(args) {}
-#define trace4(args) {}
-#define trace5(args) {}
-#endif /* qh_NOtrace */
-
-/***** -qhull.c prototypes (alphabetical after qhull) ********************/
-
-void 	qh_qhull (void);
-boolT   qh_addpoint (pointT *furthest, facetT *facet, boolT checkdist);
-void 	qh_buildhull(void);
-void    qh_buildtracing (pointT *furthest, facetT *facet);
-void    qh_build_withrestart (void);
-void 	qh_errexit2(int exitcode, facetT *facet, facetT *otherfacet);
-void    qh_findhorizon(pointT *point, facetT *facet, int *goodvisible,int *goodhorizon);
-pointT *qh_nextfurthest (facetT **visible);
-void 	qh_partitionall(setT *vertices, pointT *points,int npoints);
-void    qh_partitioncoplanar (pointT *point, facetT *facet, realT *dist);
-void    qh_partitionpoint (pointT *point, facetT *facet);
-void 	qh_partitionvisible(boolT allpoints, int *numpoints);
-void    qh_precision (char *reason);
-void	qh_printsummary(FILE *fp);
-
-/***** -global.c internal prototypes (alphabetical) ***********************/
-
-void    qh_appendprint (qh_PRINT format);
-void 	qh_freebuild (boolT allmem);
-void 	qh_freebuffers (void);
-void    qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc);
-int     qh_strtol (const char *s, char **endp);
-double  qh_strtod (const char *s, char **endp);
-
-/***** -stat.c internal prototypes (alphabetical) ***********************/
-
-void	qh_allstatA (void);
-void	qh_allstatB (void);
-void	qh_allstatC (void);
-void	qh_allstatD (void);
-void	qh_allstatE (void);
-void	qh_allstatE2 (void);
-void	qh_allstatF (void);
-void	qh_allstatG (void);
-void	qh_allstatH (void);
-void 	qh_freebuffers (void);
-void    qh_initbuffers (coordT *points, int numpoints, int dim, boolT ismalloc);
-
-#endif /* qhDEFqhulla */
diff --git a/extern/qhull/src/qhull_interface.cpp b/extern/qhull/src/qhull_interface.cpp
deleted file mode 100644
index 6ecc640e82b..00000000000
--- a/extern/qhull/src/qhull_interface.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
  ---------------------------------
-*/
-
-#include 
-#include 
-
-//--- Include qhull, so it works from with in a C++ source file
-//---
-//--- In MVC one cannot just do:
-//---
-//---    extern "C"
-//---    {
-//---      #include "qhull_a.h"
-//---    }
-//---
-//--- Because qhull_a.h includes math.h, which can not appear
-//--- inside a extern "C" declaration.
-//---
-//--- Maybe that why Numerical recipes in C avoid this problem, by removing
-//--- standard include headers from its header files and add them in the
-//--- respective source files instead.
-//---
-//--- [K. Erleben]
-
-#if defined(__cplusplus)
-extern "C"
-{
-#endif
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#if defined(__cplusplus)
-}
-#endif
-
-/*********************************************************************/
-/*                                                                   */
-/*                                                                   */
-/*                                                                   */
-/*                                                                   */
-/*********************************************************************/
-
-void compute_convex_hull(void)
-{  
-	int dim;  	              /* dimension of points */
-	int numpoints;            /* number of points */
-	coordT *points;           /* array of coordinates for each point */ 
-	boolT ismalloc;           /* True if qhull should free points in qh_freeqhull() or reallocation */ 
-	char flags[]= "qhull Tv"; /* option flags for qhull, see qh_opt.htm */
-	FILE *outfile= stdout;    /* output from qh_produce_output()			
-	                             use NULL to skip qh_produce_output() */ 
-	FILE *errfile= stderr;    /* error messages from qhull code */ 
-	int exitcode;             /* 0 if no error from qhull */
-	facetT *facet;	          /* set by FORALLfacets */
-	int curlong, totlong;	  /* memory remaining after qh_memfreeshort */
-
-   	/* initialize dim, numpoints, points[], ismalloc here */
-	exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
-							flags, outfile, errfile);
-	if (!exitcode) { /* if no error */ 
-		/* 'qh facet_list' contains the convex hull */
-		FORALLfacets {
-			/* ... your code ... */ 
-		}
-	}
-	qh_freeqhull(!qh_ALL);  
-	qh_memfreeshort (&curlong, &totlong);
-	if (curlong || totlong)
-		fprintf (errfile, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n", 
-		             totlong, curlong);
-};
-
-/*********************************************************************/
-/*                                                                   */
-/*                                                                   */
-/*                                                                   */
-/*                                                                   */
-/*********************************************************************/
-
-void main() 
-{ 
-	cout << "Hello world" << endl;
-	
-	cout << "Press any key..." << endl;  
-	
-	while(!_kbhit());
-
-};
diff --git a/extern/qhull/src/qset.c b/extern/qhull/src/qset.c
deleted file mode 100644
index 9e78464c07e..00000000000
--- a/extern/qhull/src/qset.c
+++ /dev/null
@@ -1,1301 +0,0 @@
-/*
  ---------------------------------
-
-   qset.c 
-   implements set manipulations needed for quickhull 
-
-   see qh-set.htm and qset.h
-
-   copyright (c) 1993-2002 The Geometry Center        
-*/
-
-#include 
-#include 
-/*** uncomment here and qhull_a.h 
-     if string.h does not define memcpy()
-#include 
-*/
-#include "qset.h"
-#include "mem.h"
-
-#ifndef qhDEFqhull
-typedef struct ridgeT ridgeT;
-typedef struct facetT facetT;
-void    qh_errexit(int exitcode, facetT *, ridgeT *);
-#endif
-
-/*=============== internal macros ===========================*/
-
-/*---------------------------------
-   
-  SETsizeaddr_(set) 
-    return pointer to actual size+1 of set (set CANNOT be NULL!!)
-      
-  notes:
-    *SETsizeaddr==NULL or e[*SETsizeaddr-1].p==NULL
-*/
-#define SETsizeaddr_(set) (&((set)->e[(set)->maxsize].i))
-
-/*============ functions in alphabetical order ===================*/
-  
-/*----------------------------------
-   
-  qh_setaddnth( setp, nth, newelem)
-    adds newelem as n'th element of sorted or unsorted *setp
-      
-  notes:
-    *setp and newelem must be defined
-    *setp may be a temp set
-    nth=0 is first element
-    errors if nth is out of bounds
-   
-  design:
-    expand *setp if empty or full
-    move tail of *setp up one
-    insert newelem
-*/
-void qh_setaddnth(setT **setp, int nth, void *newelem) {
-  int *sizep, oldsize, i;
-  void **oldp, **newp;
-
-  if (!*setp || !*(sizep= SETsizeaddr_(*setp))) {
-    qh_setlarger(setp);
-    sizep= SETsizeaddr_(*setp);
-  }
-  oldsize= *sizep - 1;
-  if (nth < 0 || nth > oldsize) {
-    fprintf (qhmem.ferr, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
-    qh_setprint (qhmem.ferr, "", *setp);
-    qh_errexit (qhmem_ERRqhull, NULL, NULL);
-  }
-  (*sizep)++;
-  oldp= SETelemaddr_(*setp, oldsize, void);   /* NULL */
-  newp= oldp+1;
-  for (i= oldsize-nth+1; i--; )  /* move at least NULL  */
-    *(newp--)= *(oldp--);       /* may overwrite *sizep */
-  *newp= newelem;
-} /* setaddnth */
-
-
-/*----------------------------------
-   
-  setaddsorted( setp, newelem )
-    adds an newelem into sorted *setp
-      
-  notes:
-    *setp and newelem must be defined
-    *setp may be a temp set
-    nop if newelem already in set
-  
-  design:
-    find newelem's position in *setp
-    insert newelem
-*/
-void qh_setaddsorted(setT **setp, void *newelem) {
-  int newindex=0;
-  void *elem, **elemp;
-
-  FOREACHelem_(*setp) {          /* could use binary search instead */
-    if (elem < newelem)
-      newindex++;
-    else if (elem == newelem)
-      return;
-    else
-      break;
-  }
-  qh_setaddnth(setp, newindex, newelem);
-} /* setaddsorted */
-
-
-/*---------------------------------
-  
-  qh_setappend( setp, newelem)
-    append newelem to *setp
-
-  notes:
-    *setp may be a temp set
-    *setp and newelem may be NULL
-
-  design:
-    expand *setp if empty or full
-    append newelem to *setp
-    
-*/
-void qh_setappend(setT **setp, void *newelem) {
-  int *sizep;
-  void **endp;
-
-  if (!newelem)
-    return;
-  if (!*setp || !*(sizep= SETsizeaddr_(*setp))) {
-    qh_setlarger(setp);
-    sizep= SETsizeaddr_(*setp);
-  }
-  *(endp= &((*setp)->e[(*sizep)++ - 1].p))= newelem;
-  *(++endp)= NULL;
-} /* setappend */
-
-/*---------------------------------
-  
-  qh_setappend_set( setp, setA) 
-    appends setA to *setp
-
-  notes:
-    *setp can not be a temp set
-    *setp and setA may be NULL
-
-  design:
-    setup for copy
-    expand *setp if it is too small
-    append all elements of setA to *setp 
-*/
-void qh_setappend_set(setT **setp, setT *setA) {
-  int *sizep, sizeA, size;
-  setT *oldset;
-
-  if (!setA)
-    return;
-  SETreturnsize_(setA, sizeA);
-  if (!*setp)
-    *setp= qh_setnew (sizeA);
-  sizep= SETsizeaddr_(*setp);
-  if (!(size= *sizep))
-    size= (*setp)->maxsize;
-  else
-    size--;
-  if (size + sizeA > (*setp)->maxsize) {
-    oldset= *setp;
-    *setp= qh_setcopy (oldset, sizeA);
-    qh_setfree (&oldset);
-    sizep= SETsizeaddr_(*setp);
-  }
-  *sizep= size+sizeA+1;   /* memcpy may overwrite */
-  if (sizeA > 0) 
-    memcpy((char *)&((*setp)->e[size].p), (char *)&(setA->e[0].p), SETelemsize *(sizeA+1));
-} /* setappend_set */
-
-
-/*---------------------------------
-  
-  qh_setappend2ndlast( setp, newelem )
-    makes newelem the next to the last element in *setp
-
-  notes:
-    *setp must have at least one element
-    newelem must be defined
-    *setp may be a temp set
-
-  design:
-    expand *setp if empty or full
-    move last element of *setp up one
-    insert newelem
-*/
-void qh_setappend2ndlast(setT **setp, void *newelem) {
-  int *sizep;
-  void **endp, **lastp;
-  
-  if (!*setp || !*(sizep= SETsizeaddr_(*setp))) {
-    qh_setlarger(setp);
-    sizep= SETsizeaddr_(*setp);
-  }
-  endp= SETelemaddr_(*setp, (*sizep)++ -1, void); /* NULL */
-  lastp= endp-1;
-  *(endp++)= *lastp;
-  *endp= NULL;    /* may overwrite *sizep */
-  *lastp= newelem;
-} /* setappend2ndlast */
-
-
-/*---------------------------------
-  
-  qh_setcheck( set, typename, id ) 
-    check set for validity
-    report errors with typename and id
-
-  design:
-    checks that maxsize, actual size, and NULL terminator agree
-*/
-void qh_setcheck(setT *set, char *tname, int id) {
-  int maxsize, size;
-  int waserr= 0;
-
-  if (!set)
-    return;
-  SETreturnsize_(set, size);
-  maxsize= set->maxsize;
-  if (size > maxsize || !maxsize) {
-    fprintf (qhmem.ferr, "qhull internal error (qh_setcheck): actual size %d of %s%d is greater than max size %d\n",
-	     size, tname, id, maxsize);
-    waserr= 1;
-  }else if (set->e[size].p) {
-    fprintf (qhmem.ferr, "qhull internal error (qh_setcheck): %s%d (size %d max %d) is not null terminated.\n",
-	     tname, id, maxsize, size-1);
-    waserr= 1;
-  }
-  if (waserr) {
-    qh_setprint (qhmem.ferr, "ERRONEOUS", set);
-    qh_errexit (qhmem_ERRqhull, NULL, NULL);
-  }
-} /* setcheck */
-
-
-/*---------------------------------
-  
-  qh_setcompact( set )
-    remove internal NULLs from an unsorted set
-
-  returns:
-    updated set
-
-  notes:
-    set may be NULL
-    it would be faster to swap tail of set into holes, like qh_setdel
-
-  design:
-    setup pointers into set
-    skip NULLs while copying elements to start of set 
-    update the actual size
-*/
-void qh_setcompact(setT *set) {
-  int size;
-  void **destp, **elemp, **endp, **firstp;
-
-  if (!set)
-    return;
-  SETreturnsize_(set, size);
-  destp= elemp= firstp= SETaddr_(set, void);
-  endp= destp + size;
-  while (1) {
-    if (!(*destp++ = *elemp++)) {
-      destp--;
-      if (elemp > endp)
-	break;
-    }
-  }
-  qh_settruncate (set, destp-firstp);
-} /* setcompact */
-
-
-/*---------------------------------
-  
-  qh_setcopy( set, extra )
-    make a copy of a sorted or unsorted set with extra slots
-
-  returns:
-    new set
-
-  design:
-    create a newset with extra slots
-    copy the elements to the newset
-    
-*/
-setT *qh_setcopy(setT *set, int extra) {
-  setT *newset;
-  int size;
-
-  if (extra < 0)
-    extra= 0;
-  SETreturnsize_(set, size);
-  newset= qh_setnew(size+extra);
-  *SETsizeaddr_(newset)= size+1;    /* memcpy may overwrite */
-  memcpy((char *)&(newset->e[0].p), (char *)&(set->e[0].p), SETelemsize *(size+1));
-  return (newset);
-} /* setcopy */
-
-
-/*---------------------------------
-  
-  qh_setdel( set, oldelem )
-    delete oldelem from an unsorted set
-
-  returns:
-    returns oldelem if found
-    returns NULL otherwise
-    
-  notes:
-    set may be NULL
-    oldelem must not be NULL;
-    only deletes one copy of oldelem in set
-     
-  design:
-    locate oldelem
-    update actual size if it was full
-    move the last element to the oldelem's location
-*/
-void *qh_setdel(setT *set, void *oldelem) {
-  void **elemp, **lastp;
-  int *sizep;
-
-  if (!set)
-    return NULL;
-  elemp= SETaddr_(set, void);
-  while (*elemp != oldelem && *elemp)
-    elemp++;
-  if (*elemp) {
-    sizep= SETsizeaddr_(set);
-    if (!(*sizep)--)         /*  if was a full set */
-      *sizep= set->maxsize;  /*     *sizep= (maxsize-1)+ 1 */
-    lastp= SETelemaddr_(set, *sizep-1, void);
-    *elemp= *lastp;      /* may overwrite itself */
-    *lastp= NULL;
-    return oldelem;
-  }
-  return NULL;
-} /* setdel */
-
-
-/*---------------------------------
-  
-  qh_setdellast( set) 
-    return last element of set or NULL
-
-  notes:
-    deletes element from set
-    set may be NULL
-
-  design:
-    return NULL if empty
-    if full set
-      delete last element and set actual size
-    else
-      delete last element and update actual size 
-*/
-void *qh_setdellast(setT *set) {
-  int setsize;  /* actually, actual_size + 1 */
-  int maxsize;
-  int *sizep;
-  void *returnvalue;
-  
-  if (!set || !(set->e[0].p))
-    return NULL;
-  sizep= SETsizeaddr_(set);
-  if ((setsize= *sizep)) {
-    returnvalue= set->e[setsize - 2].p;
-    set->e[setsize - 2].p= NULL;
-    (*sizep)--;
-  }else {
-    maxsize= set->maxsize;
-    returnvalue= set->e[maxsize - 1].p;
-    set->e[maxsize - 1].p= NULL;
-    *sizep= maxsize;
-  }
-  return returnvalue;
-} /* setdellast */
-
-
-/*---------------------------------
-  
-  qh_setdelnth( set, nth )
-    deletes nth element from unsorted set 
-    0 is first element
-
-  returns:
-    returns the element (needs type conversion)
-
-  notes:
-    errors if nth invalid
-
-  design:
-    setup points and check nth
-    delete nth element and overwrite with last element
-*/
-void *qh_setdelnth(setT *set, int nth) {
-  void **elemp, **lastp, *elem;
-  int *sizep;
-
-
-  elemp= SETelemaddr_(set, nth, void);
-  sizep= SETsizeaddr_(set);
-  if (!(*sizep)--)         /*  if was a full set */
-    *sizep= set->maxsize;  /*     *sizep= (maxsize-1)+ 1 */
-  if (nth < 0 || nth >= *sizep) {
-    fprintf (qhmem.ferr, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
-    qh_setprint (qhmem.ferr, "", set);
-    qh_errexit (qhmem_ERRqhull, NULL, NULL);
-  }
-  lastp= SETelemaddr_(set, *sizep-1, void);
-  elem= *elemp;
-  *elemp= *lastp;      /* may overwrite itself */
-  *lastp= NULL;
-  return elem;
-} /* setdelnth */
-
-/*---------------------------------
-  
-  qh_setdelnthsorted( set, nth )
-    deletes nth element from sorted set
-
-  returns:
-    returns the element (use type conversion)
-  
-  notes:
-    errors if nth invalid
-    
-  see also: 
-    setnew_delnthsorted
-
-  design:
-    setup points and check nth
-    copy remaining elements down one
-    update actual size  
-*/
-void *qh_setdelnthsorted(setT *set, int nth) {
-  void **newp, **oldp, *elem;
-  int *sizep;
-
-  sizep= SETsizeaddr_(set);
-  if (nth < 0 || (*sizep && nth >= *sizep-1) || nth >= set->maxsize) {
-    fprintf (qhmem.ferr, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
-    qh_setprint (qhmem.ferr, "", set);
-    qh_errexit (qhmem_ERRqhull, NULL, NULL);
-  }
-  newp= SETelemaddr_(set, nth, void);
-  elem= *newp;
-  oldp= newp+1;
-  while ((*(newp++)= *(oldp++)))
-    ; /* copy remaining elements and NULL */
-  if (!(*sizep)--)         /*  if was a full set */
-    *sizep= set->maxsize;  /*     *sizep= (max size-1)+ 1 */
-  return elem;
-} /* setdelnthsorted */
-
-
-/*---------------------------------
-  
-  qh_setdelsorted( set, oldelem )
-    deletes oldelem from sorted set
-
-  returns:
-    returns oldelem if it was deleted
-  
-  notes:
-    set may be NULL
-
-  design:
-    locate oldelem in set
-    copy remaining elements down one
-    update actual size  
-*/
-void *qh_setdelsorted(setT *set, void *oldelem) {
-  void **newp, **oldp;
-  int *sizep;
-
-  if (!set)
-    return NULL;
-  newp= SETaddr_(set, void);
-  while(*newp != oldelem && *newp)
-    newp++;
-  if (*newp) {
-    oldp= newp+1;
-    while ((*(newp++)= *(oldp++)))
-      ; /* copy remaining elements */
-    sizep= SETsizeaddr_(set);
-    if (!(*sizep)--)    /*  if was a full set */
-      *sizep= set->maxsize;  /*     *sizep= (max size-1)+ 1 */
-    return oldelem;
-  }
-  return NULL;
-} /* setdelsorted */
-
-
-/*---------------------------------
-  
-  qh_setduplicate( set, elemsize )
-    duplicate a set of elemsize elements
-
-  notes:
-    use setcopy if retaining old elements
-
-  design:
-    create a new set
-    for each elem of the old set
-      create a newelem
-      append newelem to newset
-*/
-setT *qh_setduplicate (setT *set, int elemsize) {
-  void		*elem, **elemp, *newElem;
-  setT		*newSet;
-  int		size;
-  
-  if (!(size= qh_setsize (set)))
-    return NULL;
-  newSet= qh_setnew (size);
-  FOREACHelem_(set) {
-    newElem= qh_memalloc (elemsize);
-    memcpy (newElem, elem, elemsize);
-    qh_setappend (&newSet, newElem);
-  }
-  return newSet;
-} /* setduplicate */
-
-
-/*---------------------------------
-  
-  qh_setequal(  )
-    returns 1 if two sorted sets are equal, otherwise returns 0
-
-  notes:
-    either set may be NULL
-
-  design:
-    check size of each set
-    setup pointers
-    compare elements of each set
-*/
-int qh_setequal(setT *setA, setT *setB) {
-  void **elemAp, **elemBp;
-  int sizeA, sizeB;
-  
-  SETreturnsize_(setA, sizeA);
-  SETreturnsize_(setB, sizeB);
-  if (sizeA != sizeB)
-    return 0;
-  if (!sizeA)
-    return 1;
-  elemAp= SETaddr_(setA, void);
-  elemBp= SETaddr_(setB, void);
-  if (!memcmp((char *)elemAp, (char *)elemBp, sizeA*SETelemsize))
-    return 1;
-  return 0;
-} /* setequal */
-
-
-/*---------------------------------
-  
-  qh_setequal_except( setA, skipelemA, setB, skipelemB )
-    returns 1 if sorted setA and setB are equal except for skipelemA & B
-
-  returns:
-    false if either skipelemA or skipelemB are missing
-  
-  notes:
-    neither set may be NULL
-
-    if skipelemB is NULL, 
-      can skip any one element of setB
-
-  design:
-    setup pointers
-    search for skipelemA, skipelemB, and mismatches
-    check results
-*/
-int qh_setequal_except (setT *setA, void *skipelemA, setT *setB, void *skipelemB) {
-  void **elemA, **elemB;
-  int skip=0;
-
-  elemA= SETaddr_(setA, void);
-  elemB= SETaddr_(setB, void);
-  while (1) {
-    if (*elemA == skipelemA) {
-      skip++;
-      elemA++;
-    }
-    if (skipelemB) {
-      if (*elemB == skipelemB) {
-        skip++;
-        elemB++;
-      }
-    }else if (*elemA != *elemB) {
-      skip++;
-      if (!(skipelemB= *elemB++))
-        return 0;
-    }
-    if (!*elemA)
-      break;
-    if (*elemA++ != *elemB++) 
-      return 0;
-  }
-  if (skip != 2 || *elemB)
-    return 0;
-  return 1;
-} /* setequal_except */
-  
-
-/*---------------------------------
-  
-  qh_setequal_skip( setA, skipA, setB, skipB )
-    returns 1 if sorted setA and setB are equal except for elements skipA & B
-
-  returns:
-    false if different size
-
-  notes:
-    neither set may be NULL
-
-  design:
-    setup pointers
-    search for mismatches while skipping skipA and skipB
-*/
-int qh_setequal_skip (setT *setA, int skipA, setT *setB, int skipB) {
-  void **elemA, **elemB, **skipAp, **skipBp;
-
-  elemA= SETaddr_(setA, void);
-  elemB= SETaddr_(setB, void);
-  skipAp= SETelemaddr_(setA, skipA, void);
-  skipBp= SETelemaddr_(setB, skipB, void);
-  while (1) {
-    if (elemA == skipAp)
-      elemA++;
-    if (elemB == skipBp)
-      elemB++;
-    if (!*elemA)
-      break;
-    if (*elemA++ != *elemB++) 
-      return 0;
-  }
-  if (*elemB)
-    return 0;
-  return 1;
-} /* setequal_skip */
-  
-
-/*---------------------------------
-  
-  qh_setfree( setp )
-    frees the space occupied by a sorted or unsorted set
-
-  returns:
-    sets setp to NULL
-    
-  notes:
-    set may be NULL
-
-  design:
-    free array
-    free set
-*/
-void qh_setfree(setT **setp) {
-  int size;
-  void **freelistp;  /* used !qh_NOmem */
-  
-  if (*setp) {
-    size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize; 
-    if (size <= qhmem.LASTsize) {
-      qh_memfree_(*setp, size, freelistp);
-    }else
-      qh_memfree (*setp, size);
-    *setp= NULL;
-  }
-} /* setfree */
-
-
-/*---------------------------------
-  
-  qh_setfree2( setp, elemsize )
-    frees the space occupied by a set and its elements
-
-  notes:
-    set may be NULL
-
-  design:
-    free each element
-    free set 
-*/
-void qh_setfree2 (setT **setp, int elemsize) {
-  void		*elem, **elemp;
-  
-  FOREACHelem_(*setp)
-    qh_memfree (elem, elemsize);
-  qh_setfree (setp);
-} /* setfree2 */
-
-
-      
-/*---------------------------------
-  
-  qh_setfreelong( setp )
-    frees a set only if it's in long memory
-
-  returns:
-    sets setp to NULL if it is freed
-    
-  notes:
-    set may be NULL
-
-  design:
-    if set is large
-      free it    
-*/
-void qh_setfreelong(setT **setp) {
-  int size;
-  
-  if (*setp) {
-    size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize; 
-    if (size > qhmem.LASTsize) {
-      qh_memfree (*setp, size);
-      *setp= NULL;
-    }
-  }
-} /* setfreelong */
-
-
-/*---------------------------------
-  
-  qh_setin( set, setelem )
-    returns 1 if setelem is in a set, 0 otherwise
-
-  notes:
-    set may be NULL or unsorted
-
-  design:
-    scans set for setelem
-*/
-int qh_setin(setT *set, void *setelem) {
-  void *elem, **elemp;
-
-  FOREACHelem_(set) {
-    if (elem == setelem)
-      return 1;
-  }
-  return 0;
-} /* setin */
-
-
-/*---------------------------------
-  
-  qh_setindex( set, atelem )
-    returns the index of atelem in set.   
-    returns -1, if not in set or maxsize wrong
-
-  notes:
-    set may be NULL and may contain nulls.
-
-  design:
-    checks maxsize
-    scans set for atelem
-*/
-int qh_setindex(setT *set, void *atelem) {
-  void **elem;
-  int size, i;
-
-  SETreturnsize_(set, size);
-  if (size > set->maxsize)
-    return -1;
-  elem= SETaddr_(set, void);
-  for (i=0; i < size; i++) {
-    if (*elem++ == atelem)
-      return i;
-  }
-  return -1;
-} /* setindex */
-
-
-/*---------------------------------
-  
-  qh_setlarger( oldsetp )
-    returns a larger set that contains all elements of *oldsetp
-
-  notes:
-    the set is at least twice as large
-    if temp set, updates qhmem.tempstack
-
-  design:
-    creates a new set
-    copies the old set to the new set
-    updates pointers in tempstack
-    deletes the old set
-*/
-void qh_setlarger(setT **oldsetp) {
-  int size= 1, *sizep;
-  setT *newset, *set, **setp, *oldset;
-  void **oldp, **newp;
-
-  if (*oldsetp) {
-    oldset= *oldsetp;
-    SETreturnsize_(oldset, size);
-    qhmem.cntlarger++;
-    qhmem.totlarger += size+1;
-    newset= qh_setnew(2 * size);
-    oldp= SETaddr_(oldset, void);
-    newp= SETaddr_(newset, void);
-    memcpy((char *)newp, (char *)oldp, (size+1) * SETelemsize);
-    sizep= SETsizeaddr_(newset);
-    *sizep= size+1;
-    FOREACHset_((setT *)qhmem.tempstack) {
-      if (set == oldset)
-	*(setp-1)= newset;
-    }
-    qh_setfree(oldsetp);
-  }else 
-    newset= qh_setnew(3);
-  *oldsetp= newset;
-} /* setlarger */
-
-
-/*---------------------------------
-  
-  qh_setlast(  )
-    return last element of set or NULL (use type conversion)
-
-  notes:
-    set may be NULL
-
-  design:
-    return last element  
-*/
-void *qh_setlast(setT *set) {
-  int size;
-
-  if (set) {
-    size= *SETsizeaddr_(set);
-    if (!size) 
-      return SETelem_(set, set->maxsize - 1);
-    else if (size > 1)
-      return SETelem_(set, size - 2);
-  }
-  return NULL;
-} /* setlast */
-
-
-/*---------------------------------
-  
-  qh_setnew( setsize )
-    creates and allocates space for a set
-
-  notes:
-    setsize means the number of elements (NOT including the NULL terminator)
-    use qh_settemp/qh_setfreetemp if set is temporary
-
-  design:
-    allocate memory for set
-    roundup memory if small set
-    initialize as empty set
-*/
-setT *qh_setnew(int setsize) {
-  setT *set;
-  int sizereceived; /* used !qh_NOmem */
-  int size;
-  void **freelistp; /* used !qh_NOmem */
-
-  if (!setsize)
-    setsize++;
-  size= sizeof(setT) + setsize * SETelemsize;
-  if ((unsigned) size <= (unsigned) qhmem.LASTsize) {
-    qh_memalloc_(size, freelistp, set, setT);
-#ifndef qh_NOmem
-    sizereceived= qhmem.sizetable[ qhmem.indextable[size]];
-    if (sizereceived > size) 
-      setsize += (sizereceived - size)/SETelemsize;
-#endif
-  }else
-    set= (setT*)qh_memalloc (size);
-  set->maxsize= setsize;
-  set->e[setsize].i= 1;
-  set->e[0].p= NULL;
-  return (set);
-} /* setnew */
-
-
-/*---------------------------------
-  
-  qh_setnew_delnthsorted( set, size, nth, prepend )
-    creates a sorted set not containing nth element
-    if prepend, the first prepend elements are undefined
-
-  notes:
-    set must be defined
-    checks nth
-    see also: setdelnthsorted
-
-  design:
-    create new set
-    setup pointers and allocate room for prepend'ed entries
-    append head of old set to new set
-    append tail of old set to new set
-*/
-setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend) {
-  setT *newset;
-  void **oldp, **newp;
-  int tailsize= size - nth -1, newsize;
-
-  if (tailsize < 0) {
-    fprintf (qhmem.ferr, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
-    qh_setprint (qhmem.ferr, "", set);
-    qh_errexit (qhmem_ERRqhull, NULL, NULL);
-  }
-  newsize= size-1 + prepend;
-  newset= qh_setnew(newsize);
-  newset->e[newset->maxsize].i= newsize+1;  /* may be overwritten */
-  oldp= SETaddr_(set, void);
-  newp= SETaddr_(newset, void) + prepend;
-  switch (nth) {
-  case 0:
-    break;
-  case 1:
-    *(newp++)= *oldp++;
-    break;
-  case 2:
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    break;
-  case 3:
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    break;
-  case 4:
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    break;
-  default:
-    memcpy((char *)newp, (char *)oldp, nth * SETelemsize);
-    newp += nth;
-    oldp += nth;
-    break;
-  }
-  oldp++;
-  switch (tailsize) {
-  case 0:
-    break;
-  case 1:
-    *(newp++)= *oldp++;
-    break;
-  case 2:
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    break;
-  case 3:
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    break;
-  case 4:
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    *(newp++)= *oldp++;
-    break;
-  default:
-    memcpy((char *)newp, (char *)oldp, tailsize * SETelemsize);
-    newp += tailsize;
-  }
-  *newp= NULL;
-  return(newset);
-} /* setnew_delnthsorted */
-
-
-/*---------------------------------
-  
-  qh_setprint( fp, string, set )
-    print set elements to fp with identifying string
-
-  notes:
-    never errors
-*/
-void qh_setprint(FILE *fp, char* string, setT *set) {
-  int size, k;
-
-  if (!set)
-    fprintf (fp, "%s set is null\n", string);
-  else {
-    SETreturnsize_(set, size);
-    fprintf (fp, "%s set=%p maxsize=%d size=%d elems=",
-	     string, set, set->maxsize, size);
-    if (size > set->maxsize)
-      size= set->maxsize+1;
-    for (k=0; k < size; k++)
-      fprintf(fp, " %p", set->e[k].p);
-    fprintf(fp, "\n");
-  }
-} /* setprint */
-
-/*---------------------------------
-  
-  qh_setreplace( set, oldelem, newelem )
-    replaces oldelem in set with newelem
-
-  notes:
-    errors if oldelem not in the set
-    newelem may be NULL, but it turns the set into an indexed set (no FOREACH)
-
-  design:
-    find oldelem
-    replace with newelem
-*/
-void qh_setreplace(setT *set, void *oldelem, void *newelem) {
-  void **elemp;
-  
-  elemp= SETaddr_(set, void);
-  while(*elemp != oldelem && *elemp)
-    elemp++;
-  if (*elemp)
-    *elemp= newelem;
-  else {
-    fprintf (qhmem.ferr, "qhull internal error (qh_setreplace): elem %p not found in set\n",
-       oldelem);
-    qh_setprint (qhmem.ferr, "", set);
-    qh_errexit (qhmem_ERRqhull, NULL, NULL);
-  }
-} /* setreplace */
-
-
-/*---------------------------------
-  
-  qh_setsize( set )
-    returns the size of a set
-
-  notes:
-    errors if set's maxsize is incorrect
-    same as SETreturnsize_(set)
-
-  design:
-    determine actual size of set from maxsize
-*/
-int qh_setsize(setT *set) {
-  int size, *sizep;
-  
-  if (!set)
-    return (0);
-  sizep= SETsizeaddr_(set);
-  if ((size= *sizep)) {
-    size--;
-    if (size > set->maxsize) {
-      fprintf (qhmem.ferr, "qhull internal error (qh_setsize): current set size %d is greater than maximum size %d\n",
-	       size, set->maxsize);
-      qh_setprint (qhmem.ferr, "set: ", set);
-      qh_errexit (qhmem_ERRqhull, NULL, NULL);
-    }
-  }else
-    size= set->maxsize;
-  return size;
-} /* setsize */
-
-/*---------------------------------
-  
-  qh_settemp( setsize )
-    return a stacked, temporary set of upto setsize elements
-
-  notes:
-    use settempfree or settempfree_all to release from qhmem.tempstack
-    see also qh_setnew
-
-  design:
-    allocate set
-    append to qhmem.tempstack
-    
-*/
-setT *qh_settemp(int setsize) {
-  setT *newset;
-  
-  newset= qh_setnew (setsize);
-  qh_setappend ((setT **)&qhmem.tempstack, newset);
-  if (qhmem.IStracing >= 5)
-    fprintf (qhmem.ferr, "qh_settemp: temp set %p of %d elements, depth %d\n",
-       newset, newset->maxsize, qh_setsize ((setT*)qhmem.tempstack));
-  return newset;
-} /* settemp */
-
-/*---------------------------------
-  
-  qh_settempfree( set )
-    free temporary set at top of qhmem.tempstack
-
-  notes:
-    nop if set is NULL
-    errors if set not from previous   qh_settemp
-  
-  to locate errors:
-    use 'T2' to find source and then find mis-matching qh_settemp
-
-  design:
-    check top of qhmem.tempstack
-    free it
-*/
-void qh_settempfree(setT **set) {
-  setT *stackedset;
-
-  if (!*set)
-    return;
-  stackedset= qh_settemppop ();
-  if (stackedset != *set) {
-    qh_settemppush(stackedset);
-    fprintf (qhmem.ferr, "qhull internal error (qh_settempfree): set %p (size %d) was not last temporary allocated (depth %d, set %p, size %d)\n",
-	     *set, qh_setsize(*set), qh_setsize((setT*)qhmem.tempstack)+1,
-	     stackedset, qh_setsize(stackedset));
-    qh_errexit (qhmem_ERRqhull, NULL, NULL);
-  }
-  qh_setfree (set);
-} /* settempfree */
-
-/*---------------------------------
-  
-  qh_settempfree_all(  )
-    free all temporary sets in qhmem.tempstack
-
-  design:
-    for each set in tempstack
-      free set
-    free qhmem.tempstack
-*/
-void qh_settempfree_all(void) {
-  setT *set, **setp;
-
-  FOREACHset_((setT *)qhmem.tempstack) 
-    qh_setfree(&set);
-  qh_setfree((setT **)&qhmem.tempstack);
-} /* settempfree_all */
-
-/*---------------------------------
-  
-  qh_settemppop(  )
-    pop and return temporary set from qhmem.tempstack 
-
-  notes:
-    the returned set is permanent
-    
-  design:
-    pop and check top of qhmem.tempstack
-*/
-setT *qh_settemppop(void) {
-  setT *stackedset;
-  
-  stackedset= (setT*)qh_setdellast((setT *)qhmem.tempstack);
-  if (!stackedset) {
-    fprintf (qhmem.ferr, "qhull internal error (qh_settemppop): pop from empty temporary stack\n");
-    qh_errexit (qhmem_ERRqhull, NULL, NULL);
-  }
-  if (qhmem.IStracing >= 5)
-    fprintf (qhmem.ferr, "qh_settemppop: depth %d temp set %p of %d elements\n",
-       qh_setsize((setT*)qhmem.tempstack)+1, stackedset, qh_setsize(stackedset));
-  return stackedset;
-} /* settemppop */
-
-/*---------------------------------
-  
-  qh_settemppush( set )
-    push temporary set unto qhmem.tempstack (makes it temporary)
-
-  notes:
-    duplicates settemp() for tracing
-
-  design:
-    append set to tempstack  
-*/
-void qh_settemppush(setT *set) {
-  
-  qh_setappend ((setT**)&qhmem.tempstack, set);
-  if (qhmem.IStracing >= 5)
-    fprintf (qhmem.ferr, "qh_settemppush: depth %d temp set %p of %d elements\n",
-    qh_setsize((setT*)qhmem.tempstack), set, qh_setsize(set));
-} /* settemppush */
-
- 
-/*---------------------------------
-  
-  qh_settruncate( set, size )
-    truncate set to size elements
-
-  notes:
-    set must be defined
-  
-  see:
-    SETtruncate_
-
-  design:
-    check size
-    update actual size of set
-*/
-void qh_settruncate (setT *set, int size) {
-
-  if (size < 0 || size > set->maxsize) {
-    fprintf (qhmem.ferr, "qhull internal error (qh_settruncate): size %d out of bounds for set:\n", size);
-    qh_setprint (qhmem.ferr, "", set);
-    qh_errexit (qhmem_ERRqhull, NULL, NULL);
-  }
-  set->e[set->maxsize].i= size+1;   /* maybe overwritten */
-  set->e[size].p= NULL;
-} /* settruncate */
-    
-/*---------------------------------
-  
-  qh_setunique( set, elem )
-    add elem to unsorted set unless it is already in set
-
-  notes:
-    returns 1 if it is appended
-
-  design:
-    if elem not in set
-      append elem to set
-*/
-int qh_setunique (setT **set, void *elem) {
-
-  if (!qh_setin (*set, elem)) {
-    qh_setappend (set, elem);
-    return 1;
-  }
-  return 0;
-} /* setunique */
-    
-/*---------------------------------
-  
-  qh_setzero( set, index, size )
-    zero elements from index on
-    set actual size of set to size
-
-  notes:
-    set must be defined
-    the set becomes an indexed set (can not use FOREACH...)
-  
-  see also:
-    qh_settruncate
-    
-  design:
-    check index and size
-    update actual size
-    zero elements starting at e[index]   
-*/
-void qh_setzero (setT *set, int index, int size) {
-  int count;
-
-  if (index < 0 || index >= size || size > set->maxsize) {
-    fprintf (qhmem.ferr, "qhull internal error (qh_setzero): index %d or size %d out of bounds for set:\n", index, size);
-    qh_setprint (qhmem.ferr, "", set);
-    qh_errexit (qhmem_ERRqhull, NULL, NULL);
-  }
-  set->e[set->maxsize].i=  size+1;  /* may be overwritten */
-  count= size - index + 1;   /* +1 for NULL terminator */
-  memset ((char *)SETelemaddr_(set, index, void), 0, count * SETelemsize);
-} /* setzero */
-
-    
diff --git a/extern/qhull/src/qset.h b/extern/qhull/src/qset.h
deleted file mode 100644
index 6c0ff758de4..00000000000
--- a/extern/qhull/src/qset.h
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
  ---------------------------------
-
-   qset.h
-     header file for qset.c that implements set
-
-   see qh-set.htm and qset.c
-   
-   only uses mem.c, malloc/free
-
-   for error handling, writes message and calls
-      qh_errexit (qhmem_ERRqhull, NULL, NULL);
-   
-   set operations satisfy the following properties:
-    - sets have a max size, the actual size (if different) is stored at the end
-    - every set is NULL terminated
-    - sets may be sorted or unsorted, the caller must distinguish this
-   
-   copyright (c) 1993-2002, The Geometry Center
-*/
-
-#ifndef qhDEFset
-#define qhDEFset 1
-
-/*================= -structures- ===============*/
-
-#ifndef DEFsetT
-#define DEFsetT 1
-typedef struct setT setT;   /* a set is a sorted or unsorted array of pointers */
-#endif
-
-/*------------------------------------------
-   
-setT
-  a set or list of pointers with maximum size and actual size.
-
-variations:
-  unsorted, unique   -- a list of unique pointers with NULL terminator
-  			   user guarantees uniqueness
-  sorted	     -- a sorted list of unique pointers with NULL terminator
-  			   qset.c guarantees uniqueness
-  unsorted           -- a list of pointers terminated with NULL
-  indexed  	     -- an array of pointers with NULL elements 
-
-structure for set of n elements:
-
-	--------------
-	|  maxsize 
-	--------------
-	|  e[0] - a pointer, may be NULL for indexed sets
-	--------------
-	|  e[1]
-	
-	--------------
-	|  ...
-	--------------
-	|  e[n-1]
-	--------------
-	|  e[n] = NULL
-	--------------
-	|  ...
-	--------------
-	|  e[maxsize] - n+1 or NULL (determines actual size of set)
-	--------------
-
-*/
-
-/*-- setelemT -- internal type to allow both pointers and indices
-*/
-typedef union setelemT setelemT;
-union setelemT {
-  void    *p;
-  int      i;         /* integer used for e[maxSize] */
-};
-
-struct setT {
-  int maxsize;          /* maximum number of elements (except NULL) */
-  setelemT e[1];        /* array of pointers, tail is NULL */
-                        /* last slot (unless NULL) is actual size+1 
-                           e[maxsize]==NULL or e[e[maxsize]-1]==NULL */
-                        /* this may generate a warning since e[] contains
-			   maxsize elements */
-};
-
-/*=========== -constants- =========================*/
-
-/*-------------------------------------
-   
-  SETelemsize
-    size of a set element in bytes
-*/
-#define SETelemsize sizeof(setelemT) 
-
-
-/*=========== -macros- =========================*/
-
-/*-------------------------------------
-   
-   FOREACHsetelement_(type, set, variable)
-     define FOREACH iterator
-
-   declare:  
-     assumes *variable and **variablep are declared
-     no space in "variable)" [DEC Alpha cc compiler]
-
-   each iteration:
-     variable is set element
-     variablep is one beyond variable.  
-
-   to repeat an element:
-     variablep--; / *repeat* /
-
-   at exit:
-     variable is NULL at end of loop
-
-   example:  
-     #define FOREACHfacet_( facets ) FOREACHsetelement_( facetT, facets, facet )
-
-   notes:
-     use FOREACHsetelement_i_() if need index or include NULLs
-
-   WARNING: 
-     nested loops can't use the same variable (define another FOREACH)
-   
-     needs braces if nested inside another FOREACH
-     this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
-*/
-#define FOREACHsetelement_(type, set, variable) \
-        if (((variable= NULL), set)) for(\
-          variable##p= (type **)&((set)->e[0].p); \
-	  (variable= *variable##p++);)
-
-/*------------------------------------------
-
-   FOREACHsetelement_i_(type, set, variable)
-     define indexed FOREACH iterator
-
-   declare:  
-     type *variable, variable_n, variable_i;
-
-   each iteration:
-     variable is set element, may be NULL
-     variable_i is index, variable_n is qh_setsize()
-
-   to repeat an element:
-     variable_i--; variable_n-- repeats for deleted element
-
-   at exit:
-     variable==NULL and variable_i==variable_n
-
-   example:
-     #define FOREACHfacet_i_( facets ) FOREACHsetelement_i_( facetT, facets, facet )
-   
-   WARNING: 
-     nested loops can't use the same variable (define another FOREACH)
-   
-     needs braces if nested inside another FOREACH
-     this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
-*/
-#define FOREACHsetelement_i_(type, set, variable) \
-        if (((variable= NULL), set)) for (\
-          variable##_i= 0, variable= (type *)((set)->e[0].p), \
-                   variable##_n= qh_setsize(set);\
-          variable##_i < variable##_n;\
-          variable= (type *)((set)->e[++variable##_i].p) )
-
-/*----------------------------------------
-
-   FOREACHsetelementreverse_(type, set, variable)- 
-     define FOREACH iterator in reverse order
-
-   declare:  
-     assumes *variable and **variablep are declared
-     also declare 'int variabletemp'
-
-   each iteration:
-     variable is set element
-
-   to repeat an element:
-     variabletemp++; / *repeat* /
-
-   at exit:
-     variable is NULL
-
-   example:
-     #define FOREACHvertexreverse_( vertices ) FOREACHsetelementreverse_( vertexT, vertices, vertex )
-  
-   notes:
-     use FOREACHsetelementreverse12_() to reverse first two elements
-     WARNING: needs braces if nested inside another FOREACH
-*/
-#define FOREACHsetelementreverse_(type, set, variable) \
-        if (((variable= NULL), set)) for(\
-	   variable##temp= qh_setsize(set)-1, variable= qh_setlast(set);\
-	   variable; variable= \
-	   ((--variable##temp >= 0) ? SETelemt_(set, variable##temp, type) : NULL))
-
-/*-------------------------------------
-
-   FOREACHsetelementreverse12_(type, set, variable)- 
-     define FOREACH iterator with e[1] and e[0] reversed
-
-   declare:  
-     assumes *variable and **variablep are declared
-
-   each iteration:
-     variable is set element
-     variablep is one after variable.  
-
-   to repeat an element:
-     variablep--; / *repeat* /
-
-   at exit:
-     variable is NULL at end of loop
-  
-   example
-     #define FOREACHvertexreverse12_( vertices ) FOREACHsetelementreverse12_( vertexT, vertices, vertex )
-
-   notes:
-     WARNING: needs braces if nested inside another FOREACH
-*/
-#define FOREACHsetelementreverse12_(type, set, variable) \
-        if (((variable= NULL), set)) for(\
-          variable##p= (type **)&((set)->e[1].p); \
-	  (variable= *variable##p); \
-          variable##p == ((type **)&((set)->e[0].p))?variable##p += 2: \
-	      (variable##p == ((type **)&((set)->e[1].p))?variable##p--:variable##p++))
-
-/*-------------------------------------
-
-   FOREACHelem_( set )- 
-     iterate elements in a set
-
-   declare:  
-     void *elem, *elemp;
-
-   each iteration:
-     elem is set element
-     elemp is one beyond
-
-   to repeat an element:
-     elemp--; / *repeat* /
-
-   at exit:
-     elem == NULL at end of loop
-  
-   example:
-     FOREACHelem_(set) {
-     
-   notes:
-     WARNING: needs braces if nested inside another FOREACH
-*/
-#define FOREACHelem_(set) FOREACHsetelement_(void, set, elem)
-
-/*-------------------------------------
-
-   FOREACHset_( set )- 
-     iterate a set of sets
-
-   declare:  
-     setT *set, **setp;
-
-   each iteration:
-     set is set element
-     setp is one beyond
-
-   to repeat an element:
-     setp--; / *repeat* /
-
-   at exit:
-     set == NULL at end of loop
-  
-   example
-     FOREACHset_(sets) {
-     
-   notes:
-     WARNING: needs braces if nested inside another FOREACH
-*/
-#define FOREACHset_(sets) FOREACHsetelement_(setT, sets, set)
-
-/*-------------------------------------------
-
-   SETindex_( set, elem )
-     return index of elem in set
-
-   notes:   
-     for use with FOREACH iteration
-
-   example:
-     i= SETindex_(ridges, ridge)
-*/
-#define SETindex_(set, elem) ((void **)elem##p - (void **)&(set)->e[1].p)
-
-/*-----------------------------------------
-
-   SETref_( elem )
-     l.h.s. for modifying the current element in a FOREACH iteration
-
-   example:
-     SETref_(ridge)= anotherridge;
-*/
-#define SETref_(elem) (elem##p[-1])
-
-/*-----------------------------------------
-
-   SETelem_(set, n)
-     return the n'th element of set
-   
-   notes:
-      assumes that n is valid [0..size] and that set is defined
-      use SETelemt_() for type cast
-*/
-#define SETelem_(set, n)           ((set)->e[n].p)
-
-/*-----------------------------------------
-
-   SETelemt_(set, n, type)
-     return the n'th element of set as a type
-   
-   notes:
-      assumes that n is valid [0..size] and that set is defined
-*/
-#define SETelemt_(set, n, type)    ((type*)((set)->e[n].p))
-
-/*-----------------------------------------
-
-   SETelemaddr_(set, n, type)
-     return address of the n'th element of a set
-   
-   notes:
-      assumes that n is valid [0..size] and set is defined 
-*/
-#define SETelemaddr_(set, n, type) ((type **)(&((set)->e[n].p)))
-
-/*-----------------------------------------
-
-   SETfirst_(set)
-     return first element of set
-   
-*/
-#define SETfirst_(set)             ((set)->e[0].p)
-
-/*-----------------------------------------
-
-   SETfirstt_(set, type)
-     return first element of set as a type
-   
-*/
-#define SETfirstt_(set, type)      ((type*)((set)->e[0].p))
-
-/*-----------------------------------------
-
-   SETsecond_(set)
-     return second element of set
-   
-*/
-#define SETsecond_(set)            ((set)->e[1].p)
-
-/*-----------------------------------------
-
-   SETsecondt_(set, type)
-     return second element of set as a type
-*/
-#define SETsecondt_(set, type)     ((type*)((set)->e[1].p))
-
-/*-----------------------------------------
-
-   SETaddr_(set, type)
-       return address of set's elements
-*/
-#define SETaddr_(set,type)	   ((type **)(&((set)->e[0].p)))
-
-/*-----------------------------------------
-
-   SETreturnsize_(set, size) 
-     return size of a set
-   
-   notes:
-      set must be defined
-      use qh_setsize(set) unless speed is critical
-*/
-#define SETreturnsize_(set, size) (((size)= ((set)->e[(set)->maxsize].i))?(--(size)):((size)= (set)->maxsize))
-
-/*-----------------------------------------
-
-   SETempty_(set) 
-     return true (1) if set is empty
-   
-   notes:
-      set may be NULL
-*/
-#define SETempty_(set) 	          (!set || (SETfirst_(set) ? 0:1))
-
-/*-----------------------------------------
-
-   SETtruncate_(set)
-     return first element of set
-
-   see:
-     qh_settruncate()
-   
-*/
-#define SETtruncate_(set, size) {set->e[set->maxsize].i= size+1; /* maybe overwritten */ \
-      set->e[size].p= NULL;}
-
-/*======= prototypes in alphabetical order ============*/
-
-void  qh_setaddsorted(setT **setp, void *elem);
-void  qh_setaddnth(setT **setp, int nth, void *newelem);
-void  qh_setappend(setT **setp, void *elem);
-void  qh_setappend_set(setT **setp, setT *setA);
-void  qh_setappend2ndlast(setT **setp, void *elem);
-void  qh_setcheck(setT *set, char *tname, int id);
-void  qh_setcompact(setT *set);
-setT *qh_setcopy(setT *set, int extra);
-void *qh_setdel(setT *set, void *elem);
-void *qh_setdellast(setT *set);
-void *qh_setdelnth(setT *set, int nth);
-void *qh_setdelnthsorted(setT *set, int nth);
-void *qh_setdelsorted(setT *set, void *newelem);
-setT *qh_setduplicate( setT *set, int elemsize);
-int   qh_setequal(setT *setA, setT *setB);
-int   qh_setequal_except (setT *setA, void *skipelemA, setT *setB, void *skipelemB);
-int   qh_setequal_skip (setT *setA, int skipA, setT *setB, int skipB);
-void  qh_setfree(setT **set);
-void  qh_setfree2( setT **setp, int elemsize);
-void  qh_setfreelong(setT **set);
-int   qh_setin(setT *set, void *setelem);
-int   qh_setindex(setT *set, void *setelem);
-void  qh_setlarger(setT **setp);
-void *qh_setlast(setT *set);
-setT *qh_setnew(int size);
-setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend);
-void  qh_setprint(FILE *fp, char* string, setT *set);
-void  qh_setreplace(setT *set, void *oldelem, void *newelem);
-int   qh_setsize(setT *set);
-setT *qh_settemp(int setsize);
-void  qh_settempfree(setT **set);
-void  qh_settempfree_all(void);
-setT *qh_settemppop(void);
-void  qh_settemppush(setT *set);
-void  qh_settruncate (setT *set, int size);
-int   qh_setunique (setT **set, void *elem);
-void  qh_setzero (setT *set, int index, int size);
-
-
-#endif /* qhDEFset */
diff --git a/extern/qhull/src/qvoronoi.c b/extern/qhull/src/qvoronoi.c
deleted file mode 100644
index ebeb7367b87..00000000000
--- a/extern/qhull/src/qvoronoi.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
  ---------------------------------
-
-   qvoronoi.c
-     compute Voronoi diagrams and furthest-point Voronoi
-     diagrams using qhull
-
-   see unix.c for full interface
-
-   copyright (c) 1993-2002, The Geometry Center
-*/
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include "qhull.h"
-#include "mem.h"
-#include "qset.h"
-
-#if __MWERKS__ && __POWERPC__
-#include 
-#include 
-#include 
-#include 
-
-#elif __cplusplus
-extern "C" {
-  int isatty (int);
-}
-
-#elif _MSC_VER
-#include 
-#define isatty _isatty
-
-#else
-int isatty (int);  /* returns 1 if stdin is a tty
-		   if "Undefined symbol" this can be deleted along with call in main() */
-#endif
-
-/*---------------------------------
-
-  qh_prompt 
-    long prompt for qhull
-    
-  notes:
-    restricted version of qhull.c
- 
-  see:
-    concise prompt below
-*/  
-
-/* duplicated in qvoron_f.htm and qvoronoi.htm */
-char hidden_options[]=" d n m v H U Qb QB Qc Qf Qg Qi Qm Qr QR Qv Qx TR E V Fa FA FC Fp FS Ft FV Pv Gt Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 ";
-
-char qh_prompta[]= "\n\
-qvoronoi- compute the Voronoi diagram\n\
-    http://www.geom.umn.edu/software/qhull  %s\n\
-\n\
-input (stdin):\n\
-    first lines: dimension and number of points (or vice-versa).\n\
-    other lines: point coordinates, best if one point per line\n\
-    comments:    start with a non-numeric character\n\
-\n\
-options:\n\
-    Qu   - compute furthest-site Voronoi diagram\n\
-    Qt   - triangulated output\n\
-    QJ   - joggled input instead of merged facets\n\
-\n\
-Qhull control options:\n\
-    Qz   - add point-at-infinity to Voronoi diagram\n\
-    QJn  - randomly joggle input in range [-n,n]\n\
-%s%s%s%s";  /* split up qh_prompt for Visual C++ */
-char qh_promptb[]= "\
-    Qs   - search all points for the initial simplex\n\
-    QGn  - Voronoi vertices if visible from point n, -n if not\n\
-    QVn  - Voronoi vertices for input point n, -n if not\n\
-\n\
-";
-char qh_promptc[]= "\
-Trace options:\n\
-    T4   - trace at level n, 4=all, 5=mem/gauss, -1= events\n\
-    Tc   - check frequently during execution\n\
-    Ts   - statistics\n\
-    Tv   - verify result: structure, convexity, and in-circle test\n\
-    Tz   - send all output to stdout\n\
-    TFn  - report summary when n or more facets created\n\
-    TI file - input data from file, no spaces or single quotes\n\
-    TO file - output results to file, may be enclosed in single quotes\n\
-    TPn  - turn on tracing when point n added to hull\n\
-     TMn - turn on tracing at merge n\n\
-     TWn - trace merge facets when width > n\n\
-    TVn  - stop qhull after adding point n, -n for before (see TCn)\n\
-     TCn - stop qhull after building cone for point n (see TVn)\n\
-\n\
-Precision options:\n\
-    Cn   - radius of centrum (roundoff added).  Merge facets if non-convex\n\
-     An  - cosine of maximum angle.  Merge facets if cosine > n or non-convex\n\
-           C-0 roundoff, A-0.99/C-0.01 pre-merge, A0.99/C0.01 post-merge\n\
-    Rn   - randomly perturb computations by a factor of [1-n,1+n]\n\
-    Wn   - min facet width for non-coincident point (before roundoff)\n\
-\n\
-Output formats (may be combined; if none, produces a summary to stdout):\n\
-    s    - summary to stderr\n\
-    p    - Voronoi vertices\n\
-    o    - OFF format (dim, Voronoi vertices, and Voronoi regions)\n\
-    i    - Delaunay regions (use 'Pp' to avoid warning)\n\
-    f    - facet dump\n\
-\n\
-";
-char qh_promptd[]= "\
-More formats:\n\
-    Fc   - count plus coincident points (by Voronoi vertex)\n\
-    Fd   - use cdd format for input (homogeneous with offset first)\n\
-    FD   - use cdd format for output (offset first)\n\
-    FF   - facet dump without ridges\n\
-    Fi   - separating hyperplanes for bounded Voronoi regions\n\
-    FI   - ID for each Voronoi vertex\n\
-    Fm   - merge count for each Voronoi vertex (511 max)\n\
-    Fn   - count plus neighboring Voronoi vertices for each Voronoi vertex\n\
-    FN   - count and Voronoi vertices for each Voronoi region\n\
-    Fo   - separating hyperplanes for unbounded Voronoi regions\n\
-    FO   - options and precision constants\n\
-    FP   - nearest point and distance for each coincident point\n\
-    FQ   - command used for qvoronoi\n\
-    Fs   - summary: #int (8), dimension, #points, tot vertices, tot facets,\n\
-                    for output: #Voronoi regions, #Voronoi vertices,\n\
-                                #coincident points, #non-simplicial regions\n\
-                    #real (2), max outer plane and min vertex\n\
-    Fv   - Voronoi diagram as Voronoi vertices between adjacent input sites\n\
-    Fx   - extreme points of Delaunay triangulation (on convex hull)\n\
-\n\
-";
-char qh_prompte[]= "\
-Geomview options (2-d only)\n\
-    Ga   - all points as dots\n\
-     Gp  -  coplanar points and vertices as radii\n\
-     Gv  -  vertices as spheres\n\
-    Gi   - inner planes only\n\
-     Gn  -  no planes\n\
-     Go  -  outer planes only\n\
-    Gc	 - centrums\n\
-    Gh   - hyperplane intersections\n\
-    Gr   - ridges\n\
-    GDn  - drop dimension n in 3-d and 4-d output\n\
-\n\
-Print options:\n\
-    PAn  - keep n largest Voronoi vertices by 'area'\n\
-    Pdk:n - drop facet if normal[k] <= n (default 0.0)\n\
-    PDk:n - drop facet if normal[k] >= n\n\
-    Pg   - print good Voronoi vertices (needs 'QGn' or 'QVn')\n\
-    PFn  - keep Voronoi vertices whose 'area' is at least n\n\
-    PG   - print neighbors of good Voronoi vertices\n\
-    PMn  - keep n Voronoi vertices with most merges\n\
-    Po   - force output.  If error, output neighborhood of facet\n\
-    Pp   - do not report precision problems\n\
-\n\
-    .    - list of all options\n\
-    -    - one line descriptions of all options\n\
-";
-/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
-
-/*---------------------------------
-
-  qh_prompt2
-    synopsis for qhull 
-*/  
-char qh_prompt2[]= "\n\
-qvoronoi- compute the Voronoi diagram. Qhull %s\n\
-    input (stdin): dimension, number of points, point coordinates\n\
-    comments start with a non-numeric character\n\
-\n\
-options (qvoronoi.htm):\n\
-    Qu   - compute furthest-site Voronoi diagram\n\
-    Qt   - triangulated output\n\
-    QJ   - joggled input instead of merged facets\n\
-    Tv   - verify result: structure, convexity, and in-circle test\n\
-    .    - concise list of all options\n\
-    -    - one-line description of all options\n\
-\n\
-output options (subset):\n\
-    s    - summary of results (default)\n\
-    p    - Voronoi vertices\n\
-    o    - OFF file format (dim, Voronoi vertices, and Voronoi regions)\n\
-    FN   - count and Voronoi vertices for each Voronoi region\n\
-    Fv   - Voronoi diagram as Voronoi vertices between adjacent input sites\n\
-    Fi   - separating hyperplanes for bounded regions, 'Fo' for unbounded\n\
-    G    - Geomview output (2-d only)\n\
-    QVn  - Voronoi vertices for input point n, -n if not\n\
-    TO file- output results to file, may be enclosed in single quotes\n\
-\n\
-examples:\n\
-rbox c P0 D2 | qvoronoi s o         rbox c P0 D2 | qvoronoi Fi\n\
-rbox c P0 D2 | qvoronoi Fo          rbox c P0 D2 | qvoronoi Fv\n\
-rbox c P0 D2 | qvoronoi s Qu Fv     rbox c P0 D2 | qvoronoi Qu Fo\n\
-rbox c G1 d D2 | qvoronoi s p       rbox c G1 d D2 | qvoronoi QJ s p\n\
-rbox c P0 D2 | qvoronoi s Fv QV0\n\
-\n\
-";
-/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
-
-/*---------------------------------
-
-  qh_prompt3
-    concise prompt for qhull 
-*/  
-char qh_prompt3[]= "\n\
-Qhull %s.\n\
-Except for 'F.' and 'PG', upper-case options take an argument.\n\
-\n\
- OFF_format     p_vertices     i_delaunay     summary        facet_dump\n\
-\n\
- Fcoincident    Fd_cdd_in      FD_cdd_out     FF-dump-xridge Fi_bounded\n\
- Fxtremes       Fmerges        Fneighbors     FNeigh_region  FOptions\n\
- Fo_unbounded   FPoint_near    FQvoronoi      Fsummary       Fvoronoi\n\
- FIDs\n\
-\n\
- Gvertices      Gpoints        Gall_points    Gno_planes     Ginner\n\
- Gcentrums      Ghyperplanes   Gridges        Gouter         GDrop_dim\n\
-\n\
- PArea_keep     Pdrop d0:0D0   Pgood          PFacet_area_keep\n\
- PGood_neighbors PMerge_keep   Poutput_forced Pprecision_not\n\
-\n\
- QG_vertex_good QJoggle        Qsearch_1st    Qtriangulate   Qupper_voronoi\n\
- QV_point_good  Qzinfinite\n\
-\n\
- T4_trace       Tcheck_often   Tstatistics    Tverify        Tz_stdout\n\
- TFacet_log     TInput_file    TPoint_trace   TMerge_trace   TOutput_file\n\
- TWide_trace    TVertex_stop   TCone_stop\n\
-\n\
- Angle_max      Centrum_size   Random_dist    Wide_outside\n\
-";
-
-/*---------------------------------
-  
-  main( argc, argv )
-    processes the command line, calls qhull() to do the work, and exits
-  
-  design:
-    initializes data structures
-    reads points
-    finishes initialization
-    computes convex hull and other structures
-    checks the result
-    writes the output
-    frees memory
-*/
-int main(int argc, char *argv[]) {
-  int curlong, totlong; /* used !qh_NOmem */
-  int exitcode, numpoints, dim;
-  coordT *points;
-  boolT ismalloc;
-
-#if __MWERKS__ && __POWERPC__
-  char inBuf[BUFSIZ], outBuf[BUFSIZ], errBuf[BUFSIZ];
-  SIOUXSettings.showstatusline= false;
-  SIOUXSettings.tabspaces= 1;
-  SIOUXSettings.rows= 40;
-  if (setvbuf (stdin, inBuf, _IOFBF, sizeof(inBuf)) < 0   /* w/o, SIOUX I/O is slow*/
-  || setvbuf (stdout, outBuf, _IOFBF, sizeof(outBuf)) < 0
-  || (stdout != stderr && setvbuf (stderr, errBuf, _IOFBF, sizeof(errBuf)) < 0)) 
-    fprintf (stderr, "qhull internal warning (main): could not change stdio to fully buffered.\n");
-  argc= ccommand(&argv);
-#endif
-
-  if ((argc == 1) && isatty( 0 /*stdin*/)) {      
-    fprintf(stdout, qh_prompt2, qh_VERSION);
-    exit(qh_ERRnone);
-  }
-  if (argc > 1 && *argv[1] == '-' && !*(argv[1]+1)) {
-    fprintf(stdout, qh_prompta, qh_VERSION,  
-		qh_promptb, qh_promptc, qh_promptd, qh_prompte);
-    exit(qh_ERRnone);
-  }
-  if (argc >1 && *argv[1] == '.' && !*(argv[1]+1)) {
-    fprintf(stdout, qh_prompt3, qh_VERSION);
-    exit(qh_ERRnone);
-  }
-  qh_init_A (stdin, stdout, stderr, argc, argv);  /* sets qh qhull_command */
-  exitcode= setjmp (qh errexit); /* simple statement for CRAY J916 */
-  if (!exitcode) {
-    qh_option ("voronoi  _bbound-last  _coplanar-keep", NULL, NULL);
-    qh DELAUNAY= True;     /* 'v'   */
-    qh VORONOI= True; 
-    qh SCALElast= True;    /* 'Qbb' */
-    qh_checkflags (qh qhull_command, hidden_options);
-    qh_initflags (qh qhull_command);
-    points= qh_readpoints (&numpoints, &dim, &ismalloc);
-    if (dim >= 5) {
-      qh_option ("_merge-exact", NULL, NULL);
-      qh MERGEexact= True; /* 'Qx' always */
-    }
-    qh_init_B (points, numpoints, dim, ismalloc);
-    qh_qhull();
-    qh_check_output();
-    qh_produce_output();
-    if (qh VERIFYoutput && !qh FORCEoutput && !qh STOPpoint && !qh STOPcone)
-      qh_check_points();
-    exitcode= qh_ERRnone;
-  }
-  qh NOerrexit= True;  /* no more setjmp */
-#ifdef qh_NOmem
-  qh_freeqhull( True);
-#else
-  qh_freeqhull( False);
-  qh_memfreeshort (&curlong, &totlong);
-  if (curlong || totlong) 
-    fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
-       totlong, curlong);
-#endif
-  return exitcode;
-} /* main */
-
diff --git a/extern/qhull/src/rbox.c b/extern/qhull/src/rbox.c
deleted file mode 100644
index 1c288bddc96..00000000000
--- a/extern/qhull/src/rbox.c
+++ /dev/null
@@ -1,788 +0,0 @@
-/*
  ---------------------------------
-
-   rbox.c
-     Generate input points for qhull.
-   
-   notes:
-     50 points generated for 'rbox D4'
-
-     This code needs a full rewrite.  It needs separate procedures for each 
-     distribution with common, helper procedures.
-   
-   WARNING: 
-     incorrect range if qh_RANDOMmax is defined wrong (user.h)
-*/
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "user.h"
-#if __MWERKS__ && __POWERPC__
-#include 
-#include 
-#include 
-#include 
-#endif
-
-#ifdef _MSC_VER  /* Microsoft Visual C++ */
-#pragma warning( disable : 4244)  /* conversion from double to int */
-#endif
-
-#define MINVALUE 0.8
-#define MAXdim 200
-#define PI 3.1415926535897932384
-#define DEFAULTzbox 1e6
-
-char prompt[]= "\n\
--rbox- generate various point distributions.  Default is random in cube.\n\
-\n\
-args (any order, space separated):                    Version: 2001/06/24\n\
-  3000    number of random points in cube, lens, spiral, sphere or grid\n\
-  D3      dimension 3-d\n\
-  c       add a unit cube to the output ('c G2.0' sets size)\n\
-  d       add a unit diamond to the output ('d G2.0' sets size)\n\
-  l       generate a regular 3-d spiral\n\
-  r       generate a regular polygon, ('r s Z1 G0.1' makes a cone)\n\
-  s       generate cospherical points\n\
-  x       generate random points in simplex, may use 'r' or 'Wn'\n\
-  y       same as 'x', plus simplex\n\
-  Pn,m,r  add point [n,m,r] first, pads with 0\n\
-\n\
-  Ln      lens distribution of radius n.  Also 's', 'r', 'G', 'W'.\n\
-  Mn,m,r  lattice (Mesh) rotated by [n,-m,0], [m,n,0], [0,0,r], ...\n\
-          '27 M1,0,1' is {0,1,2} x {0,1,2} x {0,1,2}.  Try 'M3,4 z'.\n\
-  W0.1    random distribution within 0.1 of the cube's or sphere's surface\n\
-  Z0.5 s  random points in a 0.5 disk projected to a sphere\n\
-  Z0.5 s G0.6 same as Z0.5 within a 0.6 gap\n\
-\n\
-  Bn      bounding box coordinates, default %2.2g\n\
-  h       output as homogeneous coordinates for cdd\n\
-  n       remove command line from the first line of output\n\
-  On      offset coordinates by n\n\
-  t       use time as the random number seed (default is command line)\n\
-  tn      use n as the random number seed\n\
-  z       print integer coordinates, default 'Bn' is %2.2g\n\
-";
-
-/* ------------------------------ prototypes ----------------*/
-int roundi( double a);
-void out1( double a);
-void out2n( double a, double b);
-void out3n( double a, double b, double c);
-int     qh_rand( void);
-void    qh_srand( int seed);
-
-
-/* ------------------------------ globals -------------------*/
-
-    FILE *fp;
-    int isinteger= 0;
-    double out_offset= 0.0;
-
-
-/*--------------------------------------------
--rbox-  main procedure of rbox application
-*/
-int main(int argc, char **argv) {
-    int i,j,k;
-    int gendim;
-    int cubesize, diamondsize, seed=0, count, apex;
-    int dim=3 , numpoints= 0, totpoints, addpoints=0;
-    int issphere=0, isaxis=0,  iscdd= 0, islens= 0, isregular=0, iswidth=0, addcube=0;
-    int isgap=0, isspiral=0, NOcommand= 0, adddiamond=0, istime=0;
-    int isbox=0, issimplex=0, issimplex2=0, ismesh=0;
-    double width=0.0, gap=0.0, radius= 0.0;
-    double coord[MAXdim], offset, meshm=3.0, meshn=4.0, meshr=5.0;
-    double *simplex, *simplexp;
-    int nthroot, mult[MAXdim];
-    double norm, factor, randr, rangap, lensangle= 0, lensbase= 1;
-    double anglediff, angle, x, y, cube= 0.0, diamond= 0.0;
-    double box= qh_DEFAULTbox; /* scale all numbers before output */
-    double randmax= qh_RANDOMmax;
-    char command[200], *s, seedbuf[200];    
-    time_t timedata;
-
-#if __MWERKS__ && __POWERPC__
-    char inBuf[BUFSIZ], outBuf[BUFSIZ], errBuf[BUFSIZ];
-    SIOUXSettings.showstatusline= False;
-    SIOUXSettings.tabspaces= 1;
-    SIOUXSettings.rows= 40;
-    if (setvbuf (stdin, inBuf, _IOFBF, sizeof(inBuf)) < 0   /* w/o, SIOUX I/O is slow*/
-    || setvbuf (stdout, outBuf, _IOFBF, sizeof(outBuf)) < 0
-    || (stdout != stderr && setvbuf (stderr, errBuf, _IOFBF, sizeof(errBuf)) < 0)) 
-      	fprintf ( stderr, "qhull internal warning (main): could not change stdio to fully buffered.\n");
-    argc= ccommand(&argv);
-#endif
-    if (argc == 1) {
- 	printf (prompt, box, DEFAULTzbox);
-    	exit(1);
-    }
-    if ((s = strrchr( argv[0], '\\'))) /* Borland gives full path */
-      strcpy (command, s+1);
-    else
-      strcpy (command, argv[0]);
-    if ((s= strstr (command, ".EXE"))
-    ||  (s= strstr (command, ".exe")))
-      *s= '\0';
-    /* ============= read flags =============== */
-    for (i=1; i < argc; i++) {
-  	if (strlen (command) + strlen(argv[i]) + 1 < sizeof(command) ) {
-	    strcat (command, " ");
-	    strcat (command, argv[i]);
-	}
-        if (isdigit (argv[i][0])) {
-      	    numpoints= atoi (argv[i]);
-      	    continue;
-	}
-	if (argv[i][0] == '-')
-	  (argv[i])++;
-        switch (argv[i][0]) {
-	  case 'c':
-	    addcube= 1;
-	    if (i+1 < argc && argv[i+1][0] == 'G')
-	      cube= (double) atof (&argv[++i][1]);
-	    break;
-	  case 'd':
-	    adddiamond= 1;
-	    if (i+1 < argc && argv[i+1][0] == 'G')
-	      diamond= (double) atof (&argv[++i][1]);
-	    break;
-	  case 'h':
-	    iscdd= 1;
-            break;
-	  case 'l':
-	    isspiral= 1;
-            break;
-	  case 'n':
-	    NOcommand= 1;
-	    break;
-	  case 'r':
-	    isregular= 1;
-	    break;
-	  case 's':
-	    issphere= 1;
-            break;
-	  case 't':
-	    istime= 1;
-	    if (isdigit (argv[i][1]))
-	      seed= atoi (&argv[i][1]);
-	    else {
-	      seed= time (&timedata);
-	      sprintf (seedbuf, "%d", seed);
-	      strcat (command, seedbuf);
-	    }
-            break;
-	  case 'x':
-	    issimplex= 1;
-	    break;
-	  case 'y':
-	    issimplex2= 1;
-	    break;
-	  case 'z':
-	    isinteger= 1;
-	    break;
-	  case 'B':
-	    box= (double) atof (&argv[i][1]);
-	    isbox= 1;
-	    break;
-	  case 'D':
-	    dim= atoi (&argv[i][1]);
-	    if (dim < 1
-	    || dim > MAXdim) {
-		fprintf (stderr, "rbox error: dim %d too large or too small\n", dim);
-		exit (1);
-	    }
-            break;
-	  case 'G':
-	    if (argv[i][1])
-	      gap= (double) atof (&argv[i][1]);
-	    else
-	      gap= 0.5;
-	    isgap= 1;
-	    break;
-	  case 'L':
-	    if (argv[i][1])
-	      radius= (double) atof (&argv[i][1]);
-	    else
-	      radius= 10;
-	    islens= 1;
-	    break;
-	  case 'M':
-	    ismesh= 1;
-    	    s= argv[i]+1;
-	    if (*s)
-	      meshn= strtod (s, &s);
-	    if (*s == ',')
-	      meshm= strtod (++s, &s);
-	    else
-	      meshm= 0.0;
-	    if (*s == ',')
-	      meshr= strtod (++s, &s);
-	    else
-	      meshr= sqrt (meshn*meshn + meshm*meshm);
-	    if (*s) {
-	      fprintf (stderr, "rbox warning: assuming 'M3,4,5' since mesh args are not integers or reals\n");
-	      meshn= 3.0, meshm=4.0, meshr=5.0;
-	    }
-	    break;
-	  case 'O':
-	    out_offset= (double) atof (&argv[i][1]);
-	    break;
-	  case 'P':
-	    addpoints++;
-	    break;
-	  case 'W':
-	    width= (double) atof (&argv[i][1]);
-	    iswidth= 1;
-	    break;
-	  case 'Z':
-	    if (argv[i][1])
-	      radius= (double) atof (&argv[i][1]);
-	    else
-	      radius= 1.0;
-	    isaxis= 1;
-	    break;
-	  default:
-            fprintf (stderr, "rbox warning: unknown flag %s.\nExecute 'rbox' without arguments for documentation.\n", argv[i]);
-	}
-    }
-    /* ============= defaults, constants, and sizes =============== */
-    if (isinteger && !isbox)
-      box= DEFAULTzbox;
-    if (addcube) {
-      cubesize= floor(ldexp(1.0,dim)+0.5);
-      if (cube == 0.0)
-        cube= box;
-    }else
-      cubesize= 0;
-    if (adddiamond) {
-      diamondsize= 2*dim;
-      if (diamond == 0.0)
-        diamond= box;
-    }else
-      diamondsize= 0;
-    if (islens) {
-      if (isaxis) {
-  	fprintf (stderr, "rbox error: can not combine 'Ln' with 'Zn'\n");
-  	exit(1);
-      }
-      if (radius <= 1.0) {
-  	fprintf (stderr, "rbox error: lens radius %.2g should be greater than 1.0\n",
-  	       radius);
-  	exit(1);
-      }
-      lensangle= asin (1.0/radius);
-      lensbase= radius * cos (lensangle);
-    }
-    if (!numpoints) {
-      if (issimplex2)
-	; /* ok */
-      else if (isregular + issimplex + islens + issphere + isaxis + isspiral + iswidth + ismesh) {
-	fprintf (stderr, "rbox error: missing count\n");
-	exit(1);
-      }else if (adddiamond + addcube + addpoints)
-	; /* ok */
-      else { 
-	numpoints= 50;  /* ./rbox D4 is the test case */
-	issphere= 1;
-      }
-    }
-    if ((issimplex + islens + isspiral + ismesh > 1) 
-    || (issimplex + issphere + isspiral + ismesh > 1)) {
-      fprintf (stderr, "rbox error: can only specify one of 'l', 's', 'x', 'Ln', or 'Mn,m,r' ('Ln s' is ok).\n");
-      exit(1);
-    }
-    fp= stdout;
-    /* ============= print header with total points =============== */
-    if (issimplex || ismesh)
-      totpoints= numpoints;
-    else if (issimplex2)
-      totpoints= numpoints+dim+1;
-    else if (isregular) {
-      totpoints= numpoints;
-      if (dim == 2) {
-      	if (islens)
-      	  totpoints += numpoints - 2;
-      }else if (dim == 3) {
-      	if (islens)
-      	  totpoints += 2 * numpoints;
-        else if (isgap)
-          totpoints += 1 + numpoints;
-        else
-          totpoints += 2;
-      }
-    }else
-      totpoints= numpoints + isaxis;
-    totpoints += cubesize + diamondsize + addpoints;
-    if (iscdd) 
-      fprintf(fp, "%s\nbegin\n        %d %d %s\n", 
-            NOcommand ? "" : command, 
-            totpoints, dim+1,
-            isinteger ? "integer" : "real");
-    else if (NOcommand)
-      fprintf(fp,  "%d\n%d\n", dim, totpoints);
-    else
-      fprintf(fp,  "%d %s\n%d\n", dim, command, totpoints);
-    /* ============= seed randoms =============== */
-    if (istime == 0) {
-      for (s=command; *s; s++) {
-	if (issimplex2 && *s == 'y') /* make 'y' same seed as 'x' */
-	  i= 'x';
-	else
-	  i= *s;
-	seed= 11*seed + i;
-      }
-    } /* else, seed explicitly set to n or to time */
-    qh_RANDOMseed_(seed);
-    /* ============= explicit points =============== */
-    for (i=1; i < argc; i++) {
-      if (argv[i][0] == 'P') {
-	s= argv[i]+1;
-	count= 0;
-	if (iscdd)
-	  out1( 1.0);
-	while (*s) {
-	  out1( strtod (s, &s));
-	  count++;
-	  if (*s) { 
-	    if (*s++ != ',') {
-	      fprintf (stderr, "rbox error: missing comma after coordinate in %s\n\n", argv[i]);
-	      exit (1);
-	    }
-          }
-	}
-	if (count < dim) {
-	  for (k= dim-count; k--; )
-	    out1( 0.0);
-	}else if (count > dim) {
-	  fprintf (stderr, "rbox error: %d coordinates instead of %d coordinates in %s\n\n", 
-                 count, dim, argv[i]);
-	  exit (1);
-	}
-	fprintf (fp, "\n");
-      }
-    }
-    /* ============= simplex distribution =============== */
-    if (issimplex+issimplex2) {
-      if (!(simplex= malloc( dim * (dim+1) * sizeof(double)))) {
-	fprintf (stderr, "insufficient memory for simplex\n");
-	exit(0);
-      }
-      simplexp= simplex;
-      if (isregular) {
-        for (i= 0; i randmax/2)
-	    coord[dim-1]= -coord[dim-1];
-	/* ============= project 'Wn' point toward boundary =============== */
-	}else if (iswidth && !issphere) {
-	  j= qh_RANDOMint % gendim;
-	  if (coord[j] < 0)
-	    coord[j]= -1.0 - coord[j] * width;
-	  else
-	    coord[j]= 1.0 - coord[j] * width;
-	}
-	/* ============= write point =============== */
-	if (iscdd)
-	  out1( 1.0);
-	for (k=0; k < dim; k++) 
-	  out1( coord[k] * box);
-	fprintf (fp, "\n");
-      }
-    }
-    /* ============= write cube vertices =============== */
-    if (addcube) {
-      for (j=0; j=0; k--) {
-	  if (j & ( 1 << k))
-	    out1( cube);
-	  else
-	    out1( -cube);
-	}
-	fprintf (fp, "\n");
-      }
-    }
-    /* ============= write diamond vertices =============== */
-    if (adddiamond) {
-      for (j=0; j=0; k--) {
-	  if (j/2 != k)
-	    out1( 0.0);
-	  else if (j & 0x1)
-	    out1( diamond);
-	  else
-	    out1( -diamond);
-	}
-	fprintf (fp, "\n");
-      }
-    }
-    if (iscdd)
-      fprintf (fp, "end\nhull\n");
-    return 0;
-  } /* rbox */
-
-/*------------------------------------------------
--outxxx - output functions
-*/
-int roundi( double a) {
-  if (a < 0.0) {
-    if (a - 0.5 < INT_MIN) {
-      fprintf(stderr, "rbox input error: coordinate %2.2g is too large.  Reduce 'Bn'\n", a);
-      exit (1);
-    }
-    return a - 0.5;
-  }else {
-    if (a + 0.5 > INT_MAX) {
-      fprintf(stderr, "rbox input error: coordinate %2.2g is too large.  Reduce 'Bn'\n", a);
-      exit (1);
-    }
-    return a + 0.5;
-  }
-} /* roundi */
-
-void out1(double a) {
-
-  if (isinteger) 
-    fprintf(fp, "%d ", roundi( a+out_offset));
-  else
-    fprintf(fp, qh_REAL_1, a+out_offset);
-} /* out1 */
-
-void out2n( double a, double b) {
-
-  if (isinteger)
-    fprintf(fp, "%d %d\n", roundi(a+out_offset), roundi(b+out_offset));
-  else
-    fprintf(fp, qh_REAL_2n, a+out_offset, b+out_offset);
-} /* out2n */
-
-void out3n( double a, double b, double c) { 
-
-  if (isinteger)
-    fprintf(fp, "%d %d %d\n", roundi(a+out_offset), roundi(b+out_offset), roundi(c+out_offset));
-  else
-    fprintf(fp, qh_REAL_3n, a+out_offset, b+out_offset, c+out_offset);
-} /* out3n */
-
-/*-------------------------------------------------
--rand & srand- generate pseudo-random number between 1 and 2^31 -2
-  from Park & Miller's minimimal standard random number generator
-  Communications of the ACM, 31:1192-1201, 1988.
-notes:
-  does not use 0 or 2^31 -1
-  this is silently enforced by qh_srand()
-  copied from geom2.c
-*/
-static int seed = 1;  /* global static */
-
-int qh_rand( void) {
-#define qh_rand_a 16807
-#define qh_rand_m 2147483647
-#define qh_rand_q 127773  /* m div a */
-#define qh_rand_r 2836    /* m mod a */
-  int lo, hi, test;
-
-  hi = seed / qh_rand_q;  /* seed div q */
-  lo = seed % qh_rand_q;  /* seed mod q */
-  test = qh_rand_a * lo - qh_rand_r * hi;
-  if (test > 0)
-    seed= test;
-  else
-    seed= test + qh_rand_m;
-  return seed;
-} /* rand */
-
-void qh_srand( int newseed) {
-  if (newseed < 1)
-    seed= 1;
-  else if (newseed >= qh_rand_m)
-    seed= qh_rand_m - 1;
-  else
-    seed= newseed;
-} /* qh_srand */
-
diff --git a/extern/qhull/src/stat.c b/extern/qhull/src/stat.c
deleted file mode 100644
index ede0323cb88..00000000000
--- a/extern/qhull/src/stat.c
+++ /dev/null
@@ -1,700 +0,0 @@
-/*
  ---------------------------------
-
-   stat.c 
-   contains all statistics that are collected for qhull
-
-   see qh-stat.htm and stat.h
-
-   copyright (c) 1993-2002, The Geometry Center
-*/
-
-#include "qhull_a.h"
-
-/*============ global data structure ==========*/
-
-#if qh_QHpointer
-qhstatT *qh_qhstat=NULL;  /* global data structure */
-#else
-qhstatT qh_qhstat;   /* add "={0}" if this causes a compiler error */
-#endif
-
-/*========== functions in alphabetic order ================*/
-
-/*---------------------------------
-  
-  qh_allstatA()
-    define statistics in groups of 20
-
-  notes:
-    (otherwise, 'gcc -O2' uses too much memory)
-    uses qhstat.next
-*/
-void qh_allstatA (void) {
-  
-   /* zdef_(type,name,doc,average) */
-  zzdef_(zdoc, Zdoc2, "precision statistics", -1);
-  zdef_(zinc, Znewvertex, NULL, -1);
-  zdef_(wadd, Wnewvertex, "ave. distance of a new vertex to a facet (not 0s)", Znewvertex);
-  zzdef_(wmax, Wnewvertexmax, "max. distance of a new vertex to a facet", -1);
-  zdef_(wmax, Wvertexmax, "max. distance of an output vertex to a facet", -1);
-  zdef_(wmin, Wvertexmin, "min. distance of an output vertex to a facet", -1);
-  zdef_(wmin, Wmindenom, "min. denominator in hyperplane computation", -1);
-
-  qhstat precision= qhstat next;  /* call qh_precision for each of these */
-  zzdef_(zdoc, Zdoc3, "precision problems (corrected unless 'Q0' or an error)", -1);
-  zzdef_(zinc, Zcoplanarridges, "coplanar half ridges in output", -1);
-  zzdef_(zinc, Zconcaveridges, "concave half ridges in output", -1);
-  zzdef_(zinc, Zflippedfacets, "flipped facets", -1);
-  zzdef_(zinc, Zcoplanarhorizon, "coplanar horizon facets for new vertices", -1);
-  zzdef_(zinc, Zcoplanarpart, "coplanar points during partitioning", -1);
-  zzdef_(zinc, Zminnorm, "degenerate hyperplanes recomputed with gaussian elimination", -1);
-  zzdef_(zinc, Znearlysingular, "nearly singular or axis-parallel hyperplanes", -1);
-  zzdef_(zinc, Zback0, "zero divisors during back substitute", -1);
-  zzdef_(zinc, Zgauss0, "zero divisors during gaussian elimination", -1);
-  zzdef_(zinc, Zmultiridge, "ridges with multiple neighbors", -1);
-}
-void qh_allstatB (void) {
-  zzdef_(zdoc, Zdoc1, "summary information", -1);
-  zdef_(zinc, Zvertices, "number of vertices in output", -1);
-  zdef_(zinc, Znumfacets, "number of facets in output", -1);
-  zdef_(zinc, Znonsimplicial, "number of non-simplicial facets in output", -1);
-  zdef_(zinc, Znowsimplicial, "number of simplicial facets that were merged", -1);
-  zdef_(zinc, Znumridges, "number of ridges in output", -1);
-  zdef_(zadd, Znumridges, "average number of ridges per facet", Znumfacets);
-  zdef_(zmax, Zmaxridges, "maximum number of ridges", -1);
-  zdef_(zadd, Znumneighbors, "average number of neighbors per facet", Znumfacets);
-  zdef_(zmax, Zmaxneighbors, "maximum number of neighbors", -1);
-  zdef_(zadd, Znumvertices, "average number of vertices per facet", Znumfacets);
-  zdef_(zmax, Zmaxvertices, "maximum number of vertices", -1);
-  zdef_(zadd, Znumvneighbors, "average number of neighbors per vertex", Zvertices);
-  zdef_(zmax, Zmaxvneighbors, "maximum number of neighbors", -1);
-  zdef_(wadd, Wcpu, "cpu seconds for qhull after input", -1);
-  zdef_(zinc, Ztotvertices, "vertices created altogether", -1);
-  zzdef_(zinc, Zsetplane, "facets created altogether", -1);
-  zdef_(zinc, Ztotridges, "ridges created altogether", -1);
-  zdef_(zinc, Zpostfacets, "facets before post merge", -1);
-  zdef_(zadd, Znummergetot, "average merges per facet (at most 511)", Znumfacets);
-  zdef_(zmax, Znummergemax, "  maximum merges for a facet (at most 511)", -1);
-  zdef_(zinc, Zangle, NULL, -1);
-  zdef_(wadd, Wangle, "average angle (cosine) of facet normals for all ridges", Zangle);
-  zdef_(wmax, Wanglemax, "  maximum angle (cosine) of facet normals across a ridge", -1);
-  zdef_(wmin, Wanglemin, "  minimum angle (cosine) of facet normals across a ridge", -1);
-  zdef_(wadd, Wareatot, "total area of facets", -1);
-  zdef_(wmax, Wareamax, "  maximum facet area", -1);
-  zdef_(wmin, Wareamin, "  minimum facet area", -1);
-}  
-void qh_allstatC (void) {
-  zdef_(zdoc, Zdoc9, "build hull statistics", -1);
-  zzdef_(zinc, Zprocessed, "points processed", -1);
-  zzdef_(zinc, Zretry, "retries due to precision problems", -1);
-  zdef_(wmax, Wretrymax, "  max. random joggle", -1);
-  zdef_(zmax, Zmaxvertex, "max. vertices at any one time", -1);
-  zdef_(zinc, Ztotvisible, "ave. visible facets per iteration", Zprocessed);
-  zdef_(zinc, Zinsidevisible, "  ave. visible facets without an horizon neighbor", Zprocessed);
-  zdef_(zadd, Zvisfacettot,  "  ave. facets deleted per iteration", Zprocessed);
-  zdef_(zmax, Zvisfacetmax,  "    maximum", -1);
-  zdef_(zadd, Zvisvertextot, "ave. visible vertices per iteration", Zprocessed);
-  zdef_(zmax, Zvisvertexmax, "    maximum", -1);
-  zdef_(zinc, Ztothorizon, "ave. horizon facets per iteration", Zprocessed);
-  zdef_(zadd, Znewfacettot,  "ave. new or merged facets per iteration", Zprocessed);
-  zdef_(zmax, Znewfacetmax,  "    maximum (includes initial simplex)", -1);
-  zdef_(wadd, Wnewbalance, "average new facet balance", Zprocessed);
-  zdef_(wadd, Wnewbalance2, "  standard deviation", -1);
-  zdef_(wadd, Wpbalance, "average partition balance", Zpbalance);
-  zdef_(wadd, Wpbalance2, "  standard deviation", -1);
-  zdef_(zinc, Zpbalance, "  number of trials", -1);
-  zdef_(zinc, Zsearchpoints, "searches of all points for initial simplex", -1);
-  zdef_(zinc, Zdetsimplex, "determinants computed (area & initial hull)", -1);
-  zdef_(zinc, Znoarea, "determinants not computed because vertex too low", -1);
-  zdef_(zinc, Znotmax, "points ignored (not above max_outside)", -1);
-  zdef_(zinc, Znotgood, "points ignored (not above a good facet)", -1);
-  zdef_(zinc, Znotgoodnew, "points ignored (didn't create a good new facet)", -1);
-  zdef_(zinc, Zgoodfacet, "good facets found", -1);
-  zzdef_(zinc, Znumvisibility, "distance tests for facet visibility", -1);
-  zdef_(zinc, Zdistvertex, "distance tests to report minimum vertex", -1);
-  zdef_(zinc, Ztotcheck, "points checked for facets' outer planes", -1);
-  zzdef_(zinc, Zcheckpart, "  ave. distance tests per check", Ztotcheck);
-}
-void qh_allstatD(void) {
-  zdef_(zdoc, Zdoc4, "partitioning statistics (see previous for outer planes)", -1);
-  zzdef_(zadd, Zdelvertextot, "total vertices deleted", -1);
-  zdef_(zmax, Zdelvertexmax, "    maximum vertices deleted per iteration", -1);
-  zdef_(zinc, Zfindbest, "calls to findbest", -1);
-  zdef_(zadd, Zfindbesttot, " ave. facets tested", Zfindbest);
-  zdef_(zmax, Zfindbestmax, " max. facets tested", -1);
-  zdef_(zadd, Zfindcoplanar, " ave. coplanar search", Zfindbest);
-  zdef_(zinc, Zfindnew, "calls to findbestnew", -1);
-  zdef_(zadd, Zfindnewtot, " ave. facets tested", Zfindnew);
-  zdef_(zmax, Zfindnewmax, " max. facets tested", -1);
-  zdef_(zinc, Zfindnewjump, " ave. clearly better", Zfindnew);
-  zdef_(zinc, Zfindnewsharp, " calls due to qh_sharpnewfacets", -1);
-  zdef_(zinc, Zfindhorizon, "calls to findhorizon", -1);
-  zdef_(zadd, Zfindhorizontot, " ave. facets tested", Zfindhorizon);
-  zdef_(zmax, Zfindhorizonmax, " max. facets tested", -1);
-  zdef_(zinc, Zfindjump,       " ave. clearly better", Zfindhorizon);
-  zdef_(zinc, Zparthorizon, " horizon facets better than bestfacet", -1);
-  zdef_(zinc, Zpartangle, "angle tests for repartitioned coplanar points", -1);
-  zdef_(zinc, Zpartflip, "  repartitioned coplanar points for flipped orientation", -1);
-  zdef_(zinc, Zpartinside, "inside points", -1);
-  zdef_(zinc, Zpartnear, "  inside points kept with a facet", -1);
-  zdef_(zinc, Zcoplanarinside, "  inside points that were coplanar with a facet", -1);
-  zdef_(wadd, Wmaxout, "difference in max_outside at final check", -1);
-}
-void qh_allstatE(void) {
-  zzdef_(zinc, Zpartitionall, "distance tests for initial partition", -1);
-  zdef_(zinc, Ztotpartition, "partitions of a point", -1);
-  zzdef_(zinc, Zpartition, "distance tests for partitioning", -1);
-  zzdef_(zinc, Zdistcheck, "distance tests for checking flipped facets", -1); 
-  zzdef_(zinc, Zdistconvex, "distance tests for checking convexity", -1); 
-  zdef_(zinc, Zdistgood, "distance tests for checking good point", -1); 
-  zdef_(zinc, Zdistio, "distance tests for output", -1); 
-  zdef_(zinc, Zdiststat, "distance tests for statistics", -1); 
-  zdef_(zinc, Zdistplane, "total number of distance tests", -1);
-  zdef_(zinc, Ztotpartcoplanar, "partitions of coplanar points or deleted vertices", -1);
-  zzdef_(zinc, Zpartcoplanar, "   distance tests for these partitions", -1);
-  zdef_(zinc, Zcomputefurthest, "distance tests for computing furthest", -1);
-}
-void qh_allstatE2(void) {
-  zdef_(zdoc, Zdoc5, "statistics for matching ridges", -1);
-  zdef_(zinc, Zhashlookup, "total lookups for matching ridges of new facets", -1);
-  zdef_(zinc, Zhashtests, "average number of tests to match a ridge", Zhashlookup);
-  zdef_(zinc, Zhashridge, "total lookups of subridges (duplicates and boundary)", -1);
-  zdef_(zinc, Zhashridgetest, "average number of tests per subridge", Zhashridge);
-  zdef_(zinc, Zdupsame, "duplicated ridges in same merge cycle", -1);
-  zdef_(zinc, Zdupflip, "duplicated ridges with flipped facets", -1);
-
-  zdef_(zdoc, Zdoc6, "statistics for determining merges", -1);
-  zdef_(zinc, Zangletests, "angles computed for ridge convexity", -1);
-  zdef_(zinc, Zbestcentrum, "best merges used centrum instead of vertices",-1);
-  zzdef_(zinc, Zbestdist, "distance tests for best merge", -1);
-  zzdef_(zinc, Zcentrumtests, "distance tests for centrum convexity", -1);
-  zzdef_(zinc, Zdistzero, "distance tests for checking simplicial convexity", -1);
-  zdef_(zinc, Zcoplanarangle, "coplanar angles in getmergeset", -1);
-  zdef_(zinc, Zcoplanarcentrum, "coplanar centrums in getmergeset", -1);
-  zdef_(zinc, Zconcaveridge, "concave ridges in getmergeset", -1);
-}
-void qh_allstatF(void) {
-  zdef_(zdoc, Zdoc7, "statistics for merging", -1);
-  zdef_(zinc, Zpremergetot, "merge iterations", -1);
-  zdef_(zadd, Zmergeinittot, "ave. initial non-convex ridges per iteration", Zpremergetot);
-  zdef_(zadd, Zmergeinitmax, "  maximum", -1);
-  zdef_(zadd, Zmergesettot, "  ave. additional non-convex ridges per iteration", Zpremergetot);
-  zdef_(zadd, Zmergesetmax, "  maximum additional in one pass", -1);
-  zdef_(zadd, Zmergeinittot2, "initial non-convex ridges for post merging", -1);
-  zdef_(zadd, Zmergesettot2, "  additional non-convex ridges", -1);
-  zdef_(wmax, Wmaxoutside, "max distance of vertex or coplanar point above facet (w/roundoff)", -1);
-  zdef_(wmin, Wminvertex, "max distance of merged vertex below facet (or roundoff)", -1);
-  zdef_(zinc, Zwidefacet, "centrums frozen due to a wide merge", -1);
-  zdef_(zinc, Zwidevertices, "centrums frozen due to extra vertices", -1);
-  zzdef_(zinc, Ztotmerge, "total number of facets or cycles of facets merged", -1);
-  zdef_(zinc, Zmergesimplex, "merged a simplex", -1);
-  zdef_(zinc, Zonehorizon, "simplices merged into coplanar horizon", -1);
-  zzdef_(zinc, Zcyclehorizon, "cycles of facets merged into coplanar horizon", -1);
-  zzdef_(zadd, Zcyclefacettot, "  ave. facets per cycle", Zcyclehorizon);
-  zdef_(zmax, Zcyclefacetmax, "  max. facets", -1);
-  zdef_(zinc, Zmergeintohorizon, "new facets merged into horizon", -1);
-  zdef_(zinc, Zmergenew, "new facets merged", -1);
-  zdef_(zinc, Zmergehorizon, "horizon facets merged into new facets", -1);
-  zdef_(zinc, Zmergevertex, "vertices deleted by merging", -1);
-  zdef_(zinc, Zcyclevertex, "vertices deleted by merging into coplanar horizon", -1);
-  zdef_(zinc, Zdegenvertex, "vertices deleted by degenerate facet", -1);
-  zdef_(zinc, Zmergeflipdup, "merges due to flipped facets in duplicated ridge", -1);
-  zdef_(zinc, Zneighbor, "merges due to redundant neighbors", -1);
-  zdef_(zadd, Ztestvneighbor, "non-convex vertex neighbors", -1); 
-}
-void qh_allstatG(void) {
-  zdef_(zinc, Zacoplanar, "merges due to angle coplanar facets", -1);
-  zdef_(wadd, Wacoplanartot, "  average merge distance", Zacoplanar);
-  zdef_(wmax, Wacoplanarmax, "  maximum merge distance", -1);
-  zdef_(zinc, Zcoplanar, "merges due to coplanar facets", -1);
-  zdef_(wadd, Wcoplanartot, "  average merge distance", Zcoplanar);
-  zdef_(wmax, Wcoplanarmax, "  maximum merge distance", -1);
-  zdef_(zinc, Zconcave, "merges due to concave facets", -1);
-  zdef_(wadd, Wconcavetot, "  average merge distance", Zconcave);
-  zdef_(wmax, Wconcavemax, "  maximum merge distance", -1);
-  zdef_(zinc, Zavoidold, "coplanar/concave merges due to avoiding old merge", -1);
-  zdef_(wadd, Wavoidoldtot, "  average merge distance", Zavoidold);
-  zdef_(wmax, Wavoidoldmax, "  maximum merge distance", -1);
-  zdef_(zinc, Zdegen, "merges due to degenerate facets", -1);
-  zdef_(wadd, Wdegentot, "  average merge distance", Zdegen);
-  zdef_(wmax, Wdegenmax, "  maximum merge distance", -1);
-  zdef_(zinc, Zflipped, "merges due to removing flipped facets", -1);
-  zdef_(wadd, Wflippedtot, "  average merge distance", Zflipped);
-  zdef_(wmax, Wflippedmax, "  maximum merge distance", -1);
-  zdef_(zinc, Zduplicate, "merges due to duplicated ridges", -1);
-  zdef_(wadd, Wduplicatetot, "  average merge distance", Zduplicate);
-  zdef_(wmax, Wduplicatemax, "  maximum merge distance", -1);
-}
-void qh_allstatH(void) {
-  zdef_(zdoc, Zdoc8, "renamed vertex statistics", -1);
-  zdef_(zinc, Zrenameshare, "renamed vertices shared by two facets", -1);
-  zdef_(zinc, Zrenamepinch, "renamed vertices in a pinched facet", -1);
-  zdef_(zinc, Zrenameall, "renamed vertices shared by multiple facets", -1);
-  zdef_(zinc, Zfindfail, "rename failures due to duplicated ridges", -1);
-  zdef_(zinc, Zdupridge, "  duplicate ridges detected", -1);
-  zdef_(zinc, Zdelridge, "deleted ridges due to renamed vertices", -1);
-  zdef_(zinc, Zdropneighbor, "dropped neighbors due to renamed vertices", -1);
-  zdef_(zinc, Zdropdegen, "degenerate facets due to dropped neighbors", -1);
-  zdef_(zinc, Zdelfacetdup, "  facets deleted because of no neighbors", -1);
-  zdef_(zinc, Zremvertex, "vertices removed from facets due to no ridges", -1);
-  zdef_(zinc, Zremvertexdel, "  deleted", -1);
-  zdef_(zinc, Zintersectnum, "vertex intersections for locating redundant vertices", -1);
-  zdef_(zinc, Zintersectfail, "intersections failed to find a redundant vertex", -1);
-  zdef_(zinc, Zintersect, "intersections found redundant vertices", -1);
-  zdef_(zadd, Zintersecttot, "   ave. number found per vertex", Zintersect);
-  zdef_(zmax, Zintersectmax, "   max. found for a vertex", -1);
-  zdef_(zinc, Zvertexridge, NULL, -1);
-  zdef_(zadd, Zvertexridgetot, "  ave. number of ridges per tested vertex", Zvertexridge);
-  zdef_(zmax, Zvertexridgemax, "  max. number of ridges per tested vertex", -1);
-
-  zdef_(zdoc, Zdoc10, "memory usage statistics (in bytes)", -1);
-  zdef_(zadd, Zmemfacets, "for facets and their normals, neighbor and vertex sets", -1);
-  zdef_(zadd, Zmemvertices, "for vertices and their neighbor sets", -1);
-  zdef_(zadd, Zmempoints, "for input points and outside and coplanar sets",-1);
-  zdef_(zadd, Zmemridges, "for ridges and their vertex sets", -1);
-} /* allstat */
-
-void qh_allstatI(void) {
-  qhstat vridges= qhstat next;
-  zzdef_(zdoc, Zdoc11, "Voronoi ridge statistics", -1);
-  zzdef_(zinc, Zridge, "non-simplicial Voronoi vertices for all ridges", -1);
-  zzdef_(wadd, Wridge, "  ave. distance to ridge", Zridge);
-  zzdef_(wmax, Wridgemax, "  max. distance to ridge", -1);
-  zzdef_(zinc, Zridgemid, "bounded ridges", -1);
-  zzdef_(wadd, Wridgemid, "  ave. distance of midpoint to ridge", Zridgemid);
-  zzdef_(wmax, Wridgemidmax, "  max. distance of midpoint to ridge", -1);
-  zzdef_(zinc, Zridgeok, "bounded ridges with ok normal", -1);
-  zzdef_(wadd, Wridgeok, "  ave. angle to ridge", Zridgeok);
-  zzdef_(wmax, Wridgeokmax, "  max. angle to ridge", -1);
-  zzdef_(zinc, Zridge0, "bounded ridges with near-zero normal", -1);
-  zzdef_(wadd, Wridge0, "  ave. angle to ridge", Zridge0);
-  zzdef_(wmax, Wridge0max, "  max. angle to ridge", -1);
-
-  zdef_(zdoc, Zdoc12, "Triangulation statistics (Qt)", -1);
-  zdef_(zinc, Ztricoplanar, "non-simplicial facets triangulated", -1);
-  zdef_(zadd, Ztricoplanartot, "  ave. new facets created (may be deleted)", Ztricoplanar);
-  zdef_(zmax, Ztricoplanarmax, "  max. new facets created", -1);
-  zdef_(zinc, Ztrinull, "null new facets deleted (duplicated vertex)", -1);
-  zdef_(zinc, Ztrimirror, "mirrored pairs of new facets deleted (same vertices)", -1);
-  zdef_(zinc, Ztridegen, "degenerate new facets in output (same ridge)", -1);
-} /* allstat */
-
-/*---------------------------------
-  
-  qh_allstatistics()
-    reset printed flag for all statistics
-*/
-void qh_allstatistics (void) {
-  int i;
-  
-  for (i=ZEND; i--; ) 
-    qhstat printed[i]= False;
-} /* allstatistics */
-
-#if qh_KEEPstatistics
-/*---------------------------------
-  
-  qh_collectstatistics()
-    collect statistics for qh.facet_list
-
-*/
-void qh_collectstatistics (void) {
-  facetT *facet, *neighbor, **neighborp;
-  vertexT *vertex, **vertexp;
-  realT dotproduct, dist;
-  int sizneighbors, sizridges, sizvertices, i;
-  
-  qh old_randomdist= qh RANDOMdist;
-  qh RANDOMdist= False;
-  zval_(Zmempoints)= qh num_points * qh normal_size + 
-                             sizeof (qhT) + sizeof (qhstatT);
-  zval_(Zmemfacets)= 0;
-  zval_(Zmemridges)= 0;
-  zval_(Zmemvertices)= 0;
-  zval_(Zangle)= 0;
-  wval_(Wangle)= 0.0;
-  zval_(Znumridges)= 0;
-  zval_(Znumfacets)= 0;
-  zval_(Znumneighbors)= 0;
-  zval_(Znumvertices)= 0;
-  zval_(Znumvneighbors)= 0;
-  zval_(Znummergetot)= 0;
-  zval_(Znummergemax)= 0;
-  zval_(Zvertices)= qh num_vertices - qh_setsize (qh del_vertices);
-  if (qh MERGING || qh APPROXhull || qh JOGGLEmax < REALmax/2)
-    wmax_(Wmaxoutside, qh max_outside);
-  if (qh MERGING)
-    wmin_(Wminvertex, qh min_vertex);
-  FORALLfacets
-    facet->seen= False;
-  if (qh DELAUNAY) {
-    FORALLfacets {
-      if (facet->upperdelaunay != qh UPPERdelaunay)
-        facet->seen= True; /* remove from angle statistics */
-    }
-  }
-  FORALLfacets {
-    if (facet->visible && qh NEWfacets)
-      continue;
-    sizvertices= qh_setsize (facet->vertices);
-    sizneighbors= qh_setsize (facet->neighbors);
-    sizridges= qh_setsize (facet->ridges);
-    zinc_(Znumfacets);
-    zadd_(Znumvertices, sizvertices);
-    zmax_(Zmaxvertices, sizvertices);
-    zadd_(Znumneighbors, sizneighbors);
-    zmax_(Zmaxneighbors, sizneighbors);
-    zadd_(Znummergetot, facet->nummerge);
-    i= facet->nummerge; /* avoid warnings */
-    zmax_(Znummergemax, i); 
-    if (!facet->simplicial) {
-      if (sizvertices == qh hull_dim) {
-	zinc_(Znowsimplicial);
-      }else {
-        zinc_(Znonsimplicial);
-      }
-    }
-    if (sizridges) {
-      zadd_(Znumridges, sizridges);
-      zmax_(Zmaxridges, sizridges);
-    }
-    zadd_(Zmemfacets, sizeof (facetT) + qh normal_size + 2*sizeof (setT) 
-       + SETelemsize * (sizneighbors + sizvertices));
-    if (facet->ridges) {
-      zadd_(Zmemridges,
-	 sizeof (setT) + SETelemsize * sizridges + sizridges * 
-         (sizeof (ridgeT) + sizeof (setT) + SETelemsize * (qh hull_dim-1))/2);
-    }
-    if (facet->outsideset)
-      zadd_(Zmempoints, sizeof (setT) + SETelemsize * qh_setsize (facet->outsideset));
-    if (facet->coplanarset)
-      zadd_(Zmempoints, sizeof (setT) + SETelemsize * qh_setsize (facet->coplanarset));
-    if (facet->seen) /* Delaunay upper envelope */
-      continue;
-    facet->seen= True;
-    FOREACHneighbor_(facet) {
-      if (neighbor == qh_DUPLICATEridge || neighbor == qh_MERGEridge
-	  || neighbor->seen || !facet->normal || !neighbor->normal)
-	continue;
-      dotproduct= qh_getangle(facet->normal, neighbor->normal);
-      zinc_(Zangle);
-      wadd_(Wangle, dotproduct);
-      wmax_(Wanglemax, dotproduct)
-      wmin_(Wanglemin, dotproduct)
-    }
-    if (facet->normal) {
-      FOREACHvertex_(facet->vertices) {
-        zinc_(Zdiststat);
-        qh_distplane(vertex->point, facet, &dist);
-        wmax_(Wvertexmax, dist);
-        wmin_(Wvertexmin, dist);
-      }
-    }
-  }
-  FORALLvertices {
-    if (vertex->deleted)
-      continue;
-    zadd_(Zmemvertices, sizeof (vertexT));
-    if (vertex->neighbors) {
-      sizneighbors= qh_setsize (vertex->neighbors);
-      zadd_(Znumvneighbors, sizneighbors);
-      zmax_(Zmaxvneighbors, sizneighbors);
-      zadd_(Zmemvertices, sizeof (vertexT) + SETelemsize * sizneighbors);
-    }
-  }
-  qh RANDOMdist= qh old_randomdist;
-} /* collectstatistics */
-#endif /* qh_KEEPstatistics */
-
-/*---------------------------------
-  
-  qh_freestatistics(  )
-    free memory used for statistics
-*/
-void qh_freestatistics (void) {
-
-#if qh_QHpointer
-  free (qh_qhstat);
-  qh_qhstat= NULL;
-#endif
-} /* freestatistics */
-
-/*---------------------------------
-  
-  qh_initstatistics(  )
-    allocate and initialize statistics
-
-  notes:
-    uses malloc() instead of qh_memalloc() since mem.c not set up yet
-*/
-void qh_initstatistics (void) {
-  int i;
-  realT realx;
-  int intx;
-
-#if qh_QHpointer
-  if (!(qh_qhstat= (qhstatT *)malloc (sizeof(qhstatT)))) {
-    fprintf (qhmem.ferr, "qhull error (qh_initstatistics): insufficient memory\n");
-    exit (1);  /* can not use qh_errexit() */
-  }
-#endif
-  
-  qhstat next= 0;
-  qh_allstatA();
-  qh_allstatB();
-  qh_allstatC();
-  qh_allstatD();
-  qh_allstatE();
-  qh_allstatE2();
-  qh_allstatF();
-  qh_allstatG();
-  qh_allstatH();
-  qh_allstatI();
-  if (qhstat next > sizeof(qhstat id)) {
-    fprintf (qhmem.ferr, "qhull error (qh_initstatistics): increase size of qhstat.id[].\n\
-      qhstat.next %d should be <= sizeof(qhstat id) %ld\n", qhstat next, sizeof(qhstat id));
-#if 0 /* for locating error, Znumridges should be duplicated */
-    for (i=0; i < ZEND; i++) {
-      int j;
-      for (j=i+1; j < ZEND; j++) {
-	if (qhstat id[i] == qhstat id[j]) {
-          fprintf (qhmem.ferr, "qhull error (qh_initstatistics): duplicated statistic %d at indices %d and %d\n", 
-	      qhstat id[i], i, j);
-	}
-      }
-    }
-#endif 
-    exit (1);  /* can not use qh_errexit() */
-  }
-  qhstat init[zinc].i= 0;
-  qhstat init[zadd].i= 0;
-  qhstat init[zmin].i= INT_MAX;
-  qhstat init[zmax].i= INT_MIN;
-  qhstat init[wadd].r= 0;
-  qhstat init[wmin].r= REALmax;
-  qhstat init[wmax].r= -REALmax;
-  for (i=0; i < ZEND; i++) {
-    if (qhstat type[i] > ZTYPEreal) {
-      realx= qhstat init[(unsigned char)(qhstat type[i])].r;
-      qhstat stats[i].r= realx;
-    }else if (qhstat type[i] != zdoc) {
-      intx= qhstat init[(unsigned char)(qhstat type[i])].i;
-      qhstat stats[i].i= intx;
-    }
-  }
-} /* initstatistics */
-
-/*---------------------------------
-  
-  qh_newstats(  )
-    returns True if statistics for zdoc
-
-  returns:
-    next zdoc
-*/
-boolT qh_newstats (int index, int *nextindex) {
-  boolT isnew= False;
-  int start, i;
-
-  if (qhstat type[qhstat id[index]] == zdoc) 
-    start= index+1;
-  else
-    start= index;
-  for (i= start; i < qhstat next && qhstat type[qhstat id[i]] != zdoc; i++) {
-    if (!qh_nostatistic(qhstat id[i]) && !qhstat printed[qhstat id[i]])
-	isnew= True;
-  }
-  *nextindex= i;
-  return isnew;
-} /* newstats */
-
-/*---------------------------------
-  
-  qh_nostatistic( index )
-    true if no statistic to print
-*/
-boolT qh_nostatistic (int i) {
-  
-  if ((qhstat type[i] > ZTYPEreal
-       &&qhstat stats[i].r == qhstat init[(unsigned char)(qhstat type[i])].r)
-      || (qhstat type[i] < ZTYPEreal
-	  &&qhstat stats[i].i == qhstat init[(unsigned char)(qhstat type[i])].i))
-    return True;
-  return False;
-} /* nostatistic */
-
-#if qh_KEEPstatistics
-/*---------------------------------
-  
-  qh_printallstatistics( fp, string )
-    print all statistics with header 'string'
-*/
-void qh_printallstatistics (FILE *fp, char *string) {
-
-  qh_allstatistics();
-  qh_collectstatistics();
-  qh_printstatistics (fp, string);
-  qh_memstatistics (fp);
-}
-
-
-/*---------------------------------
-  
-  qh_printstatistics( fp, string )
-    print statistics to a file with header 'string'
-    skips statistics with qhstat.printed[] (reset with qh_allstatistics)
-
-  see: 
-    qh_printallstatistics()
-*/
-void qh_printstatistics (FILE *fp, char *string) {
-  int i, k;
-  realT ave;
-  
-  if (qh num_points != qh num_vertices) {
-    wval_(Wpbalance)= 0;
-    wval_(Wpbalance2)= 0;
-  }else
-    wval_(Wpbalance2)= qh_stddev (zval_(Zpbalance), wval_(Wpbalance), 
-                                 wval_(Wpbalance2), &ave);
-  wval_(Wnewbalance2)= qh_stddev (zval_(Zprocessed), wval_(Wnewbalance), 
-                                 wval_(Wnewbalance2), &ave);
-  fprintf (fp, "\n\
-%s\n\
- qhull invoked by: %s | %s\n%s with options:\n%s\n", string, qh rbox_command, 
-     qh qhull_command, qh_VERSION, qh qhull_options);
-  fprintf (fp, "\nprecision constants:\n\
- %6.2g max. abs. coordinate in the (transformed) input ('Qbd:n')\n\
- %6.2g max. roundoff error for distance computation ('En')\n\
- %6.2g max. roundoff error for angle computations\n\
- %6.2g min. distance for outside points ('Wn')\n\
- %6.2g min. distance for visible facets ('Vn')\n\
- %6.2g max. distance for coplanar facets ('Un')\n\
- %6.2g max. facet width for recomputing centrum and area\n\
-", 
-  qh MAXabs_coord, qh DISTround, qh ANGLEround, qh MINoutside, 
-        qh MINvisible, qh MAXcoplanar, qh WIDEfacet);
-  if (qh KEEPnearinside)
-    fprintf(fp, "\
- %6.2g max. distance for near-inside points\n", qh NEARinside);
-  if (qh premerge_cos < REALmax/2) fprintf (fp, "\
- %6.2g max. cosine for pre-merge angle\n", qh premerge_cos);
-  if (qh PREmerge) fprintf (fp, "\
- %6.2g radius of pre-merge centrum\n", qh premerge_centrum);
-  if (qh postmerge_cos < REALmax/2) fprintf (fp, "\
- %6.2g max. cosine for post-merge angle\n", qh postmerge_cos);
-  if (qh POSTmerge) fprintf (fp, "\
- %6.2g radius of post-merge centrum\n", qh postmerge_centrum);
-  fprintf (fp, "\
- %6.2g max. distance for merging two simplicial facets\n\
- %6.2g max. roundoff error for arithmetic operations\n\
- %6.2g min. denominator for divisions\n\
-  zero diagonal for Gauss: ", qh ONEmerge, REALepsilon, qh MINdenom);
-  for (k=0; k < qh hull_dim; k++)
-    fprintf (fp, "%6.2e ", qh NEARzero[k]);
-  fprintf (fp, "\n\n");
-  for (i=0 ; i < qhstat next; ) 
-    qh_printstats (fp, i, &i);
-} /* printstatistics */
-#endif /* qh_KEEPstatistics */
-
-/*---------------------------------
-  
-  qh_printstatlevel( fp, id )
-    print level information for a statistic
-
-  notes:
-    nop if id >= ZEND, printed, or same as initial value
-*/
-void qh_printstatlevel (FILE *fp, int id, int start) {
-#define NULLfield "       "
-
-  if (id >= ZEND || qhstat printed[id])
-    return;
-  if (qhstat type[id] == zdoc) {
-    fprintf (fp, "%s\n", qhstat doc[id]);
-    return;
-  }
-  start= 0; /* not used */
-  if (qh_nostatistic(id) || !qhstat doc[id])
-    return;
-  qhstat printed[id]= True;
-  if (qhstat count[id] != -1 
-      && qhstat stats[(unsigned char)(qhstat count[id])].i == 0)
-    fprintf (fp, " *0 cnt*");
-  else if (qhstat type[id] >= ZTYPEreal && qhstat count[id] == -1)
-    fprintf (fp, "%7.2g", qhstat stats[id].r);
-  else if (qhstat type[id] >= ZTYPEreal && qhstat count[id] != -1)
-    fprintf (fp, "%7.2g", qhstat stats[id].r/ qhstat stats[(unsigned char)(qhstat count[id])].i);
-  else if (qhstat type[id] < ZTYPEreal && qhstat count[id] == -1)
-    fprintf (fp, "%7d", qhstat stats[id].i);
-  else if (qhstat type[id] < ZTYPEreal && qhstat count[id] != -1)
-    fprintf (fp, "%7.3g", (realT) qhstat stats[id].i / qhstat stats[(unsigned char)(qhstat count[id])].i);
-  fprintf (fp, " %s\n", qhstat doc[id]);
-} /* printstatlevel */
-
-
-/*---------------------------------
-  
-  qh_printstats( fp, index, nextindex )
-    print statistics for a zdoc group
-
-  returns:
-    next zdoc if non-null
-*/
-void qh_printstats (FILE *fp, int index, int *nextindex) {
-  int j, nexti;
-
-  if (qh_newstats (index, &nexti)) {
-    fprintf (fp, "\n");
-    for (j=index; j--------------------------------
-  
-  qh_stddev( num, tot, tot2, ave )
-    compute the standard deviation and average from statistics
-
-    tot2 is the sum of the squares
-  notes:
-    computes r.m.s.: 
-      (x-ave)^2 
-      == x^2 - 2x tot/num +   (tot/num)^2
-      == tot2 - 2 tot tot/num + tot tot/num 
-      == tot2 - tot ave
-*/
-realT qh_stddev (int num, realT tot, realT tot2, realT *ave) {
-  realT stddev;
-
-  *ave= tot/num;
-  stddev= sqrt (tot2/num - *ave * *ave);
-  return stddev;
-} /* stddev */
-
-#endif /* qh_KEEPstatistics */ 
-
-#if !qh_KEEPstatistics
-void    qh_collectstatistics (void) {}
-void    qh_printallstatistics (FILE *fp, char *string) {};
-void    qh_printstatistics (FILE *fp, char *string) {}
-#endif
-
diff --git a/extern/qhull/src/stat.h b/extern/qhull/src/stat.h
deleted file mode 100644
index 1dae54ed21d..00000000000
--- a/extern/qhull/src/stat.h
+++ /dev/null
@@ -1,520 +0,0 @@
-  /*
  ---------------------------------
-
-   stat.h 
-     contains all statistics that are collected for qhull
-
-   see qh-stat.htm and stat.c
-
-   copyright (c) 1993-2002, The Geometry Center
-
-   recompile qhull if you change this file
-
-   Integer statistics are Z* while real statistics are W*.  
-
-   define maydebugx to call a routine at every statistic event
-
-*/
-
-#ifndef qhDEFstat
-#define qhDEFstat 1
-
-
-/*---------------------------------
-
-  qh_KEEPstatistics
-    0 turns off statistic gathering (except zzdef/zzinc/zzadd/zzval/wwval)
-*/
-#ifndef qh_KEEPstatistics
-#define qh_KEEPstatistics 1
-#endif
-
-/*---------------------------------
-
-  Zxxx for integers, Wxxx for reals
-
-  notes:
-    be sure that all statistics are defined in stat.c
-      otherwise initialization may core dump
-    can pick up all statistics by:
-      grep '[zw].*_[(][ZW]' *.c >z.x
-    remove trailers with query">-
-    remove leaders with  query-replace-regexp [ ^I]+  (
-*/
-#if qh_KEEPstatistics
-enum statistics {     /* alphabetical after Z/W */
-    Zacoplanar,
-    Wacoplanarmax,
-    Wacoplanartot,
-    Zangle,
-    Wangle,
-    Wanglemax,
-    Wanglemin,
-    Zangletests,
-    Wareatot,
-    Wareamax,
-    Wareamin,
-    Zavoidold,
-    Wavoidoldmax,
-    Wavoidoldtot,
-    Zback0,
-    Zbestcentrum,
-    Zbestdist,
-    Zcentrumtests,
-    Zcheckpart,
-    Zcomputefurthest,
-    Zconcave,
-    Wconcavemax,
-    Wconcavetot,
-    Zconcaveridges,
-    Zconcaveridge,
-    Zcoplanar,
-    Wcoplanarmax,
-    Wcoplanartot,
-    Zcoplanarangle,
-    Zcoplanarcentrum,
-    Zcoplanarhorizon,
-    Zcoplanarinside,
-    Zcoplanarpart,
-    Zcoplanarridges,
-    Wcpu,
-    Zcyclefacetmax,
-    Zcyclefacettot,
-    Zcyclehorizon,
-    Zcyclevertex,
-    Zdegen,
-    Wdegenmax,
-    Wdegentot,
-    Zdegenvertex,
-    Zdelfacetdup, 
-    Zdelridge,
-    Zdelvertextot,
-    Zdelvertexmax,
-    Zdetsimplex,
-    Zdistcheck,
-    Zdistconvex,
-    Zdistgood,
-    Zdistio,
-    Zdistplane,
-    Zdiststat,
-    Zdistvertex,
-    Zdistzero,
-    Zdoc1,
-    Zdoc2,
-    Zdoc3,
-    Zdoc4,
-    Zdoc5,
-    Zdoc6,
-    Zdoc7,
-    Zdoc8,
-    Zdoc9,
-    Zdoc10,
-    Zdoc11,
-    Zdoc12,
-    Zdropdegen,
-    Zdropneighbor,
-    Zdupflip,
-    Zduplicate,
-    Wduplicatemax,
-    Wduplicatetot,
-    Zdupridge,
-    Zdupsame,
-    Zflipped, 
-    Wflippedmax, 
-    Wflippedtot, 
-    Zflippedfacets,
-    Zfindbest,
-    Zfindbestmax,
-    Zfindbesttot,
-    Zfindcoplanar,
-    Zfindfail,
-    Zfindhorizon,
-    Zfindhorizonmax,
-    Zfindhorizontot,
-    Zfindjump,
-    Zfindnew,
-    Zfindnewmax,
-    Zfindnewtot,
-    Zfindnewjump,
-    Zfindnewsharp,
-    Zgauss0,
-    Zgoodfacet,
-    Zhashlookup,
-    Zhashridge,
-    Zhashridgetest,
-    Zhashtests,
-    Zinsidevisible,
-    Zintersect,
-    Zintersectfail,
-    Zintersectmax,
-    Zintersectnum,
-    Zintersecttot,
-    Zmaxneighbors,
-    Wmaxout,
-    Wmaxoutside,
-    Zmaxridges,
-    Zmaxvertex,
-    Zmaxvertices,
-    Zmaxvneighbors,
-    Zmemfacets,
-    Zmempoints,
-    Zmemridges,
-    Zmemvertices,
-    Zmergeflipdup,
-    Zmergehorizon,
-    Zmergeinittot,
-    Zmergeinitmax,
-    Zmergeinittot2,
-    Zmergeintohorizon,
-    Zmergenew,
-    Zmergesettot,
-    Zmergesetmax,
-    Zmergesettot2,
-    Zmergesimplex,
-    Zmergevertex,
-    Wmindenom,
-    Wminvertex,
-    Zminnorm,
-    Zmultiridge,
-    Znearlysingular,
-    Zneighbor,
-    Wnewbalance,
-    Wnewbalance2,
-    Znewfacettot,
-    Znewfacetmax,
-    Znewvertex,
-    Wnewvertex,
-    Wnewvertexmax,
-    Znoarea,
-    Znonsimplicial,
-    Znowsimplicial,
-    Znotgood,
-    Znotgoodnew,
-    Znotmax,
-    Znumfacets,
-    Znummergemax,
-    Znummergetot,
-    Znumneighbors,
-    Znumridges,
-    Znumvertices,
-    Znumvisibility,
-    Znumvneighbors,
-    Zonehorizon,
-    Zpartangle,
-    Zpartcoplanar,
-    Zpartflip,
-    Zparthorizon,
-    Zpartinside,
-    Zpartition, 
-    Zpartitionall,
-    Zpartnear,
-    Zpbalance,
-    Wpbalance,
-    Wpbalance2, 
-    Zpostfacets, 
-    Zpremergetot,
-    Zprocessed,
-    Zremvertex,
-    Zremvertexdel,
-    Zrenameall,
-    Zrenamepinch,
-    Zrenameshare,
-    Zretry,
-    Wretrymax,
-    Zridge,
-    Wridge,
-    Wridgemax,
-    Zridge0,
-    Wridge0,
-    Wridge0max,
-    Zridgemid,
-    Wridgemid,
-    Wridgemidmax,
-    Zridgeok,
-    Wridgeok,
-    Wridgeokmax,
-    Zsearchpoints,
-    Zsetplane,
-    Ztestvneighbor,
-    Ztotcheck,
-    Ztothorizon,
-    Ztotmerge,
-    Ztotpartcoplanar,
-    Ztotpartition,
-    Ztotridges,
-    Ztotvertices,
-    Ztotvisible,
-    Ztricoplanar,
-    Ztricoplanarmax,
-    Ztricoplanartot,
-    Ztridegen,
-    Ztrimirror,
-    Ztrinull,
-    Wvertexmax,
-    Wvertexmin,
-    Zvertexridge,
-    Zvertexridgetot,
-    Zvertexridgemax,
-    Zvertices,
-    Zvisfacettot,
-    Zvisfacetmax,
-    Zvisvertextot,
-    Zvisvertexmax,
-    Zwidefacet,
-    Zwidevertices,
-    ZEND};
-
-/*---------------------------------
-
-  Zxxx/Wxxx statistics that remain defined if qh_KEEPstatistics=0
-
-  notes:
-    be sure to use zzdef, zzinc, etc. with these statistics (no double checking!)
-*/
-#else
-enum statistics {     /* for zzdef etc. macros */
-  Zback0,
-  Zbestdist,
-  Zcentrumtests,
-  Zcheckpart,
-  Zconcaveridges,
-  Zcoplanarhorizon,
-  Zcoplanarpart,
-  Zcoplanarridges,
-  Zcyclefacettot,
-  Zcyclehorizon,
-  Zdelvertextot,
-  Zdistcheck,
-  Zdistconvex,
-  Zdistzero,
-  Zdoc1,
-  Zdoc2,
-  Zdoc3,
-  Zdoc11,
-  Zflippedfacets,
-  Zgauss0,
-  Zminnorm,
-  Zmultiridge,
-  Znearlysingular,
-  Wnewvertexmax,
-  Znumvisibility,
-  Zpartcoplanar,
-  Zpartition,
-  Zpartitionall,
-  Zprocessed,
-  Zretry,
-  Zridge,
-  Wridge,
-  Wridgemax,
-  Zridge0,
-  Wridge0,
-  Wridge0max,
-  Zridgemid,
-  Wridgemid,
-  Wridgemidmax,
-  Zridgeok,
-  Wridgeok,
-  Wridgeokmax,
-  Zsetplane,
-  Ztotmerge,
-    ZEND};
-#endif
-
-/*---------------------------------
-  
-  ztype
-    the type of a statistic sets its initial value.  
-
-  notes:
-    The type should be the same as the macro for collecting the statistic
-*/
-enum ztypes {zdoc,zinc,zadd,zmax,zmin,ZTYPEreal,wadd,wmax,wmin,ZTYPEend};
-
-/*========== macros and constants =============*/
-
-/*----------------------------------
-  
-  MAYdebugx
-    define as maydebug() to be called frequently for error trapping
-*/
-#define MAYdebugx 
-
-/*----------------------------------
-  
-  zzdef_, zdef_( type, name, doc, -1)
-    define a statistic (assumes 'qhstat.next= 0;')
-
-  zdef_( type, name, doc, count)
-    define an averaged statistic
-    printed as name/count
-*/
-#define zzdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \
-   qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype
-#if qh_KEEPstatistics
-#define zdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \
-   qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype
-#else
-#define zdef_(type,name,doc,count)
-#endif
-
-/*----------------------------------
-  
-  zzinc_( name ), zinc_( name)
-    increment an integer statistic
-*/
-#define zzinc_(id) {MAYdebugx; qhstat stats[id].i++;}
-#if qh_KEEPstatistics
-#define zinc_(id) {MAYdebugx; qhstat stats[id].i++;}
-#else
-#define zinc_(id) {}
-#endif
-
-/*----------------------------------
-  
-  zzadd_( name, value ), zadd_( name, value ), wadd_( name, value )
-    add value to an integer or real statistic
-*/
-#define zzadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);}
-#define wwadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);}
-#if qh_KEEPstatistics
-#define zadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);}
-#define wadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);}
-#else
-#define zadd_(id, val) {}
-#define wadd_(id, val) {}
-#endif
-
-/*----------------------------------
-
-  zzval_( name ), zval_( name ), wwval_( name )
-    set or return value of a statistic
-*/
-#define zzval_(id) ((qhstat stats[id]).i)
-#define wwval_(id) ((qhstat stats[id]).r)
-#if qh_KEEPstatistics
-#define zval_(id) ((qhstat stats[id]).i)
-#define wval_(id) ((qhstat stats[id]).r)
-#else
-#define zval_(id) qhstat tempi
-#define wval_(id) qhstat tempr
-#endif
-
-/*----------------------------------
-
-  zmax_( id, val ), wmax_( id, value )
-    maximize id with val
-*/
-#define wwmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));}
-#if qh_KEEPstatistics
-#define zmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].i,(val));}
-#define wmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));}
-#else
-#define zmax_(id, val) {}
-#define wmax_(id, val) {}
-#endif
-
-/*----------------------------------
-
-  zmin_( id, val ), wmin_( id, value )
-    minimize id with val
-*/
-#if qh_KEEPstatistics
-#define zmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].i,(val));}
-#define wmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].r,(val));}
-#else
-#define zmin_(id, val) {}
-#define wmin_(id, val) {}
-#endif
-
-/*================== stat.h types ==============*/
-
-
-/*----------------------------------
- 
-  intrealT
-    union of integer and real, used for statistics
-*/
-typedef union intrealT intrealT;    /* union of int and realT */
-union intrealT {
-    int i;
-    realT r;
-};
-
-/*----------------------------------
-  
-  qhstat
-    global data structure for statistics
-  
-  notes:
-   access to qh_qhstat is via the "qhstat" macro.  There are two choices
-   qh_QHpointer = 1     access globals via a pointer
-                        enables qh_saveqhull() and qh_restoreqhull()
-		= 0     qh_qhstat is a static data structure
-		        only one instance of qhull() can be active at a time
-			default value
-   qh_QHpointer is defined in qhull.h
-
-   allocated in stat.c
-*/
-typedef struct qhstatT qhstatT; 
-#if qh_QHpointer
-#define qhstat qh_qhstat->
-extern qhstatT *qh_qhstat;
-#else
-#define qhstat qh_qhstat.
-extern qhstatT qh_qhstat; 
-#endif
-struct qhstatT {  
-  intrealT   stats[ZEND];     /* integer and real statistics */
-  unsigned   char id[ZEND+10]; /* id's in print order */
-  char      *doc[ZEND];       /* array of documentation strings */
-  short int  count[ZEND];     /* -1 if none, else index of count to use */
-  char       type[ZEND];      /* type, see ztypes above */
-  char       printed[ZEND];   /* true, if statistic has been printed */
-  intrealT   init[ZTYPEend];  /* initial values by types, set initstatistics */
-
-  int        next;            /* next index for zdef_ */
-  int        precision;       /* index for precision problems */
-  int        vridges;         /* index for Voronoi ridges */
-  int        tempi;
-  realT      tempr;
-};
-
-/*========== function prototypes ===========*/
-
-void    qh_allstatA(void);
-void    qh_allstatB(void);
-void    qh_allstatC(void);
-void    qh_allstatD(void);
-void    qh_allstatE(void);
-void    qh_allstatE2(void);
-void    qh_allstatF(void);
-void    qh_allstatG(void);
-void    qh_allstatH(void);
-void    qh_allstatI(void);
-void    qh_allstatistics (void);
-void    qh_collectstatistics (void);
-void	qh_freestatistics (void);
-void    qh_initstatistics (void);
-boolT 	qh_newstats (int index, int *nextindex);
-boolT 	qh_nostatistic (int i);
-void    qh_printallstatistics (FILE *fp, char *string);
-void    qh_printstatistics (FILE *fp, char *string);
-void  	qh_printstatlevel (FILE *fp, int id, int start);
-void  	qh_printstats (FILE *fp, int index, int *nextindex);
-realT   qh_stddev (int num, realT tot, realT tot2, realT *ave);
-
-#endif   /* qhDEFstat */
diff --git a/extern/qhull/src/unix.c b/extern/qhull/src/unix.c
deleted file mode 100644
index 5ec5feab16c..00000000000
--- a/extern/qhull/src/unix.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
  ---------------------------------
-
-   unix.c
-     command line interface to qhull
-	 includes SIOUX interface for Macintoshes
-
-   see qh-qhull.htm
-
-   copyright (c) 1993-2002, The Geometry Center
-*/
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include "qhull.h"
-#include "mem.h"
-#include "qset.h"
-
-#if __MWERKS__ && __POWERPC__
-#include 
-#include 
-#include 
-#include 
-
-#elif __cplusplus
-extern "C" {
-  int isatty (int);
-}
-
-#elif _MSC_VER
-#include 
-#define isatty _isatty
-
-#else
-int isatty (int);  /* returns 1 if stdin is a tty
-		   if "Undefined symbol" this can be deleted along with call in main() */
-#endif
-
-/*---------------------------------
-
-  qh_prompt 
-    long prompt for qhull
-    
-  see:
-    concise prompt below
-*/  
-char qh_prompta[]= "\n\
-qhull- compute convex hulls and related structures.\n\
-    http://www.geom.umn.edu/software/qhull  %s\n\
-\n\
-input (stdin):\n\
-    first lines: dimension and number of points (or vice-versa).\n\
-    other lines: point coordinates, best if one point per line\n\
-    comments:    start with a non-numeric character\n\
-    halfspaces:  use dim plus one and put offset after coefficients.\n\
-                 May be preceeded by a single interior point ('H').\n\
-\n\
-options:\n\
-    d    - Delaunay triangulation by lifting points to a paraboloid\n\
-    d Qu - furthest-site Delaunay triangulation (upper convex hull)\n\
-    v    - Voronoi diagram (dual of the Delaunay triangulation)\n\
-    v Qu - furthest-site Voronoi diagram\n\
-    Hn,n,... - halfspace intersection about point [n,n,0,...]\n\
-    Qt   - triangulated output\n\
-    QJ   - joggled input instead of merged facets\n\
-    Qc   - keep coplanar points with nearest facet\n\
-    Qi   - keep interior points with nearest facet\n\
-\n\
-Qhull control options:\n\
-    Qbk:n   - scale coord k so that low bound is n\n\
-      QBk:n - scale coord k so that upper bound is n (QBk is %2.2g)\n\
-    QbB  - scale input to unit cube centered at the origin\n\
-    Qbb  - scale last coordinate to [0,m] for Delaunay triangulations\n\
-    Qbk:0Bk:0 - remove k-th coordinate from input\n\
-    QJn  - randomly joggle input in range [-n,n]\n\
-    QRn  - random rotation (n=seed, n=0 time, n=-1 time/no rotate)\n\
-%s%s%s%s";  /* split up qh_prompt for Visual C++ */
-char qh_promptb[]= "\
-    Qf   - partition point to furthest outside facet\n\
-    Qg   - only build good facets (needs 'QGn', 'QVn', or 'PdD')\n\
-    Qm   - only process points that would increase max_outside\n\
-    Qr   - process random outside points instead of furthest ones\n\
-    Qs   - search all points for the initial simplex\n\
-    Qu   - for 'd' or 'v', compute upper hull without point at-infinity\n\
-              returns furthest-site Delaunay triangulation\n\
-    Qv   - test vertex neighbors for convexity\n\
-    Qx   - exact pre-merges (skips coplanar and angle-coplanar facets)\n\
-    Qz   - add point-at-infinity to Delaunay triangulation\n\
-    QGn  - good facet if visible from point n, -n for not visible\n\
-    QVn  - good facet if it includes point n, -n if not\n\
-    Q0   - turn off default premerge with 'C-0'/'Qx'\n\
-    Q1	   - sort merges by type instead of angle\n\
-    Q2   - merge all non-convex at once instead of independent sets\n\
-    Q3   - do not merge redundant vertices\n\
-    Q4   - avoid old->new merges\n\
-    Q5   - do not correct outer planes at end of qhull\n\
-    Q6   - do not pre-merge concave or coplanar facets\n\
-    Q7   - depth-first processing instead of breadth-first\n\
-    Q8   - do not process near-inside points\n\
-    Q9   - process furthest of furthest points\n\
-    Q10  - no special processing for narrow distributions\n\
-    Q11  - copy normals and recompute centrums for tricoplanar facets\n\
-\n\
-";
-char qh_promptc[]= "\
-Topts- Trace options:\n\
-    T4   - trace at level n, 4=all, 5=mem/gauss, -1= events\n\
-    Tc   - check frequently during execution\n\
-    Ts   - print statistics\n\
-    Tv   - verify result: structure, convexity, and point inclusion\n\
-    Tz   - send all output to stdout\n\
-    TFn  - report summary when n or more facets created\n\
-    TI file - input data from file, no spaces or single quotes\n\
-    TO file - output results to file, may be enclosed in single quotes\n\
-    TPn  - turn on tracing when point n added to hull\n\
-     TMn - turn on tracing at merge n\n\
-     TWn - trace merge facets when width > n\n\
-    TRn  - rerun qhull n times.  Use with 'QJn'\n\
-    TVn  - stop qhull after adding point n, -n for before (see TCn)\n\
-     TCn - stop qhull after building cone for point n (see TVn)\n\
-\n\
-Precision options:\n\
-    Cn   - radius of centrum (roundoff added).  Merge facets if non-convex\n\
-     An  - cosine of maximum angle.  Merge facets if cosine > n or non-convex\n\
-           C-0 roundoff, A-0.99/C-0.01 pre-merge, A0.99/C0.01 post-merge\n\
-    En   - max roundoff error for distance computation\n\
-    Rn   - randomly perturb computations by a factor of [1-n,1+n]\n\
-    Vn   - min distance above plane for a visible facet (default 3C-n or En)\n\
-    Un   - max distance below plane for a new, coplanar point (default Vn)\n\
-    Wn   - min facet width for outside point (before roundoff, default 2Vn)\n\
-\n\
-Output formats (may be combined; if none, produces a summary to stdout):\n\
-    f    - facet dump\n\
-    G    - Geomview output (see below)\n\
-    i    - vertices incident to each facet\n\
-    m    - Mathematica output (2-d and 3-d)\n\
-    o    - OFF format (dim, points and facets; Voronoi regions)\n\
-    n    - normals with offsets\n\
-    p    - vertex coordinates or Voronoi vertices (coplanar points if 'Qc')\n\
-    s    - summary (stderr)\n\
-\n\
-";
-char qh_promptd[]= "\
-More formats:\n\
-    Fa   - area for each facet\n\
-    FA   - compute total area and volume for option 's'\n\
-    Fc   - count plus coplanar points for each facet\n\
-           use 'Qc' (default) for coplanar and 'Qi' for interior\n\
-    FC   - centrum or Voronoi center for each facet\n\
-    Fd   - use cdd format for input (homogeneous with offset first)\n\
-    FD   - use cdd format for numeric output (offset first)\n\
-    FF   - facet dump without ridges\n\
-    Fi   - inner plane for each facet\n\
-           for 'v', separating hyperplanes for bounded Voronoi regions\n\
-    FI   - ID of each facet\n\
-    Fm   - merge count for each facet (511 max)\n\
-    Fn   - count plus neighboring facets for each facet\n\
-    FN   - count plus neighboring facets for each point\n\
-    Fo   - outer plane (or max_outside) for each facet\n\
-           for 'v', separating hyperplanes for unbounded Voronoi regions\n\
-    FO   - options and precision constants\n\
-    Fp   - dim, count, and intersection coordinates (halfspace only)\n\
-    FP   - nearest vertex and distance for each coplanar point\n\
-    FQ   - command used for qhull\n\
-    Fs   - summary: #int (8), dimension, #points, tot vertices, tot facets,\n\
-                      output: #vertices, #facets, #coplanars, #nonsimplicial\n\
-                    #real (2), max outer plane, min vertex\n\
-    FS   - sizes:   #int (0)\n\
-                    #real(2) tot area, tot volume\n\
-    Ft   - triangulation with centrums for non-simplicial facets (OFF format)\n\
-    Fv   - count plus vertices for each facet\n\
-           for 'v', Voronoi diagram as Voronoi vertices for pairs of sites\n\
-    FV   - average of vertices (a feasible point for 'H')\n\
-    Fx   - extreme points (in order for 2-d)\n\
-\n\
-";
-char qh_prompte[]= "\
-Geomview options (2-d, 3-d, and 4-d; 2-d Voronoi)\n\
-    Ga   - all points as dots\n\
-     Gp  -  coplanar points and vertices as radii\n\
-     Gv  -  vertices as spheres\n\
-    Gi   - inner planes only\n\
-     Gn  -  no planes\n\
-     Go  -  outer planes only\n\
-    Gc   - centrums\n\
-    Gh   - hyperplane intersections\n\
-    Gr   - ridges\n\
-    GDn  - drop dimension n in 3-d and 4-d output\n\
-    Gt   - for 3-d 'd', transparent outer ridges\n\
-\n\
-Print options:\n\
-    PAn  - keep n largest facets by area\n\
-    Pdk:n - drop facet if normal[k] <= n (default 0.0)\n\
-    PDk:n - drop facet if normal[k] >= n\n\
-    Pg   - print good facets (needs 'QGn' or 'QVn')\n\
-    PFn  - keep facets whose area is at least n\n\
-    PG   - print neighbors of good facets\n\
-    PMn  - keep n facets with most merges\n\
-    Po   - force output.  If error, output neighborhood of facet\n\
-    Pp   - do not report precision problems\n\
-\n\
-    .    - list of all options\n\
-    -    - one line descriptions of all options\n\
-";
-/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
-
-/*---------------------------------
-
-  qh_prompt2
-    synopsis for qhull
-*/
-char qh_prompt2[]= "\n\
-qhull- compute convex hulls and related structures.  %s\n\
-    input (stdin): dimension, n, point coordinates\n\
-    comments start with a non-numeric character\n\
-    halfspace: use dim+1 and put offsets after coefficients\n\
-\n\
-options (qh-quick.htm):\n\
-    d    - Delaunay triangulation by lifting points to a paraboloid\n\
-    d Qu - furthest-site Delaunay triangulation (upper convex hull)\n\
-    v    - Voronoi diagram as the dual of the Delaunay triangulation\n\
-    v Qu - furthest-site Voronoi diagram\n\
-    H1,1 - Halfspace intersection about [1,1,0,...] via polar duality\n\
-    Qt   - triangulated output\n\
-    QJ   - joggled input instead of merged facets\n\
-    Tv   - verify result: structure, convexity, and point inclusion\n\
-    .    - concise list of all options\n\
-    -    - one-line description of all options\n\
-\n\
-Output options (subset):\n\
-    s    - summary of results (default)\n\
-    i    - vertices incident to each facet\n\
-    n    - normals with offsets\n\
-    p    - vertex coordinates (if 'Qc', includes coplanar points)\n\
-           if 'v', Voronoi vertices\n\
-    Fp   - halfspace intersections\n\
-    Fx   - extreme points (convex hull vertices)\n\
-    FA   - compute total area and volume\n\
-    o    - OFF format (if 'v', outputs Voronoi regions)\n\
-    G    - Geomview output (2-d, 3-d and 4-d)\n\
-    m    - Mathematica output (2-d and 3-d)\n\
-    QVn  - print facets that include point n, -n if not\n\
-    TO file- output results to file, may be enclosed in single quotes\n\
-\n\
-examples:\n\
-    rbox c d D2 | qhull Qc s f Fx | more      rbox 1000 s | qhull Tv s FA\n\
-    rbox 10 D2 | qhull d QJ s i TO result     rbox 10 D2 | qhull v QJ p\n\
-    rbox 10 D2 | qhull d Qu QJ m              rbox 10 D2 | qhull v Qu QJ o\n\
-    rbox c | qhull n                          rbox c | qhull FV n | qhull H Fp\n\
-    rbox d D12 | qhull QR0 FA                 rbox c D7 | qhull FA TF1000\n\
-    rbox y 1000 W0 | qhull                    rbox 10 | qhull v QJ o Fv\n\
-\n\
-";
-/* for opts, don't assign 'e' or 'E' to a flag (already used for exponent) */
-
-/*---------------------------------
-
-  qh_prompt3
-    concise prompt for qhull
-*/
-char qh_prompt3[]= "\n\
-Qhull %s.\n\
-Except for 'F.' and 'PG', upper-case options take an argument.\n\
-\n\
- delaunay       voronoi	       Geomview       Halfspace      facet_dump\n\
- incidences     mathematica    normals        OFF_format     points\n\
- summary\n\
-\n\
- Farea          FArea-total    Fcoplanars     FCentrums      Fd-cdd-in\n\
- FD-cdd-out     FF-dump-xridge Finner         FIDs           Fmerges\n\
- Fneighbors     FNeigh-vertex  Fouter         FOptions       Fpoint-intersect\n\
- FPoint_near    FQhull         Fsummary       FSize          Ftriangles\n\
- Fvertices      Fvoronoi       FVertex-ave    Fxtremes\n\
-\n\
- Gvertices      Gpoints        Gall_points    Gno_planes     Ginner\n\
- Gcentrums      Ghyperplanes   Gridges        Gouter         GDrop_dim\n\
- Gtransparent\n\
-\n\
- PArea-keep     Pdrop d0:0D0   Pgood          PFacet_area_keep\n\
- PGood_neighbors PMerge-keep   Poutput_forced Pprecision_not\n\
-\n\
- QbBound 0:0.5  Qbk:0Bk:0_drop QbB-scale-box  Qbb-scale-last Qcoplanar\n\
- Qfurthest      Qgood_only     QGood_point    Qinterior      Qmax_out\n\
- QJoggle        Qrandom        QRotate        Qsearch_1st    Qtriangulate\n\
- QupperDelaunay QVertex_good   Qvneighbors    Qxact_merge    Qzinfinite\n\
-\n\
- Q0_no_premerge Q1_no_angle    Q2_no_independ Q3_no_redundant Q4_no_old\n\
- Q5_no_check_out Q6_no_concave Q7_depth_first Q8_no_near_in  Q9_pick_furthest\n\
- Q10_no_narrow  Q11_trinormals\n\
-\n\
- T4_trace       Tcheck_often   Tstatistics    Tverify        Tz_stdout\n\
- TFacet_log     TInput_file    TPoint_trace   TMerge_trace   TOutput_file\n\
- TRerun         TWide_trace    TVertex_stop   TCone_stop\n\
-\n\
- Angle_max      Centrum_size   Error_round    Random_dist    Visible_min\n\
- Ucoplanar_max  Wide_outside\n\
-";
-
-/*---------------------------------
-
-  main( argc, argv )
-    processes the command line, calls qhull() to do the work, and exits
-
-  design:
-    initializes data structures
-    reads points
-    finishes initialization
-    computes convex hull and other structures
-    checks the result
-    writes the output
-    frees memory
-*/
-int main(int argc, char *argv[]) {
-  int curlong, totlong; /* used !qh_NOmem */
-  int exitcode, numpoints, dim;
-  coordT *points;
-  boolT ismalloc;
-
-#if __MWERKS__ && __POWERPC__
-  char inBuf[BUFSIZ], outBuf[BUFSIZ], errBuf[BUFSIZ];
-  SIOUXSettings.showstatusline= false;
-  SIOUXSettings.tabspaces= 1;
-  SIOUXSettings.rows= 40;
-  if (setvbuf (stdin, inBuf, _IOFBF, sizeof(inBuf)) < 0   /* w/o, SIOUX I/O is slow*/
-  || setvbuf (stdout, outBuf, _IOFBF, sizeof(outBuf)) < 0
-  || (stdout != stderr && setvbuf (stderr, errBuf, _IOFBF, sizeof(errBuf)) < 0))
-    fprintf (stderr, "qhull internal warning (main): could not change stdio to fully buffered.\n");
-  argc= ccommand(&argv);
-#endif
-
-  if ((argc == 1) && isatty( 0 /*stdin*/)) {
-    fprintf(stdout, qh_prompt2, qh_VERSION);
-    exit(qh_ERRnone);
-  }
-  if (argc > 1 && *argv[1] == '-' && !*(argv[1]+1)) {
-    fprintf(stdout, qh_prompta, qh_VERSION, qh_DEFAULTbox,
-		qh_promptb, qh_promptc, qh_promptd, qh_prompte);
-    exit(qh_ERRnone);
-  }
-  if (argc >1 && *argv[1] == '.' && !*(argv[1]+1)) {
-    fprintf(stdout, qh_prompt3, qh_VERSION);
-    exit(qh_ERRnone);
-  }
-  qh_init_A (stdin, stdout, stderr, argc, argv);  /* sets qh qhull_command */
-  exitcode= setjmp (qh errexit); /* simple statement for CRAY J916 */
-  if (!exitcode) {
-    qh_initflags (qh qhull_command);
-    points= qh_readpoints (&numpoints, &dim, &ismalloc);
-    qh_init_B (points, numpoints, dim, ismalloc);
-    qh_qhull();
-    qh_check_output();
-    qh_produce_output();
-    if (qh VERIFYoutput && !qh FORCEoutput && !qh STOPpoint && !qh STOPcone)
-      qh_check_points();
-    exitcode= qh_ERRnone;
-  }
-  qh NOerrexit= True;  /* no more setjmp */
-#ifdef qh_NOmem
-  qh_freeqhull( True);
-#else
-  qh_freeqhull( False);
-  qh_memfreeshort (&curlong, &totlong);
-  if (curlong || totlong)
-    fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
-       totlong, curlong);
-#endif
-  return exitcode;
-} /* main */
-
diff --git a/extern/qhull/src/user.c b/extern/qhull/src/user.c
deleted file mode 100644
index 94b31aaf99f..00000000000
--- a/extern/qhull/src/user.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
  ---------------------------------
-
-   user.c 
-   user redefinable functions
-
-   see README.txt  see COPYING.txt for copyright information.
-
-   see qhull.h for data structures, macros, and user-callable functions.
-
-   see user_eg.c, unix.c, and qhull_interface.cpp for examples.
-
-   see user.h for user-definable constants
-
-      use qh_NOmem in mem.h to turn off memory management
-      use qh_NOmerge in user.h to turn off facet merging
-      set qh_KEEPstatistics in user.h to 0 to turn off statistics
-
-   This is unsupported software.  You're welcome to make changes,
-   but you're on your own if something goes wrong.  Use 'Tc' to
-   check frequently.  Usually qhull will report an error if 
-   a data structure becomes inconsistent.  If so, it also reports
-   the last point added to the hull, e.g., 102.  You can then trace
-   the execution of qhull with "T4P102".  
-
-   Please report any errors that you fix to qhull@geom.umn.edu
-
-   call_qhull is a template for calling qhull from within your application
-
-   if you recompile and load this module, then user.o will not be loaded
-   from qhull.a
-
-   you can add additional quick allocation sizes in qh_user_memsizes
-
-   if the other functions here are redefined to not use qh_print...,
-   then io.o will not be loaded from qhull.a.  See user_eg.c for an
-   example.  We recommend keeping io.o for the extra debugging 
-   information it supplies.
-*/
-
-#include "qhull_a.h" 
-
-/*---------------------------------
-
-  qh_call_qhull( void )
-    template for calling qhull from inside your program
-    remove #if 0, #endif to compile
-
-  returns: 
-    exit code (see qh_ERR... in qhull.h)
-    all memory freed
-
-  notes:
-    This can be called any number of times.  
-
-  see:
-    qh_call_qhull_once()
-    
-*/
-#if 0
-{
-  int dim;	            /* dimension of points */
-  int numpoints;            /* number of points */
-  coordT *points;           /* array of coordinates for each point */
-  boolT ismalloc;           /* True if qhull should free points in qh_freeqhull() or reallocation */
-  char flags[]= "qhull Tv"; /* option flags for qhull, see qh_opt.htm */
-  FILE *outfile= stdout;    /* output from qh_produce_output()
-			       use NULL to skip qh_produce_output() */
-  FILE *errfile= stderr;    /* error messages from qhull code */
-  int exitcode;             /* 0 if no error from qhull */
-  facetT *facet;	    /* set by FORALLfacets */
-  int curlong, totlong;	    /* memory remaining after qh_memfreeshort */
-
-  /* initialize dim, numpoints, points[], ismalloc here */
-  exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
-                      flags, outfile, errfile); 
-  if (!exitcode) {                  /* if no error */
-    /* 'qh facet_list' contains the convex hull */
-    FORALLfacets {
-       /* ... your code ... */
-    }
-  }
-  qh_freeqhull(!qh_ALL);
-  qh_memfreeshort (&curlong, &totlong);
-  if (curlong || totlong) 
-    fprintf (errfile, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n", totlong, curlong);
-}
-#endif
-
-/*---------------------------------
-
-  qh_new_qhull( dim, numpoints, points, ismalloc, qhull_cmd, outfile, errfile )
-    build new qhull data structure and return exitcode (0 if no errors)
-
-  notes:
-    do not modify points until finished with results.
-      The qhull data structure contains pointers into the points array.
-    do not call qhull functions before qh_new_qhull().
-      The qhull data structure is not initialized until qh_new_qhull().
-
-    outfile may be null
-    qhull_cmd must start with "qhull "
-    projects points to a new point array for Delaunay triangulations ('d' and 'v')
-    transforms points into a new point array for halfspace intersection ('H')
-       
-
-  To allow multiple, concurrent calls to qhull() 
-    - set qh_QHpointer in user.h
-    - use qh_save_qhull and qh_restore_qhull to swap the global data structure between calls.
-    - use qh_freeqhull(qh_ALL) to free intermediate convex hulls
-
-  see:
-    user_eg.c for an example
-*/
-int qh_new_qhull (int dim, int numpoints, coordT *points, boolT ismalloc, 
-		char *qhull_cmd, FILE *outfile, FILE *errfile) {
-  int exitcode, hulldim;
-  boolT new_ismalloc;
-  static boolT firstcall = True;
-  coordT *new_points;
-
-  if (firstcall) {
-    qh_meminit (errfile);
-    firstcall= False;
-  }
-  if (strncmp (qhull_cmd,"qhull ", 6)) {
-    fprintf (errfile, "qh_new_qhull: start qhull_cmd argument with \"qhull \"\n");
-    exit(1);
-  }
-  qh_initqhull_start (NULL, outfile, errfile);
-  trace1(( qh ferr, "qh_new_qhull: build new Qhull for %d %d-d points with %s\n", numpoints, dim, qhull_cmd));
-  exitcode = setjmp (qh errexit);
-  if (!exitcode)
-  {
-    qh NOerrexit = False;
-    qh_initflags (qhull_cmd);
-    if (qh DELAUNAY)
-      qh PROJECTdelaunay= True;
-    if (qh HALFspace) {
-      /* points is an array of halfspaces, 
-         the last coordinate of each halfspace is its offset */
-      hulldim= dim-1;
-      qh_setfeasible (hulldim); 
-      new_points= qh_sethalfspace_all (dim, numpoints, points, qh feasible_point);
-      new_ismalloc= True;
-      if (ismalloc)
-	free (points);
-    }else {
-      hulldim= dim;
-      new_points= points;
-      new_ismalloc= ismalloc;
-    }
-    qh_init_B (new_points, numpoints, hulldim, new_ismalloc);
-    qh_qhull();
-    qh_check_output();
-    if (outfile)
-      qh_produce_output(); 
-    if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
-      qh_check_points();
-  }
-  qh NOerrexit = True;
-  return exitcode;
-} /* new_qhull */
-
-/*---------------------------------
-  
-  qh_errexit( exitcode, facet, ridge )
-    report and exit from an error
-    report facet and ridge if non-NULL
-    reports useful information such as last point processed
-    set qh.FORCEoutput to print neighborhood of facet
-
-  see: 
-    qh_errexit2() in qhull.c for printing 2 facets
-
-  design:
-    check for error within error processing
-    compute qh.hulltime
-    print facet and ridge (if any)
-    report commandString, options, qh.furthest_id
-    print summary and statistics (including precision statistics)
-    if qh_ERRsingular
-      print help text for singular data set
-    exit program via long jump (if defined) or exit()      
-*/
-void qh_errexit(int exitcode, facetT *facet, ridgeT *ridge) {
-
-  if (qh ERREXITcalled) {
-    fprintf (qh ferr, "\nqhull error while processing previous error.  Exit program\n");
-    exit(1);
-  }
-  qh ERREXITcalled= True;
-  if (!qh QHULLfinished)
-    qh hulltime= qh_CPUclock - qh hulltime;
-  qh_errprint("ERRONEOUS", facet, NULL, ridge, NULL);
-  fprintf (qh ferr, "\nWhile executing: %s | %s\n", qh rbox_command, qh qhull_command);
-  fprintf(qh ferr, "Options selected for Qhull %s:\n%s\n", qh_VERSION, qh qhull_options);
-  if (qh furthest_id >= 0) {
-    fprintf(qh ferr, "Last point added to hull was p%d.", qh furthest_id);
-    if (zzval_(Ztotmerge))
-      fprintf(qh ferr, "  Last merge was #%d.", zzval_(Ztotmerge));
-    if (qh QHULLfinished)
-      fprintf(qh ferr, "\nQhull has finished constructing the hull.");
-    else if (qh POSTmerging)
-      fprintf(qh ferr, "\nQhull has started post-merging.");
-    fprintf (qh ferr, "\n");
-  }
-  if (qh FORCEoutput && (qh QHULLfinished || (!facet && !ridge)))
-    qh_produce_output();
-  else {
-    if (exitcode != qh_ERRsingular && zzval_(Zsetplane) > qh hull_dim+1) {
-      fprintf (qh ferr, "\nAt error exit:\n");
-      qh_printsummary (qh ferr);
-      if (qh PRINTstatistics) {
-	qh_collectstatistics();
-	qh_printstatistics(qh ferr, "at error exit");
-	qh_memstatistics (qh ferr);
-      }
-    }
-    if (qh PRINTprecision)
-      qh_printstats (qh ferr, qhstat precision, NULL);
-  }
-  if (!exitcode)
-    exitcode= qh_ERRqhull;
-  else if (exitcode == qh_ERRsingular)
-    qh_printhelp_singular(qh ferr);
-  else if (exitcode == qh_ERRprec && !qh PREmerge)
-    qh_printhelp_degenerate (qh ferr);
-  if (qh NOerrexit) {
-    fprintf (qh ferr, "qhull error while ending program.  Exit program\n");
-    exit(1);
-  }
-  qh NOerrexit= True;
-  longjmp(qh errexit, exitcode);
-} /* errexit */
-
-
-/*---------------------------------
-  
-  qh_errprint( fp, string, atfacet, otherfacet, atridge, atvertex )
-    prints out the information of facets and ridges to fp
-    also prints neighbors and geomview output
-    
-  notes:
-    except for string, any parameter may be NULL
-*/
-void qh_errprint(char *string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex) {
-  int i;
-
-  if (atfacet) {
-    fprintf(qh ferr, "%s FACET:\n", string);
-    qh_printfacet(qh ferr, atfacet);
-  }
-  if (otherfacet) {
-    fprintf(qh ferr, "%s OTHER FACET:\n", string);
-    qh_printfacet(qh ferr, otherfacet);
-  }
-  if (atridge) {
-    fprintf(qh ferr, "%s RIDGE:\n", string);
-    qh_printridge(qh ferr, atridge);
-    if (atridge->top && atridge->top != atfacet && atridge->top != otherfacet)
-      qh_printfacet(qh ferr, atridge->top);
-    if (atridge->bottom
-	&& atridge->bottom != atfacet && atridge->bottom != otherfacet)
-      qh_printfacet(qh ferr, atridge->bottom);
-    if (!atfacet)
-      atfacet= atridge->top;
-    if (!otherfacet)
-      otherfacet= otherfacet_(atridge, atfacet);
-  }
-  if (atvertex) {
-    fprintf(qh ferr, "%s VERTEX:\n", string);
-    qh_printvertex (qh ferr, atvertex);
-  }
-  if (qh fout && qh FORCEoutput && atfacet && !qh QHULLfinished && !qh IStracing) {
-    fprintf(qh ferr, "ERRONEOUS and NEIGHBORING FACETS to output\n");
-    for (i= 0; i < qh_PRINTEND; i++)  /* use fout for geomview output */
-      qh_printneighborhood (qh fout, qh PRINTout[i], atfacet, otherfacet,
-			    !qh_ALL);
-  }
-} /* errprint */
-
-
-/*---------------------------------
-  
-  qh_printfacetlist( fp, facetlist, facets, printall )
-    print all fields for a facet list and/or set of facets to fp
-    if !printall, 
-      only prints good facets
-
-  notes:
-    also prints all vertices
-*/
-void qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall) {
-  facetT *facet, **facetp;
-
-  qh_printbegin (qh ferr, qh_PRINTfacets, facetlist, facets, printall);
-  FORALLfacet_(facetlist)
-    qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);
-  FOREACHfacet_(facets)
-    qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);
-  qh_printend (qh ferr, qh_PRINTfacets, facetlist, facets, printall);
-} /* printfacetlist */
-
-
-/*---------------------------------
-  
-  qh_user_memsizes()
-    allocate up to 10 additional, quick allocation sizes
-
-  notes:
-    increase maximum number of allocations in qh_initqhull_mem()
-*/
-void qh_user_memsizes (void) {
-
-  /* qh_memsize (size); */
-} /* user_memsizes */
-
diff --git a/extern/qhull/src/user.h b/extern/qhull/src/user.h
deleted file mode 100644
index 79558967a52..00000000000
--- a/extern/qhull/src/user.h
+++ /dev/null
@@ -1,762 +0,0 @@
-/*
  ---------------------------------
-
-   user.h
-   user redefinable constants
-
-   see qh-user.htm.  see COPYING for copyright information.
-
-   before reading any code, review qhull.h for data structure definitions and 
-   the "qh" macro.
-*/
-
-#ifndef qhDEFuser
-#define qhDEFuser 1
-
-/*============= data types and configuration macros ==========*/
-
-/*----------------------------------
-  
-  realT
-    set the size of floating point numbers
-  
-  qh_REALdigits 
-    maximimum number of significant digits
-  
-  qh_REAL_1, qh_REAL_2n, qh_REAL_3n
-    format strings for printf
-  
-  qh_REALmax, qh_REALmin
-    maximum and minimum (near zero) values  
-  
-  qh_REALepsilon
-    machine roundoff.  Maximum roundoff error for addition and multiplication.
-    
-  notes:
-   Select whether to store floating point numbers in single precision (float)
-   or double precision (double).
-   
-   Use 'float' to save about 8% in time and 25% in space.  This is particularly
-   help if high-d where convex hulls are space limited.  Using 'float' also
-   reduces the printed size of Qhull's output since numbers have 8 digits of 
-   precision.
-   
-   Use 'double' when greater arithmetic precision is needed.  This is needed
-   for Delaunay triangulations and Voronoi diagrams when you are not merging 
-   facets.
-
-   If 'double' gives insufficient precision, your data probably includes
-   degeneracies.  If so you should use facet merging (done by default)
-   or exact arithmetic (see imprecision section of manual, qh-impre.htm).  
-   You may also use option 'Po' to force output despite precision errors.
-
-   You may use 'long double', but many format statements need to be changed
-   and you may need a 'long double' square root routine.  S. Grundmann
-   (sg@eeiwzb.et.tu-dresden.de) has done this.  He reports that the code runs 
-   much slower with little gain in precision.    
-
-   WARNING: on some machines,    int f(){realT a= REALmax;return (a == REALmax);}
-      returns False.  Use (a > REALmax/2) instead of (a == REALmax).
-
-   REALfloat =   1      all numbers are 'float' type
-             =   0      all numbers are 'double' type
-*/
-#define REALfloat 0
-
-#if (REALfloat == 1)
-#define realT float
-#define REALmax FLT_MAX
-#define REALmin FLT_MIN
-#define REALepsilon FLT_EPSILON
-#define qh_REALdigits 8   /* maximum number of significant digits */
-#define qh_REAL_1 "%6.8g "
-#define qh_REAL_2n "%6.8g %6.8g\n"
-#define qh_REAL_3n "%6.8g %6.8g %6.8g\n"
-
-#elif (REALfloat == 0)
-#define realT double
-#define REALmax DBL_MAX
-#define REALmin DBL_MIN
-#define REALepsilon DBL_EPSILON
-#define qh_REALdigits 16    /* maximum number of significant digits */
-#define qh_REAL_1 "%6.16g "
-#define qh_REAL_2n "%6.16g %6.16g\n"
-#define qh_REAL_3n "%6.16g %6.16g %6.16g\n"
-
-#else
-#error unknown float option
-#endif
-
-/*----------------------------------
-  
-  qh_CPUclock
-    define the clock() function for reporting the total time spent by Qhull
-    returns CPU ticks as a 'long int'
-    qh_CPUclock is only used for reporting the total time spent by Qhull
-
-  qh_SECticks 
-    the number of clock ticks per second
-
-  notes:
-    looks for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or assumes microseconds
-    to define a custom clock, set qh_CLOCKtype to 0
-
-    if your system does not use clock() to return CPU ticks, replace
-    qh_CPUclock with the corresponding function.  It is converted
-    to unsigned long to prevent wrap-around during long runs.
-   
-
-   Set qh_CLOCKtype to
-   
-     1	   	for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or microsecond
-                Note:  may fail if more than 1 hour elapsed time
-
-     2	   	use qh_clock() with POSIX times() (see global.c)
-*/
-#define qh_CLOCKtype 1  /* change to the desired number */
-
-#if (qh_CLOCKtype == 1)
-
-#if defined (CLOCKS_PER_SECOND)
-#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
-#define qh_SECticks CLOCKS_PER_SECOND
-
-#elif defined (CLOCKS_PER_SEC)
-#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
-#define qh_SECticks CLOCKS_PER_SEC
-
-#elif defined (CLK_TCK)
-#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
-#define qh_SECticks CLK_TCK
-
-#else
-#define qh_CPUclock    ((unsigned long)clock())  /* return CPU clock */
-#define qh_SECticks 1E6
-#endif
-
-#elif (qh_CLOCKtype == 2)
-#define qh_CPUclock    qh_clock()  /* return CPU clock */
-#define qh_SECticks 100
-
-#else /* qh_CLOCKtype == ? */
-#error unknown clock option
-#endif
-
-/*----------------------------------
-  
-  qh_RANDOMtype, qh_RANDOMmax, qh_RANDOMseed
-    define random number generator
-
-    qh_RANDOMint generates a random integer between 0 and qh_RANDOMmax.  
-    qh_RANDOMseed sets the random number seed for qh_RANDOMint
-
-  Set qh_RANDOMtype (default 5) to:
-    1       for random() with 31 bits (UCB)
-    2       for rand() with RAND_MAX or 15 bits (system 5)
-    3       for rand() with 31 bits (Sun)
-    4       for lrand48() with 31 bits (Solaris)
-    5       for qh_rand() with 31 bits (included with Qhull)
-  
-  notes:
-    Random numbers are used by rbox to generate point sets.  Random
-    numbers are used by Qhull to rotate the input ('QRn' option),
-    simulate a randomized algorithm ('Qr' option), and to simulate
-    roundoff errors ('Rn' option).
-
-    Random number generators differ between systems.  Most systems provide
-    rand() but the period varies.  The period of rand() is not critical
-    since qhull does not normally use random numbers.  
-
-    The default generator is Park & Miller's minimal standard random
-    number generator [CACM 31:1195 '88].  It is included with Qhull.
-
-    If qh_RANDOMmax is wrong, qhull will report a warning and Geomview 
-    output will likely be invisible.
-*/
-#define qh_RANDOMtype 5   /* *** change to the desired number *** */
-
-#if (qh_RANDOMtype == 1)
-#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, random()/MAX */
-#define qh_RANDOMint random()
-#define qh_RANDOMseed_(seed) srandom(seed);
-
-#elif (qh_RANDOMtype == 2)
-#ifdef RAND_MAX
-#define qh_RANDOMmax ((realT)RAND_MAX)
-#else
-#define qh_RANDOMmax ((realT)32767)   /* 15 bits (System 5) */
-#endif
-#define qh_RANDOMint  rand()
-#define qh_RANDOMseed_(seed) srand((unsigned)seed);
-  
-#elif (qh_RANDOMtype == 3)
-#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, Sun */
-#define qh_RANDOMint  rand()
-#define qh_RANDOMseed_(seed) srand((unsigned)seed);
-
-#elif (qh_RANDOMtype == 4)
-#define qh_RANDOMmax ((realT)0x7fffffffUL)  /* 31 bits, lrand38()/MAX */
-#define qh_RANDOMint lrand48()
-#define qh_RANDOMseed_(seed) srand48(seed);
-
-#elif (qh_RANDOMtype == 5)
-#define qh_RANDOMmax ((realT)2147483646UL)  /* 31 bits, qh_rand/MAX */
-#define qh_RANDOMint qh_rand()
-#define qh_RANDOMseed_(seed) qh_srand(seed);
-/* unlike rand(), never returns 0 */
-
-#else
-#error: unknown random option
-#endif
-
-/*----------------------------------
-  
-  qh_ORIENTclock
-    0 for inward pointing normals by Geomview convention
-*/
-#define qh_ORIENTclock 0 
-
-
-/*========= performance related constants =========*/
-
-/*----------------------------------
-  
-  qh_HASHfactor
-    total hash slots / used hash slots.  Must be at least 1.1.
-      
-  notes:
-    =2 for at worst 50% occupancy for qh hash_table and normally 25% occupancy
-*/
-#define qh_HASHfactor 2
-
-/*----------------------------------
-  
-  qh_VERIFYdirect
-    with 'Tv' verify all points against all facets if op count is smaller
-
-  notes:
-    if greater, calls qh_check_bestdist() instead
-*/
-#define qh_VERIFYdirect 1000000 
-
-/*----------------------------------
-  
-  qh_INITIALsearch
-     if qh_INITIALmax, search points up to this dimension
-*/
-#define qh_INITIALsearch 6
-
-/*----------------------------------
-  
-  qh_INITIALmax
-    if dim >= qh_INITIALmax, use min/max coordinate points for initial simplex
-      
-  notes:
-    from points with non-zero determinants
-    use option 'Qs' to override (much slower)
-*/
-#define qh_INITIALmax 8
-
-/*----------------------------------
-  
-  qh_JOGGLEdefault
-    default qh.JOGGLEmax is qh.DISTround * qh_JOGGLEdefault
-
-  notes:
-    rbox s r 100 | qhull QJ1e-15 QR0 generates 90% faults at distround 7e-16
-    rbox s r 100 | qhull QJ1e-14 QR0 generates 70% faults
-    rbox s r 100 | qhull QJ1e-13 QR0 generates 35% faults
-    rbox s r 100 | qhull QJ1e-12 QR0 generates 8% faults
-    rbox s r 100 | qhull QJ1e-11 QR0 generates 1% faults
-    rbox s r 100 | qhull QJ1e-10 QR0 generates 0% faults
-    rbox 1000 W0 | qhull QJ1e-12 QR0 generates 86% faults
-    rbox 1000 W0 | qhull QJ1e-11 QR0 generates 20% faults
-    rbox 1000 W0 | qhull QJ1e-10 QR0 generates 2% faults
-    the later have about 20 points per facet, each of which may interfere
-
-    pick a value large enough to avoid retries on most inputs
-*/
-#define qh_JOGGLEdefault 30000.0
-
-/*----------------------------------
-  
-  qh_JOGGLEincrease
-    factor to increase qh.JOGGLEmax on qh_JOGGLEretry or qh_JOGGLEagain
-*/
-#define qh_JOGGLEincrease 10.0
-
-/*----------------------------------
-  
-  qh_JOGGLEretry
-    if ZZretry = qh_JOGGLEretry, increase qh.JOGGLEmax
-
-  notes:
-    try twice at the original value in case of bad luck the first time
-*/
-#define qh_JOGGLEretry 2
-
-/*----------------------------------
-  
-  qh_JOGGLEagain
-    every following qh_JOGGLEagain, increase qh.JOGGLEmax
-
-  notes:
-    1 is OK since it's already failed qh_JOGGLEretry times
-*/
-#define qh_JOGGLEagain 1
-
-/*----------------------------------
-  
-  qh_JOGGLEmaxincrease
-    maximum qh.JOGGLEmax due to qh_JOGGLEincrease
-    relative to qh.MAXwidth
-
-  notes:
-    qh.joggleinput will retry at this value until qh_JOGGLEmaxretry
-*/
-#define qh_JOGGLEmaxincrease 1e-2
-
-/*----------------------------------
-  
-  qh_JOGGLEmaxretry
-    stop after qh_JOGGLEmaxretry attempts
-*/
-#define qh_JOGGLEmaxretry 100
-
-/*========= memory constants =========*/
-
-/*----------------------------------
-  
-  qh_MEMalign
-    memory alignment for qh_meminitbuffers() in global.c
-    
-  notes:
-    to avoid bus errors, memory allocation must consider alignment requirements.
-    malloc() automatically takes care of alignment.   Since mem.c manages
-    its own memory, we need to explicitly specify alignment in
-    qh_meminitbuffers().
-
-    A safe choice is sizeof(double).  sizeof(float) may be used if doubles 
-    do not occur in data structures and pointers are the same size.  Be careful
-    of machines (e.g., DEC Alpha) with large pointers. 
-
-    If using gcc, best alignment is
-              #define qh_MEMalign fmax_(__alignof__(realT),__alignof__(void *))
-*/
-#define qh_MEMalign fmax_(sizeof(realT), sizeof(void *))
-
-/*----------------------------------
-  
-  qh_MEMbufsize
-    size of additional memory buffers
-    
-  notes:
-    used for qh_meminitbuffers() in global.c
-*/
-#define qh_MEMbufsize 0x10000       /* allocate 64K memory buffers */
-
-/*----------------------------------
-  
-  qh_MEMinitbuf
-    size of initial memory buffer
-    
-  notes:
-    use for qh_meminitbuffers() in global.c
-*/
-#define qh_MEMinitbuf 0x20000      /* initially allocate 128K buffer */
-
-/*----------------------------------
-  
-  qh_INFINITE
-    on output, indicates Voronoi center at infinity
-*/
-#define qh_INFINITE  -10.101
-
-/*----------------------------------
-  
-  qh_DEFAULTbox
-    default box size (Geomview expects 0.5)
-*/
-#define qh_DEFAULTbox 0.5 
-
-/*======= conditional compilation ============================*/
-
-/*----------------------------------
-
-  __cplusplus
-    defined by C++ compilers
-
-  __MSC_VER
-    defined by Microsoft Visual C++
-  
-  __MWERKS__ && __POWERPC__
-    defined by Metrowerks when compiling for the Power Macintosh
-
-  __STDC__
-    defined for strict ANSI C 
-*/
-
-/*----------------------------------
- 
-  qh_COMPUTEfurthest 
-    compute furthest distance to an outside point instead of storing it with the facet
-    =1 to compute furthest
-  
-  notes:
-    computing furthest saves memory but costs time
-      about 40% more distance tests for partitioning
-      removes facet->furthestdist 
-*/
-#define qh_COMPUTEfurthest 0
-                         
-/*----------------------------------
- 
-  qh_KEEPstatistics   
-    =0 removes most of statistic gathering and reporting
-
-  notes:
-    if 0, code size is reduced by about 4%.
-*/
-#define qh_KEEPstatistics 1
-                       
-/*----------------------------------
- 
-  qh_MAXoutside 
-    record outer plane for each facet
-    =1 to record facet->maxoutside
-  
-  notes:
-    this takes a realT per facet and slightly slows down qhull
-    it produces better outer planes for geomview output 
-*/
-#define qh_MAXoutside 1
-
-/*----------------------------------
- 
-  qh_NOmerge
-    disables facet merging if defined
-    
-  notes:
-    This saves about 10% space.
-    
-    Unless 'Q0'
-      qh_NOmerge sets 'QJ' to avoid precision errors
-
-    #define qh_NOmerge    
-
-  see:
-    qh_NOmem in mem.c
-    
-    see user.c/user_eg.c for removing io.o
-*/  
-    
-/*----------------------------------
- 
-  qh_NOtrace
-    no tracing if defined 
-  
-  notes:
-    This saves about 5% space.
-
-    #define qh_NOtrace
-*/    
-
-/*----------------------------------
-  
-  qh_QHpointer
-    access global data with pointer or static structure
-
-  qh_QHpointer  = 1     access globals via a pointer to allocated memory
-                        enables qh_saveqhull() and qh_restoreqhull()
-			costs about 8% in time and 2% in space
-
-		= 0     qh_qh and qh_qhstat are static data structures
-		        only one instance of qhull() can be active at a time
-			default value
-
-  notes:
-    all global variables for qhull are in qh, qhmem, and qhstat
-    qh is defined in qhull.h
-    qhmem is defined in mem.h
-    qhstat is defined in stat.h
-
-  see:
-    user_eg.c for an example
-*/
-#define qh_QHpointer 0
-#if 0  /* sample code */
-    qhT *oldqhA, *oldqhB;
-
-    exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
-                      flags, outfile, errfile); 
-    /* use results from first call to qh_new_qhull */
-    oldqhA= qh_save_qhull();
-    exitcode= qh_new_qhull (dimB, numpointsB, pointsB, ismalloc,
-                      flags, outfile, errfile); 
-    /* use results from second call to qh_new_qhull */
-    oldqhB= qh_save_qhull();
-    qh_restore_qhull (&oldqhA);
-    /* use results from first call to qh_new_qhull */
-    qh_freeqhull (qh_ALL);  /* frees all memory used by first call */
-    qh_restore_qhull (&oldqhB);
-    /* use results from second call to qh_new_qhull */
-    qh_freeqhull (!qh_ALL); /* frees long memory used by second call */
-    qh_memfreeshort (&curlong, &totlong);  /* frees short memory and memory allocator */
-#endif
-
-/*----------------------------------
- 
-  qh_QUICKhelp        
-    =1 to use abbreviated help messages, e.g., for degenerate inputs
-*/
-#define qh_QUICKhelp    0  
-
-/* ============ -merge constants- ====================
-
-   These constants effect facet merging.  You probably will not need
-   to modify these.  They effect the performance of facet merging.
-*/
-
-/*----------------------------------
-  
-  qh_DIMmergeVertex
-    max dimension for vertex merging (it is not effective in high-d)
-*/
-#define qh_DIMmergeVertex 6
-
-/*----------------------------------
-  
-  qh_DIMreduceBuild
-     max dimension for vertex reduction during build (slow in high-d)
-*/
-#define qh_DIMreduceBuild 5
-
-/*----------------------------------
-     
-  qh_BESTcentrum
-     if > 2*dim+n vertices, qh_findbestneighbor() tests centrums (faster)
-     else, qh_findbestneighbor() tests all vertices (much better merges)
-
-  qh_BESTcentrum2
-     if qh_BESTcentrum2 * DIM3 + BESTcentrum < #vertices tests centrums
-*/
-#define qh_BESTcentrum 20
-#define qh_BESTcentrum2 2
-
-/*----------------------------------
-  
-  qh_BESTnonconvex
-    if > dim+n neighbors, qh_findbestneighbor() tests nonconvex ridges.
-    
-  notes:
-    It is needed because qh_findbestneighbor is slow for large facets
-*/
-#define qh_BESTnonconvex 15 
-
-/*----------------------------------
-  
-  qh_MAXnewmerges
-    if >n newmerges, qh_merge_nonconvex() calls qh_reducevertices_centrums.
-     
-  notes:
-    It is needed because postmerge can merge many facets at once
-*/
-#define qh_MAXnewmerges 2
-
-/*----------------------------------
-  
-  qh_MAXnewcentrum
-    if <= dim+n vertices (n approximates the number of merges),
-      reset the centrum in qh_updatetested() and qh_mergecycle_facets()
-    
-  notes:
-    needed to reduce cost and because centrums may move too much if 
-    many vertices in high-d
-*/
-#define qh_MAXnewcentrum 5
-
-/*----------------------------------
-  
-  qh_COPLANARratio
-    for 3-d+ merging, qh.MINvisible is n*premerge_centrum
-
-  notes:
-    for non-merging, it's DISTround
-*/
-#define qh_COPLANARratio 3
-
-/*----------------------------------
-  
-  qh_DISToutside
-    When is a point clearly outside of a facet?  
-    Stops search in qh_findbestnew or qh_partitionall
-    qh_findbest uses qh.MINoutside since since it is only called if no merges.
-     
-  notes:
-    'Qf' always searches for best facet
-    if !qh.MERGING, same as qh.MINoutside. 
-    if qh_USEfindbestnew, increase value since neighboring facets may be ill-behaved
-      [Note: Zdelvertextot occurs normally with interior points]
-            RBOX 1000 s Z1 G1e-13 t1001188774 | QHULL Tv
-    When there is a sharp edge, need to move points to a
-    clearly good facet; otherwise may be lost in another partitioning.
-    if too big then O(n^2) behavior for partitioning in cone
-    if very small then important points not processed
-    Needed in qh_partitionall for
-      RBOX 1000 s Z1 G1e-13 t1001032651 | QHULL Tv
-    Needed in qh_findbestnew for many instances of
-      RBOX 1000 s Z1 G1e-13 t | QHULL Tv
-
-  See:  
-    qh_DISToutside -- when is a point clearly outside of a facet
-    qh_SEARCHdist -- when is facet coplanar with the best facet?
-    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
-*/
-#define qh_DISToutside ((qh_USEfindbestnew ? 2 : 1) * \
-     fmax_((qh MERGING ? 2 : 1)*qh MINoutside, qh max_outside))
-
-/*----------------------------------
-  
-  qh_RATIOnearinside
-    ratio of qh.NEARinside to qh.ONEmerge for retaining inside points for
-    qh_check_maxout().  
-  
-  notes:
-    This is overkill since do not know the correct value.
-    It effects whether 'Qc' reports all coplanar points
-    Not used for 'd' since non-extreme points are coplanar
-*/
-#define qh_RATIOnearinside 5
-
-/*----------------------------------
-  
-  qh_SEARCHdist
-    When is a facet coplanar with the best facet?  
-    qh_findbesthorizon: all coplanar facets of the best facet need to be searched.
-
-  See:
-    qh_DISToutside -- when is a point clearly outside of a facet
-    qh_SEARCHdist -- when is facet coplanar with the best facet?
-    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
-*/
-#define qh_SEARCHdist ((qh_USEfindbestnew ? 2 : 1) * \
-      (qh max_outside + 2 * qh DISTround + fmax_( qh MINvisible, qh MAXcoplanar)));
-
-/*----------------------------------
-  
-  qh_USEfindbestnew
-     Always use qh_findbestnew for qh_partitionpoint, otherwise use
-     qh_findbestnew if merged new facet or sharpnewfacets.
-  
-  See:
-    qh_DISToutside -- when is a point clearly outside of a facet
-    qh_SEARCHdist -- when is facet coplanar with the best facet?
-    qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
-*/
-#define qh_USEfindbestnew (zzval_(Ztotmerge) > 50)
-
-/*----------------------------------
-  
-  qh_WIDEcoplanar
-    n*MAXcoplanar or n*MINvisible for a WIDEfacet 
-    
-    if vertex is further than qh.WIDEfacet from the hyperplane
-    then its ridges are not counted in computing the area, and
-    the facet's centrum is frozen. 
-    
-  notes:
-   qh.WIDEfacet= max(qh.MAXoutside,qh_WIDEcoplanar*qh.MAXcoplanar,
-      qh_WIDEcoplanar * qh.MINvisible);
-*/
-#define qh_WIDEcoplanar 6
-
-/*----------------------------------
-  
-  qh_MAXnarrow
-    max. cosine in initial hull that sets qh.NARROWhull
-       
-  notes:
-    If qh.NARROWhull, the initial partition does not make 
-    coplanar points.  If narrow, a coplanar point can be 
-    coplanar to two facets of opposite orientations and
-    distant from the exact convex hull.
-
-    Conservative estimate.  Don't actually see problems until it is -1.0
-*/
-#define qh_MAXnarrow -0.99999999
-
-/*----------------------------------
-  
-  qh_WARNnarrow
-    max. cosine in initial hull to warn about qh.NARROWhull
-      
-  notes:
-    this is a conservative estimate.  
-    Don't actually see problems until it is -1.0.  See qh-impre.htm
-*/
-#define qh_WARNnarrow -0.999999999999999
-
-/*----------------------------------
-  
-  qh_ZEROdelaunay
-    a zero Delaunay facet occurs for input sites coplanar with their convex hull
-    the last normal coefficient of a zero Delaunay facet is within
-        qh_ZEROdelaunay * qh.ANGLEround of 0
-      
-  notes:
-    qh_ZEROdelaunay does not allow for joggled input ('QJ').
-
-    You can avoid zero Delaunay facets by surrounding the input with a box.
-
-    Use option 'PDk:-n' to explicitly define zero Delaunay facets
-      k= dimension of input sites (e.g., 3 for 3-d Delaunay triangulation)
-      n= the cutoff for zero Delaunay facets (e.g., 'PD3:-1e-12')
-*/
-#define qh_ZEROdelaunay 2
-
-#endif /* qh_DEFuser */
-
-
-
diff --git a/extern/qhull/src/user_eg.c b/extern/qhull/src/user_eg.c
deleted file mode 100644
index 97e4aa7a89a..00000000000
--- a/extern/qhull/src/user_eg.c
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
  ---------------------------------
-
-  user_eg.c
-  sample code for calling qhull() from an application
-  
-  call with:
-
-     user_eg "cube/diamond options" "delaunay options" "halfspace options"
-
-  for example:
-
-     user_eg                             # return summaries
-
-     user_eg "n" "o" "Fp"                # return normals, OFF, points
-
-     user_eg "n Qt" "o" "Fp"             # triangulated cube
-
-     user_eg "QR0 p" "QR0 v p" "QR0 Fp"  # rotate input and return points
-                                         # 'v' returns Voronoi
-					 # transform is rotated for halfspaces
-
-   main() makes three runs of qhull.
-
-     1) compute the convex hull of a cube
-
-     2a) compute the Delaunay triangulation of random points
-
-     2b) find the Delaunay triangle closest to a point.
-
-     3) compute the halfspace intersection of a diamond
-
- notes:
- 
-   For another example, see main() in unix.c and user_eg2.c.
-   These examples, call qh_qhull() directly.  They allow
-   tighter control on the code loaded with Qhull.
-
-   For a simple C++ example, see qhull_interface.cpp
-
-   Summaries are sent to stderr if other output formats are used
-
-   compiled by 'make user_eg'
-
-   see qhull.h for data structures, macros, and user-callable functions.
-*/
-
-#include "qhull_a.h"
-
-/*-------------------------------------------------
--internal function prototypes
-*/
-void print_summary (void);
-void makecube (coordT *points, int numpoints, int dim);
-void makeDelaunay (coordT *points, int numpoints, int dim, int seed);
-void findDelaunay (int dim);
-void makehalf (coordT *points, int numpoints, int dim);
-
-/*-------------------------------------------------
--print_summary()
-*/
-void print_summary (void) {
-  facetT *facet;
-  int k;
-
-  printf ("\n%d vertices and %d facets with normals:\n", 
-                 qh num_vertices, qh num_facets);
-  FORALLfacets {
-    for (k=0; k < qh hull_dim; k++) 
-      printf ("%6.2g ", facet->normal[k]);
-    printf ("\n");
-  }
-}
-
-/*--------------------------------------------------
--makecube- set points to vertices of cube
-  points is numpoints X dim
-*/
-void makecube (coordT *points, int numpoints, int dim) {
-  int j,k;
-  coordT *point;
-
-  for (j=0; jvertices) {
-    for (k=0; k < dim; k++)
-      printf ("%5.2f ", vertex->point[k]);
-    printf ("\n");
-  }
-} /*.findDelaunay.*/
-
-/*--------------------------------------------------
--makehalf- set points to halfspaces for a (dim)-dimensional diamond
-  points is numpoints X dim+1
-
-  each halfspace consists of dim coefficients followed by an offset
-*/
-void makehalf (coordT *points, int numpoints, int dim) {
-  int j,k;
-  coordT *point;
-
-  for (j=0; j= 2 ? argv[1] : "");
-  numpoints= SIZEcube;
-  makecube (points, numpoints, DIM);
-  for (i=numpoints; i--; )
-    rows[i]= points+dim*i;
-  qh_printmatrix (outfile, "input", rows, numpoints, dim);
-  exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
-                      flags, outfile, errfile); 
-  if (!exitcode) {                  /* if no error */
-    /* 'qh facet_list' contains the convex hull */
-    print_summary();
-    FORALLfacets {
-       /* ... your code ... */
-    }
-  }
-  qh_freeqhull(!qh_ALL);                   /* free long memory  */
-  qh_memfreeshort (&curlong, &totlong);    /* free short memory and memory allocator */
-  if (curlong || totlong) 
-    fprintf (errfile, "qhull internal warning (user_eg, #1): did not free %d bytes of long memory (%d pieces)\n", totlong, curlong);
-
-  /*
-    Run 2: Delaunay triangulation
-  */
-
-  printf( "\ncompute 3-d Delaunay triangulation\n");
-  sprintf (flags, "qhull s d Tcv %s", argc >= 3 ? argv[2] : "");
-  numpoints= SIZEcube;
-  makeDelaunay (points, numpoints, dim, time(NULL));
-  for (i=numpoints; i--; )
-    rows[i]= points+dim*i;
-  qh_printmatrix (outfile, "input", rows, numpoints, dim);
-  exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
-                      flags, outfile, errfile); 
-  if (!exitcode) {                  /* if no error */
-    /* 'qh facet_list' contains the convex hull */
-    /* If you want a Voronoi diagram ('v') and do not request output (i.e., outfile=NULL), 
-       call qh_setvoronoi_all() after qh_new_qhull(). */
-    print_summary();
-    FORALLfacets {
-       /* ... your code ... */
-    }
-    printf( "\nfind 3-d Delaunay triangle closest to [0.5, 0.5, ...]\n");
-    exitcode= setjmp (qh errexit);  
-    if (!exitcode) {
-      /* Trap Qhull errors in findDelaunay().  Without the setjmp(), Qhull
-         will exit() after reporting an error */
-      qh NOerrexit= False;
-      findDelaunay (DIM);
-    }
-    qh NOerrexit= True;
-  }
-#if qh_QHpointer  /* see user.h */
-  {
-    qhT *oldqhA, *oldqhB;
-    coordT pointsB[DIM*TOTpoints]; /* array of coordinates for each point */
-
-
-    printf( "\nsave first triangulation and compute a new triangulation\n");
-    oldqhA= qh_save_qhull();
-    sprintf (flags, "qhull s d Tcv %s", argc >= 3 ? argv[2] : "");
-    numpoints= SIZEcube;
-    makeDelaunay (pointsB, numpoints, dim, time(NULL)+1);
-    for (i=numpoints; i--; )
-      rows[i]= pointsB+dim*i;
-    qh_printmatrix (outfile, "input", rows, numpoints, dim);
-    exitcode= qh_new_qhull (dim, numpoints, pointsB, ismalloc,
-                      flags, outfile, errfile); 
-    if (!exitcode)
-      print_summary();
-    printf( "\nsave second triangulation and restore first one\n");
-    oldqhB= qh_save_qhull();
-    qh_restore_qhull (&oldqhA);
-    print_summary();
-    printf( "\nfree first triangulation and restore second one.\n");
-    qh_freeqhull (qh_ALL);               /* free short and long memory used by first call */
-			                 /* do not use qh_memfreeshort */
-    qh_restore_qhull (&oldqhB);
-    print_summary();
-  }
-#endif
-  qh_freeqhull(!qh_ALL);                 /* free long memory */
-  qh_memfreeshort (&curlong, &totlong);  /* free short memory and memory allocator */
-  if (curlong || totlong) 
-    fprintf (errfile, "qhull internal warning (user_eg, #2): did not free %d bytes of long memory (%d pieces)\n", totlong, curlong);
-
-  /*
-    Run 3: halfspace intersection about the origin
-  */
-  printf( "\ncompute halfspace intersection about the origin for a diamond\n");
-  sprintf (flags, "qhull H0 s Tcv %s", argc >= 4 ? argv[3] : "Fp");
-  numpoints= SIZEcube;
-  makehalf (points, numpoints, dim);
-  for (i=numpoints; i--; )
-    rows[i]= points+(dim+1)*i;
-  qh_printmatrix (outfile, "input as halfspace coefficients + offsets", rows, numpoints, dim+1);
-  /* use qh_sethalfspace_all to transform the halfspaces yourself.  
-     If so, set 'qh feasible_point and do not use option 'Hn,...' [it would retransform the halfspaces]
-  */
-  exitcode= qh_new_qhull (dim+1, numpoints, points, ismalloc,
-                      flags, outfile, errfile); 
-  if (!exitcode) 
-    print_summary();
-  qh_freeqhull (!qh_ALL);
-  qh_memfreeshort (&curlong, &totlong);
-  if (curlong || totlong)  /* could also check previous runs */
-    fprintf (stderr, "qhull internal warning (user_eg, #3): did not free %d bytes of long memory (%d pieces)\n",
-       totlong, curlong);
-  return exitcode;
-} /* main */
-
diff --git a/extern/qhull/src/user_eg2.c b/extern/qhull/src/user_eg2.c
deleted file mode 100644
index 1eb42ccfe8a..00000000000
--- a/extern/qhull/src/user_eg2.c
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
  ---------------------------------
-
-  user_eg2.c
-
-  sample code for calling qhull() from an application.
-
-  See user_eg.c for a simpler method using qh_new_qhull().
-  The method used here and in unix.c gives you additional
-  control over Qhull. 
-  
-  call with:
-
-     user_eg2 "triangulated cube/diamond options" "delaunay options" "halfspace options"
-
-  for example:
-
-     user_eg2                             # return summaries
-
-     user_eg2 "n" "o" "Fp"                # return normals, OFF, points
-
-     user_eg2 "QR0 p" "QR0 v p" "QR0 Fp"  # rotate input and return points
-                                         # 'v' returns Voronoi
-					 # transform is rotated for halfspaces
-
-   main() makes three runs of qhull.
-
-     1) compute the convex hull of a cube, and incrementally add a diamond
-
-     2a) compute the Delaunay triangulation of random points, and add points.
-
-     2b) find the Delaunay triangle closest to a point.
-
-     3) compute the halfspace intersection of a diamond, and add a cube
-
- notes:
- 
-   summaries are sent to stderr if other output formats are used
-
-   derived from unix.c and compiled by 'make user_eg2'
-
-   see qhull.h for data structures, macros, and user-callable functions.
-   
-   If you want to control all output to stdio and input to stdin,
-   set the #if below to "1" and delete all lines that contain "io.c".  
-   This prevents the loading of io.o.  Qhull will
-   still write to 'qh ferr' (stderr) for error reporting and tracing.
-
-   Defining #if 1, also prevents user.o from being loaded.
-*/
-
-#include "qhull_a.h"
-
-/*-------------------------------------------------
--internal function prototypes
-*/
-void print_summary (void);
-void makecube (coordT *points, int numpoints, int dim);
-void adddiamond (coordT *points, int numpoints, int numnew, int dim);
-void makeDelaunay (coordT *points, int numpoints, int dim);
-void addDelaunay (coordT *points, int numpoints, int numnew, int dim);
-void findDelaunay (int dim);
-void makehalf (coordT *points, int numpoints, int dim);
-void addhalf (coordT *points, int numpoints, int numnew, int dim, coordT *feasible);
-
-/*-------------------------------------------------
--print_summary()
-*/
-void print_summary (void) {
-  facetT *facet;
-  int k;
-
-  printf ("\n%d vertices and %d facets with normals:\n", 
-                 qh num_vertices, qh num_facets);
-  FORALLfacets {
-    for (k=0; k < qh hull_dim; k++) 
-      printf ("%6.2g ", facet->normal[k]);
-    printf ("\n");
-  }
-}
-
-/*--------------------------------------------------
--makecube- set points to vertices of cube
-  points is numpoints X dim
-*/
-void makecube (coordT *points, int numpoints, int dim) {
-  int j,k;
-  coordT *point;
-
-  for (j=0; jvertices) {
-    for (k=0; k < dim-1; k++)
-      printf ("%5.2f ", vertex->point[k]);
-    printf ("\n");
-  }
-} /*.findDelaunay.*/
-
-/*--------------------------------------------------
--makehalf- set points to halfspaces for a (dim)-d diamond
-  points is numpoints X dim+1
-
-  each halfspace consists of dim coefficients followed by an offset
-*/
-void makehalf (coordT *points, int numpoints, int dim) {
-  int j,k;
-  coordT *point;
-
-  for (j=0; j= 2 ? argv[1] : "");
-    qh_initflags (options);
-    printf( "\ncompute triangulated convex hull of cube after rotating input\n");
-    makecube (array[0], SIZEcube, DIM);
-    qh_init_B (array[0], SIZEcube, DIM, ismalloc);
-    qh_qhull();
-    qh_check_output();
-    qh_triangulate();  /* requires option 'Q11' if want to add points */ 
-    print_summary ();
-    if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
-      qh_check_points ();
-    printf( "\nadd points in a diamond\n");
-    adddiamond (array[0], SIZEcube, SIZEdiamond, DIM);
-    qh_check_output();
-    print_summary (); 
-    qh_produce_output();  /* delete this line to help avoid io.c */
-    if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
-      qh_check_points ();
-  }
-  qh NOerrexit= True;
-  qh_freeqhull (!qh_ALL);
-  qh_memfreeshort (&curlong, &totlong);
-  /*
-    Run 2: Delaunay triangulation
-  */
-  qh_init_A (stdin, stdout, stderr, 0, NULL);
-  exitcode= setjmp (qh errexit);
-  if (!exitcode) {
-    coordT array[TOTpoints][DIM];
-
-    strcat (qh rbox_command, "user_eg Delaunay");
-    sprintf (options, "qhull s d Tcv %s", argc >= 3 ? argv[2] : "");
-    qh_initflags (options);
-    printf( "\ncompute 2-d Delaunay triangulation\n");
-    makeDelaunay (array[0], SIZEcube, DIM);
-    /* Instead of makeDelaunay with qh_setdelaunay, you may
-       produce a 2-d array of points, set DIM to 2, and set 
-       qh PROJECTdelaunay to True.  qh_init_B will call 
-       qh_projectinput to project the points to the paraboloid
-       and add a point "at-infinity".
-    */
-    qh_init_B (array[0], SIZEcube, DIM, ismalloc);
-    qh_qhull();
-    /* If you want Voronoi ('v') without qh_produce_output(), call
-       qh_setvoronoi_all() after qh_qhull() */
-    qh_check_output();
-    print_summary ();
-    qh_produce_output();  /* delete this line to help avoid io.c */
-    if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
-      qh_check_points ();
-    printf( "\nadd points to triangulation\n");
-    addDelaunay (array[0], SIZEcube, SIZEdiamond, DIM); 
-    qh_check_output();
-    qh_produce_output();  /* delete this line to help avoid io.c */
-    if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
-      qh_check_points ();
-    printf( "\nfind Delaunay triangle closest to [0.5, 0.5, ...]\n");
-    findDelaunay (DIM);
-  }
-  qh NOerrexit= True;
-  qh_freeqhull (!qh_ALL);
-  qh_memfreeshort (&curlong, &totlong);
-  /*
-    Run 3: halfspace intersection
-  */
-  qh_init_A (stdin, stdout, stderr, 0, NULL);
-  exitcode= setjmp (qh errexit);
-  if (!exitcode) {
-    coordT array[TOTpoints][DIM+1];  /* +1 for halfspace offset */
-    pointT *points;
-
-    strcat (qh rbox_command, "user_eg halfspaces");
-    sprintf (options, "qhull H0 s Tcv %s", argc >= 4 ? argv[3] : "");
-    qh_initflags (options);
-    printf( "\ncompute halfspace intersection about the origin for a diamond\n");
-    makehalf (array[0], SIZEcube, DIM);
-    qh_setfeasible (DIM); /* from io.c, sets qh feasible_point from 'Hn,n' */
-    /* you may malloc and set qh feasible_point directly.  It is only used for
-       option 'Fp' */
-    points= qh_sethalfspace_all ( DIM+1, SIZEcube, array[0], qh feasible_point); 
-    qh_init_B (points, SIZEcube, DIM, True); /* qh_freeqhull frees points */
-    qh_qhull();
-    qh_check_output();
-    qh_produce_output();  /* delete this line to help avoid io.c */
-    if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
-      qh_check_points ();
-    printf( "\nadd halfspaces for cube to intersection\n");
-    addhalf (array[0], SIZEcube, SIZEdiamond, DIM, qh feasible_point); 
-    qh_check_output();
-    qh_produce_output();  /* delete this line to help avoid io.c */
-    if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
-      qh_check_points ();
-  }
-  qh NOerrexit= True;
-  qh NOerrexit= True;
-  qh_freeqhull (!qh_ALL);
-  qh_memfreeshort (&curlong, &totlong);
-  if (curlong || totlong)  /* could also check previous runs */
-    fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
-       totlong, curlong);
-  return exitcode;
-} /* main */
-
-#if 1    /* use 1 to prevent loading of io.o and user.o */
-/*-------------------------------------------
--errexit- return exitcode to system after an error
-  assumes exitcode non-zero
-  prints useful information
-  see qh_errexit2() in qhull.c for 2 facets
-*/
-void qh_errexit(int exitcode, facetT *facet, ridgeT *ridge) {
-
-  if (qh ERREXITcalled) {
-    fprintf (qh ferr, "qhull error while processing previous error.  Exit program\n");
-    exit(1);
-  }
-  qh ERREXITcalled= True;
-  if (!qh QHULLfinished)
-    qh hulltime= (unsigned)clock() - qh hulltime;
-  fprintf (qh ferr, "\nWhile executing: %s | %s\n", qh rbox_command, qh qhull_command);
-  fprintf(qh ferr, "Options selected:\n%s\n", qh qhull_options);
-  if (qh furthest_id >= 0) {
-    fprintf(qh ferr, "\nLast point added to hull was p%d", qh furthest_id);
-    if (zzval_(Ztotmerge))
-      fprintf(qh ferr, "  Last merge was #%d.", zzval_(Ztotmerge));
-    if (qh QHULLfinished)
-      fprintf(qh ferr, "\nQhull has finished constructing the hull.");
-    else if (qh POSTmerging)
-      fprintf(qh ferr, "\nQhull has started post-merging");
-    fprintf(qh ferr, "\n\n");
-  }
-  if (qh NOerrexit) {
-    fprintf (qh ferr, "qhull error while ending program.  Exit program\n");
-    exit(1);
-  }
-  if (!exitcode)
-    exitcode= qh_ERRqhull;
-  qh NOerrexit= True;
-  longjmp(qh errexit, exitcode);
-} /* errexit */
-
-
-/*-------------------------------------------
--errprint- prints out the information of the erroneous object
-    any parameter may be NULL, also prints neighbors and geomview output
-*/
-void qh_errprint(char *string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex) {
-
-  fprintf (qh ferr, "%s facets f%d f%d ridge r%d vertex v%d\n",
-	   string, getid_(atfacet), getid_(otherfacet), getid_(atridge),
-	   getid_(atvertex));
-} /* errprint */
-
-
-void qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall) {
-  facetT *facet, **facetp;
-
-  /* remove these calls to help avoid io.c */
-  qh_printbegin (qh ferr, qh_PRINTfacets, facetlist, facets, printall);/*io.c*/
-  FORALLfacet_(facetlist)                                              /*io.c*/
-    qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);          /*io.c*/
-  FOREACHfacet_(facets)                                                /*io.c*/
-    qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);          /*io.c*/
-  qh_printend (qh ferr, qh_PRINTfacets, facetlist, facets, printall);  /*io.c*/
-
-  FORALLfacet_(facetlist)
-    fprintf( qh ferr, "facet f%d\n", facet->id);
-} /* printfacetlist */
-
-
-
-/*-----------------------------------------
--user_memsizes- allocate up to 10 additional, quick allocation sizes
-*/
-void qh_user_memsizes (void) {
-
-  /* qh_memsize (size); */
-} /* user_memsizes */
-
-#endif
diff --git a/extern/solid/CMakeLists.txt b/extern/solid/CMakeLists.txt
deleted file mode 100644
index 7840dd6b423..00000000000
--- a/extern/solid/CMakeLists.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-# $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, Blender Foundation
-# All rights reserved.
-#
-# The Original Code is: all of this file.
-#
-# Contributor(s): Jacques Beaurain.
-#
-# ***** END GPL LICENSE BLOCK *****
-
-SET(INC include src src/broad src/complex src/convex ../qhull/include)
-
-FILE(GLOB SRC src/*.cpp src/convex/*.cpp src/complex/*.cpp src/broad/*.cpp)
-
-ADD_DEFINITIONS(-DUSE_DOUBLES -DQHULL -D_LIB)
-
-BLENDERLIB(extern_solid "${SRC}" "${INC}")
-#, libtype=['game2','player'], priority=[45, 75]
diff --git a/extern/solid/LICENSE_GPL.txt b/extern/solid/LICENSE_GPL.txt
deleted file mode 100644
index 07db89585a2..00000000000
--- a/extern/solid/LICENSE_GPL.txt
+++ /dev/null
@@ -1,349 +0,0 @@
-
- The SOLID library is Copyright (C) 2001-2003  Dtecta.
-
- You may use, distribute and copy the SOLID library under the terms of
- GNU General Public License version 2, which is displayed below.
-
--------------------------------------------------------------------------
-
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    
-    Copyright (C)   
-
-    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.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  , 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
-
--------------------------------------------------------------------------
diff --git a/extern/solid/LICENSE_QPL.txt b/extern/solid/LICENSE_QPL.txt
deleted file mode 100644
index 3fca00466e2..00000000000
--- a/extern/solid/LICENSE_QPL.txt
+++ /dev/null
@@ -1,110 +0,0 @@
-
- The SOLID library is Copyright (C) 2001-2003  Dtecta.
-
- You may use, distribute and copy the SOLID library under the terms of
- the Q Public License, which is displayed below.
-
--------------------------------------------------------------------------
-			     THE Q PUBLIC LICENSE
-				  version 1.0
-
-		   Copyright (C) 1999-2000 Trolltech AS, Norway.
-		       Everyone is permitted to copy and
-		       distribute this license document.
-
-The intent of this license is to establish freedom to share and change the
-software regulated by this license under the open source model.
-
-This license applies to any software containing a notice placed by the
-copyright holder saying that it may be distributed under the terms of
-the Q Public License version 1.0.  Such software is herein referred to as
-the Software.  This license covers modification and distribution of the
-Software, use of third-party application programs based on the Software,
-and development of free software which uses the Software.
-
-				 Granted Rights
-
-1. You are granted the non-exclusive rights set forth in this license
-   provided you agree to and comply with any and all conditions in this
-   license.  Whole or partial distribution of the Software, or software
-   items that link with the Software, in any form signifies acceptance of
-   this license.
-
-2. You may copy and distribute the Software in unmodified form provided
-   that the entire package, including - but not restricted to - copyright,
-   trademark notices and disclaimers, as released by the initial developer
-   of the Software, is distributed.
-
-3. You may make modifications to the Software and distribute your
-   modifications, in a form that is separate from the Software, such as
-   patches. The following restrictions apply to modifications:
-
-     a. Modifications must not alter or remove any copyright notices in
-        the Software.
-
-     b. When modifications to the Software are released under this
-        license, a non-exclusive royalty-free right is granted to the
-        initial developer of the Software to distribute your modification
-        in future versions of the Software provided such versions remain
-        available under these terms in addition to any other license(s) of
-        the initial developer.
-
-4. You may distribute machine-executable forms of the Software or
-   machine-executable forms of modified versions of the Software, provided
-   that you meet these restrictions:
-
-     a. You must include this license document in the distribution.
-
-     b. You must ensure that all recipients of the machine-executable forms
-        are also able to receive the complete machine-readable source code
-        to the distributed Software, including all modifications, without
-        any charge beyond the costs of data transfer, and place prominent
-        notices in the distribution explaining this.
-
-     c. You must ensure that all modifications included in the
-        machine-executable forms are available under the terms of this
-        license.
-
-5. You may use the original or modified versions of the Software to
-   compile, link and run application programs legally developed by you
-   or by others.
-
-6. You may develop application programs, reusable components and other
-   software items that link with the original or modified versions of the
-   Software.  These items, when distributed, are subject to the following
-   requirements:
-
-     a. You must ensure that all recipients of machine-executable forms of
-        these items are also able to receive and use the complete
-        machine-readable source code to the items without any charge
-        beyond the costs of data transfer.
-
-     b. You must explicitly license all recipients of your items to use
-        and re-distribute original and modified versions of the items in
-        both machine-executable and source code forms. The recipients must
-        be able to do so without any charges whatsoever, and they must be
-        able to re-distribute to anyone they choose.
-
-
-     c. If the items are not available to the general public, and the
-        initial developer of the Software requests a copy of the items,
-        then you must supply one.
-
-			    Limitations of Liability
-
-In no event shall the initial developers or copyright holders be liable
-for any damages whatsoever, including - but not restricted to - lost
-revenue or profits or other direct, indirect, special, incidental or
-consequential damages, even if they have been advised of the possibility
-of such damages, except to the extent invariable law, if any, provides
-otherwise.
-
-			          No Warranty
-
-The Software and this license document are provided AS IS with NO WARRANTY
-OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS
-FOR A PARTICULAR PURPOSE.
-                                 Choice of Law
-
-This license is governed by the Laws of Norway. Disputes shall be settled
-by Oslo City Court.
diff --git a/extern/solid/Makefile b/extern/solid/Makefile
deleted file mode 100644
index 206dc21c3fb..00000000000
--- a/extern/solid/Makefile
+++ /dev/null
@@ -1,56 +0,0 @@
-# -*- mode: gnumakefile; tab-width: 8; indent-tabs-mode: t; -*-
-# vim: tabstop=8
-#
-# $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.
-#
-# The Original Code is: all of this file.
-#
-# Contributor(s): GSR
-#
-# ***** END GPL LICENSE BLOCK *****
-#
-#
-
-include nan_definitions.mk
-
-SOURCEDIR = extern/solid
-LIBNAMES = solid solid_broad solid_convex solid_complex
-DIR = $(OCGDIR)/extern/
-DIRS = src
-
-include nan_subdirs.mk
-
-install:  $(ALL_OR_DEBUG)
-	@[ -d $(NAN_SOLID) ] || mkdir -p $(NAN_SOLID)
-	@[ -d $(NAN_SOLID)/include/SOLID ] || mkdir -p $(NAN_SOLID)/include/SOLID
-	@[ -d $(NAN_SOLID)/include/SOLID/MT ] || mkdir -p $(NAN_SOLID)/include/SOLID/MT
-	@[ -d $(NAN_SOLID)/lib/$(DEBUG_DIR) ] || mkdir -p $(NAN_SOLID)/lib/$(DEBUG_DIR)
-	@for i in $(LIBNAMES); do \
-	    $(NANBLENDERHOME)/intern/tools/cpifdiff.sh $(DIR)/$$i/$(DEBUG_DIR)lib$$i.a $(NAN_SOLID)/lib/$(DEBUG_DIR) ; \
-	    if [ $(OS) = darwin ] ; then \
-            ranlib $(NAN_SOLID)/lib/$(DEBUG_DIR)lib$$i.a ; \
-        fi ; \
-	done
-	@$(NANBLENDERHOME)/intern/tools/cpifdiff.sh include/*.h $(NAN_SOLID)/include/SOLID
-	@$(NANBLENDERHOME)/intern/tools/cpifdiff.sh include/MT/*.h $(NAN_SOLID)/include/SOLID/MT
-
-
diff --git a/extern/solid/README.txt b/extern/solid/README.txt
deleted file mode 100644
index 348d92b35cb..00000000000
--- a/extern/solid/README.txt
+++ /dev/null
@@ -1,55 +0,0 @@
-
-		 SOLID - Software Library for Interference Detection
-
-SOLID is a software library containing functions for performing
-intersection tests and proximity queries that are useful in the context
-of collision detection. Collision detection is the process of detecting
-pairs of geometric objects that are intersecting or are within a given
-proximity of each other. In particular, SOLID is useful for detecting
-collisions between objects that are moving relatively of each other over
-time. The motions of objects are controlled by the client application,
-and are not determined or affected by SOLID. 
-
-This open-source edition of SOLID version 3 is released under the terms of
-either the GNU Public License (GPL) or the Q Public License (QPL). This means
-that for software created with SOLID version 3 you must comply with the terms
-of one of these licenses. You may choose wich of these licenses best suits
-your purpose. See the following files contained in this distribution for a
-complete list of terms and conditions of these licenses:  
-
-		 LICENSE_QPL.txt	 The Q Public License 
-		 LICENSE_GPL.txt	 The GNU General Public License
-
-These licenses do not permit the use of SOLID 3 in closed-source software
-products. For enquiries about commercial use of SOLID, please contact
-info@dtecta.com.    
-
-SOLID 3 uses Qhull from The Geometry Center of the University of Minnesota.
-Qhull is copyrighted as noted below.  Qhull is free software and may be
-obtained via anonymous ftp from geom.umn.edu.   
-        
-                    Qhull, Copyright (c) 1993-2002
-
-       The National Science and Technology Research Center for
-        Computation and Visualization of Geometric Structures
-                        (The Geometry Center)
-                       University of Minnesota
-                            400 Lind Hall
-                        207 Church Street S.E.
-                      Minneapolis, MN 55455  USA
-
-                       email: qhull@geom.umn.edu
-
-Installation
-
-For details on how to install SOLID see the documention in the 'doc' directory.
-
-Platforms
-
-SOLID 3 has been tested on the following platforms:
-
-    Linux IA32  gcc 2.95.3, gcc 3.3
-	Win32		MSVC++ 6.0 SP4, MSVC++ 7.1 
-
-  
-
diff --git a/extern/solid/SConscript b/extern/solid/SConscript
deleted file mode 100644
index 8c54442ca73..00000000000
--- a/extern/solid/SConscript
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/python
-import sys
-
-Import('env')
-
-defs = 'USE_DOUBLES QHULL _LIB'
-cflags = []
-
-if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
-    defs += ' WIN32 NDEBUG _WINDOWS _LIB'
-    cflags += ['/MT', '/W3', '/GX', '/Og', '/Ot', '/Ob1', '/Op', '/G6']
-elif env['OURPLATFORM']=='win32-mingw':
-    defs += ' NDEBUG'
-    cflags += ['-O2']
-elif sys.platform=='linux2' or sys.platform=='linux-i386' or sys.platform=='freebsd4' or sys.platform=='freebsd5' or sys.platform=='openbsd3' or sys.platform=='sunos5':
-    defs += ' NDEBUG'
-    cflags += ['-O2']
-elif sys.platform=='darwin' :
-    defs += ' NDEBUG'
-    cflags += ['-O2','-pipe', '-fPIC', '-funsigned-char', '-ffast-math']
-
-else:
-    print "################################################"
-    print 
-    print "Check if solid builds on your platform correctly"
-    print "Add your platform specific defines"
-    print "and cflags / cxxflags to the"
-    print "extern/solid/SConscript file"
-
-sources = env.Glob('src/*.cpp') + env.Glob('src/convex/*.cpp') + env.Glob('src/complex/*.cpp') + env.Glob('src/broad/*.cpp')
-
-incs = 'include src src/broad src/complex src/convex ../qhull/include'
-
-env.BlenderLib ( libname='extern_solid', sources=sources, includes=Split(incs), defines=Split(defs), libtype=['extern'], priority=[10] , compileflags = cflags)
diff --git a/extern/solid/SOLID/SOLID.h b/extern/solid/SOLID/SOLID.h
deleted file mode 100644
index 37d74340f8c..00000000000
--- a/extern/solid/SOLID/SOLID.h
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef SOLID_H
-#define SOLID_H
-
-#include "SOLID_types.h"
-
-#ifdef __cplusplus
-extern "C" { 
-#endif
-    
-	DT_DECLARE_HANDLE(DT_ObjectHandle);
-	DT_DECLARE_HANDLE(DT_SceneHandle);
-	DT_DECLARE_HANDLE(DT_ShapeHandle);
-	DT_DECLARE_HANDLE(DT_VertexBaseHandle);
-	DT_DECLARE_HANDLE(DT_RespTableHandle);
-	DT_DECLARE_HANDLE(DT_ArchiveHandle);
-
-	typedef unsigned int DT_ResponseClass;
-
-	typedef enum DT_ResponseType { 
-		DT_NO_RESPONSE,                  /* No response (obsolete) */        
-		DT_BROAD_RESPONSE,      
-		DT_SIMPLE_RESPONSE,              /* No collision data */
-		DT_WITNESSED_RESPONSE,           /* A point common to both objects
-											is returned as collision data
-										 */
-		DT_DEPTH_RESPONSE                /* The penetration depth is returned
-											as collision data. The penetration depth
-											is the shortest vector over which one 
-											object needs to be translated in order
-											to bring the objects in touching contact. 
-										 */ 
-	} DT_ResponseType;
-    
-/* For witnessed response, the following structure represents a common point. The world 
-   coordinates of 'point1' and 'point2' coincide. 'normal' is the zero vector.
-   
-   For depth response, the following structure represents the penetration depth. 
-   'point1' en 'point2' are the witness points of the penetration depth in world coordinates.
-   The penetration depth vector in world coordinates is represented by 'normal'.
-*/
-
-	typedef struct DT_CollData {
-		DT_Vector3 point1;               /* Point in object1 in world coordinates */ 
-		DT_Vector3 point2;               /* Point in object2 in world coordinates */
-		DT_Vector3 normal;               /* point2 - point1 */ 
-	} DT_CollData;
-
-/* A response callback is called by SOLID for each pair of collding objects. 'client-data'
-   is a pointer to an arbitrary structure in the client application. The client objects are
-   pointers to structures in the client application associated with the coliding objects.
-   'coll_data' is the collision data computed by SOLID.
-*/
-
-	typedef DT_Bool (*DT_ResponseCallback)(void *client_data,
-										   void *client_object1,
-										   void *client_object2,
-										   const DT_CollData *coll_data);
-										
-/* Shape definition */
-
-
-	extern DECLSPEC DT_ShapeHandle DT_NewBox(DT_Scalar x, DT_Scalar y, DT_Scalar z);
-	extern DECLSPEC DT_ShapeHandle DT_NewCone(DT_Scalar radius, DT_Scalar height);
-	extern DECLSPEC DT_ShapeHandle DT_NewCylinder(DT_Scalar radius, DT_Scalar height);
-	extern DECLSPEC DT_ShapeHandle DT_NewSphere(DT_Scalar radius);
-	extern DECLSPEC DT_ShapeHandle DT_NewPoint(const DT_Vector3 point);
-	extern DECLSPEC DT_ShapeHandle DT_NewLineSegment(const DT_Vector3 source, const DT_Vector3 target);
-	extern DECLSPEC DT_ShapeHandle DT_NewMinkowski(DT_ShapeHandle shape1, DT_ShapeHandle shape2);
-	extern DECLSPEC DT_ShapeHandle DT_NewHull(DT_ShapeHandle shape1, DT_ShapeHandle shape2);
-
-	extern DECLSPEC DT_VertexBaseHandle DT_NewVertexBase(const void *pointer, DT_Size stride);
-	extern DECLSPEC void DT_DeleteVertexBase(DT_VertexBaseHandle vertexBase);	
-	extern DECLSPEC void DT_ChangeVertexBase(DT_VertexBaseHandle vertexBase, const void *pointer);
-
-	extern DECLSPEC DT_ShapeHandle DT_NewComplexShape(DT_VertexBaseHandle vertexBase);
-	extern DECLSPEC void           DT_EndComplexShape();
-
-	extern DECLSPEC DT_ShapeHandle DT_NewPolytope(DT_VertexBaseHandle vertexBase);
-	extern DECLSPEC void           DT_EndPolytope();
-
-	extern DECLSPEC void DT_Begin();
-	extern DECLSPEC void DT_End();
-
-	extern DECLSPEC void DT_Vertex(const DT_Vector3 vertex);
-	extern DECLSPEC void DT_VertexIndex(DT_Index index);
-
-	extern DECLSPEC void DT_VertexIndices(DT_Count count, const DT_Index *indices);
-	extern DECLSPEC void DT_VertexRange(DT_Index first, DT_Count count); 
-
-	extern DECLSPEC void DT_DeleteShape(DT_ShapeHandle shape);
-
-/* Object  */
-
-	extern DECLSPEC DT_ObjectHandle DT_CreateObject(
-		void *client_object,      /* pointer to object in client memory */
-		DT_ShapeHandle shape  /* the shape or geometry of the object */
-		);
-
-	extern DECLSPEC void DT_DestroyObject(DT_ObjectHandle object);
-
-
-
-	extern DECLSPEC void DT_SetPosition(DT_ObjectHandle object, const DT_Vector3 position);
-	extern DECLSPEC void DT_SetOrientation(DT_ObjectHandle object, const DT_Quaternion orientation);
-	extern DECLSPEC void DT_SetScaling(DT_ObjectHandle object, const DT_Vector3 scaling);
-
-/* The margin is an offset from the actual shape. The actual geometry of an
-   object is the set of points whose distance to the transformed shape is at 
-   most the  margin. During the lifetime of an object the margin can be 
-   modified. 
-*/
-   
-	extern DECLSPEC void DT_SetMargin(DT_ObjectHandle object, DT_Scalar margin);
-
-
-/* These commands assume a column-major 4x4 OpenGL matrix representation */
-
-	extern DECLSPEC void DT_SetMatrixf(DT_ObjectHandle object, const float *m); 
-	extern DECLSPEC void DT_GetMatrixf(DT_ObjectHandle object, float *m); 
-
-	extern DECLSPEC void DT_SetMatrixd(DT_ObjectHandle object, const double *m); 
-	extern DECLSPEC void DT_GetMatrixd(DT_ObjectHandle object, double *m); 
-
-	extern DECLSPEC void DT_GetBBox(DT_ObjectHandle object, DT_Vector3 min, DT_Vector3 max);
-
-
-	extern DECLSPEC DT_Bool  DT_GetIntersect(DT_ObjectHandle object1, DT_ObjectHandle object2,
-												DT_Vector3 v);
-/* This next command returns the distance between the objects. De returned
-   closest points are given in world coordinates.
-*/
-	extern DECLSPEC DT_Scalar DT_GetClosestPair(DT_ObjectHandle object1, DT_ObjectHandle object2,
-												DT_Vector3 point1, DT_Vector3 point2);  
-
-	extern DECLSPEC DT_Bool   DT_GetCommonPoint(DT_ObjectHandle object1, DT_ObjectHandle object2,
-												DT_Vector3 point);
-
-	extern DECLSPEC DT_Bool   DT_GetPenDepth(DT_ObjectHandle object1, DT_ObjectHandle object2,
-											 DT_Vector3 point1, DT_Vector3 point2);  
-
-/* Scene */
-
-	extern DECLSPEC DT_SceneHandle DT_CreateScene(); 
-	extern DECLSPEC void           DT_DestroyScene(DT_SceneHandle scene);
-
-	extern DECLSPEC void DT_AddObject(DT_SceneHandle scene, DT_ObjectHandle object);
-	extern DECLSPEC void DT_RemoveObject(DT_SceneHandle scene, DT_ObjectHandle object);
-
-/* Note that objects can be assigned to multiple scenes! */
-
-/* Response */
-
-/* Response tables are defined independent of the scenes in which they are used.
-   Multiple response tables can be used in one scene, and a response table
-   can be shared among scenes.
-*/
-	extern DECLSPEC DT_RespTableHandle DT_CreateRespTable(); 
-	extern DECLSPEC void               DT_DestroyRespTable(DT_RespTableHandle respTable); 
-
-/* Responses are defined on (pairs of) response classes. Each response table 
-   maintains its set of response classes.
-*/
-	extern DECLSPEC DT_ResponseClass DT_GenResponseClass(DT_RespTableHandle respTable);
-
-/* To each object for which a response is defined in the response table a
-   response class needs to be assigned. 
-*/
-
-	extern DECLSPEC void DT_SetResponseClass(DT_RespTableHandle respTable,
-											 DT_ObjectHandle object,
-											 DT_ResponseClass responseClass);
-
-	extern DECLSPEC void DT_ClearResponseClass(DT_RespTableHandle respTable, 
-											   DT_ObjectHandle object);
-
-	extern DECLSPEC void DT_CallResponse(DT_RespTableHandle respTable,
-										 DT_ObjectHandle object1,
-										 DT_ObjectHandle object2,
-										 const DT_CollData *coll_data);
-
-/* For each pair of objects multiple responses can be defined. A response is a callback
-   together with its response type and client data. */
-    
-/* Responses can be defined for all pairs of response classes... */
-	extern DECLSPEC void DT_AddDefaultResponse(DT_RespTableHandle respTable,
-											   DT_ResponseCallback response, 
-											   DT_ResponseType type, void *client_data);
-
-	extern DECLSPEC void DT_RemoveDefaultResponse(DT_RespTableHandle respTable,
-												  DT_ResponseCallback response);
-/* ...per response class... */
-	extern DECLSPEC void DT_AddClassResponse(DT_RespTableHandle respTable,
-											 DT_ResponseClass responseClass,
-											 DT_ResponseCallback response,
-											 DT_ResponseType type, void *client_data);
-
-	extern DECLSPEC void DT_RemoveClassResponse(DT_RespTableHandle respTable,
-												DT_ResponseClass responseClass,
-												DT_ResponseCallback response);
-
-/* ... and per pair of response classes...*/
-	extern DECLSPEC void DT_AddPairResponse(DT_RespTableHandle respTable,
-											DT_ResponseClass responseClass1,
-											DT_ResponseClass responseClass2, 
-											DT_ResponseCallback response,
-											DT_ResponseType type, void *client_data);
-	extern DECLSPEC void DT_RemovePairResponse(DT_RespTableHandle respTable,
-											   DT_ResponseClass responseClass1,
-											   DT_ResponseClass responseClass2,
-											   DT_ResponseCallback response);
-
-/* The next command calls the response callbacks for all intersecting pairs of objects in a scene. 
-   'DT_Test' returns the number of pairs of objects for which callbacks have been called. 
-*/
- 
-	extern DECLSPEC DT_Count DT_Test(DT_SceneHandle scene, DT_RespTableHandle respTable);
-
-/* Set the maximum relative error in the closest points and penetration depth
-   computation. The default for `max_error' is 1.0e-3. Larger errors result
-   in better performance. Non-positive error tolerances are ignored.
-*/ 
-
-	extern DECLSPEC void DT_SetAccuracy(DT_Scalar max_error);
-
-/* Set the maximum tolerance on relative errors due to rounding.  The default for `tol_error' 
-   is the machine epsilon. Very large tolerances result in false collisions. Setting tol_error too small 
-   results in missed collisions. Non-positive error tolerances are ignored. 
-*/ 
-    
-	extern DECLSPEC void DT_SetTolerance(DT_Scalar tol_error);
-
-
-/* This function returns the client pointer to the first object in a scene hit by the ray 
-   (actually a line segment) defined by the points 'from' en 'to'. The spot is the hit point 
-   on the object in local coordinates. 'normal' is the normal to the surface of the object in
-   world coordinates. The ignore_client pointer is used to make one of the objects transparent.
-
-   NB: Currently ray tests are implemented for spheres, boxes, and meshes only!!
-*/   
-
-	extern DECLSPEC void *DT_RayCast(DT_SceneHandle scene, void *ignore_client,
-									 const DT_Vector3 source, const DT_Vector3 target,
-									 DT_Scalar max_param, DT_Scalar *param, DT_Vector3 normal);
-
-/* Similar, only here a single object is tested and a boolean is returned */
-
-	extern DECLSPEC DT_Bool DT_ObjectRayCast(DT_ObjectHandle object,
-											 const DT_Vector3 source, const DT_Vector3 target,
-											 DT_Scalar max_param, DT_Scalar *param, DT_Vector3 normal);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/extern/solid/SOLID/SOLID_broad.h b/extern/solid/SOLID/SOLID_broad.h
deleted file mode 100644
index 74e4214fa67..00000000000
--- a/extern/solid/SOLID/SOLID_broad.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef SOLID_BROAD_H
-#define SOLID_BROAD_H
-
-#include "SOLID_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-    
-	DT_DECLARE_HANDLE(BP_SceneHandle);
-	DT_DECLARE_HANDLE(BP_ProxyHandle);
-	
-	typedef void (*BP_Callback)(void *client_data,
-								void *object1,
-								void *object2);
-
-	typedef bool (*BP_RayCastCallback)(void *client_data,
-									   void *object,
-									   const DT_Vector3 source,
-									   const DT_Vector3 target,
-									   DT_Scalar *lambda);
-	
-	extern DECLSPEC BP_SceneHandle BP_CreateScene(void *client_data,
-												  BP_Callback beginOverlap,
-												  BP_Callback endOverlap);
-	
-	extern DECLSPEC void           BP_DestroyScene(BP_SceneHandle scene);
-	
-	extern DECLSPEC BP_ProxyHandle BP_CreateProxy(BP_SceneHandle scene, 
-												  void *object,
-												  const DT_Vector3 min, 
-												  const DT_Vector3 max);
-	
-	extern DECLSPEC void           BP_DestroyProxy(BP_SceneHandle scene, 
-												  BP_ProxyHandle proxy);
-	
-	extern DECLSPEC void BP_SetBBox(BP_ProxyHandle proxy, 
-									const DT_Vector3 min, 
-									const DT_Vector3 max);
-	
-	extern DECLSPEC void *BP_RayCast(BP_SceneHandle scene, 
-									 BP_RayCastCallback objectRayCast, 
-									 void *client_data,
-									 const DT_Vector3 source,
-									 const DT_Vector3 target,
-									 DT_Scalar *lambda);		
-	
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/extern/solid/SOLID/SOLID_types.h b/extern/solid/SOLID/SOLID_types.h
deleted file mode 100644
index 630594e447f..00000000000
--- a/extern/solid/SOLID/SOLID_types.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef SOLID_TYPES_H
-#define SOLID_TYPES_H
-
-#ifndef DECLSPEC
-# ifdef WIN32
-#  define DECLSPEC __declspec(dllexport)
-# else
-#  define DECLSPEC
-# endif
-#endif
-
-#define DT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
-    
-
-typedef unsigned short DT_Index;
-typedef unsigned short DT_Count;
-typedef unsigned int   DT_Size;
-typedef float          DT_Scalar; 
-typedef int            DT_Bool;
-
-#define DT_FALSE 0
-#define DT_TRUE  1
-
-#define DT_CONTINUE 0
-#define DT_DONE 1
-
-typedef DT_Scalar DT_Vector3[3]; 
-typedef DT_Scalar DT_Quaternion[4]; 
-
-#endif
diff --git a/extern/solid/VisualC6/broad/broad.dsp b/extern/solid/VisualC6/broad/broad.dsp
deleted file mode 100644
index 1161d68fcd6..00000000000
--- a/extern/solid/VisualC6/broad/broad.dsp
+++ /dev/null
@@ -1,132 +0,0 @@
-# Microsoft Developer Studio Project File - Name="broad" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=broad - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "broad.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "broad.mak" CFG="broad - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "broad - Win32 Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "broad - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "broad - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-LINK32=cwlink.exe
-MTL=midl.exe
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF  "$(CFG)" == "broad - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-LINK32=cwlink.exe
-MTL=midl.exe
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MT /W3 /GX /Zd /Od /I "../../include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ENDIF 
-
-# Begin Target
-
-# Name "broad - Win32 Release"
-# Name "broad - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE="..\..\src\broad\BP_C-api.cpp"
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\broad\BP_EndpointList.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\broad\BP_Proxy.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\broad\BP_Scene.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=..\..\src\broad\BP_Endpoint.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\broad\BP_EndpointList.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\broad\BP_Proxy.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\broad\BP_ProxyList.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\broad\BP_Scene.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/extern/solid/VisualC6/complex/complex.dsp b/extern/solid/VisualC6/complex/complex.dsp
deleted file mode 100644
index 74ea67b9e23..00000000000
--- a/extern/solid/VisualC6/complex/complex.dsp
+++ /dev/null
@@ -1,116 +0,0 @@
-# Microsoft Developer Studio Project File - Name="complex" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=complex - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "complex.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "complex.mak" CFG="complex - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "complex - Win32 Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "complex - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "complex - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-LINK32=cwlink.exe
-MTL=midl.exe
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../include" /I "../../src/convex" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF  "$(CFG)" == "complex - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-LINK32=cwlink.exe
-MTL=midl.exe
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MT /W3 /GX /Zd /Od /I "../../include" /I "../../src/convex" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ENDIF 
-
-# Begin Target
-
-# Name "complex - Win32 Release"
-# Name "complex - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\..\src\complex\DT_BBoxTree.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\complex\DT_Complex.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=..\..\src\complex\DT_BBoxTree.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\complex\DT_CBox.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\complex\DT_Complex.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/extern/solid/VisualC6/convex/convex.dsp b/extern/solid/VisualC6/convex/convex.dsp
deleted file mode 100644
index ec9caace9d9..00000000000
--- a/extern/solid/VisualC6/convex/convex.dsp
+++ /dev/null
@@ -1,232 +0,0 @@
-# Microsoft Developer Studio Project File - Name="convex" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=convex - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "convex.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "convex.mak" CFG="convex - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "convex - Win32 Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "convex - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "convex - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-LINK32=cwlink.exe
-MTL=midl.exe
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../include" /I "../../../qhull/include" /D "NDEBUG" /D "QHULL" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF  "$(CFG)" == "convex - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-LINK32=cwlink.exe
-MTL=midl.exe
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MT /W3 /GX /Zd /Od /I "../../include" /I "../../../qhull/include" /D "_DEBUG" /D "QHULL" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ENDIF 
-
-# Begin Target
-
-# Name "convex - Win32 Release"
-# Name "convex - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Accuracy.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Box.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Cone.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Convex.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Cylinder.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Facet.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_LineSegment.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_PenDepth.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Point.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Polyhedron.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Polytope.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Sphere.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Triangle.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Accuracy.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Array.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Box.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Cone.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Convex.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Cylinder.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Facet.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_GJK.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Hull.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_IndexArray.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_LineSegment.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Minkowski.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_PenDepth.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Point.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Polyhedron.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Polytope.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Shape.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Sphere.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Transform.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_Triangle.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\convex\DT_VertexBase.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/extern/solid/VisualC6/dynamics/dynamics.dsp b/extern/solid/VisualC6/dynamics/dynamics.dsp
deleted file mode 100644
index 9659cbf8a56..00000000000
--- a/extern/solid/VisualC6/dynamics/dynamics.dsp
+++ /dev/null
@@ -1,120 +0,0 @@
-# Microsoft Developer Studio Project File - Name="dynamics" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=dynamics - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "dynamics.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "dynamics.mak" CFG="dynamics - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "dynamics - Win32 Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "dynamics - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "dynamics - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-LINK32=cwlink.exe
-MTL=midl.exe
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF  "$(CFG)" == "dynamics - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-LINK32=cwlink.exe
-MTL=midl.exe
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MD /W3 /GX /Zd /Od /I "../../include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ENDIF 
-
-# Begin Target
-
-# Name "dynamics - Win32 Release"
-# Name "dynamics - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\..\examples\dynamics\Dynamic.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\examples\dynamics\Kinetic.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\examples\dynamics\RigidBody.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=..\..\examples\dynamics\Dynamic.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\examples\dynamics\Kinetic.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\examples\dynamics\RigidBody.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/extern/solid/VisualC6/gldemo/gldemo.dsp b/extern/solid/VisualC6/gldemo/gldemo.dsp
deleted file mode 100644
index f3cde286161..00000000000
--- a/extern/solid/VisualC6/gldemo/gldemo.dsp
+++ /dev/null
@@ -1,102 +0,0 @@
-# Microsoft Developer Studio Project File - Name="gldemo" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=gldemo - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "gldemo.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "gldemo.mak" CFG="gldemo - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "gldemo - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "gldemo - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "gldemo - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-
-!ELSEIF  "$(CFG)" == "gldemo - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MD /W3 /GX /Zd /Od /I "../../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "gldemo - Win32 Release"
-# Name "gldemo - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\..\examples\gldemo.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/extern/solid/VisualC6/mnm/mnm.dsp b/extern/solid/VisualC6/mnm/mnm.dsp
deleted file mode 100644
index 2df6d951794..00000000000
--- a/extern/solid/VisualC6/mnm/mnm.dsp
+++ /dev/null
@@ -1,100 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mnm" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=mnm - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "mnm.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "mnm.mak" CFG="mnm - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "mnm - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "mnm - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "mnm - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../include" /I "../../examples/dynamics" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-
-!ELSEIF  "$(CFG)" == "mnm - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MD /W3 /GX /Zd /Od /I "../../include" /I "../../examples/dynamics" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "mnm - Win32 Release"
-# Name "mnm - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\..\examples\mnm.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/extern/solid/VisualC6/physics/physics.dsp b/extern/solid/VisualC6/physics/physics.dsp
deleted file mode 100644
index dd69b6a35b2..00000000000
--- a/extern/solid/VisualC6/physics/physics.dsp
+++ /dev/null
@@ -1,100 +0,0 @@
-# Microsoft Developer Studio Project File - Name="physics" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=physics - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "physics.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "physics.mak" CFG="physics - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "physics - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "physics - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "physics - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../include" /I "../../examples/dynamics" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-
-!ELSEIF  "$(CFG)" == "physics - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MD /W3 /GX /Zd /Od /I "../../include" /I "../../examples/dynamics" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "physics - Win32 Release"
-# Name "physics - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\..\examples\physics.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/extern/solid/VisualC6/sample/sample.dsp b/extern/solid/VisualC6/sample/sample.dsp
deleted file mode 100644
index c6e0423cd04..00000000000
--- a/extern/solid/VisualC6/sample/sample.dsp
+++ /dev/null
@@ -1,102 +0,0 @@
-# Microsoft Developer Studio Project File - Name="sample" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=sample - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "sample.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "sample.mak" CFG="sample - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "sample - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "sample - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "sample - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-
-!ELSEIF  "$(CFG)" == "sample - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MD /W3 /GX /Zd /Od /I "../../include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "sample - Win32 Release"
-# Name "sample - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=..\..\examples\sample.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/extern/solid/VisualC6/solid.dsw b/extern/solid/VisualC6/solid.dsw
deleted file mode 100644
index 397cc4bf371..00000000000
--- a/extern/solid/VisualC6/solid.dsw
+++ /dev/null
@@ -1,89 +0,0 @@
-Microsoft Developer Studio Workspace File, Format Version 6.00
-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
-
-###############################################################################
-
-Project: "broad"=".\broad\broad.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "complex"=".\complex\complex.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "convex"=".\convex\convex.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-    Begin Project Dependency
-    Project_Dep_Name qhull
-    End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "qhull"="..\..\qhull\VisualC6\qhull\qhull.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "solid"=".\solid\solid.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-    Begin Project Dependency
-    Project_Dep_Name broad
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name complex
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name convex
-    End Project Dependency
-}}}
-
-###############################################################################
-
-Global:
-
-Package=<5>
-{{{
-}}}
-
-Package=<3>
-{{{
-}}}
-
-###############################################################################
-
diff --git a/extern/solid/VisualC6/solid/solid.dsp b/extern/solid/VisualC6/solid/solid.dsp
deleted file mode 100644
index 4ac7459c2f9..00000000000
--- a/extern/solid/VisualC6/solid/solid.dsp
+++ /dev/null
@@ -1,148 +0,0 @@
-# Microsoft Developer Studio Project File - Name="solid" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=solid - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "solid.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "solid.mak" CFG="solid - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "solid - Win32 Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "solid - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "solid - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-LINK32=cwlink.exe
-MTL=midl.exe
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../include" /I "../../src/convex" /I "../../src/complex" /D "NDEBUG" /D "QHULL" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-# Begin Special Build Tool
-SOURCE="$(InputPath)"
-PostBuild_Cmds=XCOPY   /Y   ..\..\include\SOLID*.h   ..\..\..\..\..\lib\windows\solid\include\solid\  	XCOPY   /Y   Release\*.lib   ..\..\..\..\..\lib\windows\solid\lib\ 
-# End Special Build Tool
-
-!ELSEIF  "$(CFG)" == "solid - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-LINK32=cwlink.exe
-MTL=midl.exe
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MT /W3 /GX /Zd /Od /I "../../include" /I "../../src/convex" /I "../../src/complex" /D "_DEBUG" /D "QHULL" /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-# Begin Special Build Tool
-SOURCE="$(InputPath)"
-PostBuild_Cmds=XCOPY   /Y   ..\..\include\SOLID*.h   ..\..\..\..\..\lib\windows\solid\include\solid\  	XCOPY   /Y   Debug\*.lib   ..\..\..\..\..\lib\windows\solid\lib\Debug\ 
-# End Special Build Tool
-
-!ENDIF 
-
-# Begin Target
-
-# Name "solid - Win32 Release"
-# Name "solid - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE="..\..\src\DT_C-api.cpp"
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\DT_Encounter.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\DT_Object.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\DT_RespTable.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\DT_Scene.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=..\..\src\DT_AlgoTable.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\DT_Encounter.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\DT_Object.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\DT_Response.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\DT_RespTable.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\DT_Scene.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/extern/solid/VisualC6/solid_dll/solid_dll.dsp b/extern/solid/VisualC6/solid_dll/solid_dll.dsp
deleted file mode 100644
index eed092502e0..00000000000
--- a/extern/solid/VisualC6/solid_dll/solid_dll.dsp
+++ /dev/null
@@ -1,147 +0,0 @@
-# Microsoft Developer Studio Project File - Name="solid_dll" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=solid_dll - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "solid_dll.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "solid_dll.mak" CFG="solid_dll - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "solid_dll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "solid_dll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "solid_dll - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "../../lib/win32/vc6"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOLID_DLL_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../include" /I "../../src/convex" /I "../../src/complex" /D "NDEBUG" /D "USE_DOUBLES" /D "QHULL" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOLID_DLL_EXPORTS" /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../../lib/win32/vc6/solid.dll"
-
-!ELSEIF  "$(CFG)" == "solid_dll - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "../../lib/win32/vc6"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOLID_DLL_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /MD /W3 /GX /Zd /Od /I "../../include" /I "../../src/convex" /I "../../src/complex" /D "_DEBUG" /D "QHULL" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOLID_DLL_EXPORTS" /YX /FD /GZ /c
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"../../lib/win32/vc6/solidd.dll" /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "solid_dll - Win32 Release"
-# Name "solid_dll - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE="..\..\src\DT_C-api.cpp"
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\DT_Encounter.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\DT_Object.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\DT_RespTable.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\DT_Scene.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=..\..\src\DT_AlgoTable.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\DT_Encounter.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\DT_Object.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\DT_Response.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\DT_RespTable.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\..\src\DT_Scene.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/extern/solid/include/GEN_MinMax.h b/extern/solid/include/GEN_MinMax.h
deleted file mode 100644
index 9ea961cfe4f..00000000000
--- a/extern/solid/include/GEN_MinMax.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef GEN_MINMAX_H
-#define GEN_MINMAX_H
-
-template 
-inline const T& GEN_min(const T& a, const T& b) 
-{
-  return b < a ? b : a;
-}
-
-template 
-inline const T& GEN_max(const T& a, const T& b) 
-{
-  return  a < b ? b : a;
-}
-
-template 
-inline const T& GEN_clamped(const T& a, const T& lb, const T& ub) 
-{
-	return a < lb ? lb : (ub < a ? ub : a); 
-}
-
-template 
-inline void GEN_set_min(T& a, const T& b) 
-{
-    if (b < a) 
-	{
-		a = b;
-	}
-}
-
-template 
-inline void GEN_set_max(T& a, const T& b) 
-{
-    if (a < b) 
-	{
-		a = b;
-	}
-}
-
-template 
-inline void GEN_clamp(T& a, const T& lb, const T& ub) 
-{
-	if (a < lb) 
-	{
-		a = lb; 
-	}
-	else if (ub < a) 
-	{
-		a = ub;
-	}
-}
-
-#endif
diff --git a/extern/solid/include/GEN_random.h b/extern/solid/include/GEN_random.h
deleted file mode 100644
index 4690a05511a..00000000000
--- a/extern/solid/include/GEN_random.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef GEN_RANDOM_H
-#define GEN_RANDOM_H
-
-#ifdef MT19937
-
-#include 
-#include 
-
-#define GEN_RAND_MAX UINT_MAX
-
-inline void         GEN_srand(unsigned int seed) { init_genrand(seed); }
-inline unsigned int GEN_rand()                   { return genrand_int32(); }
-
-#else
-
-#include 
-
-#define GEN_RAND_MAX RAND_MAX
-
-inline void         GEN_srand(unsigned int seed) { srand(seed); } 
-inline unsigned int GEN_rand()                   { return rand(); }
-
-#endif
-
-#endif
-
diff --git a/extern/solid/include/MT/Interval.h b/extern/solid/include/MT/Interval.h
deleted file mode 100644
index c6ba2fc1681..00000000000
--- a/extern/solid/include/MT/Interval.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef INTERVAL_H
-#define INTERVAL_H
-
-#if defined (__sgi)
-#include 
-#else
-#include 
-#endif
-
-#include 
-#include 
-
-namespace MT {
-
-	template 
-	class Interval {
-	public:
-		Interval() {}
-		
-
-#if _MSC_VER <= 1200
-        explicit Interval(const Scalar& x) 
-		    : m_lb(x), m_ub(x)
-	    {}
-        
- 
-		Interval(const Scalar& lb, const Scalar& ub) 
-			: m_lb(lb), m_ub(ub)
-		{
-			assert(lb <= ub);
-		}
-#else
-		template 
-		explicit Interval(const Scalar2& x) 
-			: m_lb(x), m_ub(x)
-		{}
-		
-		template 
-		Interval(const Scalar2& lb, const Scalar2& ub) 
-			: m_lb(lb), m_ub(ub)
-		{
-			assert(lb <= ub);
-		}
-		
-		template 
-		Interval(const Interval& z) 
-		{ 
-			*this = z; 
-		}
-		
-		template 
-		Interval& operator=(const Interval& z) 
-		{ 
-			m_lb = Scalar(z.lower()); 
-			m_ub = Scalar(z.upper()); 
-			return *this;
-		}
-#endif
-      
-		
-
-		Scalar&       lower()       { return m_lb; }
-		const Scalar& lower() const { return m_lb; }
-		
-		Scalar&       upper()       { return m_ub; }
-		const Scalar& upper() const { return m_ub; }
-		 
-		Scalar center() const { return (m_lb + m_ub) * Scalar(0.5); } 
-		Scalar extent() const { return (m_ub - m_lb) * Scalar(0.5); } 
-
-	
-	protected:
-		Scalar m_lb, m_ub;
-	};
-
-	template 
-	inline Interval 
-	operator+(const Interval& z1, const Interval& z2)
-	{
-		return Interval(z1.lower() + z2.lower(), 
-								z1.upper() + z2.upper());
-	}
-
-	template 
-	inline Interval 
-	operator-(const Interval& z1, const Interval& z2)
-	{
-		return Interval(z1.lower() - z2.upper(), 
-								z1.upper() - z2.lower());
-	}
-	
-	template 
-	inline std::ostream& 
-	operator<<(std::ostream& os, const Interval& z)
-	{
-		return os << '[' << z.lower() << ", " << z.upper() << ']';
-	}
-
-	template 
-	inline Scalar 
-	median(const Interval& z) 
-	{
-		return (z.lower() + z.upper()) * Scalar(0.5);
-	}
-	
-	template 
-	inline Scalar 
-	width(const Interval& z) 
-	{
-		return z.upper() - z.lower();
-	}
-	
-	template 
-	inline bool 
-	overlap(const Interval& z1, const Interval& z2) 
-	{
-		return z1.lower() <= z2.upper() && z2.lower() <= z1.upper();
-	}
-
-	template 
-	inline bool 
-	in(const Interval& z1, const Interval& z2) 
-	{
-		return z2.lower() <= z1.lower() && z1.upper() <= z2.upper();
-	}
-
-	template 
-	inline bool 
-	in(Scalar x, const Interval& z) 
-	{
-		return z.lower() <= x && x <= z.upper();
-	}
-	
-	template 
-	inline Interval 
-	widen(const Interval& z, const Scalar& x) 
-	{
-		return Interval(z.lower() - x, z.upper() + x);
-	}	
-		
-	template
-	inline Interval
-	hull(const Interval& z1, const Interval& z2)
-	{
-		return Interval(GEN_min(z1.lower(), z2.lower()), 
-								GEN_max(z1.upper(), z2.upper()));
-	}	
-   
-   template
-	inline Interval
-	operator+(Scalar x, const Interval& z)
-	{
-		return Interval(x + z.lower(), x + z.upper());
-	}
-}
-
-#endif
diff --git a/extern/solid/include/MT/Matrix3x3.h b/extern/solid/include/MT/Matrix3x3.h
deleted file mode 100644
index 85e0d4cac84..00000000000
--- a/extern/solid/include/MT/Matrix3x3.h
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef MATRIX3X3_H
-#define MATRIX3X3_H
-
-#if defined (__sgi)
-#include 
-#else
-#include 
-#endif
-
-#include "Vector3.h"
-#include "Quaternion.h"
-
-namespace MT {
-
-  // Row-major 3x3 matrix
-  
-	template 
-	class Matrix3x3 {
-	public:
-		Matrix3x3() {}
-		
-		template 
-		explicit Matrix3x3(const Scalar2 *m) { setValue(m); }
-		
-		explicit Matrix3x3(const Quaternion& q) { setRotation(q); }
-		
-		template 
-		Matrix3x3(const Scalar2& yaw, const Scalar2& pitch, const Scalar2& roll)
-		{ 
-			setEuler(yaw, pitch, roll);
-		}
-		
-		template 
-		Matrix3x3(const Scalar2& xx, const Scalar2& xy, const Scalar2& xz,
-				  const Scalar2& yx, const Scalar2& yy, const Scalar2& yz,
-				  const Scalar2& zx, const Scalar2& zy, const Scalar2& zz)
-		{ 
-			setValue(xx, xy, xz, 
-					 yx, yy, yz, 
-					 zx, zy, zz);
-		}
-		
-		Vector3&  operator[](int i)
-		{ 
-			assert(0 <= i && i < 3);
-			return m_el[i]; 
-		}
-		
-		const Vector3& operator[](int i) const
-		{
-			assert(0 <= i && i < 3);
-			return m_el[i]; 
-		}
-		
-		Matrix3x3& operator*=(const Matrix3x3& m); 
-		
-		template 
-		void setValue(const Scalar2 *m)
-		{
-			m_el[0][0] = Scalar(m[0]); 
-			m_el[1][0] = Scalar(m[1]); 
-			m_el[2][0] = Scalar(m[2]);
-			m_el[0][1] = Scalar(m[4]); 
-			m_el[1][1] = Scalar(m[5]); 
-			m_el[2][1] = Scalar(m[6]);
-			m_el[0][2] = Scalar(m[8]); 
-			m_el[1][2] = Scalar(m[9]); 
-			m_el[2][2] = Scalar(m[10]);
-		}
-
-		template 
-		void setValue(const Scalar2& xx, const Scalar2& xy, const Scalar2& xz, 
-					  const Scalar2& yx, const Scalar2& yy, const Scalar2& yz, 
-					  const Scalar2& zx, const Scalar2& zy, const Scalar2& zz)
-		{
-			m_el[0][0] = Scalar(xx); 
-			m_el[0][1] = Scalar(xy); 
-			m_el[0][2] = Scalar(xz);
-			m_el[1][0] = Scalar(yx); 
-			m_el[1][1] = Scalar(yy); 
-			m_el[1][2] = Scalar(yz);
-			m_el[2][0] = Scalar(zx); 
-			m_el[2][1] = Scalar(zy); 
-			m_el[2][2] = Scalar(zz);
-		}
-  
-		void setRotation(const Quaternion& q) 
-		{
-			Scalar d = q.length2();
-			assert(d != Scalar(0.0));
-			Scalar s = Scalar(2.0) / d;
-			Scalar xs = q[0] * s,   ys = q[1] * s,   zs = q[2] * s;
-			Scalar wx = q[3] * xs,  wy = q[3] * ys,  wz = q[3] * zs;
-			Scalar xx = q[0] * xs,  xy = q[0] * ys,  xz = q[0] * zs;
-			Scalar yy = q[1] * ys,  yz = q[1] * zs,  zz = q[2] * zs;
-			setValue(Scalar(1.0) - (yy + zz), xy - wz, xz + wy,
-					 xy + wz, Scalar(1.0) - (xx + zz), yz - wx,
-					 xz - wy, yz + wx, Scalar(1.0) - (xx + yy));
-		}
-		
-		template  
-		void setEuler(const Scalar2& yaw, const Scalar2& pitch, const Scalar2& roll) 
-		{
-			Scalar cy(Scalar_traits::cos(yaw)); 
-			Scalar sy(Scalar_traits::sin(yaw)); 
-			Scalar cp(Scalar_traits::cos(pitch)); 
-			Scalar sp(Scalar_traits::sin(pitch)); 
-			Scalar cr(Scalar_traits::cos(roll));
-			Scalar sr(Scalar_traits::sin(roll));
-			Scalar cc = cy * cr; 
-			Scalar cs = cy * sr; 
-			Scalar sc = sy * cr; 
-			Scalar ss = sy * sr;
-			setValue(cy * cp, -sc + sp * cs,  ss - sp * cc,
-					 sy * cp,  cc + sp * ss, -cs + sp * sc,
-					     -sp,       cp * sr,       cp * cr);
-		}
-		void setIdentity()
-		{ 
-			setValue(Scalar(1.0), Scalar(0.0), Scalar(0.0), 
-					 Scalar(0.0), Scalar(1.0), Scalar(0.0), 
-					 Scalar(0.0), Scalar(0.0), Scalar(1.0)); 
-		}
-    
-		template 
-		void getValue(Scalar2 *m) const 
-		{
-			m[0]  = Scalar2(m_el[0][0]); 
-			m[1]  = Scalar2(m_el[1][0]);
-			m[2]  = Scalar2(m_el[2][0]);
-			m[3]  = Scalar2(0.0); 
-			m[4]  = Scalar2(m_el[0][1]);
-			m[5]  = Scalar2(m_el[1][1]);
-			m[6]  = Scalar2(m_el[2][1]);
-			m[7]  = Scalar2(0.0); 
-			m[8]  = Scalar2(m_el[0][2]); 
-			m[9]  = Scalar2(m_el[1][2]);
-			m[10] = Scalar2(m_el[2][2]);
-			m[11] = Scalar2(0.0); 
-		}
-		
-		void getRotation(Quaternion& q) const
-		{
-			Scalar trace = m_el[0][0] + m_el[1][1] + m_el[2][2];
-			
-			if (trace > Scalar(0.0)) 
-			{
-				Scalar s = Scalar_traits::sqrt(trace + Scalar(1.0));
-				q[3] = s * Scalar(0.5);
-				s = Scalar(0.5) / s;
-				
-				q[0] = (m_el[2][1] - m_el[1][2]) * s;
-				q[1] = (m_el[0][2] - m_el[2][0]) * s;
-				q[2] = (m_el[1][0] - m_el[0][1]) * s;
-			} 
-			else 
-			{
-				int i = m_el[0][0] < m_el[1][1] ? 
-					(m_el[1][1] < m_el[2][2] ? 2 : 1) :
-					(m_el[0][0] < m_el[2][2] ? 2 : 0); 
-				int j = (i + 1) % 3;  
-				int k = (i + 2) % 3;
-				
-				Scalar s = Scalar_traits::sqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + Scalar(1.0));
-				q[i] = s * Scalar(0.5);
-				s = Scalar(0.5) / s;
-				
-				q[3] = (m_el[k][j] - m_el[j][k]) * s;
-				q[j] = (m_el[j][i] + m_el[i][j]) * s;
-				q[k] = (m_el[k][i] + m_el[i][k]) * s;
-			}
-		}
-
-
-		
-		template 
-		void getEuler(Scalar2& yaw, Scalar2& pitch, Scalar2& roll) const
-		{
-			pitch = Scalar2(Scalar_traits::asin(-m_el[2][0]));
-			if (pitch < Scalar_traits::TwoTimesPi())
-			{
-				if (pitch > Scalar_traits::TwoTimesPi())
-				{
-					yaw = Scalar2(Scalar_traits::atan2(m_el[1][0], m_el[0][0]));
-					roll = Scalar2(Scalar_traits::atan2(m_el[2][1], m_el[2][2]));
-				}
-				else 
-				{
-					yaw = Scalar2(-Scalar_traits::atan2(-m_el[0][1], m_el[0][2]));
-					roll = Scalar2(0.0);
-				}
-			}
-			else
-			{
-				yaw = Scalar2(Scalar_traits::atan2(-m_el[0][1], m_el[0][2]));
-				roll = Scalar2(0.0);
-			}
-		}
-
-		Vector3 getScaling() const
-		{
-			return Vector3(m_el[0][0] * m_el[0][0] + m_el[1][0] * m_el[1][0] + m_el[2][0] * m_el[2][0],
-								   m_el[0][1] * m_el[0][1] + m_el[1][1] * m_el[1][1] + m_el[2][1] * m_el[2][1],
-								   m_el[0][2] * m_el[0][2] + m_el[1][2] * m_el[1][2] + m_el[2][2] * m_el[2][2]);
-		}
-		
-		
-		Matrix3x3 scaled(const Vector3& s) const
-		{
-			return Matrix3x3(m_el[0][0] * s[0], m_el[0][1] * s[1], m_el[0][2] * s[2],
-									 m_el[1][0] * s[0], m_el[1][1] * s[1], m_el[1][2] * s[2],
-									 m_el[2][0] * s[0], m_el[2][1] * s[1], m_el[2][2] * s[2]);
-		}
-
-		Scalar            determinant() const;
-		Matrix3x3 adjoint() const;
-		Matrix3x3 absolute() const;
-		Matrix3x3 transpose() const;
-		Matrix3x3 inverse() const; 
-		
-		Matrix3x3 transposeTimes(const Matrix3x3& m) const;
-		Matrix3x3 timesTranspose(const Matrix3x3& m) const;
-		
-		Scalar tdot(int c, const Vector3& v) const 
-		{
-			return m_el[0][c] * v[0] + m_el[1][c] * v[1] + m_el[2][c] * v[2];
-		}
-		
-	protected:
-		Scalar cofac(int r1, int c1, int r2, int c2) const 
-		{
-			return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1];
-		}
-
-		Vector3 m_el[3];
-	};
-	
-	template 
-	inline std::ostream& 
-	operator<<(std::ostream& os, const Matrix3x3& m)
-	{
-		return os << m[0] << std::endl << m[1] << std::endl << m[2] << std::endl;
-	}
-	
-	template 
-	inline Matrix3x3& 
-	Matrix3x3::operator*=(const Matrix3x3& m)
-	{
-		setValue(m.tdot(0, m_el[0]), m.tdot(1, m_el[0]), m.tdot(2, m_el[0]),
-				 m.tdot(0, m_el[1]), m.tdot(1, m_el[1]), m.tdot(2, m_el[1]),
-				 m.tdot(0, m_el[2]), m.tdot(1, m_el[2]), m.tdot(2, m_el[2]));
-		return *this;
-	}
-	
-	template 
-	inline Scalar 
-	Matrix3x3::determinant() const
-	{ 
-		return triple((*this)[0], (*this)[1], (*this)[2]);
-	}
-	
-
-	template 
-	inline Matrix3x3 
-	Matrix3x3::absolute() const
-	{
-		return Matrix3x3(
-			Scalar_traits::abs(m_el[0][0]), Scalar_traits::abs(m_el[0][1]), Scalar_traits::abs(m_el[0][2]),
-			Scalar_traits::abs(m_el[1][0]), Scalar_traits::abs(m_el[1][1]), Scalar_traits::abs(m_el[1][2]),
-			Scalar_traits::abs(m_el[2][0]), Scalar_traits::abs(m_el[2][1]), Scalar_traits::abs(m_el[2][2]));
-	}
-
-	template 
-	inline Matrix3x3 
-	Matrix3x3::transpose() const 
-	{
-		return Matrix3x3(m_el[0][0], m_el[1][0], m_el[2][0],
-								 m_el[0][1], m_el[1][1], m_el[2][1],
-								 m_el[0][2], m_el[1][2], m_el[2][2]);
-	}
-	
-	template 
-	inline Matrix3x3 
-	Matrix3x3::adjoint() const 
-	{
-		return Matrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2),
-								 cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0),
-								 cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1));
-	}
-	
-	template 
-	inline Matrix3x3 
-	Matrix3x3::inverse() const
-	{
-		Vector3 co(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1));
-		Scalar det = (*this)[0].dot(co);
-		assert(det != Scalar(0.0));
-		Scalar s = Scalar(1.0) / det;
-		return Matrix3x3(co[0] * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
-								 co[1] * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
-								 co[2] * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
-	}
-	
-	template 
-	inline Matrix3x3 
-	Matrix3x3::transposeTimes(const Matrix3x3& m) const
-	{
-		return Matrix3x3(
-			m_el[0][0] * m[0][0] + m_el[1][0] * m[1][0] + m_el[2][0] * m[2][0],
-			m_el[0][0] * m[0][1] + m_el[1][0] * m[1][1] + m_el[2][0] * m[2][1],
-			m_el[0][0] * m[0][2] + m_el[1][0] * m[1][2] + m_el[2][0] * m[2][2],
-			m_el[0][1] * m[0][0] + m_el[1][1] * m[1][0] + m_el[2][1] * m[2][0],
-			m_el[0][1] * m[0][1] + m_el[1][1] * m[1][1] + m_el[2][1] * m[2][1],
-			m_el[0][1] * m[0][2] + m_el[1][1] * m[1][2] + m_el[2][1] * m[2][2],
-			m_el[0][2] * m[0][0] + m_el[1][2] * m[1][0] + m_el[2][2] * m[2][0],
-			m_el[0][2] * m[0][1] + m_el[1][2] * m[1][1] + m_el[2][2] * m[2][1],
-			m_el[0][2] * m[0][2] + m_el[1][2] * m[1][2] + m_el[2][2] * m[2][2]);
-	}
-	
-	template 
-	inline Matrix3x3 
-	Matrix3x3::timesTranspose(const Matrix3x3& m) const
-	{
-		return Matrix3x3(
-			m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]),
-			m_el[1].dot(m[0]), m_el[1].dot(m[1]), m_el[1].dot(m[2]),
-			m_el[2].dot(m[0]), m_el[2].dot(m[1]), m_el[2].dot(m[2]));
-		
-	}
-
-	template 
-	inline Vector3 
-	operator*(const Matrix3x3& m, const Vector3& v) 
-	{
-		return Vector3(m[0].dot(v), m[1].dot(v), m[2].dot(v));
-	}
-	
-
-	template 
-	inline Vector3
-	operator*(const Vector3& v, const Matrix3x3& m)
-	{
-		return Vector3(m.tdot(0, v), m.tdot(1, v), m.tdot(2, v));
-	}
-
-	template 
-	inline Matrix3x3 
-	operator*(const Matrix3x3& m1, const Matrix3x3& m2)
-	{
-		return Matrix3x3(
-			m2.tdot(0, m1[0]), m2.tdot(1, m1[0]), m2.tdot(2, m1[0]),
-			m2.tdot(0, m1[1]), m2.tdot(1, m1[1]), m2.tdot(2, m1[1]),
-			m2.tdot(0, m1[2]), m2.tdot(1, m1[2]), m2.tdot(2, m1[2]));
-	}
-}
-
-#endif
diff --git a/extern/solid/include/MT/Quaternion.h b/extern/solid/include/MT/Quaternion.h
deleted file mode 100644
index a925f21cd5d..00000000000
--- a/extern/solid/include/MT/Quaternion.h
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef QUATERNION_H
-#define QUATERNION_H
-
-#if defined (__sgi)
-#include 
-#else
-#include 
-#endif
-
-#include "Tuple4.h"
-#include "Vector3.h"
-
-namespace MT {
-
-	template 	
-	class Quaternion : public Tuple4 {
-	public:
-		Quaternion() {}
-		
-		template 
-		explicit Quaternion(const Scalar2 *v) : Tuple4(v) {}
-		
-		template 
-		Quaternion(const Scalar2& x, const Scalar2& y, const Scalar2& z, const Scalar2& w) 
-			: Tuple4(x, y, z, w) 
-		{}
-		
-		Quaternion(const Vector3& axis, const Scalar& angle) 
-		{ 
-			setRotation(axis, angle); 
-		}
-
-		template 
-		Quaternion(const Scalar2& yaw, const Scalar2& pitch, const Scalar2& roll)
-		{ 
-			setEuler(yaw, pitch, roll); 
-		}
-
-		void setRotation(const Vector3& axis, const Scalar& angle)
-		{
-			Scalar d = axis.length();
-			assert(d != Scalar(0.0));
-			Scalar s = Scalar_traits::sin(angle * Scalar(0.5)) / d;
-			setValue(axis[0] * s, axis[1] * s, axis[2] * s, 
-					 Scalar_traits::cos(angle * Scalar(0.5)));
-		}
-
-		template 
-		void setEuler(const Scalar2& yaw, const Scalar2& pitch, const Scalar2& roll)
-		{
-			Scalar halfYaw = Scalar(yaw) * Scalar(0.5);  
-			Scalar halfPitch = Scalar(pitch) * Scalar(0.5);  
-			Scalar halfRoll = Scalar(roll) * Scalar(0.5);  
-			Scalar cosYaw = Scalar_traits::cos(halfYaw);
-			Scalar sinYaw = Scalar_traits::sin(halfYaw);
-			Scalar cosPitch = Scalar_traits::cos(halfPitch);
-			Scalar sinPitch = Scalar_traits::sin(halfPitch);
-			Scalar cosRoll = Scalar_traits::cos(halfRoll);
-			Scalar sinRoll = Scalar_traits::sin(halfRoll);
-			setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
-					 cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
-					 sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
-					 cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
-		}
-  
-		Quaternion& operator+=(const Quaternion& q)
-		{
-			this->m_co[0] += q[0]; this->m_co[1] += q[1]; this->m_co[2] += q[2]; this->m_co[3] += q[3];
-			return *this;
-		}
-		
-		Quaternion& operator-=(const Quaternion& q) 
-		{
-			this->m_co[0] -= q[0]; this->m_co[1] -= q[1]; this->m_co[2] -= q[2]; this->m_co[3] -= q[3];
-			return *this;
-		}
-
-		Quaternion& operator*=(const Scalar& s)
-		{
-			this->m_co[0] *= s; this->m_co[1] *= s; this->m_co[2] *= s; this->m_co[3] *= s;
-			return *this;
-		}
-		
-		Quaternion& operator/=(const Scalar& s) 
-		{
-			assert(s != Scalar(0.0));
-			return *this *= Scalar(1.0) / s;
-		}
-  
-		Quaternion& operator*=(const Quaternion& q)
-		{
-			setValue(this->m_co[3] * q[0] + this->m_co[0] * q[3] + this->m_co[1] * q[2] - this->m_co[2] * q[1],
-					 this->m_co[3] * q[1] + this->m_co[1] * q[3] + this->m_co[2] * q[0] - this->m_co[0] * q[2],
-					 this->m_co[3] * q[2] + this->m_co[2] * q[3] + this->m_co[0] * q[1] - this->m_co[1] * q[0],
-					 this->m_co[3] * q[3] - this->m_co[0] * q[0] - this->m_co[1] * q[1] - this->m_co[2] * q[2]);
-			return *this;
-		}
-	
-		Scalar dot(const Quaternion& q) const
-		{
-			return this->m_co[0] * q[0] + this->m_co[1] * q[1] + this->m_co[2] * q[2] + this->m_co[3] * q[3];
-		}
-
-		Scalar length2() const
-		{
-			return dot(*this);
-		}
-
-		Scalar length() const
-		{
-			return Scalar_traits::sqrt(length2());
-		}
-
-		Quaternion& normalize() 
-		{
-			return *this /= length();
-		}
-		
-		Quaternion normalized() const 
-		{
-			return *this / length();
-		} 
-
-		Scalar angle(const Quaternion& q) const 
-		{
-			Scalar s = Scalar_traits::sqrt(length2() * q.length2());
-			assert(s != Scalar(0.0));
-			return Scalar_traits::acos(dot(q) / s);
-		}
-   
-		Quaternion conjugate() const 
-		{
-			return Quaternion(-this->m_co[0], -this->m_co[1], -this->m_co[2], this->m_co[3]);
-		}
-
-		Quaternion inverse() const
-		{
-			return conjugate / length2();
-		}
-		
-		Quaternion slerp(const Quaternion& q, const Scalar& t) const
-		{
-			Scalar theta = angle(q);
-			if (theta != Scalar(0.0))
-			{
-				Scalar d = Scalar(1.0) / Scalar_traits::sin(theta);
-				Scalar s0 = Scalar_traits::sin((Scalar(1.0) - t) * theta);
-				Scalar s1 = Scalar_traits::sin(t * theta);   
-				return Quaternion((this->m_co[0] * s0 + q[0] * s1) * d,
-										  (this->m_co[1] * s0 + q[1] * s1) * d,
-										  (this->m_co[2] * s0 + q[2] * s1) * d,
-										  (this->m_co[3] * s0 + q[3] * s1) * d);
-			}
-			else
-			{
-				return *this;
-			}
-		}
-
-		static Quaternion random() 
-		{
-			// From: "Uniform Random Rotations", Ken Shoemake, Graphics Gems III, 
-            //       pg. 124-132
-			Scalar x0 = Scalar_traits::random();
-			Scalar r1 = Scalar_traits::sqrt(Scalar(1.0) - x0);
-			Scalar r2 = Scalar_traits::sqrt(x0);
-			Scalar t1 = Scalar_traits::TwoTimesPi() * Scalar_traits::random();
-			Scalar t2 = Scalar_traits::TwoTimesPi() * Scalar_traits::random();
-			Scalar c1 = Scalar_traits::cos(t1);
-			Scalar s1 = Scalar_traits::sin(t1);
-			Scalar c2 = Scalar_traits::cos(t2);
-			Scalar s2 = Scalar_traits::sin(t2);
-			return Quaternion(s1 * r1, c1 * r1, s2 * r2, c2 * r2);
-		}
-
-	};
-
-	template 
-	inline Quaternion
-	operator+(const Quaternion& q1, const Quaternion& q2)
-	{
-		return Quaternion(q1[0] + q2[0], q1[1] + q2[1], q1[2] + q2[2], q1[3] + q2[3]);
-	}
-	
-	template 
-	inline Quaternion
-	operator-(const Quaternion& q1, const Quaternion& q2)
-	{
-		return Quaternion(q1[0] - q2[0], q1[1] - q2[1], q1[2] - q2[2], q1[3] - q2[3]);
-	}
-	
-	template 
-	inline Quaternion
-	operator-(const Quaternion& q)
-	{
-		return Quaternion(-q[0], -q[1], -q[2], -q[3]);
-	}
-
-	template 
-	inline Quaternion
-	operator*(const Quaternion& q, const Scalar& s)
-	{
-		return Quaternion(q[0] * s, q[1] * s, q[2] * s, q[3] * s);
-	}
-	
-	template 
-	inline Quaternion
-	operator*(const Scalar& s, const Quaternion& q)
-	{
-		return q * s;
-	}
-	
-	template 
-	inline Quaternion
-	operator*(const Quaternion& q1, const Quaternion& q2) {
-		return Quaternion(q1[3] * q2[0] + q1[0] * q2[3] + q1[1] * q2[2] - q1[2] * q2[1],
-								  q1[3] * q2[1] + q1[1] * q2[3] + q1[2] * q2[0] - q1[0] * q2[2],
-								  q1[3] * q2[2] + q1[2] * q2[3] + q1[0] * q2[1] - q1[1] * q2[0],
-								  q1[3] * q2[3] - q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2]); 
-	}
-	
-	template 
-	inline Quaternion
-	operator*(const Quaternion& q, const Vector3& w)
-	{
-		return Quaternion( q[3] * w[0] + q[1] * w[2] - q[2] * w[1],
-								   q[3] * w[1] + q[2] * w[0] - q[0] * w[2],
-								   q[3] * w[2] + q[0] * w[1] - q[1] * w[0],
-								  -q[0] * w[0] - q[1] * w[1] - q[2] * w[2]); 
-	}
-	
-	template 
-	inline Quaternion
-	operator*(const Vector3& w, const Quaternion& q)
-	{
-		return Quaternion( w[0] * q[3] + w[1] * q[2] - w[2] * q[1],
-								   w[1] * q[3] + w[2] * q[0] - w[0] * q[2],
-								   w[2] * q[3] + w[0] * q[1] - w[1] * q[0],
-								  -w[0] * q[0] - w[1] * q[1] - w[2] * q[2]); 
-	}
-	
-	template 
-	inline Scalar 
-	dot(const Quaternion& q1, const Quaternion& q2) 
-	{ 
-		return q1.dot(q2); 
-	}
-
-	template 
-	inline Scalar
-	length2(const Quaternion& q) 
-	{ 
-		return q.length2(); 
-	}
-
-	template 
-	inline Scalar
-	length(const Quaternion& q) 
-	{ 
-		return q.length(); 
-	}
-
-	template 
-	inline Scalar
-	angle(const Quaternion& q1, const Quaternion& q2) 
-	{ 
-		return q1.angle(q2); 
-	}
-
-	template 
-	inline Quaternion
-	conjugate(const Quaternion& q) 
-	{
-		return q.conjugate();
-	}
-
-	template 
-	inline Quaternion
-	inverse(const Quaternion& q) 
-	{
-		return q.inverse();
-	}
-
-	template 
-	inline Quaternion
-	slerp(const Quaternion& q1, const Quaternion& q2, const Scalar& t) 
-	{
-		return q1.slerp(q2, t);
-	}
-	
-}
-
-#endif
diff --git a/extern/solid/include/MT/Transform.h b/extern/solid/include/MT/Transform.h
deleted file mode 100644
index b80dc1bc18b..00000000000
--- a/extern/solid/include/MT/Transform.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef TRANSFORM_H
-#define TRANSFORM_H
-
-#include "Vector3.h"
-#include "Matrix3x3.h"
-
-namespace MT {
-
-	template 
-	class Transform {
-		enum { 
-			TRANSLATION = 0x01,
-			ROTATION    = 0x02,
-			RIGID       = TRANSLATION | ROTATION,  
-			SCALING     = 0x04,
-			LINEAR      = ROTATION | SCALING,
-			AFFINE      = TRANSLATION | LINEAR
-		};
-    
-	public:
-		Transform() {}
-		
-		template 
-		explicit Transform(const Scalar2 *m) { setValue(m); }
-
-		explicit Transform(const Quaternion& q, 
-						   const Vector3& c = Vector3(Scalar(0), Scalar(0), Scalar(0))) 
-			: m_basis(q),
-			  m_origin(c),
-			  m_type(RIGID)
-		{}
-
-		explicit Transform(const Matrix3x3& b, 
-						   const Vector3& c = Vector3(Scalar(0), Scalar(0), Scalar(0)), 
-						   unsigned int type = AFFINE)
-			: m_basis(b),
-			  m_origin(c),
-			  m_type(type)
-		{}
-
-		Vector3 operator()(const Vector3& x) const
-		{
-			return Vector3(m_basis[0].dot(x) + m_origin[0], 
-								   m_basis[1].dot(x) + m_origin[1], 
-								   m_basis[2].dot(x) + m_origin[2]);
-		}
-    
-		Vector3 operator*(const Vector3& x) const
-		{
-			return (*this)(x);
-		}
-
-		Matrix3x3&       getBasis()          { return m_basis; }
-		const Matrix3x3& getBasis()    const { return m_basis; }
-
-		Vector3&         getOrigin()         { return m_origin; }
-		const Vector3&   getOrigin()   const { return m_origin; }
-
-		Quaternion getRotation() const { return m_basis.getRotation(); }
-		template 
-		void setValue(const Scalar2 *m) 
-		{
-			m_basis.setValue(m);
-			m_origin.setValue(&m[12]);
-			m_type = AFFINE;
-		}
-
-		template 
-		void getValue(Scalar2 *m) const 
-		{
-			m_basis.getValue(m);
-			m_origin.getValue(&m[12]);
-			m[15] = Scalar2(1.0);
-		}
-
-		void setOrigin(const Vector3& origin) 
-		{ 
-			m_origin = origin;
-			m_type |= TRANSLATION;
-		}
-
-		void setBasis(const Matrix3x3& basis)
-		{ 
-			m_basis = basis;
-			m_type |= LINEAR;
-		}
-
-		void setRotation(const Quaternion& q)
-		{
-			m_basis.setRotation(q);
-			m_type = (m_type & ~LINEAR) | ROTATION;
-		}
-
-    	void scale(const Vector3& scaling)
-		{
-			m_basis = m_basis.scaled(scaling);
-			m_type |= SCALING;
-		}
-    
-		void setIdentity()
-		{
-			m_basis.setIdentity();
-			m_origin.setValue(Scalar(0.0), Scalar(0.0), Scalar(0.0));
-			m_type = 0x0;
-		}
-		
-		bool isIdentity() const { return m_type == 0x0; }
-    
-		Transform& operator*=(const Transform& t) 
-		{
-			m_origin += m_basis * t.m_origin;
-			m_basis *= t.m_basis;
-			m_type |= t.m_type; 
-			return *this;
-		}
-
-		Transform inverse() const
-		{ 
-			Matrix3x3 inv = (m_type & SCALING) ? 
-				                    m_basis.inverse() : 
-				                    m_basis.transpose();
-			
-			return Transform(inv, inv * -m_origin, m_type);
-		}
-
-		Transform inverseTimes(const Transform& t) const;  
-
-		Transform operator*(const Transform& t) const;
-
-	private:
-		
-		Matrix3x3 m_basis;
-		Vector3   m_origin;
-		unsigned int      m_type;
-	};
-
-
-	template 
-	inline Transform 
-	Transform::inverseTimes(const Transform& t) const  
-	{
-		Vector3 v = t.getOrigin() - m_origin;
-		if (m_type & SCALING) 
-		{
-			Matrix3x3 inv = m_basis.inverse();
-			return Transform(inv * t.getBasis(), inv * v, 
-									 m_type | t.m_type);
-		}
-		else 
-		{
-			return Transform(m_basis.transposeTimes(t.m_basis),
-									 v * m_basis, m_type | t.m_type);
-		}
-	}
-
-	template 
-	inline Transform 
-	Transform::operator*(const Transform& t) const
-	{
-		return Transform(m_basis * t.m_basis, 
-								 (*this)(t.m_origin), 
-								 m_type | t.m_type);
-	}	
-}
-
-#endif
diff --git a/extern/solid/include/MT/Tuple3.h b/extern/solid/include/MT/Tuple3.h
deleted file mode 100644
index 52ea33b7f58..00000000000
--- a/extern/solid/include/MT/Tuple3.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef TUPLE3_H
-#define TUPLE3_H
-
-#if defined (__sgi)
-#include 
-#else
-#include 
-#endif
-
-#include 
-
-namespace MT {
-
-	template 
-	class Tuple3 {
-	public:
-		Tuple3() {}
-		
-		template 
-		explicit Tuple3(const Scalar2 *v) 
-		{ 
-			setValue(v);
-		}
-		
-		template 
-		Tuple3(const Scalar2& x, const Scalar2& y, const Scalar2& z) 
-		{ 
-			setValue(x, y, z); 
-		}
-		
-		template 
-		Tuple3(const Tuple3& t) 
-		{ 
-			*this = t; 
-		}
-		
-		template 
-		Tuple3& operator=(const Tuple3& t) 
-		{ 
-			m_co[0] = Scalar(t[0]); 
-			m_co[1] = Scalar(t[1]); 
-			m_co[2] = Scalar(t[2]);
-			return *this;
-		}
-		
-		operator       Scalar *()       { return m_co; }
-		operator const Scalar *() const { return m_co; }
-
-		Scalar&       operator[](int i)       { return m_co[i];	}      
-		const Scalar& operator[](int i) const { return m_co[i]; }
-
-		Scalar&       x()       { return m_co[0]; }
-		const Scalar& x() const { return m_co[0]; }
-		
-		Scalar&       y()       { return m_co[1]; }
-		const Scalar& y() const { return m_co[1]; }
-		
-		Scalar&       z()       { return m_co[2]; }
-		const Scalar& z() const { return m_co[2]; }
-
-		template 
-		void setValue(const Scalar2 *v) 
-		{
-			m_co[0] = Scalar(v[0]); 
-			m_co[1] = Scalar(v[1]); 
-			m_co[2] = Scalar(v[2]);
-		}
-
-		template 
-		void setValue(const Scalar2& x, const Scalar2& y, const Scalar2& z)
-		{
-			m_co[0] = Scalar(x); 
-			m_co[1] = Scalar(y); 
-			m_co[2] = Scalar(z);
-		}
-
-		template 
-		void getValue(Scalar2 *v) const 
-		{
-			v[0] = Scalar2(m_co[0]);
-			v[1] = Scalar2(m_co[1]);
-			v[2] = Scalar2(m_co[2]);
-		}
-    
-	protected:
-		Scalar m_co[3];                            
-	};
-
-	template 
-	inline std::ostream& 
-	operator<<(std::ostream& os, const Tuple3& t)
-	{
-		return os << t[0] << ' ' << t[1] << ' ' << t[2];
-	}
-}
-
-#endif
diff --git a/extern/solid/include/MT/Tuple4.h b/extern/solid/include/MT/Tuple4.h
deleted file mode 100644
index 6930541271e..00000000000
--- a/extern/solid/include/MT/Tuple4.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef TUPLE4_H
-#define TUPLE4_H
-
-#if defined (__sgi)
-#include 
-#else
-#include 
-#endif
-
-#include 
-
-namespace MT {
-
-	template 
-	class Tuple4 {
-	public:
-		Tuple4() {}
-		
-		template 
-		explicit Tuple4(const Scalar2 *v) 
-		{ 
-			setValue(v);
-		}
-		
-		template 
-		Tuple4(const Scalar2& x, const Scalar2& y, const Scalar2& z, const Scalar2& w) 
-		{ 
-			setValue(x, y, z, w); 
-		}
-		
-		operator       Scalar *()       { return m_co; }
-		operator const Scalar *() const { return m_co; }
-
-		Scalar&       operator[](int i)       { return m_co[i]; }      
-		const Scalar& operator[](int i) const {	return m_co[i];	}
-		
-		Scalar&       x()       { return m_co[0]; }
-		const Scalar& x() const { return m_co[0]; }
-		
-		Scalar&       y()       { return m_co[1]; }
-		const Scalar& y() const { return m_co[1]; }
-		
-		Scalar&       z()       { return m_co[2]; }
-		const Scalar& z() const { return m_co[2]; }
-
-		Scalar&       w()       { return m_co[3]; }
-		const Scalar& w() const { return m_co[3]; }
-    
-		template 
-		void setValue(const Scalar2 *v) 
-		{
-			m_co[0] = Scalar(v[0]); 
-			m_co[1] = Scalar(v[1]); 
-			m_co[2] = Scalar(v[2]);
-			m_co[3] = Scalar(v[3]);
-		}
-
-		template 
-		void setValue(const Scalar2& x, const Scalar2& y, const Scalar2& z, const Scalar2& w)
-		{
-			m_co[0] = Scalar(x); 
-			m_co[1] = Scalar(y); 
-			m_co[2] = Scalar(z);
-			m_co[3] = Scalar(w);
-		}
-
-		template 
-		void getValue(Scalar2 *v) const 
-		{
-			v[0] = Scalar2(m_co[0]);
-			v[1] = Scalar2(m_co[1]);
-			v[2] = Scalar2(m_co[2]);
-			v[3] = Scalar2(m_co[3]);
-		}
-
-	protected:
-		Scalar m_co[4];
-	};
-
-	template 
-	inline std::ostream&
-	operator<<(std::ostream& os, const Tuple4& t)
-	{
-		return os << t[0] << ' ' << t[1] << ' ' << t[2] << ' ' << t[3];
-	}
-
-}
-
-#endif
diff --git a/extern/solid/include/MT/Vector3.h b/extern/solid/include/MT/Vector3.h
deleted file mode 100644
index b569c003f59..00000000000
--- a/extern/solid/include/MT/Vector3.h
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef VECTOR3_H
-#define VECTOR3_H
-
-#if defined (__sgi)
-#include 
-#else
-#include 
-#endif
-
-#include "Tuple3.h"
-
-namespace MT {
-
-	template 	
-	class Vector3 : public Tuple3 {
-	public:
-		Vector3() {}
-	
-		template 
-		explicit Vector3(const Scalar2 *v) : Tuple3(v) {}
-		
-		template 
-		Vector3(const Scalar2& x, const Scalar2& y, const Scalar2& z) 
-			: Tuple3(x, y, z) 
-		{}
-		
-		Vector3& operator+=(const Vector3& v)
-		{
-			this->m_co[0] += v[0]; this->m_co[1] += v[1]; this->m_co[2] += v[2];
-			return *this;
-		}
-		
-		Vector3& operator-=(const Vector3& v) 
-		{
-			this->m_co[0] -= v[0]; this->m_co[1] -= v[1]; this->m_co[2] -= v[2];
-			return *this;
-		}
-
-		Vector3& operator*=(const Scalar& s)
-		{
-			this->m_co[0] *= s; this->m_co[1] *= s; this->m_co[2] *= s;
-			return *this;
-		}
-		
-		Vector3& operator/=(const Scalar& s) 
-		{
-			assert(s != Scalar(0.0));
-			return *this *= Scalar(1.0) / s;
-		}
-  
-		Scalar dot(const Vector3& v) const
-		{
-			return this->m_co[0] * v[0] + this->m_co[1] * v[1] + this->m_co[2] * v[2];
-		}
-
-		Scalar length2() const
-		{
-			return dot(*this);
-		}
-
-		Scalar length() const
-		{
-			return Scalar_traits::sqrt(length2());
-		}
-
-		Scalar distance2(const Vector3& v) const 
-		{
-			return (v - *this).length2();
-		}
-
-		Scalar distance(const Vector3& v) const 
-		{
-			return (v - *this).length();
-		}
-		
-		Vector3& normalize() 
-		{
-			return *this /= length();
-		}
-		
-		Vector3 normalized() const 
-		{
-			return *this / length();
-		} 
-
-		Scalar angle(const Vector3& v) const 
-		{
-			Scalar s = Scalar_traits::sqrt(length2() * v.length2());
-			assert(s != Scalar(0.0));
-			return Scalar_traits::acos(dot(v) / s);
-		}
-   
-		Vector3 absolute() const 
-		{
-			return Vector3(Scalar_traits::abs(this->m_co[0]), 
-								   Scalar_traits::abs(this->m_co[1]), 
-								   Scalar_traits::abs(this->m_co[2]));
-		}
-
-		Vector3 cross(const Vector3& v) const
-		{
-			return Vector3(this->m_co[1] * v[2] - this->m_co[2] * v[1],
-								   this->m_co[2] * v[0] - this->m_co[0] * v[2],
-								   this->m_co[0] * v[1] - this->m_co[1] * v[0]);
-		}
-		
-		Scalar triple(const Vector3& v1, const Vector3& v2) const
-		{
-			return this->m_co[0] * (v1[1] * v2[2] - v1[2] * v2[1]) + 
-				   this->m_co[1] * (v1[2] * v2[0] - v1[0] * v2[2]) + 
-				   this->m_co[2] * (v1[0] * v2[1] - v1[1] * v2[0]);
-		}
-
-		int minAxis() const
-		{
-			return this->m_co[0] < this->m_co[1] ? (this->m_co[0] < this->m_co[2] ? 0 : 2) : (this->m_co[1] < this->m_co[2] ? 1 : 2);
-		}
-
-		int maxAxis() const 
-		{
-			return this->m_co[0] < this->m_co[1] ? (this->m_co[1] < this->m_co[2] ? 2 : 1) : (this->m_co[0] < this->m_co[2] ? 2 : 0);
-		}
-
-		int furthestAxis() const
-		{
-			return absolute().minAxis();
-		}
-
-		int closestAxis() const 
-		{
-			return absolute().maxAxis();
-		}
-
-		Vector3 lerp(const Vector3& v, const Scalar& t) const 
-		{
-			return Vector3(this->m_co[0] + (v[0] - this->m_co[0]) * t,
-								   this->m_co[1] + (v[1] - this->m_co[1]) * t,
-								   this->m_co[2] + (v[2] - this->m_co[2]) * t);
-		}
-    
-		static Vector3 random() 
-		{
-			Scalar z = Scalar(2.0) * Scalar_traits::random() - Scalar(1.0);
-			Scalar r = Scalar_traits::sqrt(Scalar(1.0) - z * z);
-			Scalar t = Scalar_traits::TwoTimesPi() * Scalar_traits::random();
-			return Vector3(r * Scalar_traits::cos(t), 
-								   r * Scalar_traits::sin(t), 
-								   z);
-		}
-	};
-
-	template 
-	inline Vector3 
-	operator+(const Vector3& v1, const Vector3& v2) 
-	{
-		return Vector3(v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]);
-	}
-
-	template 
-	inline Vector3 
-	operator-(const Vector3& v1, const Vector3& v2)
-	{
-		return Vector3(v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]);
-	}
-	
-	template 
-	inline Vector3 
-	operator-(const Vector3& v)
-	{
-		return Vector3(-v[0], -v[1], -v[2]);
-	}
-	
-	template 
-	inline Vector3 
-	operator*(const Vector3& v, const Scalar& s)
-	{
-		return Vector3(v[0] * s, v[1] * s, v[2] * s);
-	}
-	
-	template 
-	inline Vector3 
-	operator*(const Scalar& s, const Vector3& v)
-	{ 
-		return v * s; 
-	}
-	
-	template 
-	inline Vector3
-	operator/(const Vector3& v, const Scalar& s)
-	{
-		assert(s != Scalar(0.0));
-		return v * (Scalar(1.0) / s);
-	}
-	
-	template 
-	inline Scalar 
-	dot(const Vector3& v1, const Vector3& v2) 
-	{ 
-		return v1.dot(v2); 
-	}
-	
-	template 
-	inline Scalar
-	length2(const Vector3& v) 
-	{ 
-		return v.length2(); 
-	}
-
-	template 
-	inline Scalar
-	length(const Vector3& v) 
-	{ 
-		return v.length(); 
-	}
-
-	template 
-	inline Scalar
-	distance2(const Vector3& v1, const Vector3& v2) 
-	{ 
-		return v1.distance2(v2); 
-	}
-
-	template 
-	inline Scalar
-	distance(const Vector3& v1, const Vector3& v2) 
-	{ 
-		return v1.distance(v2); 
-	}
-
-	template 
-	inline Scalar
-	angle(const Vector3& v1, const Vector3& v2) 
-	{ 
-		return v1.angle(v2); 
-	}
-
-	template 
-	inline Vector3 
-	cross(const Vector3& v1, const Vector3& v2) 
-	{ 
-		return v1.cross(v2); 
-	}
-
-	template 
-	inline Scalar
-	triple(const Vector3& v1, const Vector3& v2, const Vector3& v3)
-	{
-		return v1.triple(v2, v3);
-	}
-
-	template 
-	inline Vector3 
-	lerp(const Vector3& v1, const Vector3& v2, const Scalar& t)
-	{
-		return v1.lerp(v2, t);
-	}
-
-}
-
-#endif
diff --git a/extern/solid/include/MT_BBox.h b/extern/solid/include/MT_BBox.h
deleted file mode 100644
index b5dc537e0d9..00000000000
--- a/extern/solid/include/MT_BBox.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef MT_BBOX_H
-#define MT_BBOX_H
-
-#include "MT_Scalar.h"
-#include "MT_Point3.h"
-#include "MT_Vector3.h"
-
-#include  
-#include "MT_Interval.h" 
-
-
-
-class MT_BBox : public MT::Tuple3 {
-public:
-    MT_BBox() {}
-	MT_BBox(const MT_Point3& p)
-		: MT::Tuple3(MT_Interval(p[0]), 
-				                  MT_Interval(p[1]), 
-				                  MT_Interval(p[2]))
-	{}
-	MT_BBox(const MT_Point3& lb, const MT_Point3& ub)
-		: MT::Tuple3(MT_Interval(lb[0], ub[0]),
-				                  MT_Interval(lb[1], ub[1]),
-				                  MT_Interval(lb[2], ub[2]))
-	{}
-	MT_BBox(const MT_Interval& x, const MT_Interval& y, const MT_Interval& z) 
-		: MT::Tuple3(x, y, z) 
-	{}
-
-	MT_Point3 getMin() const 
-	{ 
-		return MT_Point3(m_co[0].lower(), m_co[1].lower(), m_co[2].lower());
-	}
-
-	MT_Point3 getMax() const 
-	{ 
-		return MT_Point3(m_co[0].upper(), m_co[1].upper(), m_co[2].upper());
-	}
-	
-	MT_Point3 getCenter() const
-	{
-		return MT_Point3(MT::median(m_co[0]), MT::median(m_co[1]), MT::median(m_co[2]));
-	}
-
-	MT_Vector3 getExtent() const
-	{
-		return MT_Vector3(MT::width(m_co[0]) * MT_Scalar(0.5), MT::width(m_co[1]) * MT_Scalar(0.5), MT::width(m_co[2]) * MT_Scalar(0.5));
-	}
-
-	void extend(const MT_Vector3& v) 
-	{
-		m_co[0] = MT::widen(m_co[0], v[0]);
-		m_co[1] = MT::widen(m_co[1], v[1]);
-		m_co[2] = MT::widen(m_co[2], v[2]);
-	}
-
-    bool overlaps(const MT_BBox& b) const 
-	{
-        return MT::overlap(m_co[0], b[0]) &&
-			   MT::overlap(m_co[1], b[1]) &&
-			   MT::overlap(m_co[2], b[2]);
-    }
-
-	bool inside(const MT_BBox& b) const 
-	{
-        return MT::in(m_co[0], b[0]) &&
-			   MT::in(m_co[1], b[1]) &&
-			   MT::in(m_co[2], b[2]);
-    }
-
-	MT_BBox hull(const MT_BBox& b) const 
-	{
-		return MT_BBox(MT::hull(m_co[0], b[0]), 
-					   MT::hull(m_co[1], b[1]), 
-					   MT::hull(m_co[2], b[2])); 
-	}
-
-	bool contains(const MT_Point3& p) const 
-	{
-		return MT::in(p[0], m_co[0]) && MT::in(p[1], m_co[1]) && MT::in(p[2], m_co[2]);
-	}
-};
-
-inline MT_BBox operator+(const MT_BBox& b1, const MT_BBox& b2) 
-{
-	return MT_BBox(b1[0] + b2[0], b1[1] + b2[1], b1[2] + b2[2]);
-}
-
-inline MT_BBox operator-(const MT_BBox& b1, const MT_BBox& b2) 
-{
-	return MT_BBox(b1[0] - b2[0], b1[1] - b2[1], b1[2] - b2[2]);
-}
-
-#endif
-
-
diff --git a/extern/solid/include/MT_Interval.h b/extern/solid/include/MT_Interval.h
deleted file mode 100644
index 25ebfd0a67d..00000000000
--- a/extern/solid/include/MT_Interval.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef MT_INTERVAL_H
-#define MT_INTERVAL_H
-
-#include 
-
-#include "MT_Scalar.h"
-
-typedef MT::Interval MT_Interval;
-
-#endif
diff --git a/extern/solid/include/MT_Matrix3x3.h b/extern/solid/include/MT_Matrix3x3.h
deleted file mode 100644
index f7572f90fa2..00000000000
--- a/extern/solid/include/MT_Matrix3x3.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef MT_MATRIX3X3_H
-#define MT_MATRIX3X3_H
-
-#include "MT_Scalar.h"
-#include 
-
-typedef MT::Matrix3x3 MT_Matrix3x3;
-
-
-
-#endif
diff --git a/extern/solid/include/MT_Point3.h b/extern/solid/include/MT_Point3.h
deleted file mode 100644
index ca84f652b65..00000000000
--- a/extern/solid/include/MT_Point3.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef MT_POINT3_H
-#define MT_POINT3_H
-
-#include "MT_Vector3.h"
-
-typedef MT_Vector3 MT_Point3;
-
-#endif
diff --git a/extern/solid/include/MT_Quaternion.h b/extern/solid/include/MT_Quaternion.h
deleted file mode 100644
index ca860db711c..00000000000
--- a/extern/solid/include/MT_Quaternion.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef MT_QUATERNION_H
-#define MT_QUATERNION_H
-
-#include "MT_Scalar.h"
-#include 
-
-typedef MT::Quaternion MT_Quaternion;
-
-#endif
-
-
-
diff --git a/extern/solid/include/MT_Scalar.h b/extern/solid/include/MT_Scalar.h
deleted file mode 100644
index 663a1f1839c..00000000000
--- a/extern/solid/include/MT_Scalar.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef MT_SCALAR_H
-#define MT_SCALAR_H
-
-#if defined (__sun__) || defined ( __sun ) || defined (__sparc) || defined (__sparc__) || defined (__sgi)
-#include 
-#include 
-#else
-#include 
-#include 
-#include 
-#endif
-
-#undef max
-
-#include "SOLID_types.h"
-
-#include "GEN_MinMax.h"
-#include "GEN_random.h"
-
-template 
-struct Scalar_traits {};
-
-template<>
-struct Scalar_traits {
-	static float TwoTimesPi() { return 6.283185307179586232f; }
-	static float epsilon() { return FLT_EPSILON; }
-	static float max() { return FLT_MAX; }
-	
-	static float random() { return float(GEN_rand()) / float(GEN_RAND_MAX); }
-#if defined (__sun) || defined (__sun__) || defined (__sparc) || defined (__APPLE__)
-	static float sqrt(float x) { return ::sqrt(x); } 
-	static float abs(float x) { return ::fabs(x); } 
-
-	static float cos(float x) { return ::cos(x); } 
-	static float sin(float x) { return ::sin(x); } 
-	static float tan(float x) { return ::tan(x); } 
-
-	static float acos(float x) { return ::acos(x); } 
-	static float asin(float x) { return ::asin(x); } 
-	static float atan(float x) { return ::atan(x); } 
-	static float atan2(float x, float y) { return ::atan2(x, y); } 
-
-	static float exp(float x) { return ::exp(x); } 
-	static float log(float x) { return ::log(x); } 
-	static float pow(float x, float y) { return ::pow(x, y); } 
-
-#else
-	static float sqrt(float x) { return ::sqrtf(x); } 
-	static float abs(float x) { return ::fabsf(x); } 
-
-	static float cos(float x) { return ::cosf(x); } 
-	static float sin(float x) { return ::sinf(x); } 
-	static float tan(float x) { return ::tanf(x); } 
-
-	static float acos(float x) { return ::acosf(x); } 
-	static float asin(float x) { return ::asinf(x); } 
-	static float atan(float x) { return ::atanf(x); } 
-	static float atan2(float x, float y) { return ::atan2f(x, y); } 
-
-	static float exp(float x) { return ::expf(x); } 
-	static float log(float x) { return ::logf(x); } 
-	static float pow(float x, float y) { return ::powf(x, y); } 
-#endif
-};
-
-template<>
-struct Scalar_traits {
-	static double TwoTimesPi() { return 6.283185307179586232; }
-	static double epsilon() { return DBL_EPSILON; }
-	static double max() { return DBL_MAX; }
-	
-	static double random() { return double(GEN_rand()) / double(GEN_RAND_MAX); }
-	static double sqrt(double x) { return ::sqrt(x); } 
-	static double abs(double x) { return ::fabs(x); } 
-
-	static double cos(double x) { return ::cos(x); } 
-	static double sin(double x) { return ::sin(x); } 
-	static double tan(double x) { return ::tan(x); } 
-
-	static double acos(double x) { return ::acos(x); } 
-	static double asin(double x) { return ::asin(x); } 
-	static double atan(double x) { return ::atan(x); } 
-	static double atan2(double x, double y) { return ::atan2(x, y); } 
-
-	static double exp(double x) { return ::exp(x); } 
-	static double log(double x) { return ::log(x); } 
-	static double pow(double x, double y) { return ::pow(x, y); } 
-};
-
-#ifdef USE_TRACER
-#include "MT_ScalarTracer.h"
-
-#ifdef USE_DOUBLES
-typedef MT_ScalarTracer   MT_Scalar;
-#else
-typedef MT_ScalarTracer    MT_Scalar;
-#endif
-
-#else
-
-#ifdef USE_DOUBLES
-typedef double   MT_Scalar;
-#else
-typedef float    MT_Scalar;
-#endif
-
-#endif
-
-
-const MT_Scalar  MT_2_PI         = Scalar_traits::TwoTimesPi();
-const MT_Scalar  MT_PI           = MT_2_PI * MT_Scalar(0.5);
-const MT_Scalar  MT_HALF_PI		 = MT_2_PI * MT_Scalar(0.25);
-const MT_Scalar  MT_RADS_PER_DEG = MT_2_PI / MT_Scalar(360.0);
-const MT_Scalar  MT_DEGS_PER_RAD = MT_Scalar(360.0) / MT_2_PI;
-
-const MT_Scalar  MT_EPSILON      = Scalar_traits::epsilon();
-const MT_Scalar  MT_INFINITY     = Scalar_traits::max();
-
-inline MT_Scalar MT_random() { return  Scalar_traits::random(); }
-inline MT_Scalar MT_abs(MT_Scalar x) { return Scalar_traits::abs(x); }
-inline MT_Scalar MT_sqrt(MT_Scalar x) { return Scalar_traits::sqrt(x); }
-
-inline MT_Scalar MT_cos(MT_Scalar x) { return Scalar_traits::cos(x); }
-inline MT_Scalar MT_sin(MT_Scalar x) { return Scalar_traits::sin(x); }
-inline MT_Scalar MT_tan(MT_Scalar x) { return Scalar_traits::tan(x); }
-
-inline MT_Scalar MT_acos(MT_Scalar x) { return Scalar_traits::acos(x); }
-inline MT_Scalar MT_asin(MT_Scalar x) { return Scalar_traits::asin(x); }
-inline MT_Scalar MT_atan(MT_Scalar x) { return Scalar_traits::atan(x); }
-inline MT_Scalar MT_atan2(MT_Scalar x, MT_Scalar y) { return Scalar_traits::atan2(x, y); }
-
-inline MT_Scalar MT_radians(MT_Scalar x) { return x * MT_RADS_PER_DEG; }
-inline MT_Scalar MT_degrees(MT_Scalar x) { return x * MT_DEGS_PER_RAD; }
-
-#endif
diff --git a/extern/solid/include/MT_Transform.h b/extern/solid/include/MT_Transform.h
deleted file mode 100644
index 66f92428054..00000000000
--- a/extern/solid/include/MT_Transform.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef MT_TRANSFORM_H
-#define MT_TRANSFORM_H
-
-#include "MT_Scalar.h"
-#include 
-
-typedef MT::Matrix3x3 MT_Matrix3x3;
-typedef MT::Transform MT_Transform;
-
-#endif
-
-
-
-
-
diff --git a/extern/solid/include/MT_Vector3.h b/extern/solid/include/MT_Vector3.h
deleted file mode 100644
index d50e80dc287..00000000000
--- a/extern/solid/include/MT_Vector3.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef MT_VECTOR3_H
-#define MT_VECTOR3_H
-
-#include "MT_Scalar.h"
-#include 
-
-typedef MT::Vector3 MT_Vector3;
-
-#ifdef CPU_CMP
-
-inline bool operator==(const MT_Vector3& p1, const MT_Vector3& p2) 
-{
-	const unsigned int *i1 = (const unsigned int *)&p1;
-	const unsigned int *i2 = (const unsigned int *)&p2;
-    return i1[0] == i2[0] && i1[1] == i2[1] && i1[2] == i2[2];
-}
-
-#else
-
-inline bool operator==(const MT_Vector3& p1, const MT_Vector3& p2) 
-{
-	return p1[0] == p2[0] && p1[1] == p2[1] && p1[2] == p2[2];
-}
-
-#endif
-
-#endif
diff --git a/extern/solid/include/SOLID.h b/extern/solid/include/SOLID.h
deleted file mode 100644
index 96d40f1ea6b..00000000000
--- a/extern/solid/include/SOLID.h
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef SOLID_H
-#define SOLID_H
-
-#include "SOLID_types.h"
-
-#ifdef __cplusplus
-extern "C" { 
-#endif
-    
-	DT_DECLARE_HANDLE(DT_ObjectHandle);
-	DT_DECLARE_HANDLE(DT_SceneHandle);
-	DT_DECLARE_HANDLE(DT_ShapeHandle);
-	DT_DECLARE_HANDLE(DT_VertexBaseHandle);
-	DT_DECLARE_HANDLE(DT_RespTableHandle);
-	DT_DECLARE_HANDLE(DT_ArchiveHandle);
-
-	typedef unsigned int DT_ResponseClass;
-
-	typedef enum DT_ResponseType { 
-		DT_NO_RESPONSE,                  /* No response (obsolete) */
-		DT_BROAD_RESPONSE,               /* Broad phase response is returned. */
-		DT_SIMPLE_RESPONSE,              /* No collision data */
-		DT_WITNESSED_RESPONSE,           /* A point common to both objects
-											is returned as collision data
-										 */
-		DT_DEPTH_RESPONSE                /* The penetration depth is returned
-											as collision data. The penetration depth
-											is the shortest vector over which one 
-											object needs to be translated in order
-											to bring the objects in touching contact. 
-										 */ 
-	} DT_ResponseType;
-    
-/* For witnessed response, the following structure represents a common point. The world 
-   coordinates of 'point1' and 'point2' coincide. 'normal' is the zero vector.
-   
-   For depth response, the following structure represents the penetration depth. 
-   'point1' en 'point2' are the witness points of the penetration depth in world coordinates.
-   The penetration depth vector in world coordinates is represented by 'normal'.
-*/
-
-	typedef struct DT_CollData {
-		DT_Vector3 point1;               /* Point in object1 in world coordinates */ 
-		DT_Vector3 point2;               /* Point in object2 in world coordinates */
-		DT_Vector3 normal;               /* point2 - point1 */ 
-	} DT_CollData;
-
-/* A response callback is called by SOLID for each pair of collding objects. 'client-data'
-   is a pointer to an arbitrary structure in the client application. The client objects are
-   pointers to structures in the client application associated with the coliding objects.
-   'coll_data' is the collision data computed by SOLID.
-*/
-
-	typedef DT_Bool (*DT_ResponseCallback)(void *client_data,
-										   void *client_object1,
-										   void *client_object2,
-										   const DT_CollData *coll_data);
-										
-/* Shape definition */
-
-
-	extern DECLSPEC DT_ShapeHandle DT_NewBox(DT_Scalar x, DT_Scalar y, DT_Scalar z);
-	extern DECLSPEC DT_ShapeHandle DT_NewCone(DT_Scalar radius, DT_Scalar height);
-	extern DECLSPEC DT_ShapeHandle DT_NewCylinder(DT_Scalar radius, DT_Scalar height);
-	extern DECLSPEC DT_ShapeHandle DT_NewSphere(DT_Scalar radius);
-	extern DECLSPEC DT_ShapeHandle DT_NewPoint(const DT_Vector3 point);
-	extern DECLSPEC DT_ShapeHandle DT_NewLineSegment(const DT_Vector3 source, const DT_Vector3 target);
-	extern DECLSPEC DT_ShapeHandle DT_NewMinkowski(DT_ShapeHandle shape1, DT_ShapeHandle shape2);
-	extern DECLSPEC DT_ShapeHandle DT_NewHull(DT_ShapeHandle shape1, DT_ShapeHandle shape2);
-
-	extern DECLSPEC DT_VertexBaseHandle DT_NewVertexBase(const void *pointer, DT_Size stride);
-	extern DECLSPEC void DT_DeleteVertexBase(DT_VertexBaseHandle vertexBase);	
-	extern DECLSPEC void DT_ChangeVertexBase(DT_VertexBaseHandle vertexBase, const void *pointer);
-
-	extern DECLSPEC DT_ShapeHandle DT_NewComplexShape(DT_VertexBaseHandle vertexBase);
-	extern DECLSPEC void           DT_EndComplexShape();
-
-	extern DECLSPEC DT_ShapeHandle DT_NewPolytope(DT_VertexBaseHandle vertexBase);
-	extern DECLSPEC void           DT_EndPolytope();
-
-	extern DECLSPEC void DT_Begin();
-	extern DECLSPEC void DT_End();
-
-	extern DECLSPEC void DT_Vertex(const DT_Vector3 vertex);
-	extern DECLSPEC void DT_VertexIndex(DT_Index index);
-
-	extern DECLSPEC void DT_VertexIndices(DT_Count count, const DT_Index *indices);
-	extern DECLSPEC void DT_VertexRange(DT_Index first, DT_Count count); 
-
-	extern DECLSPEC void DT_DeleteShape(DT_ShapeHandle shape);
-
-/* Object  */
-
-	extern DECLSPEC DT_ObjectHandle DT_CreateObject(
-		void *client_object,      /* pointer to object in client memory */
-		DT_ShapeHandle shape  /* the shape or geometry of the object */
-		);
-
-	extern DECLSPEC void DT_DestroyObject(DT_ObjectHandle object);
-
-
-
-	extern DECLSPEC void DT_SetPosition(DT_ObjectHandle object, const DT_Vector3 position);
-	extern DECLSPEC void DT_SetOrientation(DT_ObjectHandle object, const DT_Quaternion orientation);
-	extern DECLSPEC void DT_SetScaling(DT_ObjectHandle object, const DT_Vector3 scaling);
-
-/* The margin is an offset from the actual shape. The actual geometry of an
-   object is the set of points whose distance to the transformed shape is at 
-   most the  margin. During the lifetime of an object the margin can be 
-   modified. 
-*/
-   
-	extern DECLSPEC void DT_SetMargin(DT_ObjectHandle object, DT_Scalar margin);
-
-
-/* These commands assume a column-major 4x4 OpenGL matrix representation */
-
-	extern DECLSPEC void DT_SetMatrixf(DT_ObjectHandle object, const float *m); 
-	extern DECLSPEC void DT_GetMatrixf(DT_ObjectHandle object, float *m); 
-
-	extern DECLSPEC void DT_SetMatrixd(DT_ObjectHandle object, const double *m); 
-	extern DECLSPEC void DT_GetMatrixd(DT_ObjectHandle object, double *m); 
-
-	extern DECLSPEC void DT_GetBBox(DT_ObjectHandle object, DT_Vector3 min, DT_Vector3 max);
-
-	
-	extern DECLSPEC DT_Bool  DT_GetIntersect(DT_ObjectHandle object1, DT_ObjectHandle object2,
-												DT_Vector3 v);
-/* This next command returns the distance between the objects. De returned
-   closest points are given in world coordinates.
-*/
-	extern DECLSPEC DT_Scalar DT_GetClosestPair(DT_ObjectHandle object1, DT_ObjectHandle object2,
-												DT_Vector3 point1, DT_Vector3 point2);  
-
-	extern DECLSPEC DT_Bool   DT_GetCommonPoint(DT_ObjectHandle object1, DT_ObjectHandle object2,
-												DT_Vector3 point);
-
-	extern DECLSPEC DT_Bool   DT_GetPenDepth(DT_ObjectHandle object1, DT_ObjectHandle object2,
-											 DT_Vector3 point1, DT_Vector3 point2);  
-
-/* Scene */
-
-	extern DECLSPEC DT_SceneHandle DT_CreateScene(); 
-	extern DECLSPEC void           DT_DestroyScene(DT_SceneHandle scene);
-
-	extern DECLSPEC void DT_AddObject(DT_SceneHandle scene, DT_ObjectHandle object);
-	extern DECLSPEC void DT_RemoveObject(DT_SceneHandle scene, DT_ObjectHandle object);
-
-/* Note that objects can be assigned to multiple scenes! */
-
-/* Response */
-
-/* Response tables are defined independent of the scenes in which they are used.
-   Multiple response tables can be used in one scene, and a response table
-   can be shared among scenes.
-*/
-	extern DECLSPEC DT_RespTableHandle DT_CreateRespTable(); 
-	extern DECLSPEC void               DT_DestroyRespTable(DT_RespTableHandle respTable); 
-
-/* Responses are defined on (pairs of) response classes. Each response table 
-   maintains its set of response classes.
-*/
-	extern DECLSPEC DT_ResponseClass DT_GenResponseClass(DT_RespTableHandle respTable);
-
-/* To each object for which a response is defined in the response table a
-   response class needs to be assigned. 
-*/
-
-	extern DECLSPEC void DT_SetResponseClass(DT_RespTableHandle respTable,
-											 DT_ObjectHandle object,
-											 DT_ResponseClass responseClass);
-
-	extern DECLSPEC void DT_ClearResponseClass(DT_RespTableHandle respTable, 
-											   DT_ObjectHandle object);
-
-	extern DECLSPEC void DT_CallResponse(DT_RespTableHandle respTable,
-										 DT_ObjectHandle object1,
-										 DT_ObjectHandle object2,
-										 const DT_CollData *coll_data);
-
-/* For each pair of objects multiple responses can be defined. A response is a callback
-   together with its response type and client data. */
-    
-/* Responses can be defined for all pairs of response classes... */
-	extern DECLSPEC void DT_AddDefaultResponse(DT_RespTableHandle respTable,
-											   DT_ResponseCallback response, 
-											   DT_ResponseType type, void *client_data);
-
-	extern DECLSPEC void DT_RemoveDefaultResponse(DT_RespTableHandle respTable,
-												  DT_ResponseCallback response);
-/* ...per response class... */
-	extern DECLSPEC void DT_AddClassResponse(DT_RespTableHandle respTable,
-											 DT_ResponseClass responseClass,
-											 DT_ResponseCallback response,
-											 DT_ResponseType type, void *client_data);
-
-	extern DECLSPEC void DT_RemoveClassResponse(DT_RespTableHandle respTable,
-												DT_ResponseClass responseClass,
-												DT_ResponseCallback response);
-
-/* ... and per pair of response classes...*/
-	extern DECLSPEC void DT_AddPairResponse(DT_RespTableHandle respTable,
-											DT_ResponseClass responseClass1,
-											DT_ResponseClass responseClass2, 
-											DT_ResponseCallback response,
-											DT_ResponseType type, void *client_data);
-	extern DECLSPEC void DT_RemovePairResponse(DT_RespTableHandle respTable,
-											   DT_ResponseClass responseClass1,
-											   DT_ResponseClass responseClass2,
-											   DT_ResponseCallback response);
-
-/* The next command calls the response callbacks for all intersecting pairs of objects in a scene. 
-   'DT_Test' returns the number of pairs of objects for which callbacks have been called. 
-*/
- 
-	extern DECLSPEC DT_Count DT_Test(DT_SceneHandle scene, DT_RespTableHandle respTable);
-
-/* Set the maximum relative error in the closest points and penetration depth
-   computation. The default for `max_error' is 1.0e-3. Larger errors result
-   in better performance. Non-positive error tolerances are ignored.
-*/ 
-
-	extern DECLSPEC void DT_SetAccuracy(DT_Scalar max_error);
-
-/* Set the maximum tolerance on relative errors due to rounding.  The default for `tol_error' 
-   is the machine epsilon. Very large tolerances result in false collisions. Setting tol_error too small 
-   results in missed collisions. Non-positive error tolerances are ignored. 
-*/ 
-    
-	extern DECLSPEC void DT_SetTolerance(DT_Scalar tol_error);
-
-
-/* This function returns the client pointer to the first object in a scene hit by the ray 
-   (actually a line segment) defined by the points 'from' en 'to'. The spot is the hit point 
-   on the object in local coordinates. 'normal' is the normal to the surface of the object in
-   world coordinates. The ignore_client pointer is used to make one of the objects transparent.
-
-   NB: Currently ray tests are implemented for spheres, boxes, and meshes only!!
-*/   
-
-	extern DECLSPEC void *DT_RayCast(DT_SceneHandle scene, void *ignore_client,
-									 const DT_Vector3 source, const DT_Vector3 target,
-									 DT_Scalar max_param, DT_Scalar *param, DT_Vector3 normal);
-
-/* Similar, only here a single object is tested and a boolean is returned */
-
-	extern DECLSPEC DT_Bool DT_ObjectRayCast(DT_ObjectHandle object,
-											 const DT_Vector3 source, const DT_Vector3 target,
-											 DT_Scalar max_param, DT_Scalar *param, DT_Vector3 normal);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/extern/solid/include/SOLID_broad.h b/extern/solid/include/SOLID_broad.h
deleted file mode 100644
index 74e4214fa67..00000000000
--- a/extern/solid/include/SOLID_broad.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef SOLID_BROAD_H
-#define SOLID_BROAD_H
-
-#include "SOLID_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-    
-	DT_DECLARE_HANDLE(BP_SceneHandle);
-	DT_DECLARE_HANDLE(BP_ProxyHandle);
-	
-	typedef void (*BP_Callback)(void *client_data,
-								void *object1,
-								void *object2);
-
-	typedef bool (*BP_RayCastCallback)(void *client_data,
-									   void *object,
-									   const DT_Vector3 source,
-									   const DT_Vector3 target,
-									   DT_Scalar *lambda);
-	
-	extern DECLSPEC BP_SceneHandle BP_CreateScene(void *client_data,
-												  BP_Callback beginOverlap,
-												  BP_Callback endOverlap);
-	
-	extern DECLSPEC void           BP_DestroyScene(BP_SceneHandle scene);
-	
-	extern DECLSPEC BP_ProxyHandle BP_CreateProxy(BP_SceneHandle scene, 
-												  void *object,
-												  const DT_Vector3 min, 
-												  const DT_Vector3 max);
-	
-	extern DECLSPEC void           BP_DestroyProxy(BP_SceneHandle scene, 
-												  BP_ProxyHandle proxy);
-	
-	extern DECLSPEC void BP_SetBBox(BP_ProxyHandle proxy, 
-									const DT_Vector3 min, 
-									const DT_Vector3 max);
-	
-	extern DECLSPEC void *BP_RayCast(BP_SceneHandle scene, 
-									 BP_RayCastCallback objectRayCast, 
-									 void *client_data,
-									 const DT_Vector3 source,
-									 const DT_Vector3 target,
-									 DT_Scalar *lambda);		
-	
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/extern/solid/include/SOLID_types.h b/extern/solid/include/SOLID_types.h
deleted file mode 100644
index 630594e447f..00000000000
--- a/extern/solid/include/SOLID_types.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef SOLID_TYPES_H
-#define SOLID_TYPES_H
-
-#ifndef DECLSPEC
-# ifdef WIN32
-#  define DECLSPEC __declspec(dllexport)
-# else
-#  define DECLSPEC
-# endif
-#endif
-
-#define DT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
-    
-
-typedef unsigned short DT_Index;
-typedef unsigned short DT_Count;
-typedef unsigned int   DT_Size;
-typedef float          DT_Scalar; 
-typedef int            DT_Bool;
-
-#define DT_FALSE 0
-#define DT_TRUE  1
-
-#define DT_CONTINUE 0
-#define DT_DONE 1
-
-typedef DT_Scalar DT_Vector3[3]; 
-typedef DT_Scalar DT_Quaternion[4]; 
-
-#endif
diff --git a/extern/solid/make/msvc_7_0/broad/broad.vcproj b/extern/solid/make/msvc_7_0/broad/broad.vcproj
deleted file mode 100644
index adb56424e60..00000000000
--- a/extern/solid/make/msvc_7_0/broad/broad.vcproj
+++ /dev/null
@@ -1,262 +0,0 @@
-
-
-	
-		
-	
-	
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-	
-		
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-
diff --git a/extern/solid/make/msvc_7_0/complex/complex.vcproj b/extern/solid/make/msvc_7_0/complex/complex.vcproj
deleted file mode 100644
index 2a895fa28d3..00000000000
--- a/extern/solid/make/msvc_7_0/complex/complex.vcproj
+++ /dev/null
@@ -1,252 +0,0 @@
-
-
-	
-		
-	
-	
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-	
-		
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-
diff --git a/extern/solid/make/msvc_7_0/convex/convex.vcproj b/extern/solid/make/msvc_7_0/convex/convex.vcproj
deleted file mode 100644
index da088b5972f..00000000000
--- a/extern/solid/make/msvc_7_0/convex/convex.vcproj
+++ /dev/null
@@ -1,337 +0,0 @@
-
-
-	
-		
-	
-	
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-	
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-
diff --git a/extern/solid/make/msvc_7_0/solid.vcproj b/extern/solid/make/msvc_7_0/solid.vcproj
deleted file mode 100644
index d9e6332987c..00000000000
--- a/extern/solid/make/msvc_7_0/solid.vcproj
+++ /dev/null
@@ -1,462 +0,0 @@
-
-
-	
-		
-	
-	
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-	
-		
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-
diff --git a/extern/solid/make/msvc_9_0/broad/broad.vcproj b/extern/solid/make/msvc_9_0/broad/broad.vcproj
deleted file mode 100644
index c58cb08b2c3..00000000000
--- a/extern/solid/make/msvc_9_0/broad/broad.vcproj
+++ /dev/null
@@ -1,369 +0,0 @@
-
-
-	
-		
-	
-	
-	
-	
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-	
-		
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-
diff --git a/extern/solid/make/msvc_9_0/complex/complex.vcproj b/extern/solid/make/msvc_9_0/complex/complex.vcproj
deleted file mode 100644
index 1828c489fc6..00000000000
--- a/extern/solid/make/msvc_9_0/complex/complex.vcproj
+++ /dev/null
@@ -1,355 +0,0 @@
-
-
-	
-		
-	
-	
-	
-	
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-	
-		
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-
diff --git a/extern/solid/make/msvc_9_0/convex/convex.vcproj b/extern/solid/make/msvc_9_0/convex/convex.vcproj
deleted file mode 100644
index cb35a0ea199..00000000000
--- a/extern/solid/make/msvc_9_0/convex/convex.vcproj
+++ /dev/null
@@ -1,469 +0,0 @@
-
-
-	
-		
-	
-	
-	
-	
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-	
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-
diff --git a/extern/solid/make/msvc_9_0/solid.vcproj b/extern/solid/make/msvc_9_0/solid.vcproj
deleted file mode 100644
index ed81c374696..00000000000
--- a/extern/solid/make/msvc_9_0/solid.vcproj
+++ /dev/null
@@ -1,595 +0,0 @@
-
-
-	
-		
-	
-	
-	
-	
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-	
-		
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-			
-				
-					
-				
-				
-					
-				
-				
-					
-				
-				
-					
-				
-			
-		
-		
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-			
-		
-	
-	
-	
-
diff --git a/extern/solid/src/DT_AlgoTable.h b/extern/solid/src/DT_AlgoTable.h
deleted file mode 100644
index 0749ca7fdd9..00000000000
--- a/extern/solid/src/DT_AlgoTable.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_ALGOTABLE_H
-#define DT_ALGOTABLE_H
-
-#include "DT_Shape.h"
-
-template 
-class AlgoTable {
-public:
-  void addEntry(DT_ShapeType type1, DT_ShapeType type2, Function function) 
-  { 
-    table[type2][type1] = function;
-    table[type1][type2] = function;
-  }
-
-  Function lookup(DT_ShapeType type1, DT_ShapeType type2) const 
-  {
-    return table[type1][type2];
-  }
-
-private:
-  Function table[NUM_TYPES][NUM_TYPES];
-};
-
-#endif
diff --git a/extern/solid/src/DT_C-api.cpp b/extern/solid/src/DT_C-api.cpp
deleted file mode 100644
index ac16deda87d..00000000000
--- a/extern/solid/src/DT_C-api.cpp
+++ /dev/null
@@ -1,581 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-
-#include "SOLID.h"
-
-#include "DT_Box.h"
-#include "DT_Cone.h"
-#include "DT_Cylinder.h"
-#include "DT_Sphere.h"
-#include "DT_Complex.h"
-#include "DT_Polytope.h"
-#include "DT_Polyhedron.h"
-#include "DT_Point.h"
-#include "DT_LineSegment.h"
-#include "DT_Triangle.h"
-#include "DT_Minkowski.h"
-#include "DT_Hull.h"
-
-#include "DT_Response.h"
-#include "DT_RespTable.h"
-
-#include "DT_Scene.h"
-#include "DT_Object.h"
-
-#include "DT_VertexBase.h"
-
-#include "DT_Accuracy.h"
-
-typedef MT::Tuple3 T_Vertex;
-typedef std::vector T_VertexBuf;
-typedef std::vector T_IndexBuf;
-typedef std::vector T_PolyList;
-
-static T_VertexBuf vertexBuf;
-static T_IndexBuf indexBuf;
-static T_PolyList polyList; 
-
-static DT_Complex       *currentComplex    = 0;
-static DT_Polyhedron    *currentPolyhedron = 0;
-static DT_VertexBase    *currentBase = 0;
-
-
-
-
-
-		
-DT_VertexBaseHandle DT_NewVertexBase(const void *pointer, DT_Size stride) 
-{
-    return (DT_VertexBaseHandle)new DT_VertexBase(pointer, stride);
-}
-
-void DT_DeleteVertexBase(DT_VertexBaseHandle vertexBase) 
-{ 
-    delete (DT_VertexBase *)vertexBase; 
-}
-
-void DT_ChangeVertexBase(DT_VertexBaseHandle vertexBase, const void *pointer) 
-{ 
-	DT_VertexBase *base = (DT_VertexBase *)vertexBase;
-	base->setPointer(pointer);
-	const DT_ComplexList& complexList = base->getComplexList();
-	DT_ComplexList::const_iterator it;
-	for (it = complexList.begin(); it != complexList.end(); ++it)
-	{
-		(*it)->refit();
-	}
-}
-
-
-DT_ShapeHandle DT_NewBox(DT_Scalar x, DT_Scalar y, DT_Scalar z) 
-{
-    return (DT_ShapeHandle)new DT_Box(MT_Scalar(x) * MT_Scalar(0.5), 
-									  MT_Scalar(y) * MT_Scalar(0.5), 
-									  MT_Scalar(z) * MT_Scalar(0.5));
-}
-
-DT_ShapeHandle DT_NewCone(DT_Scalar radius, DT_Scalar height)
-{
-    return (DT_ShapeHandle)new DT_Cone(MT_Scalar(radius), MT_Scalar(height));
-}
-
-DT_ShapeHandle DT_NewCylinder(DT_Scalar radius, DT_Scalar height) 
-{
-    return (DT_ShapeHandle)new DT_Cylinder(MT_Scalar(radius), MT_Scalar(height));
-}
-
-DT_ShapeHandle DT_NewSphere(DT_Scalar radius) 
-{
-    return (DT_ShapeHandle)new DT_Sphere(MT_Scalar(radius));
-}
-
-DT_ShapeHandle DT_NewPoint(const DT_Vector3 point) 
-{
-	return (DT_ShapeHandle)new DT_Point(MT_Point3(point));
-}
-
-DT_ShapeHandle DT_NewLineSegment(const DT_Vector3 source, const DT_Vector3 target) 
-{
-	return (DT_ShapeHandle)new DT_LineSegment(MT_Point3(source), MT_Point3(target));
-}
-
-DT_ShapeHandle DT_NewMinkowski(DT_ShapeHandle shape1, DT_ShapeHandle shape2) 
-{
-	if (((DT_Shape *)shape1)->getType() != CONVEX ||
-		((DT_Shape *)shape2)->getType() != CONVEX) 
-	{
-		return 0;
-	}
-
-	return (DT_ShapeHandle)new DT_Minkowski(*(DT_Convex *)shape1, *(DT_Convex *)shape2);
-}
-	
-DT_ShapeHandle DT_NewHull(DT_ShapeHandle shape1, DT_ShapeHandle shape2)
-{
-	if (((DT_Shape *)shape1)->getType() != CONVEX ||
-		((DT_Shape *)shape2)->getType() != CONVEX) 
-	{
-		return 0;
-	}
-
-	return (DT_ShapeHandle)new DT_Hull(*(DT_Convex *)shape1, *(DT_Convex *)shape2);
-}
-
-DT_ShapeHandle DT_NewComplexShape(const DT_VertexBaseHandle vertexBase) 
-{
-    if (!currentComplex) 
-	{
-		currentBase = vertexBase ? (DT_VertexBase *)vertexBase : new DT_VertexBase;
-		currentComplex = new DT_Complex(currentBase);
-	}
-    return (DT_ShapeHandle)currentComplex;
-}
-
-void DT_EndComplexShape() 
-{
-    if (currentComplex) 
-	{
-        if (currentBase->getPointer() == 0) 
-		{
-            T_Vertex *vertexArray = new T_Vertex[vertexBuf.size()];   
-			assert(vertexArray);	
-            std::copy(vertexBuf.begin(), vertexBuf.end(), &vertexArray[0]);
-            currentBase->setPointer(vertexArray, true);		
-        }
-		
-		vertexBuf.clear();
-        
-        currentComplex->finish(polyList.size(), &polyList[0]);
-        polyList.clear();
-        currentComplex = 0;
-        currentBase = 0; 
-    }
-}
-
-DT_ShapeHandle DT_NewPolytope(const DT_VertexBaseHandle vertexBase) 
-{
-    if (!currentPolyhedron) 
-	{
-		currentBase = vertexBase ? (DT_VertexBase *)vertexBase : new DT_VertexBase;
-        currentPolyhedron = new DT_Polyhedron;
-		
-    }
-    return (DT_ShapeHandle)currentPolyhedron;
-}
-
-void DT_EndPolytope() 
-{
-    if (currentPolyhedron) 
-	{
-        if (currentBase->getPointer() == 0) 
-		{
-			currentBase->setPointer(&vertexBuf[0]);		
-			new (currentPolyhedron) DT_Polyhedron(currentBase, indexBuf.size(), &indexBuf[0]);
-			
-			delete currentBase;
-		}
-		else
-		{
-			new (currentPolyhedron) DT_Polyhedron(currentBase, indexBuf.size(), &indexBuf[0]);
-		}
-		vertexBuf.clear();
-        indexBuf.clear();
-        currentPolyhedron = 0;
-        currentBase = 0;
-    }
-}
-
-void DT_Begin() 
-{}
-
-void DT_End() 
-{ 
-	if (currentComplex) 
-	{
-		DT_VertexIndices(indexBuf.size(), &indexBuf[0]);
-		indexBuf.clear();
-	}
-}
-
-void DT_Vertex(const DT_Vector3 vertex)
-{
-    MT::Vector3 p(vertex);
-    int i = GEN_max((int)vertexBuf.size() - 20, 0);
-	int n = static_cast(vertexBuf.size());
-	
-    while (i != n  && !(vertexBuf[i] == p)) 
-	{
-		++i;
-	}
-
-    if (i == n) 
-	{
-		vertexBuf.push_back(p);
-	}
-    indexBuf.push_back(i);
-}
-
-
-void DT_VertexIndex(DT_Index index) { indexBuf.push_back(index); }
-
-void DT_VertexIndices(DT_Count count, const DT_Index *indices) 
-{
-    if (currentComplex) 
-	{
-		DT_Convex *poly = count == 3 ? 
-			              static_cast(new DT_Triangle(currentBase, indices[0], indices[1], indices[2])) :
-						  static_cast(new DT_Polytope(currentBase, count, indices));  
-		polyList.push_back(poly);
-      
-    }
-
-    if (currentPolyhedron) 
-	{
-		int i;
-		for (i = 0; i < count; ++i) 
-		{
-            indexBuf.push_back(indices[i]);
-        }
-    }   
-}
-
-void DT_VertexRange(DT_Index first, DT_Count count) 
-{
-    DT_Index *indices = new DT_Index[count];
-    
-	DT_Index i;
-    for (i = 0; i != count; ++i) 
-	{
-        indices[i] = first + i;
-    }
-    DT_VertexIndices(count, indices);
-
-    delete [] indices;	
-}
-
-void DT_DeleteShape(DT_ShapeHandle shape) 
-{ 
-    delete (DT_Shape *)shape; 
-}
-
-
-
-
-// Scene
-
-
-DT_SceneHandle DT_CreateScene() 
-{
-    return (DT_SceneHandle)new DT_Scene; 
-}
-
-void DT_DestroyScene(DT_SceneHandle scene) 
-{
-    delete (DT_Scene *)scene;
-}
-
-void DT_AddObject(DT_SceneHandle scene, DT_ObjectHandle object) 
-{
-    assert(scene);
-    assert(object);
-    ((DT_Scene *)scene)->addObject(*(DT_Object *)object);
-}
-
-void DT_RemoveObject(DT_SceneHandle scene, DT_ObjectHandle object) 
-{
-    assert(scene);
-    assert(object);
-    ((DT_Scene *)scene)->removeObject(*(DT_Object *)object);
-}
-
-
-// Object instantiation
-
-
-DT_ObjectHandle DT_CreateObject(void *client_object,
-                                DT_ShapeHandle shape)
-{
-	return (DT_ObjectHandle)new DT_Object(client_object, *(DT_Shape *)shape);
-}
-
-void DT_DestroyObject(DT_ObjectHandle object) 
-{
-    delete (DT_Object *)object;
-}
-
-void DT_SetMargin(DT_ObjectHandle object, DT_Scalar margin) 
-{
-    ((DT_Object *)object)->setMargin(MT_Scalar(margin));
-}
-
-
-void DT_SetScaling(DT_ObjectHandle object, const DT_Vector3 scaling) 
-{
-    ((DT_Object *)object)->setScaling(MT_Vector3(scaling));
-}
-
-void DT_SetPosition(DT_ObjectHandle object, const DT_Vector3 position) 
-{
-    ((DT_Object *)object)->setPosition(MT_Point3(position));
-}
-
-void DT_SetOrientation(DT_ObjectHandle object, const DT_Quaternion orientation) 
-{
-    ((DT_Object *)object)->setOrientation(MT_Quaternion(orientation));   
-}
-
-
-void DT_SetMatrixf(DT_ObjectHandle object, const float *m) 
-{
-    ((DT_Object *)object)->setMatrix(m);
-}
-
-void DT_GetMatrixf(DT_ObjectHandle object, float *m) 
-{
-    ((DT_Object *)object)->getMatrix(m);
-}
-
-void DT_SetMatrixd(DT_ObjectHandle object, const double *m) 
-{
-    ((DT_Object *)object)->setMatrix(m);
-}
-void DT_GetMatrixd(DT_ObjectHandle object, double *m) 
-{
-    ((DT_Object *)object)->getMatrix(m);
-}
-
-void DT_GetBBox(DT_ObjectHandle object, DT_Vector3 min, DT_Vector3 max) 
-{
-	const MT_BBox& bbox = ((DT_Object *)object)->getBBox();
-	bbox.getMin().getValue(min);
-	bbox.getMax().getValue(max);
-}
-
-DT_Bool DT_GetIntersect(DT_ObjectHandle object1, DT_ObjectHandle object2, DT_Vector3 vec)
-{
-	MT_Vector3 v;
-	DT_Bool result = intersect(*(DT_Object*)object1, *(DT_Object*)object2, v);
-	v.getValue(vec);
-	return result;
-}
-
-DT_Scalar DT_GetClosestPair(DT_ObjectHandle object1, DT_ObjectHandle object2,
-							DT_Vector3 point1, DT_Vector3 point2) 
-{
-    MT_Point3 p1, p2;
-    
-    MT_Scalar result = closest_points(*(DT_Object *)object1, 
-									  *(DT_Object *)object2,
-									  p1, p2);
-	p1.getValue(point1);
-	p2.getValue(point2);
-
-    return MT_sqrt(result);
-}
-
-DT_Bool DT_GetCommonPoint(DT_ObjectHandle object1, DT_ObjectHandle object2,
-						  DT_Vector3 point) 
-{
-    MT_Point3   p1, p2;
-	MT_Vector3  v(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0)); 
-    
-    bool result = common_point(*(DT_Object *)object1, *(DT_Object *)object2, v, p1, p2);
-
-	if (result) 
-	{
-		p1.getValue(point);
-	}
-
-    return result;
-}
-
-DT_Bool DT_GetPenDepth(DT_ObjectHandle object1, DT_ObjectHandle object2,
-				    DT_Vector3 point1, DT_Vector3 point2) 
-{
-    MT_Point3   p1, p2;
-	MT_Vector3  v(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0)); 
-    
-    bool result = penetration_depth(*(DT_Object *)object1, *(DT_Object *)object2, v, p1, p2);
-
-	if (result) 
-	{
-		p1.getValue(point1);
-		p2.getValue(point2);
-	}
-
-    return result;
-}
-
-// Response
-
-DT_RespTableHandle DT_CreateRespTable() 
-{
-    return (DT_RespTableHandle)new DT_RespTable;
-}    
-
-void DT_DestroyRespTable(DT_RespTableHandle respTable) 
-{
-    delete (DT_RespTable *)respTable;
-}
-
-DT_ResponseClass DT_GenResponseClass(DT_RespTableHandle respTable) 
-{
-	return ((DT_RespTable *)respTable)->genResponseClass();
-}
-
-void DT_SetResponseClass(DT_RespTableHandle respTable, DT_ObjectHandle object,
-						 DT_ResponseClass responseClass)
-{
-	((DT_RespTable *)respTable)->setResponseClass(object, responseClass);
-}
-
-void DT_ClearResponseClass(DT_RespTableHandle respTable, 
-						   DT_ObjectHandle object)
-{
-	((DT_RespTable *)respTable)->clearResponseClass(object);
-}
-
-void DT_CallResponse(DT_RespTableHandle respTable,
-					 DT_ObjectHandle object1,
-					 DT_ObjectHandle object2,
-					 const DT_CollData *coll_data)
-{
-	const DT_ResponseList& responseList =
-		((DT_RespTable *)respTable)->find(object1, object2);
-	
-	if (responseList.getType() != DT_NO_RESPONSE) 
-	{
-		responseList(((DT_Object *)object1)->getClientObject(), 
-					 ((DT_Object *)object2)->getClientObject(),
-					 coll_data);
-	}
-}
-
-
-void DT_AddDefaultResponse(DT_RespTableHandle respTable,
-                           DT_ResponseCallback response, 
-						   DT_ResponseType type, void *client_data)
-{
-    ((DT_RespTable *)respTable)->addDefault(DT_Response(response, type, client_data));
-}
-
-void DT_RemoveDefaultResponse(DT_RespTableHandle respTable,
-							  DT_ResponseCallback response)
-{
-      ((DT_RespTable *)respTable)->removeDefault(DT_Response(response));
-}
-
-void DT_AddClassResponse(DT_RespTableHandle respTable,
-						 DT_ResponseClass responseClass, 
-						 DT_ResponseCallback response, 
-						 DT_ResponseType type, void *client_data)
-{
-    ((DT_RespTable *)respTable)->addSingle(responseClass, 
-										   DT_Response(response, type, client_data));
-}
-
-void DT_RemoveClassResponse(DT_RespTableHandle respTable,
-							DT_ResponseClass responseClass, 
-							DT_ResponseCallback response) 
-{
-    ((DT_RespTable *)respTable)->removeSingle(responseClass, 
-											  DT_Response(response));
-}
-
-void DT_AddPairResponse(DT_RespTableHandle respTable,
-                        DT_ResponseClass responseClass1, 
-						DT_ResponseClass responseClass2, 
-                        DT_ResponseCallback response,
-						DT_ResponseType type, void *client_data)
-{
-    ((DT_RespTable *)respTable)->addPair(responseClass1, responseClass2, 
-										 DT_Response(response, type, client_data));
-}
-
-void DT_RemovePairResponse(DT_RespTableHandle respTable,
-						   DT_ResponseClass responseClass1, 
-						   DT_ResponseClass responseClass2, 
-						   DT_ResponseCallback response)
-{
-    ((DT_RespTable *)respTable)->removePair(responseClass1, responseClass2, 
-											DT_Response(response));
-}
-
-
-// Runtime
-
-void DT_SetAccuracy(DT_Scalar max_error) 
-{ 
-	if (max_error > MT_Scalar(0.0)) 
-	{
-		DT_Accuracy::setAccuracy(MT_Scalar(max_error)); 
-	}
-}
-
-void DT_SetTolerance(DT_Scalar tol_error) 
-{ 
-	if (tol_error > MT_Scalar(0.0)) 
-	{
-		DT_Accuracy::setTolerance(MT_Scalar(tol_error)); 
-	}
-}
-
-DT_Count DT_Test(DT_SceneHandle scene, DT_RespTableHandle respTable) 
-{ 
-    return ((DT_Scene *)scene)->handleCollisions((DT_RespTable *)respTable);
-}
-
-void *DT_RayCast(DT_SceneHandle scene, void *ignore_client,
-				 const DT_Vector3 source, const DT_Vector3 target,
-				 DT_Scalar max_param, DT_Scalar *param, DT_Vector3 normal) 
-{
-	DT_Scalar  lambda = max_param;
-
-	void *client_object = ((DT_Scene *)scene)->rayCast(ignore_client, source, target, 
-													   lambda, normal);
-   if (client_object)
-   {
-      *param = lambda;
-   }
-	return client_object;
-}
-
-DT_Bool DT_ObjectRayCast(DT_ObjectHandle object,
-	   				     const DT_Vector3 source, const DT_Vector3 target,
-					     DT_Scalar max_param, DT_Scalar *param, DT_Vector3 hit_normal) 
-{
-	MT_Scalar lambda = MT_Scalar(max_param);
-	MT_Vector3 normal;  
-
-	bool result = ((DT_Object *)object)->ray_cast(MT_Point3(source), MT_Point3(target), 
-												  lambda, normal);
-
-	if (result) 
-	{
-		*param = lambda;
-		normal.getValue(hit_normal);
-	}
-	return result;
-}
-
diff --git a/extern/solid/src/DT_Encounter.cpp b/extern/solid/src/DT_Encounter.cpp
deleted file mode 100644
index 36de33154a3..00000000000
--- a/extern/solid/src/DT_Encounter.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "DT_RespTable.h"
-#include "DT_Encounter.h"
-#include "DT_Object.h"
-#include "GEN_MinMax.h"
-
-DT_Bool DT_Encounter::exactTest(const DT_RespTable *respTable, int& count) const 
-{
-	const DT_ResponseList& responseList = respTable->find(m_obj_ptr1, m_obj_ptr2);
-
-   switch (responseList.getType()) 
-   {
-   case DT_BROAD_RESPONSE:
-	   return (respTable->getResponseClass(m_obj_ptr1) < respTable->getResponseClass(m_obj_ptr2)) ?
-			   responseList(m_obj_ptr1->getClientObject(), m_obj_ptr2->getClientObject(), 0) :   
-			   responseList(m_obj_ptr2->getClientObject(), m_obj_ptr1->getClientObject(), 0);    
-   case DT_SIMPLE_RESPONSE: 
-	   if (intersect(*m_obj_ptr1, *m_obj_ptr2, m_sep_axis)) 
-	   {
-		   ++count;
-		   return (respTable->getResponseClass(m_obj_ptr1) < respTable->getResponseClass(m_obj_ptr2)) ?
-			   responseList(m_obj_ptr1->getClientObject(), m_obj_ptr2->getClientObject(), 0) :   
-			   responseList(m_obj_ptr2->getClientObject(), m_obj_ptr1->getClientObject(), 0);    
- 
-	   }
-	   break;
-   case DT_WITNESSED_RESPONSE: {
-	   MT_Point3  p1, p2;
-	   
-	   if (common_point(*m_obj_ptr1, *m_obj_ptr2, m_sep_axis, p1, p2)) 
-	   { 
-		   ++count;
-           if (respTable->getResponseClass(m_obj_ptr1) < respTable->getResponseClass(m_obj_ptr2))
-           {
-			   DT_CollData coll_data;
-			   
-			   p1.getValue(coll_data.point1);
-			   p2.getValue(coll_data.point2);
-			   
-               return responseList(m_obj_ptr1->getClientObject(), m_obj_ptr2->getClientObject(), &coll_data);
-           }
-           else
-           {
-			   DT_CollData coll_data;
-			   
-			   p1.getValue(coll_data.point2);
-			   p2.getValue(coll_data.point1);
-			   
-               return responseList(m_obj_ptr2->getClientObject(), m_obj_ptr1->getClientObject(), &coll_data);
-           }
-	   }
-	   break;
-   }
-   case DT_DEPTH_RESPONSE: {
-	   MT_Point3  p1, p2;
-	   
-	   if (penetration_depth(*m_obj_ptr1, *m_obj_ptr2, m_sep_axis, p1, p2)) 
-	   { 
-		   ++count;
-           if (respTable->getResponseClass(m_obj_ptr1) < respTable->getResponseClass(m_obj_ptr2))
-           {
-			   DT_CollData coll_data;
-			   
-			   p1.getValue(coll_data.point1);
-			   p2.getValue(coll_data.point2);	
-               (p2 - p1).getValue(coll_data.normal);
-			   
-               return responseList(m_obj_ptr1->getClientObject(), m_obj_ptr2->getClientObject(), &coll_data);
-           }
-           else
-           {
-			   DT_CollData coll_data;
-			   
-			   p1.getValue(coll_data.point2);
-			   p2.getValue(coll_data.point1); 
-               (p1 - p2).getValue(coll_data.normal);
-			   
-               return responseList(m_obj_ptr2->getClientObject(), m_obj_ptr1->getClientObject(), &coll_data);
-           }
-	   }
-	   break;
-   }
-   case DT_NO_RESPONSE:
-	   break;
-   default:
-	   assert(false);
-   }
-   return DT_CONTINUE;
-}
diff --git a/extern/solid/src/DT_Encounter.h b/extern/solid/src/DT_Encounter.h
deleted file mode 100644
index f20ea3936b0..00000000000
--- a/extern/solid/src/DT_Encounter.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_ENCOUNTER_H
-#define DT_ENCOUNTER_H
-
-#include 
-
-#include "MT_Vector3.h"
-#include "DT_Object.h"
-#include "DT_Shape.h"
-
-class DT_RespTable;
-
-class DT_Encounter {
-public:
-    DT_Encounter() {}
-    DT_Encounter(DT_Object *obj_ptr1, DT_Object *obj_ptr2) 
-        : m_sep_axis(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0)) 
-    {
-		assert(obj_ptr1 != obj_ptr2);
-        if (obj_ptr2->getType() < obj_ptr1->getType() || 
-            (obj_ptr2->getType() == obj_ptr1->getType() &&
-             obj_ptr2 < obj_ptr1))
-        { 
-            m_obj_ptr1 = obj_ptr2; 
-            m_obj_ptr2 = obj_ptr1; 
-        }
-        else 
-        { 
-            m_obj_ptr1 = obj_ptr1; 
-            m_obj_ptr2 = obj_ptr2; 
-        }
-    }
-
-    DT_Object         *first()          const { return m_obj_ptr1; }
-    DT_Object         *second()         const { return m_obj_ptr2; }
-    const MT_Vector3&  separatingAxis() const { return m_sep_axis; }
-
- 	DT_Bool exactTest(const DT_RespTable *respTable, int& count) const;
-
-private:
-    DT_Object          *m_obj_ptr1;
-    DT_Object          *m_obj_ptr2;
-    mutable MT_Vector3  m_sep_axis;
-};
-
-inline bool operator<(const DT_Encounter& a, const DT_Encounter& b) 
-{ 
-    return a.first() < b.first() || 
-        (a.first() == b.first() && a.second() < b.second()); 
-}
-
-
-
-inline std::ostream& operator<<(std::ostream& os, const DT_Encounter& a) {
-    return os << '(' << a.first() << ", " << a.second() << ')';
-}
-
-
-
-typedef std::set DT_EncounterTable;
-
-#endif
diff --git a/extern/solid/src/DT_Object.cpp b/extern/solid/src/DT_Object.cpp
deleted file mode 100644
index ed43a7bdaf2..00000000000
--- a/extern/solid/src/DT_Object.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "DT_Object.h"
-#include "DT_AlgoTable.h"
-#include "DT_Convex.h" 
-#include "DT_Complex.h" 
-#include "DT_LineSegment.h" 
-#include "DT_Transform.h"
-#include "DT_Minkowski.h"
-#include "DT_Sphere.h"
-
-void DT_Object::setBBox() 
-{
-	m_bbox = m_shape.bbox(m_xform, m_margin); 
-	DT_Vector3 min, max;
-	m_bbox.getMin().getValue(min);
-	m_bbox.getMax().getValue(max);
-	
-	T_ProxyList::const_iterator it;
-	for (it = m_proxies.begin(); it != m_proxies.end(); ++it) 
-	{
-		BP_SetBBox(*it, min, max);
-	}
-}
-
-bool DT_Object::ray_cast(const MT_Point3& source, const MT_Point3& target, 
-						 MT_Scalar& lambda, MT_Vector3& normal) const 
-{	
-	MT_Transform inv_xform = m_xform.inverse();
-	MT_Point3 local_source = inv_xform(source);
-	MT_Point3 local_target = inv_xform(target);
-	MT_Vector3 local_normal;
-
-	bool result = m_shape.ray_cast(local_source, local_target, lambda, local_normal);
-    	
-	if (result) 
-	{
-		normal = local_normal * inv_xform.getBasis();
-      MT_Scalar len = normal.length();
-		if (len > MT_Scalar(0.0))
-      {
-         normal /= len;
-      }
-	}
-
-	return result;
-}
-
-
-typedef AlgoTable IntersectTable;
-typedef AlgoTable Common_pointTable;
-typedef AlgoTable Penetration_depthTable;
-typedef AlgoTable Closest_pointsTable;
-
-
-bool intersectConvexConvex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
-						   const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
-                           MT_Vector3& v) 
-{
-	DT_Transform ta(a2w, (const DT_Convex&)a);
-	DT_Transform tb(b2w, (const DT_Convex&)b);
-    return intersect((a_margin > MT_Scalar(0.0) ? static_cast(DT_Minkowski(ta, DT_Sphere(a_margin))) : static_cast(ta)), 
-			         (b_margin > MT_Scalar(0.0) ? static_cast(DT_Minkowski(tb, DT_Sphere(b_margin))) : static_cast(tb)), v);
-}
-
-bool intersectComplexConvex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
-						    const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
-                            MT_Vector3& v) 
-{
-	if (a.getType() == COMPLEX)
-	{
-		DT_Transform tb(b2w, (const DT_Convex&)b);
-		return intersect((const DT_Complex&)a, a2w, a_margin, 
-		             (b_margin > MT_Scalar(0.0) ? static_cast(DT_Minkowski(tb, DT_Sphere(b_margin))) : static_cast(tb)), v);
-	}
-	
-	bool r = intersectComplexConvex(b, b2w, b_margin, a, a2w, a_margin, v);
-	v *= -1.;
-	return r;
-}
-
-bool intersectComplexComplex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
-							 const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
-                             MT_Vector3& v) 
-{
-    return intersect((const DT_Complex&)a, a2w, a_margin, 
-					 (const DT_Complex&)b, b2w, b_margin, v);
-}
-
-IntersectTable *intersectInitialize() 
-{
-    IntersectTable *p = new IntersectTable;
-    p->addEntry(COMPLEX, COMPLEX, intersectComplexComplex);
-    p->addEntry(COMPLEX, CONVEX, intersectComplexConvex);
-    p->addEntry(CONVEX, CONVEX, intersectConvexConvex);
-    return p;
-}
-
-bool intersect(const DT_Object& a, const DT_Object& b, MT_Vector3& v) 
-{
-    static IntersectTable *intersectTable = intersectInitialize();
-    Intersect intersect = intersectTable->lookup(a.getType(), b.getType());
-    return intersect(a.m_shape, a.m_xform, a.m_margin, 
-		             b.m_shape, b.m_xform, b.m_margin, v);
-}
-
-bool common_pointConvexConvex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
-							  const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
-							  MT_Vector3& v, MT_Point3& pa, MT_Point3& pb) 
-{
-	DT_Transform ta(a2w, (const DT_Convex&)a);
-	DT_Transform tb(b2w, (const DT_Convex&)b);
-    return common_point((a_margin > MT_Scalar(0.0) ? static_cast(DT_Minkowski(ta, DT_Sphere(a_margin))) : static_cast(ta)), 
-						(b_margin > MT_Scalar(0.0) ? static_cast(DT_Minkowski(tb, DT_Sphere(b_margin))) : static_cast(tb)), v, pa, pb);
-}
-
-bool common_pointComplexConvex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
-							   const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
-							   MT_Vector3& v, MT_Point3& pa, MT_Point3& pb) 
-{
-	if (a.getType() == COMPLEX)
-	{
-		DT_Transform tb(b2w, (const DT_Convex&)b);
-		return common_point((const DT_Complex&)a, a2w, a_margin,
-					(b_margin > MT_Scalar(0.0) ? static_cast(DT_Minkowski(tb, DT_Sphere(b_margin))) : static_cast(tb)), v, pa, pb);
-	}
-	
-	bool r = common_pointComplexConvex(b, b2w, b_margin, a, a2w, a_margin, v, pb, pa);
-	v *= -1.;
-	return r;
-}
-
-bool common_pointComplexComplex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
-								const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
-								MT_Vector3& v, MT_Point3& pa, MT_Point3& pb) 
-{
-    return common_point((const DT_Complex&)a, a2w, a_margin, 
-						(const DT_Complex&)b, b2w, b_margin, v, pa, pb);
-}
-
-Common_pointTable *common_pointInitialize() 
-{
-    Common_pointTable *p = new Common_pointTable;
-    p->addEntry(COMPLEX, COMPLEX, common_pointComplexComplex);
-    p->addEntry(COMPLEX, CONVEX, common_pointComplexConvex);
-    p->addEntry(CONVEX, CONVEX, common_pointConvexConvex);
-    return p;
-}
-
-bool common_point(const DT_Object& a, const DT_Object& b, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb) 
-{
-    static Common_pointTable *common_pointTable = common_pointInitialize();
-    Common_point common_point = common_pointTable->lookup(a.getType(), b.getType());
-    return common_point(a.m_shape, a.m_xform, a.m_margin, 
-						b.m_shape, b.m_xform, b.m_margin, v, pa, pb);
-}
-
-
-
-bool penetration_depthConvexConvex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
-								   const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
-                                   MT_Vector3& v, MT_Point3& pa, MT_Point3& pb) 
-{
-    return hybrid_penetration_depth(DT_Transform(a2w, (const DT_Convex&)a), a_margin, 
-									DT_Transform(b2w, (const DT_Convex&)b), b_margin, v, pa, pb);
-}
-
-bool penetration_depthComplexConvex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
-									const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
-                                    MT_Vector3& v, MT_Point3& pa, MT_Point3& pb) 
-{
-    if (a.getType() == COMPLEX)
-    	return penetration_depth((const DT_Complex&)a, a2w, a_margin,
-							 DT_Transform(b2w, (const DT_Convex&)b), b_margin, v, pa, pb);
-
-    bool r = penetration_depthComplexConvex(b, b2w, b_margin, a, a2w, a_margin, v, pb, pa);
-    v *= -1.;
-    return r;
-}
-
-bool penetration_depthComplexComplex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
-									 const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
-                                     MT_Vector3& v, MT_Point3& pa, MT_Point3& pb) 
-{
-    return penetration_depth((const DT_Complex&)a, a2w, a_margin, (const DT_Complex&)b, b2w, b_margin, v, pa, pb);
-}
-
-Penetration_depthTable *penetration_depthInitialize() 
-{
-    Penetration_depthTable *p = new Penetration_depthTable;
-    p->addEntry(COMPLEX, COMPLEX, penetration_depthComplexComplex);
-    p->addEntry(COMPLEX, CONVEX, penetration_depthComplexConvex);
-    p->addEntry(CONVEX, CONVEX, penetration_depthConvexConvex);
-    return p;
-}
-
-bool penetration_depth(const DT_Object& a, const DT_Object& b, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb) 
-{
-    static Penetration_depthTable *penetration_depthTable = penetration_depthInitialize();
-    Penetration_depth penetration_depth = penetration_depthTable->lookup(a.getType(), b.getType());
-    return penetration_depth(a.m_shape, a.m_xform, a.m_margin, 
-		                     b.m_shape, b.m_xform, b.m_margin, v, pa, pb);
-}
-
-
-MT_Scalar closest_pointsConvexConvex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
-									 const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
-									 MT_Point3& pa, MT_Point3& pb)
-{
-	DT_Transform ta(a2w, (const DT_Convex&)a);
-	DT_Transform tb(b2w, (const DT_Convex&)b);
-    return closest_points((a_margin > MT_Scalar(0.0) ? static_cast(DT_Minkowski(ta, DT_Sphere(a_margin))) : static_cast(ta)), 
-						  (b_margin > MT_Scalar(0.0) ? static_cast(DT_Minkowski(tb, DT_Sphere(b_margin))) : static_cast(tb)), MT_INFINITY, pa, pb);
-}
-
-MT_Scalar closest_pointsComplexConvex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
-									  const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
-									  MT_Point3& pa, MT_Point3& pb)
-{
-    if (a.getType() == COMPLEX)
-    {
-	DT_Transform tb(b2w, (const DT_Convex&)b);
-	return closest_points((const DT_Complex&)a, a2w, a_margin,
-							(b_margin > MT_Scalar(0.0) ? static_cast(DT_Minkowski(tb, DT_Sphere(b_margin))) : static_cast(tb)), pa, pb);
-    }
-    
-    return closest_pointsComplexConvex(b, b2w, b_margin, a, a2w, a_margin, pb, pa);
-}
-
-MT_Scalar closest_pointsComplexComplex(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
-									   const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
-									   MT_Point3& pa, MT_Point3& pb) 
-{
-    return closest_points((const DT_Complex&)a, a2w, a_margin, 
-						  (const DT_Complex&)b, b2w, b_margin, pa, pb);
-}
-
-Closest_pointsTable *closest_pointsInitialize()
-{
-    Closest_pointsTable *p = new Closest_pointsTable;
-    p->addEntry(COMPLEX, COMPLEX, closest_pointsComplexComplex);
-    p->addEntry(COMPLEX, CONVEX, closest_pointsComplexConvex);
-    p->addEntry(CONVEX, CONVEX, closest_pointsConvexConvex);
-    return p;
-}
-
-MT_Scalar closest_points(const DT_Object& a, const DT_Object& b,
-						 MT_Point3& pa, MT_Point3& pb) 
-{
-    static Closest_pointsTable *closest_pointsTable = closest_pointsInitialize();
-    Closest_points closest_points = closest_pointsTable->lookup(a.getType(), b.getType());
-    return closest_points(a.m_shape, a.m_xform, a.m_margin, 
-						  b.m_shape, b.m_xform, b.m_margin, pa, pb);
-}
-
diff --git a/extern/solid/src/DT_Object.h b/extern/solid/src/DT_Object.h
deleted file mode 100644
index 78beee2ab57..00000000000
--- a/extern/solid/src/DT_Object.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_OBJECT_H
-#define DT_OBJECT_H
-
-#include 
-
-#include "SOLID.h"
-#include "SOLID_broad.h"
-
-#include "MT_Transform.h"
-#include "MT_Quaternion.h"
-#include "MT_BBox.h"
-#include "DT_Shape.h"
-
-class DT_Convex;
-
-class DT_Object {
-public:
-    DT_Object(void *client_object, const DT_Shape& shape) :
-		m_client_object(client_object),
-		m_shape(shape), 
-		m_margin(MT_Scalar(0.0))
-	{
-		m_xform.setIdentity();
-		setBBox();
-	}
-
-	void setMargin(MT_Scalar margin) 
-	{ 
-		m_margin = margin; 
-		setBBox();
-	}
-
-	void setScaling(const MT_Vector3& scaling)
-	{
-        m_xform.scale(scaling);
-        setBBox();
-    }
-
-    void setPosition(const MT_Point3& pos) 
-	{ 
-        m_xform.setOrigin(pos);
-        setBBox();
-    }
-    
-    void setOrientation(const MT_Quaternion& orn)
-	{
-		m_xform.setRotation(orn);
-		setBBox();
-    }
-
-	void setMatrix(const float *m) 
-	{
-        m_xform.setValue(m);
-		assert(m_xform.getBasis().determinant() != MT_Scalar(0.0));
-        setBBox();
-    }
-
-    void setMatrix(const double *m)
-	{
-        m_xform.setValue(m);
-		assert(m_xform.getBasis().determinant() != MT_Scalar(0.0));
-        setBBox();
-    }
-
-    void getMatrix(float *m) const
-	{
-        m_xform.getValue(m);
-    }
-
-    void getMatrix(double *m) const 
-	{
-        m_xform.getValue(m);
-    }
-
-	void setBBox();
-
-	const MT_BBox& getBBox() const { return m_bbox; }	
-	
-    DT_ResponseClass getResponseClass() const { return m_responseClass; }
-    
-	void setResponseClass(DT_ResponseClass responseClass) 
-	{ 
-		m_responseClass = responseClass;
-	}
-
-    DT_ShapeType getType() const { return m_shape.getType(); }
-
-    void *getClientObject() const { return m_client_object; }
-
-	bool ray_cast(const MT_Point3& source, const MT_Point3& target, 
-				  MT_Scalar& param, MT_Vector3& normal) const; 
-
-	void addProxy(BP_ProxyHandle proxy) { m_proxies.push_back(proxy); }
-
-	void removeProxy(BP_ProxyHandle proxy) 
-	{ 
-		T_ProxyList::iterator it = std::find(m_proxies.begin(), m_proxies.end(), proxy);
-		if (it != m_proxies.end()) {
-			m_proxies.erase(it);
-		}
-	}
-
-
-	friend bool intersect(const DT_Object&, const DT_Object&, MT_Vector3& v);
-	
-	friend bool common_point(const DT_Object&, const DT_Object&, MT_Vector3&, 
-							 MT_Point3&, MT_Point3&);
-	
-	friend bool penetration_depth(const DT_Object&, const DT_Object&, 
-								  MT_Vector3&, MT_Point3&, MT_Point3&);
-	
-	friend MT_Scalar closest_points(const DT_Object&, const DT_Object&, 
-									MT_Point3&, MT_Point3&);
-
-private:
-	typedef std::vector T_ProxyList;
-
-	void              *m_client_object;
-	DT_ResponseClass   m_responseClass;
-    const DT_Shape&    m_shape;
-    MT_Scalar          m_margin;
-	MT_Transform       m_xform;
-	T_ProxyList		   m_proxies;
-	MT_BBox            m_bbox;
-};
-
-#endif
-
-
-
-
-
-
-
diff --git a/extern/solid/src/DT_RespTable.cpp b/extern/solid/src/DT_RespTable.cpp
deleted file mode 100644
index 20fbfc06aac..00000000000
--- a/extern/solid/src/DT_RespTable.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "DT_RespTable.h"
-
-#include 
-
-DT_ResponseList DT_RespTable::g_emptyResponseList;
-
-DT_RespTable::~DT_RespTable()
-{
-	DT_ResponseClass i;
-	for (i = 0; i < m_responseClass; ++i) 
-	{
-		delete [] m_table[i];
-	}
-}
-
-DT_ResponseClass DT_RespTable::genResponseClass()
-{
-	DT_ResponseClass newClass = m_responseClass++;
-	DT_ResponseList *newList = new DT_ResponseList[m_responseClass];
-	assert(newList);
-	m_table.push_back(newList);
-	m_singleList.resize(m_responseClass);
-	DT_ResponseClass i;
-	for (i = 0; i < m_responseClass; ++i) 
-	{
-		newList[i].append(m_default);
-		newList[i].append(m_singleList[i]);
-	}
-	return newClass;
-}
-
-void DT_RespTable::setResponseClass(void *object, 
-									DT_ResponseClass responseClass) 
-{
-	assert(responseClass < m_responseClass);
-	m_objectMap[object] = responseClass;
-}
-
-DT_ResponseClass DT_RespTable::getResponseClass(void *object) const
-{
-	T_ObjectMap::const_iterator it = m_objectMap.find(object);
-	assert(it != m_objectMap.end());
-	return (*it).second;
-}
-
-void DT_RespTable::clearResponseClass(void *object) 
-{
-	m_objectMap.erase(object);
-}
-
-const DT_ResponseList& DT_RespTable::find(void *object1, void *object2) const
-{
-	T_ObjectMap::const_iterator it = m_objectMap.find(object1);
-	if (it != m_objectMap.end()) 
-	{
-		DT_ResponseClass responseClass1 = (*it).second;
-		it = m_objectMap.find(object2);
-		if (it != m_objectMap.end()) 
-		{
-			DT_ResponseClass responseClass2 = (*it).second;
-			if (responseClass1 < responseClass2) 
-			{
-				std::swap(responseClass1, responseClass2);
-			}
-			return m_table[responseClass1][responseClass2];
-		}
-	}
-	return g_emptyResponseList;
-}
-
-void DT_RespTable::addDefault(const DT_Response& response)
-{
-	m_default.addResponse(response);
-	DT_ResponseClass i;
-	for (i = 0; i < m_responseClass; ++i) 
-	{
-		DT_ResponseClass j;
-		for (j = 0; j <= i; ++j) 
-		{
-			m_table[i][j].addResponse(response);
-		}
-	}
-}
-
-void DT_RespTable::removeDefault(const DT_Response& response)
-{
-	m_default.removeResponse(response);
-	DT_ResponseClass i;
-	for (i = 0; i < m_responseClass; ++i) 
-	{
-		DT_ResponseClass j;
-		for (j = 0; j <= i; ++j) 
-		{
-			m_table[i][j].removeResponse(response);
-		}
-	}
-}
-
-void DT_RespTable::addSingle(DT_ResponseClass responseClass, 
-							 const DT_Response& response)
-{	
-	assert(responseClass < m_responseClass);
-	m_singleList[responseClass].addResponse(response);
-	DT_ResponseClass j;
-	for (j = 0; j < responseClass; ++j) 
-	{
-		m_table[responseClass][j].addResponse(response);
-	}
-	
-	DT_ResponseClass i;
-	for (i = responseClass; i < m_responseClass; ++i) 
-	{
-		m_table[i][responseClass].addResponse(response);
-	}
-}
-
-void DT_RespTable::removeSingle(DT_ResponseClass responseClass, 
-								const DT_Response& response)
-{	
-	assert(responseClass < m_responseClass);
-	m_singleList[responseClass].removeResponse(response);
-	DT_ResponseClass j;
-	for (j = 0; j < responseClass; ++j) 
-	{
-		m_table[responseClass][j].removeResponse(response);
-	}
-	
-	DT_ResponseClass i;
-	for (i = responseClass; i < m_responseClass; ++i) 
-	{
-		m_table[i][responseClass].removeResponse(response);
-	}
-}
-
-void DT_RespTable::addPair(DT_ResponseClass responseClass1,
-						   DT_ResponseClass responseClass2, 
-						   const DT_Response& response)
-{
-	assert(responseClass1 < m_responseClass);
-	assert(responseClass2 < m_responseClass);
-	if (responseClass1 < responseClass2) 
-	{
-		std::swap(responseClass1, responseClass2);
-	}
-	m_table[responseClass1][responseClass2].addResponse(response);
-}
-
-
-void DT_RespTable::removePair(DT_ResponseClass responseClass1,
-							  DT_ResponseClass responseClass2, 
-							  const DT_Response& response)
-{
-	assert(responseClass1 < m_responseClass);
-	assert(responseClass2 < m_responseClass);
-	if (responseClass1 < responseClass2) 
-	{
-		std::swap(responseClass1, responseClass2);
-	}
-	m_table[responseClass1][responseClass2].removeResponse(response);
-}
-
diff --git a/extern/solid/src/DT_RespTable.h b/extern/solid/src/DT_RespTable.h
deleted file mode 100644
index 9a17f562937..00000000000
--- a/extern/solid/src/DT_RespTable.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_RESPTABLE_H
-#define DT_RESPTABLE_H
-
-#include 
-#include 
-#include 
-#include 
-#include "GEN_MinMax.h"
-#include "DT_Response.h"
-
-class DT_ResponseList : public std::list {
-public:
-    DT_ResponseList() : m_type(DT_NO_RESPONSE) {}
-
-	DT_ResponseType getType() const { return m_type; }
-
-    void addResponse(const DT_Response& response) 
-	{
-        if (response.getType() != DT_NO_RESPONSE) 
-		{
-            push_back(response);
-            GEN_set_max(m_type, response.getType());
-        }
-    }
-
-    void removeResponse(const DT_Response& response) 
-	{
-		iterator it = std::find(begin(), end(), response);
-		if (it != end()) 
-		{
-			erase(it);
-			m_type = DT_NO_RESPONSE;
-			for (it = begin(); it != end(); ++it) 
-			{
-				GEN_set_max(m_type, (*it).getType());
-			}
-		}
-    }
-	
-    void append(const DT_ResponseList& responseList) 
-	{
-        if (responseList.getType() != DT_NO_RESPONSE) 
-		{
-			const_iterator it;
-			for (it = responseList.begin(); it != responseList.end(); ++it) 
-			{
-				addResponse(*it);
-			}
-		}
-	}
-
-    DT_Bool operator()(void *a, void *b, const DT_CollData *coll_data) const 
-	{
-		DT_Bool done = DT_CONTINUE;
-		const_iterator it;
-        for (it = begin(); !done && it != end(); ++it) 
-		{
-            done = (*it)(a, b, coll_data);
-        }
-		return done;
-    }
-    
-private:
-	DT_ResponseType    m_type;
-};
-
-class DT_RespTable {
-private:
-	typedef std::map T_ObjectMap; 
-	typedef std::vector T_PairTable;
-	typedef std::vector T_SingleList;
-
-public:
-	DT_RespTable() : m_responseClass(0) {}
-
-	~DT_RespTable();
-
-	DT_ResponseClass genResponseClass();
-	
-	void setResponseClass(void *object, DT_ResponseClass responseClass);
-	DT_ResponseClass getResponseClass(void *object) const;
-	
-	void clearResponseClass(void *object);
-	
-	const DT_ResponseList& find(void *object1, void *object2) const;
-
-    void addDefault(const DT_Response& response); 
-    void removeDefault(const DT_Response& response); 
-
-    void addSingle(DT_ResponseClass responseClass, 
-				   const DT_Response& response);
-    void removeSingle(DT_ResponseClass responseClass, 
-					  const DT_Response& response);
-	
-    void addPair(DT_ResponseClass responseClass1, 
-				 DT_ResponseClass responseClass2, 
-				 const DT_Response& response);
-    void removePair(DT_ResponseClass responseClass1, 
-					DT_ResponseClass responseClass2, 
-					const DT_Response& response);
-
-private:
-	static DT_ResponseList g_emptyResponseList;
-
-	T_ObjectMap      m_objectMap;
-	DT_ResponseClass m_responseClass;
-	T_PairTable      m_table;
-	T_SingleList     m_singleList;
-    DT_ResponseList  m_default;
-};
-
-#endif
-
-
-
-
diff --git a/extern/solid/src/DT_Response.h b/extern/solid/src/DT_Response.h
deleted file mode 100644
index e58d9bb9944..00000000000
--- a/extern/solid/src/DT_Response.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_RESPONSE_H
-#define DT_RESPONSE_H
-
-#include "SOLID.h"
-
-class DT_Response {
-public:
-    DT_Response(DT_ResponseCallback response    = 0, 
-				DT_ResponseType     type        = DT_NO_RESPONSE, 
-				void               *client_data = 0) 
-	  : m_response(response), 
-		m_type(type), 
-		m_client_data(client_data) {}
-    
-	DT_ResponseType getType() const { return m_type; }
-
-	DT_Bool operator()(void *a, void *b, const DT_CollData *coll_data) const 
-	{  
-		return (*m_response)(m_client_data, a, b, coll_data); 
-	}
-
-	friend bool operator==(const DT_Response& a, const DT_Response& b) 
-	{
-		return a.m_response == b.m_response;
-	}
-    
-	friend bool operator!=(const DT_Response& a, const DT_Response& b) 
-	{
-		return a.m_response != b.m_response;
-	}
-    
-private:
-    DT_ResponseCallback  m_response;
-    DT_ResponseType      m_type;
-    void                *m_client_data;
-};
-
-#endif  
-
-
diff --git a/extern/solid/src/DT_Scene.cpp b/extern/solid/src/DT_Scene.cpp
deleted file mode 100644
index 56cea1633ca..00000000000
--- a/extern/solid/src/DT_Scene.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "DT_Scene.h"
-#include "DT_Object.h"
-#include "DT_Convex.h"
-
-//#define DEBUG
-
-static void beginOverlap(void *client_data, void *object1, void *object2) 
-{
-	DT_Encounter e((DT_Object *)object1, (DT_Object *)object2);
-	DT_EncounterTable *encounterTable = static_cast(client_data);
-
-#ifdef DEBUG	
-	std::cout << "Begin: " << e << std::endl; 
-#endif
-
-	encounterTable->insert(e);
-}
-
-
-static void endOverlap(void *client_data, void *object1, void *object2) 
-{
-	DT_Encounter e((DT_Object *)object1, (DT_Object *)object2);
-	DT_EncounterTable *encounterTable = static_cast(client_data);
-
-#ifdef DEBUG
-	std::cout << "End:   " << e << std::endl; 
-#endif
-	
-	assert(encounterTable->find(e) != encounterTable->end()); 
-	encounterTable->erase(e);
-}
-
-struct DT_RayCastData {
-	DT_RayCastData(const void *ignore) 
-	  : m_ignore(ignore) 
-	{}
-
-	const void  *m_ignore;
-	MT_Vector3  m_normal;
-};
-
-static bool objectRayCast(void *client_data, 
-						  void *object,  
-						  const DT_Vector3 source,
-						  const DT_Vector3 target,
-						  DT_Scalar *lambda) 
-{
-	DT_RayCastData *data = static_cast(client_data); 
-	if (((DT_Object *)object)->getClientObject() != data->m_ignore)
-	{
-		MT_Scalar param = MT_Scalar(*lambda);
-		
-		if (((DT_Object *)object)->ray_cast(MT_Point3(source), MT_Point3(target),
-											param, data->m_normal))
-		{
-			*lambda = param;
-			return true;
-		}
-	}
-	return false;
-}
-
-DT_Scene::DT_Scene() 
-  : m_broadphase(BP_CreateScene(&m_encounterTable, &beginOverlap, &endOverlap))
-{}
-
-DT_Scene::~DT_Scene()
-{
-	BP_DestroyScene(m_broadphase);
-}
-
-void DT_Scene::addObject(DT_Object &object)
-{
-	const MT_BBox& bbox = object.getBBox();
-	DT_Vector3 min, max;
-	bbox.getMin().getValue(min);
-	bbox.getMax().getValue(max);
-    BP_ProxyHandle proxy = BP_CreateProxy(m_broadphase, &object, min, max);
-	
-#ifdef DEBUG
-	DT_EncounterTable::iterator it;	
-	std::cout << "Add " << &object << ':';
-	for (it = m_encounterTable.begin(); it != m_encounterTable.end(); ++it) {
-		std::cout << ' ' << (*it);
-	}
-	std::cout << std::endl;
-#endif
-	object.addProxy(proxy);
-    m_objectList.push_back(std::make_pair(&object, proxy));
-}
-
-
-
-void DT_Scene::removeObject(DT_Object& object)
-{
-    T_ObjectList::iterator it = m_objectList.begin();
-
-    while (it != m_objectList.end() && &object != (*it).first)
-	{
-        ++it;
-    }
-
-    if (it != m_objectList.end())
-	{
-		object.removeProxy((*it).second);
-        BP_DestroyProxy(m_broadphase, (*it).second);
-		m_objectList.erase(it);
-
-#ifdef DEBUG
-		std::cout << "Remove " << &object << ':';
-		DT_EncounterTable::iterator it;	
-		for (it = m_encounterTable.begin(); it != m_encounterTable.end(); ++it)
-		{
-			std::cout << ' ' << (*it);
-			assert((*it).first() != &object &&
-				   (*it).second() != &object);
-		}
-		std::cout << std::endl;
-#endif
-    }
-}
-
-
-
-int DT_Scene::handleCollisions(const DT_RespTable *respTable)
-{
-    int count = 0;
-
-    assert(respTable);
-
-	DT_EncounterTable::iterator it;	
-	for (it = m_encounterTable.begin(); it != m_encounterTable.end(); ++it)
-	{
-		if ((*it).exactTest(respTable, count))
-		{
-			break;
-        }
-	
-    }
-    return count;
-}
-
-void *DT_Scene::rayCast(const void *ignore_client,
-						const DT_Vector3 source, const DT_Vector3 target, 
-						DT_Scalar& lambda, DT_Vector3 normal) const 
-{
-	DT_RayCastData data(ignore_client);
-	DT_Object *object = (DT_Object *)BP_RayCast(m_broadphase, 
-												&objectRayCast, 
-												&data, 
-												source, target,
-												&lambda);
-	if (object)
-	{
-		data.m_normal.getValue(normal);
-		return object->getClientObject();
-	}
-	
-	return 0;
-}
diff --git a/extern/solid/src/DT_Scene.h b/extern/solid/src/DT_Scene.h
deleted file mode 100644
index 9b061910312..00000000000
--- a/extern/solid/src/DT_Scene.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_SCENE_H
-#define DT_SCENE_H
-
-#include 
-
-#include "SOLID_broad.h"
-#include "DT_Encounter.h"
-
-class DT_Object;
-class DT_RespTable;
-
-class DT_Scene {
-public:
-    DT_Scene();
-    ~DT_Scene();
-
-    void addObject(DT_Object& object);
-    void removeObject(DT_Object& object);
-
-    int  handleCollisions(const DT_RespTable *respTable);
-
-	void *rayCast(const void *ignore_client, 
-				  const DT_Vector3 source, const DT_Vector3 target, 
-				  DT_Scalar& lambda, DT_Vector3 normal) const;
-
-private:
-	typedef std::vector > T_ObjectList;
-
-	BP_SceneHandle      m_broadphase;
-	T_ObjectList        m_objectList;
-    DT_EncounterTable   m_encounterTable;
-};
-
-#endif
diff --git a/extern/solid/src/Makefile b/extern/solid/src/Makefile
deleted file mode 100644
index e8ef7a606c9..00000000000
--- a/extern/solid/src/Makefile
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# $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.
-#
-# The Original Code is: all of this file.
-#
-# Contributor(s): none yet.
-#
-# ***** END GPL LICENSE BLOCK *****
-#
-#
-
-SOURCEDIR = extern/solid/src
-LIBNAME = solid
-DIR = $(OCGDIR)/extern/$(LIBNAME)
-DIRS = broad complex convex
-
-include nan_subdirs.mk
-
-CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
-
-CPPFLAGS += -I../include -I$(NAN_QHULL)/include
-CPPFLAGS += -Iconvex -Icomplex
-CPPFLAGS += -DQHULL -DUSE_DOUBLES
-
-include nan_compile.mk 
-
diff --git a/extern/solid/src/broad/BP_C-api.cpp b/extern/solid/src/broad/BP_C-api.cpp
deleted file mode 100644
index 43e1172927b..00000000000
--- a/extern/solid/src/broad/BP_C-api.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "SOLID_broad.h"
-
-#include "BP_Scene.h"
-#include "BP_Proxy.h"
-
-BP_SceneHandle BP_CreateScene(void *client_data,
-							  BP_Callback beginOverlap,
-							  BP_Callback endOverlap)
-{
-	return (BP_SceneHandle)new BP_Scene(client_data, 
-										beginOverlap, 
-										endOverlap);
-}
-
- 
-void BP_DestroyScene(BP_SceneHandle scene)
-{
-	delete (BP_Scene *)scene;
-}
-	
-
-BP_ProxyHandle BP_CreateProxy(BP_SceneHandle scene, void *object,
-							  const DT_Vector3 min, const DT_Vector3 max)
-{
-	return (BP_ProxyHandle)
-		((BP_Scene *)scene)->createProxy(object, min, max);
-}
-
-
-void BP_DestroyProxy(BP_SceneHandle scene, BP_ProxyHandle proxy) 
-{
-	((BP_Scene *)scene)->destroyProxy((BP_Proxy *)proxy);
-}
-
-
-
-void BP_SetBBox(BP_ProxyHandle proxy, const DT_Vector3 min, const DT_Vector3 max)	
-{
-	((BP_Proxy *)proxy)->setBBox(min, max);
-}
-
-void *BP_RayCast(BP_SceneHandle scene, 
-				 BP_RayCastCallback objectRayCast,
-				 void *client_data,
-				 const DT_Vector3 source,
-				 const DT_Vector3 target,
-				 DT_Scalar *lambda) 
-{
-	return ((BP_Scene *)scene)->rayCast(objectRayCast,
-										client_data,
-										source,	target,
-										*lambda);
-}
-
diff --git a/extern/solid/src/broad/BP_Endpoint.h b/extern/solid/src/broad/BP_Endpoint.h
deleted file mode 100644
index 8de6e67ce65..00000000000
--- a/extern/solid/src/broad/BP_Endpoint.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef BP_ENDPOINT_H
-#define BP_ENDPOINT_H
-
-#include "SOLID_types.h"
-
-class BP_Proxy;
-
-class BP_Link {
-public:
-	BP_Link() {}
-	explicit BP_Link(BP_Proxy *proxy) :
-		m_proxy(proxy)
-	{}
-
-	DT_Index  m_index;
-	DT_Count  m_count;
-	BP_Proxy *m_proxy;
-};
-
-typedef unsigned int Uint32;
-
-class BP_Endpoint {
-public:
-    enum { 
-		MINIMUM = 0x00000000, 
-		MAXIMUM = 0x80000000,	
-		TYPEBIT = 0x00000001
-	};
-
-    BP_Endpoint() {}
-    BP_Endpoint(DT_Scalar pos, Uint32 type, BP_Link *link) 
-	  :	m_link(link)
-	{
-		setPos(pos, type);
-	}
- 
-	DT_Scalar getPos()   const { return m_pos; }
-	DT_Index&   getIndex() const { return m_link->m_index; }
-	DT_Count&   getCount() const { return m_link->m_count; }
-	BP_Proxy *getProxy() const { return m_link->m_proxy; }
-	
-	DT_Index   getEndIndex()   const { return (m_link + 1)->m_index; }
-	
-	Uint32 getType() const 
-	{ 
-		return (m_bits & TYPEBIT) ? (~m_bits & MAXIMUM) : (m_bits & MAXIMUM);
-	}
-
-	void setPos(DT_Scalar pos, Uint32 type) 
-	{
-		m_pos = pos; 
-		if ((m_bits & MAXIMUM) == type) 
-		{
-			m_bits &= ~TYPEBIT;
-		}
-		else 
-		{
-			m_bits |= TYPEBIT;
-		}
-	}
-
-private:
-	union {
-		DT_Scalar    m_pos;
-		Uint32       m_bits;
-	};
-	BP_Link        *m_link;
-};
-
-inline bool operator<(const BP_Endpoint& a, const BP_Endpoint& b) 
-{
-    return a.getPos() < b.getPos(); 
-}
-
-#endif
-
-
-
-
-
-
-
-
-
-
diff --git a/extern/solid/src/broad/BP_EndpointList.cpp b/extern/solid/src/broad/BP_EndpointList.cpp
deleted file mode 100644
index aa094ffeb0a..00000000000
--- a/extern/solid/src/broad/BP_EndpointList.cpp
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include 
-#include 
-
-#include "BP_EndpointList.h"
-#include "BP_Scene.h"
-#include "BP_Proxy.h"
-#include "BP_ProxyList.h"
-
-DT_Index BP_EndpointList::stab(const BP_Endpoint& pos, BP_ProxyList& proxies) const 
-{
-	DT_Index result = std::upper_bound(begin(), end(), pos) - begin();
-	
-	if (result != 0) 
-	{
-		DT_Index i = result - 1;
-		DT_Count count = (*this)[i].getCount(); 
-		while (count) 
-		{
-			const BP_Endpoint& endpoint = (*this)[i];
-			if (endpoint.getType() == BP_Endpoint::MINIMUM &&
-				pos < (*this)[endpoint.getEndIndex()]) 
-			{
-				proxies.add(endpoint.getProxy());
-				--count;
-			}
-			assert(i != 0 || count == 0);
-			--i;
-		}											
-	}
-	return result;
-}
-
-DT_Scalar BP_EndpointList::nextLambda(DT_Index& index, 
-									  DT_Scalar source, 
-									  DT_Scalar delta) const
-{
-	if (delta != 0.0f) 
-	{
-		if (delta < 0.0f) 
-		{
-			if (index != 0) 
-			{
-				return ((*this)[--index].getPos() - source) / delta;
-			}
-		}
-		else 
-		{
-			if (index != size()) 
-			{
-				return ((*this)[index++].getPos() - source) / delta;
-			}
-		}
-	}
-	return FLT_MAX;
-}
-
-
-void BP_EndpointList::range(const BP_Endpoint& min, 
-							const BP_Endpoint& max,
-							DT_Index& first, DT_Index& last,
-							BP_ProxyList& proxies) const 
-{
-	first = stab(min, proxies);
-	last  = std::upper_bound(begin(), end(), max) - begin();
-	
-	DT_Index i;
-	for (i = first; i != last; ++i) 
-	{
-		const BP_Endpoint& endpoint = (*this)[i];
-		if (endpoint.getType() == BP_Endpoint::MINIMUM) 
-		{
-			proxies.add(endpoint.getProxy());
-		}
-	}
-}
-
-void BP_EndpointList::addInterval(const BP_Endpoint& min, 
-								  const BP_Endpoint& max,
-								  BP_ProxyList& proxies) 
-{
-	assert(invariant());
-	DT_Index first, last;
-	range(min, max, first, last, proxies);
-	insert(begin() + last, max);
-	insert(begin() + first, min);
-	++last; 
-	
-	(*this)[first].getCount() = first != 0 ? (*this)[first - 1].getCount() : 0;
-	(*this)[last].getCount() = (*this)[last - 1].getCount();
-	
-	
-	DT_Index i;
-	for (i = first; i != last; ++i) 
-	{
-		++(*this)[i].getCount();
-		(*this)[i].getIndex() = i;
-	} 
-	for (; i != size(); ++i) 
-	{
-		(*this)[i].getIndex() = i;
-	} 
-	
-	assert(invariant());
-}
-
-void BP_EndpointList::removeInterval(DT_Index first, DT_Index last,
-									 BP_ProxyList& proxies) 
-{ 
-	assert(invariant());
-	
-	BP_Endpoint min = (*this)[first];
-	BP_Endpoint max = (*this)[last]; 
-	
-	erase(begin() + last);
-	erase(begin() + first);
-	--last;
-	
-	DT_Index i;
-	for (i = first; i != last; ++i) 
-	{
-		--(*this)[i].getCount();
-		(*this)[i].getIndex() = i;
-	} 
-	for (; i != size(); ++i) 
-	{
-		(*this)[i].getIndex() = i;
-	} 
-	
-	range(min, max, first, last, proxies);
-	
-	assert(invariant());
-}
-
-void BP_EndpointList::move(DT_Index index, DT_Scalar pos, Uint32 type,  
-						   BP_Scene& scene, T_Overlap overlap)
-{
-	assert(invariant());
-	
-	BP_Endpoint endpoint = (*this)[index];
-    DT_Scalar delta = pos - endpoint.getPos();
-	
-    if (delta != DT_Scalar(0.0)) 
-	{
-		endpoint.setPos(pos, type);
-		if (delta < DT_Scalar(0.0)) 
-		{
-			while (index != 0 && endpoint < (*this)[index - 1]) 
-			{
-				(*this)[index] = (*this)[index - 1];
-				(*this)[index].getIndex() = index;
-				encounters((*this)[index], endpoint, scene, overlap);
-				--index;
-			}
-		}
-		else 
-		{
-			DT_Index last = size() - 1;
-			while (index != last && (*this)[index + 1] < endpoint) 
-			{
-				(*this)[index] = (*this)[index + 1];
-				(*this)[index].getIndex() = index;
-				encounters(endpoint, (*this)[index], scene, overlap);
-				++index;
-			}
-		}
-		(*this)[index] = endpoint;
-		(*this)[index].getIndex() = index;
-    }
-
-	assert(invariant());
-}
-
-void BP_EndpointList::encounters(const BP_Endpoint& a, const BP_Endpoint& b,
-								 BP_Scene& scene, T_Overlap overlap)
-{
-	assert(a.getProxy() != b.getProxy());
-	
-	if (a.getType() != b.getType()) 
-	{
-		if (a.getType() == BP_Endpoint::MAXIMUM) 
-		{
-			if (overlap(*a.getProxy(), *b.getProxy())) 
-			{
-				scene.callBeginOverlap(a.getProxy()->getObject(), 
-									   b.getProxy()->getObject());
-			}
-			++a.getCount();
-			++b.getCount();
-		}
-		else 
-		{
-			if (overlap(*a.getProxy(), *b.getProxy())) 
-			{
-				scene.callEndOverlap(a.getProxy()->getObject(), 
-									 b.getProxy()->getObject());
-			}
-			--a.getCount();
-			--b.getCount();
-		}
-	}
-	else 
-	{
-		if (a.getType() == BP_Endpoint::MAXIMUM) 
-		{
-			--a.getCount();
-			++b.getCount();
-		}
-		else 
-		{
-			++a.getCount();
-			--b.getCount();
-		}
-	}
-}
diff --git a/extern/solid/src/broad/BP_EndpointList.h b/extern/solid/src/broad/BP_EndpointList.h
deleted file mode 100644
index 6154991ed3d..00000000000
--- a/extern/solid/src/broad/BP_EndpointList.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef BP_ENDPOINTLIST_H
-#define BP_ENDPOINTLIST_H
-
-//#define PARANOID
-
-#include 
-
-#include "BP_Endpoint.h"
-#include "BP_ProxyList.h"
-
-class BP_Scene;
-
-typedef bool (*T_Overlap)(const BP_Proxy& a, const BP_Proxy& b);
-
-class BP_EndpointList : public std::vector {
-public:
-	BP_EndpointList() {}
-	
-	DT_Index stab(const BP_Endpoint& pos, BP_ProxyList& proxies) const;
-	
-	DT_Index stab(DT_Scalar pos, BP_ProxyList& proxies) const
-	{
-		return stab(BP_Endpoint(pos, BP_Endpoint::MINIMUM, 0), proxies);
-	}
-	
-
-   void range(const BP_Endpoint& min, const BP_Endpoint& max, 
-			  DT_Index& first, DT_Index& last, BP_ProxyList& proxies) const;
-	
-	void range(DT_Scalar lb, DT_Scalar ub, DT_Index& first, DT_Index& last, BP_ProxyList& proxies) const 
-	{
-		range(BP_Endpoint(lb, BP_Endpoint::MINIMUM, 0), 
-			  BP_Endpoint(ub, BP_Endpoint::MAXIMUM, 0),
-			  first, last, proxies);
-	}
-	
-	void addInterval(const BP_Endpoint& min, const BP_Endpoint& max, BP_ProxyList& proxies);
-	void removeInterval(DT_Index first, DT_Index last, BP_ProxyList& proxies);
-
-	void move(DT_Index index, DT_Scalar pos, Uint32 type, BP_Scene& scene, T_Overlap overlap);	
-   
-   DT_Scalar nextLambda(DT_Index& index, DT_Scalar source, DT_Scalar target) const;
-	
-
-private:
-	void encounters(const BP_Endpoint& a, const BP_Endpoint& b,
-					    BP_Scene& scene, T_Overlap overlap);
-
-
-#ifdef PARANOID
-	bool invariant() const 
-	{
-		DT_Count count = 0;
-		DT_Index i;
-		for (i = 0; i != size(); ++i) 
-		{
-         const BP_Endpoint& endpoint = (*this)[i];
-
-			if (endpoint.getType() == BP_Endpoint::MINIMUM) 
-			{
-				++count;
-			}
-			else 
-			{
-				--count;
-			}
-			if (endpoint.getCount() != count)
-			{
-				return false;
-			}
-			if (endpoint.getIndex() != i) 
-			{
-				return false;
-			}
-		}
-		return true;
-	}
-#else
-	bool invariant() const { return true; }
-#endif
-
-};
-
-
-
-#endif
diff --git a/extern/solid/src/broad/BP_Proxy.cpp b/extern/solid/src/broad/BP_Proxy.cpp
deleted file mode 100644
index e8007df240d..00000000000
--- a/extern/solid/src/broad/BP_Proxy.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include 
-
-#include "BP_Proxy.h"
-#include "BP_Scene.h"
-
-BP_Proxy::BP_Proxy(void *object, 
-				   BP_Scene& scene) 
-  :	m_object(object),
-	m_scene(scene)
-{
-	int i;
-	for (i = 0; i < 3; ++i) 
-	{
-		new (&m_interval[i]) BP_Interval(this);
-	}
-}
-
-void BP_Proxy::add(const DT_Vector3 min,
-				   const DT_Vector3 max,
-				   BP_ProxyList& proxies) 
-{
-	int i;
-	for (i = 0; i < 3; ++i) 
-	{
-		m_scene.getList(i).addInterval(
-			BP_Endpoint(min[i], BP_Endpoint::MINIMUM, &m_interval[i].m_min), 
-			BP_Endpoint(max[i], BP_Endpoint::MAXIMUM, &m_interval[i].m_max), 
-			proxies);
-	}
-}
-
-void BP_Proxy::remove(BP_ProxyList& proxies) 
-{
-	int i;
-	for (i = 0; i < 3; ++i) 
-	{
-		m_scene.getList(i).removeInterval(
-			m_interval[i].m_min.m_index,
-			m_interval[i].m_max.m_index,
-			proxies);
-	}
-}
-
-DT_Scalar BP_Proxy::getMin(int i) const 
-{ 
-	return m_scene.getList(i)[m_interval[i].m_min.m_index].getPos(); 
-}
-
-DT_Scalar BP_Proxy::getMax(int i) const 
-{ 
-	return m_scene.getList(i)[m_interval[i].m_max.m_index].getPos(); 
-}
-
-bool overlapXY(const BP_Proxy& a, const BP_Proxy& b)
-{
-	return a.getMin(0) <= b.getMax(0) && b.getMin(0) <= a.getMax(0) && 
-		   a.getMin(1) <= b.getMax(1) && b.getMin(1) <= a.getMax(1);
-}
-
-bool overlapXZ(const BP_Proxy& a, const BP_Proxy& b)
-{
-	return a.getMin(0) <= b.getMax(0) && b.getMin(0) <= a.getMax(0) && 
-		   a.getMin(2) <= b.getMax(2) && b.getMin(2) <= a.getMax(2); 
-}
-
-bool overlapYZ(const BP_Proxy& a, const BP_Proxy& b)
-{
-	return a.getMin(1) <= b.getMax(1) && b.getMin(1) <= a.getMax(1) && 
-		   a.getMin(2) <= b.getMax(2) && b.getMin(2) <= a.getMax(2); 
-}
-
-void BP_Proxy::setBBox(const DT_Vector3 min, const DT_Vector3 max)
-{	
-	static T_Overlap overlap[3] = { overlapYZ, overlapXZ, overlapXY };
-
-	int i;
-	for (i = 0; i < 3; ++i) 
-	{
-		if (min[i] > getMax(i)) 
-		{
-			m_scene.getList(i).move(m_interval[i].m_max.m_index, max[i], 
-									BP_Endpoint::MAXIMUM, m_scene, overlap[i]);
-			m_scene.getList(i).move(m_interval[i].m_min.m_index, min[i], 
-									BP_Endpoint::MINIMUM, m_scene, overlap[i]);
-		}
-		else 
-		{
-			m_scene.getList(i).move(m_interval[i].m_min.m_index, min[i], 
-									BP_Endpoint::MINIMUM, m_scene, overlap[i]);
-			m_scene.getList(i).move(m_interval[i].m_max.m_index, max[i], 
-									BP_Endpoint::MAXIMUM, m_scene, overlap[i]);
-		}
-	}
-}
-
-
-
diff --git a/extern/solid/src/broad/BP_Proxy.h b/extern/solid/src/broad/BP_Proxy.h
deleted file mode 100644
index b4500ddca44..00000000000
--- a/extern/solid/src/broad/BP_Proxy.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef BP_PROXY_H
-#define BP_PROXY_H
-
-#include "BP_Endpoint.h"
-#include "BP_ProxyList.h"
-
-class BP_Interval {
-public:
-	BP_Interval() {}
-	BP_Interval(BP_Proxy *proxy) :
-		m_min(proxy),
-		m_max(proxy) 
-	{}
-
-	BP_Link m_min;
-	BP_Link m_max;
-};
-
-class BP_Scene;
-
-class BP_Proxy {
-public:
-    BP_Proxy(void *object, BP_Scene& scene);
-
-	void add(const DT_Vector3 min,
-			 const DT_Vector3 max,
-			 BP_ProxyList& proxies);
-	
-    void remove(BP_ProxyList& proxies);
-	
-	void setBBox(const DT_Vector3 min, const DT_Vector3 max);
-    
-    void *getObject() { return m_object; }
-
-	DT_Scalar getMin(int i) const;
-	DT_Scalar getMax(int i) const;
-
-private:
-	BP_Interval  m_interval[3];
-    void        *m_object;
-	BP_Scene&    m_scene;
-};
-
-inline bool BP_overlap(const BP_Proxy *a, const BP_Proxy *b)
-{
-	return a->getMin(0) <= b->getMax(0) && b->getMin(0) <= a->getMax(0) && 
-		   a->getMin(1) <= b->getMax(1) && b->getMin(1) <= a->getMax(1) &&
-		   a->getMin(2) <= b->getMax(2) && b->getMin(2) <= a->getMax(2);
-}
-
-#endif
-
-
-
-
diff --git a/extern/solid/src/broad/BP_ProxyList.h b/extern/solid/src/broad/BP_ProxyList.h
deleted file mode 100644
index 2f449777d2d..00000000000
--- a/extern/solid/src/broad/BP_ProxyList.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef BP_PROXYLIST_H
-#define BP_PROXYLIST_H
-
-#include 
-
-#include 
-#include 
-#include 
-
-class BP_Proxy;
-
-typedef std::pair BP_ProxyEntry; 
-
-inline bool operator<(const BP_ProxyEntry& a, const BP_ProxyEntry& b) 
-{
-	return a.first < b.first;
-}
-
-class BP_ProxyList : public std::vector {
-public:
-   BP_ProxyList(size_t n = 20) : std::vector(n) {}      
-
-	iterator add(BP_Proxy *proxy) 
-	{
-		BP_ProxyEntry entry = std::make_pair(proxy, (unsigned int)0);
-		iterator it = std::lower_bound(begin(), end(), entry);
-		if (it == end() || (*it).first != proxy) 
-		{
-			it = insert(it, entry);
-		}
-		++(*it).second;
-		return it;
-	}
-
-	void remove(BP_Proxy *proxy) 
-	{
-		BP_ProxyEntry entry = std::make_pair(proxy, (unsigned int)0);
-		iterator it = std::lower_bound(begin(), end(), entry);
-		if (it != end() && (*it).first == proxy && --(*it).second == 0) 
-		{
-			erase(it);	
-		}	
-	}
-};
-
-#endif
diff --git a/extern/solid/src/broad/BP_Scene.cpp b/extern/solid/src/broad/BP_Scene.cpp
deleted file mode 100644
index c0cd83ba311..00000000000
--- a/extern/solid/src/broad/BP_Scene.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "BP_Scene.h"
-#include "BP_Proxy.h"
-
-#include 
-
-BP_Proxy *BP_Scene::createProxy(void *object, 
-								const DT_Vector3 min,
-								const DT_Vector3 max)
-{
-	BP_Proxy *proxy = new BP_Proxy(object, *this);
-
-	proxy->add(min, max, m_proxies);
-	
-	BP_ProxyList::iterator it;
-	for (it = m_proxies.begin(); it != m_proxies.end(); ++it)
-	{
-		if ((*it).second == 3)
-		{
-			callBeginOverlap(proxy->getObject(), (*it).first->getObject());
-		}
-	}
-
-	m_proxies.clear();
-
-	return proxy;
-}
-
-void BP_Scene::destroyProxy(BP_Proxy *proxy)
-{
-	proxy->remove(m_proxies);
-	
-	BP_ProxyList::iterator it;
-	for (it = m_proxies.begin(); it != m_proxies.end(); ++it)
-	{
-		if ((*it).second == 3)
-		{
-			callEndOverlap(proxy->getObject(), (*it).first->getObject());
-		}
-	}
-	
-	m_proxies.clear();
-
-	delete proxy;
-}
-
-void *BP_Scene::rayCast(BP_RayCastCallback objectRayCast,
-						void *client_data,
-						const DT_Vector3 source, 
-						const DT_Vector3 target, 
-						DT_Scalar& lambda) const 
-{
-	void *client_object = 0;
-	
-	DT_Index index[3];
-	index[0] = m_endpointList[0].stab(source[0], m_proxies);
-	index[1] = m_endpointList[1].stab(source[1], m_proxies);
-	index[2] = m_endpointList[2].stab(source[2], m_proxies);
-
-	BP_ProxyList::iterator it;
-	for (it = m_proxies.begin(); it != m_proxies.end(); ++it) 
-	{
-		if ((*it).second == 3 &&
-            (*objectRayCast)(client_data, (*it).first->getObject(), source, target, &lambda))
-		{
-			client_object = (*it).first->getObject();
-		}
-	}
-
-	DT_Vector3 delta;
-	delta[0] = target[0] - source[0];
-	delta[1] = target[1] - source[1];
-	delta[2] = target[2] - source[2];
-	
-	DT_Vector3 lambdas;
-	lambdas[0] = m_endpointList[0].nextLambda(index[0], source[0], delta[0]);
-	lambdas[1] = m_endpointList[1].nextLambda(index[1], source[1], delta[1]);
-	lambdas[2] = m_endpointList[2].nextLambda(index[2], source[2], delta[2]);
-	int closest = lambdas[0] < lambdas[1] ? (lambdas[0] < lambdas[2] ? 0 : 2) : (lambdas[1] < lambdas[2] ? 1 : 2);
-	
-	while (lambdas[closest] < lambda)
-	{
-		if (delta[closest] < 0.0f)
-		{
-			const BP_Endpoint& endpoint = m_endpointList[closest][index[closest]];
-
-			if (endpoint.getType() == BP_Endpoint::MAXIMUM) 
-			{
-				it = m_proxies.add(endpoint.getProxy());
-				if ((*it).second == 3 &&
-					(*objectRayCast)(client_data, (*it).first->getObject(), source, target, &lambda))
-				{
-					client_object = (*it).first->getObject();
-				}
-			}
-			else
-			{
-				m_proxies.remove(endpoint.getProxy());
-			}
-		}
-		else 
-		{
-			const BP_Endpoint& endpoint = m_endpointList[closest][index[closest] - 1];
-			
-			if (endpoint.getType() == BP_Endpoint::MINIMUM) 
-			{
-				it = m_proxies.add(endpoint.getProxy());
-				if ((*it).second == 3 &&
-					(*objectRayCast)(client_data, (*it).first->getObject(), source, target, &lambda))
-				{
-					client_object = (*it).first->getObject();
-				}
-			}
-			else
-			{
-				m_proxies.remove(endpoint.getProxy());
-			}
-		}
-
-		lambdas[closest] = m_endpointList[closest].nextLambda(index[closest], source[closest], delta[closest]);
-		closest = lambdas[0] < lambdas[1] ?	(lambdas[0] < lambdas[2] ? 0 : 2) : (lambdas[1] < lambdas[2] ? 1 : 2);
-	}
-
-	m_proxies.clear();
-
-	return client_object;
-}
-
-
diff --git a/extern/solid/src/broad/BP_Scene.h b/extern/solid/src/broad/BP_Scene.h
deleted file mode 100644
index ef55374c43b..00000000000
--- a/extern/solid/src/broad/BP_Scene.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef BP_SCENE_H
-#define BP_SCENE_H
-
-#include 
-
-#include "BP_EndpointList.h"
-#include "BP_ProxyList.h"
-
-class BP_Proxy;
-
-class BP_Scene {
-public:
-    BP_Scene(void *client_data,
-			 BP_Callback beginOverlap,
-			 BP_Callback endOverlap) 
-      :	m_client_data(client_data),
-		m_beginOverlap(beginOverlap),
-		m_endOverlap(endOverlap),
-		m_proxies(20)
-	{}
-
-    ~BP_Scene() {}
-
-    BP_Proxy *createProxy(void *object, 
-						  const DT_Vector3 min,
-						  const DT_Vector3 max);
-
-    void destroyProxy(BP_Proxy *proxy);
-	
-	void *rayCast(BP_RayCastCallback objectRayCast,
-				  void *client_data,
-				  const DT_Vector3 source, 
-				  const DT_Vector3 target, 
-				  DT_Scalar& lambda) const;
-	
-  	void callBeginOverlap(void *object1, void *object2) 
-	{
-		(*m_beginOverlap)(m_client_data, object1, object2);
-	}
-	
-	void callEndOverlap(void *object1, void *object2) 
-	{
-		(*m_endOverlap)(m_client_data, object1, object2);
-	}
-	
-	BP_EndpointList& getList(int i) { return m_endpointList[i]; }
-
-private:
-	void                    *m_client_data;
-	BP_Callback              m_beginOverlap; 
-	BP_Callback              m_endOverlap; 
-    BP_EndpointList          m_endpointList[3];
-	mutable BP_ProxyList     m_proxies;
-};
-
-#endif
diff --git a/extern/solid/src/broad/Makefile b/extern/solid/src/broad/Makefile
deleted file mode 100644
index ce10e5f0bcf..00000000000
--- a/extern/solid/src/broad/Makefile
+++ /dev/null
@@ -1,41 +0,0 @@
-#
-# $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.
-#
-# The Original Code is: all of this file.
-#
-# Contributor(s): none yet.
-#
-# ***** END GPL LICENSE BLOCK *****
-#
-#
-
-LIBNAME = solid_broad
-DIR = $(OCGDIR)/extern/$(LIBNAME)
-
-CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
-
-CPPFLAGS += -I../../include -I$(NAN_QHULL)/include
-CPPFLAGS += -DQHULL -DUSE_DOUBLES
-
-include nan_compile.mk 
-
-
diff --git a/extern/solid/src/complex/DT_BBoxTree.cpp b/extern/solid/src/complex/DT_BBoxTree.cpp
deleted file mode 100644
index 4f10f61f2e2..00000000000
--- a/extern/solid/src/complex/DT_BBoxTree.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "DT_BBoxTree.h"
-
-inline DT_CBox getBBox(int first, int last, const DT_CBox *boxes, const DT_Index *indices) 
-{
-	assert(last - first >= 1);
-
-	DT_CBox bbox = boxes[indices[first]];
-	int i;
-	for (i = first; i < last; ++i) 
-	{
-		bbox = bbox.hull(boxes[indices[i]]);
-	}
-
-	return bbox;
-}
-
-DT_BBoxNode::DT_BBoxNode(int first, int last, int& node, DT_BBoxNode *free_nodes, const DT_CBox *boxes, DT_Index *indices, const DT_CBox& bbox)
-{
-	assert(last - first >= 2);
-	
-	int axis = bbox.longestAxis();
-	MT_Scalar abscissa = bbox.getCenter()[axis];
-	int i = first, mid = last;
-	while (i < mid) 
-	{
-		if (boxes[indices[i]].getCenter()[axis] < abscissa)
-		{
-			++i;
-		}
-		else
-		{
-			--mid;
-			std::swap(indices[i], indices[mid]);
-		}
-	}
-
-	if (mid == first || mid == last) 
-	{
-		mid = (first + last) / 2;
-	}
-	
-	m_lbox = getBBox(first, mid, boxes, indices);
-	m_rbox = getBBox(mid, last, boxes, indices);
-	m_flags = 0x0;
-
-	if (mid - first == 1)
-	{
-		m_flags |= LLEAF;
-		m_lchild = indices[first];
-	}
-	else 
-	{	
-		m_lchild = node++;
-		new(&free_nodes[m_lchild]) DT_BBoxNode(first, mid, node, free_nodes, boxes, indices, m_lbox);
-	}
-
-	if (last - mid == 1)
-	{
-		m_flags |= RLEAF;
-		m_rchild = indices[mid];
-	}
-	else 
-	{
-		m_rchild = node++;
-		new(&free_nodes[m_rchild]) DT_BBoxNode(mid, last, node, free_nodes, boxes, indices, m_rbox); 
-	}
-}
diff --git a/extern/solid/src/complex/DT_BBoxTree.h b/extern/solid/src/complex/DT_BBoxTree.h
deleted file mode 100644
index 3d9da6e34ba..00000000000
--- a/extern/solid/src/complex/DT_BBoxTree.h
+++ /dev/null
@@ -1,540 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_BBOXTREE_H
-#define DT_BBOXTREE_H
-
-#include 
-#include 
-
-#include "DT_Convex.h"
-#include "DT_CBox.h"
-
-
-class DT_BBoxTree {
-public:
-    enum NodeType { INTERNAL = 0, LEAF = 1 };
-    
-    DT_BBoxTree() {}
-    DT_BBoxTree(const DT_CBox& cbox, DT_Index index, NodeType type) 
-      : m_cbox(cbox),
-        m_index(index),
-        m_type(type)
-    {}
-    
-    DT_CBox  m_cbox;
-    DT_Index m_index;
-    NodeType m_type;
-};
-
-
-
-class DT_BBoxNode {
-public:
-    DT_BBoxNode() {}    
-    DT_BBoxNode(int first, int last, int& node, DT_BBoxNode *free_nodes, const DT_CBox *boxes, DT_Index *indices, const DT_CBox& bbox);
-
-    void makeChildren(DT_BBoxTree& ltree, DT_BBoxTree& rtree) const;
-    void makeChildren(const DT_CBox& added, DT_BBoxTree& ltree, DT_BBoxTree& rtree) const;
-
-    DT_CBox hull() const { return m_lbox.hull(m_rbox); }  
-    
-    enum FlagType { LLEAF = 0x80, RLEAF = 0x40 };
-
-    DT_CBox              m_lbox;
-    DT_CBox              m_rbox;
-    DT_Index             m_lchild;
-    DT_Index             m_rchild;
-    unsigned char        m_flags;
-};
-
-inline void DT_BBoxNode::makeChildren(DT_BBoxTree& ltree, DT_BBoxTree& rtree) const
-{
-    new (<ree) DT_BBoxTree(m_lbox, m_lchild, (m_flags & LLEAF) ? DT_BBoxTree::LEAF : DT_BBoxTree::INTERNAL);
-    new (&rtree) DT_BBoxTree(m_rbox, m_rchild, (m_flags & RLEAF) ? DT_BBoxTree::LEAF : DT_BBoxTree::INTERNAL);
-
-}
-
-inline void DT_BBoxNode::makeChildren(const DT_CBox& added, DT_BBoxTree& ltree, DT_BBoxTree& rtree) const
-{ 
-    new (<ree) DT_BBoxTree(m_lbox + added, m_lchild, (m_flags & LLEAF) ? DT_BBoxTree::LEAF : DT_BBoxTree::INTERNAL);
-    new (&rtree) DT_BBoxTree(m_rbox + added, m_rchild, (m_flags & RLEAF) ? DT_BBoxTree::LEAF : DT_BBoxTree::INTERNAL);
-}
-
-
-template 
-class DT_RootData {
-public:
-    DT_RootData(const DT_BBoxNode *nodes, 
-                const Shape *leaves) 
-      : m_nodes(nodes),
-        m_leaves(leaves)
-    {}
-
-    const DT_BBoxNode   *m_nodes;
-    const Shape         *m_leaves;
-};
-
-template 
-class DT_ObjectData : public DT_RootData {
-public:
-    DT_ObjectData(const DT_BBoxNode *nodes, 
-                  const Shape1 *leaves, 
-                  const MT_Transform& xform, 
-                  Shape2 plus) 
-      : DT_RootData(nodes, leaves),
-        m_xform(xform),
-        m_inv_xform(xform.inverse()),   
-        m_plus(plus),
-        m_added(computeCBox(plus, m_inv_xform))
-    {}
-
-    const MT_Transform&  m_xform;
-    MT_Transform         m_inv_xform;
-    Shape2               m_plus;
-    DT_CBox              m_added;
-};
-
-template 
-class DT_Pack {
-public:
-    DT_Pack(const DT_ObjectData& a, const DT_Convex& b)
-      : m_a(a),
-        m_b(b),
-        m_b_cbox(b.bbox(m_a.m_inv_xform))
-    {}
-    
-    DT_ObjectData  m_a;
-    const DT_Convex&               m_b;
-    DT_CBox                        m_b_cbox;
-};
-
-template 
-class DT_HybridPack : public DT_Pack {
-public:
-    DT_HybridPack(const DT_ObjectData& a, const DT_Convex& b, MT_Scalar margin)
-      : DT_Pack(a, b),
-        m_margin(margin)
-    {
-        this->m_b_cbox += computeCBox(margin, this->m_a.m_inv_xform);
-    }
-    
-    MT_Scalar m_margin;
-};
-
-template 
-class DT_DuoPack {
-public:
-    DT_DuoPack(const DT_ObjectData& a, const DT_ObjectData& b) 
-      : m_a(a),
-        m_b(b)
-    {
-        m_b2a = a.m_inv_xform * b.m_xform;
-        m_a2b = b.m_inv_xform * a.m_xform;
-        m_abs_b2a = m_b2a.getBasis().absolute();
-        m_abs_a2b = m_a2b.getBasis().absolute();    
-    }
-    
-    DT_ObjectData  m_a, m_b;
-    MT_Transform                   m_b2a, m_a2b;
-    MT_Matrix3x3                   m_abs_b2a, m_abs_a2b;
-};
-
-
-template 
-inline void refit(DT_BBoxNode& node, const DT_RootData& rd)
-{
-    node.m_lbox = (node.m_flags & DT_BBoxNode::LLEAF) ? 
-                  computeCBox(rd.m_leaves[node.m_lchild]) : 
-                  rd.m_nodes[node.m_lchild].hull(); 
-    node.m_rbox = (node.m_flags & DT_BBoxNode::RLEAF) ? 
-                  computeCBox(rd.m_leaves[node.m_rchild]) : 
-                  rd.m_nodes[node.m_rchild].hull(); 
-}
-
-
-template 
-bool ray_cast(const DT_BBoxTree& a, const DT_RootData& rd,
-              const MT_Point3& source, const MT_Point3& target, 
-              MT_Scalar& lambda, MT_Vector3& normal) 
-{
-    if (!a.m_cbox.overlapsLineSegment(source, source.lerp(target, lambda))) 
-    {
-        return false;
-    }
-
-    if (a.m_type == DT_BBoxTree::LEAF) 
-    { 
-        return ray_cast(rd, a.m_index, source, target, lambda, normal); 
-    }
-    else 
-    {
-        DT_BBoxTree ltree, rtree;
-        rd.m_nodes[a.m_index].makeChildren(ltree, rtree);
-        
-        bool lresult = ray_cast(ltree, rd, source, target, lambda, normal);
-        bool rresult = ray_cast(rtree, rd, source, target, lambda, normal);
-        return lresult || rresult;
-    }
-}
-
-
-#ifdef STATISTICS
-int num_box_tests = 0;
-#endif
-
-template 
-inline bool intersect(const DT_CBox& a, const DT_CBox& b, const DT_DuoPack& pack)
-{
-#ifdef STATISTICS
-    ++num_box_tests;
-#endif
-
-    
-    MT_Vector3 abs_pos_b2a = (pack.m_b2a(b.getCenter()) - a.getCenter()).absolute();
-    MT_Vector3 abs_pos_a2b = (pack.m_a2b(a.getCenter()) - b.getCenter()).absolute();
-    return  (a.getExtent()[0] + pack.m_abs_b2a[0].dot(b.getExtent()) >=  abs_pos_b2a[0]) && 
-            (a.getExtent()[1] + pack.m_abs_b2a[1].dot(b.getExtent()) >=  abs_pos_b2a[1]) && 
-            (a.getExtent()[2] + pack.m_abs_b2a[2].dot(b.getExtent()) >=  abs_pos_b2a[2]) && 
-            (b.getExtent()[0] + pack.m_abs_a2b[0].dot(a.getExtent()) >=  abs_pos_a2b[0]) && 
-            (b.getExtent()[1] + pack.m_abs_a2b[1].dot(a.getExtent()) >=  abs_pos_a2b[1]) &&
-            (b.getExtent()[2] + pack.m_abs_a2b[2].dot(a.getExtent()) >=  abs_pos_a2b[2]);
-}
-
-
-
-
-template 
-bool intersect(const DT_BBoxTree& a, const DT_Pack& pack, MT_Vector3& v)
-{ 
-    if (!a.m_cbox.overlaps(pack.m_b_cbox)) 
-    {
-        return false;
-    }
-
-    if (a.m_type == DT_BBoxTree::LEAF) 
-    {
-        return intersect(pack, a.m_index, v);
-    }
-    else 
-    {
-        DT_BBoxTree a_ltree, a_rtree;
-        pack.m_a.m_nodes[a.m_index].makeChildren(pack.m_a.m_added, a_ltree, a_rtree);
-        return intersect(a_ltree, pack, v) || intersect(a_rtree, pack, v);
-    }
-}
-
-template 
-bool intersect(const DT_BBoxTree& a, const DT_BBoxTree& b, const DT_DuoPack& pack, MT_Vector3& v)
-{ 
-    if (!intersect(a.m_cbox, b.m_cbox, pack)) 
-    {
-        return false;
-    }
-
-    if (a.m_type == DT_BBoxTree::LEAF && b.m_type == DT_BBoxTree::LEAF) 
-    {
-        return intersect(pack, a.m_index, b.m_index, v);
-    }
-    else if (a.m_type == DT_BBoxTree::LEAF || 
-             (b.m_type != DT_BBoxTree::LEAF && a.m_cbox.size() < b.m_cbox.size())) 
-    {
-        DT_BBoxTree b_ltree, b_rtree;
-        pack.m_b.m_nodes[b.m_index].makeChildren(pack.m_b.m_added, b_ltree, b_rtree);
-
-        return intersect(a, b_ltree, pack, v) || intersect(a, b_rtree, pack, v);
-    }
-    else 
-    {
-        DT_BBoxTree a_ltree, a_rtree;
-        pack.m_a.m_nodes[a.m_index].makeChildren(pack.m_a.m_added, a_ltree, a_rtree);
-        return intersect(a_ltree, b, pack, v) || intersect(a_rtree, b, pack, v);
-    }
-}
-
-template 
-bool common_point(const DT_BBoxTree& a, const DT_Pack& pack,  
-                  MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
-{ 
-    if (!a.m_cbox.overlaps(pack.m_b_cbox))
-    {
-        return false;
-    }
-
-    if (a.m_type == DT_BBoxTree::LEAF) 
-    {
-        return common_point(pack, a.m_index, v, pa, pb);
-    }
-    else 
-    {
-        DT_BBoxTree a_ltree, a_rtree;
-        pack.m_a.m_nodes[a.m_index].makeChildren(pack.m_a.m_added, a_ltree, a_rtree);
-        return common_point(a_ltree, pack, v, pa, pb) ||
-               common_point(a_rtree, pack, v, pa ,pb);
-    }
-}
-
-template 
-bool common_point(const DT_BBoxTree& a, const DT_BBoxTree& b, const DT_DuoPack& pack,  
-                  MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
-{ 
-    if (!intersect(a.m_cbox, b.m_cbox, pack))
-    {
-        return false;
-    }
-
-    if (a.m_type == DT_BBoxTree::LEAF && b.m_type == DT_BBoxTree::LEAF) 
-    {
-        return common_point(pack, a.m_index, b.m_index, v, pa, pb);
-    }
-    else if (a.m_type == DT_BBoxTree::LEAF || 
-             (b.m_type != DT_BBoxTree::LEAF && a.m_cbox.size() < b.m_cbox.size())) 
-    {
-        DT_BBoxTree b_ltree, b_rtree;
-        pack.m_b.m_nodes[b.m_index].makeChildren(pack.m_b.m_added, b_ltree, b_rtree);
-        return common_point(a, b_ltree, pack, v, pa, pb) ||
-               common_point(a, b_rtree, pack, v, pa, pb);
-    }
-    else 
-    {
-        DT_BBoxTree a_ltree, a_rtree;
-        pack.m_a.m_nodes[a.m_index].makeChildren(pack.m_a.m_added, a_ltree, a_rtree);
-        return common_point(a_ltree, b, pack, v, pa, pb) ||
-               common_point(a_rtree, b, pack, v, pa ,pb);
-    }
-}
-
-
-template 
-bool penetration_depth(const DT_BBoxTree& a, const DT_HybridPack& pack, 
-                       MT_Vector3& v, MT_Point3& pa, MT_Point3& pb, MT_Scalar& max_pen_len) 
-{ 
-    if (!a.m_cbox.overlaps(pack.m_b_cbox))
-    {
-        return false;
-    }
-    
-    if (a.m_type == DT_BBoxTree::LEAF) 
-    {
-        if (penetration_depth(pack, a.m_index, v, pa, pb))
-        {
-            max_pen_len = pa.distance2(pb);
-            return true;
-        }
-        else 
-        {
-            return false;
-        }
-    }
-    else 
-    {
-        DT_BBoxTree a_ltree, a_rtree;
-        pack.m_a.m_nodes[a.m_index].makeChildren(pack.m_a.m_added, a_ltree, a_rtree);
-        if (penetration_depth(a_ltree, pack, v, pa, pb, max_pen_len)) 
-        {
-            MT_Vector3 rv;
-            MT_Point3 rpa, rpb;
-            MT_Scalar rmax_pen_len;
-            if (penetration_depth(a_rtree, pack, rv, rpa, rpb, rmax_pen_len) &&
-                (max_pen_len < rmax_pen_len))
-            {
-                max_pen_len = rmax_pen_len;
-                v = rv;
-                pa = rpa;
-                pb = rpb;
-            }
-            return true;
-        }
-        else 
-        {
-            return penetration_depth(a_rtree, pack, v, pa, pb, max_pen_len);
-        }
-    }
-}
-
-template 
-bool penetration_depth(const DT_BBoxTree& a, const DT_BBoxTree& b, const DT_DuoPack& pack, 
-                       MT_Vector3& v, MT_Point3& pa, MT_Point3& pb, MT_Scalar& max_pen_len) 
-{ 
-    if (!intersect(a.m_cbox, b.m_cbox, pack))
-    {
-        return false;
-    }
-  
-    if (a.m_type == DT_BBoxTree::LEAF && b.m_type == DT_BBoxTree::LEAF) 
-    {
-        if (penetration_depth(pack, a.m_index, b.m_index, v, pa, pb))
-        {
-            max_pen_len = pa.distance2(pb);
-            return true;
-        }
-        else 
-        {
-            return false;
-        }
-    }
-    else if (a.m_type == DT_BBoxTree::LEAF || 
-             (b.m_type != DT_BBoxTree::LEAF && a.m_cbox.size() < b.m_cbox.size())) 
-    {
-        DT_BBoxTree b_ltree, b_rtree;
-        pack.m_b.m_nodes[b.m_index].makeChildren(pack.m_b.m_added, b_ltree, b_rtree);
-        if (penetration_depth(a, b_ltree, pack, v, pa, pb, max_pen_len)) 
-        {
-            MT_Point3 rpa, rpb;
-            MT_Scalar rmax_pen_len;
-            if (penetration_depth(a, b_rtree, pack, v, rpa, rpb, rmax_pen_len) &&
-                (max_pen_len < rmax_pen_len))
-            {
-                max_pen_len = rmax_pen_len;
-                pa = rpa;
-                pb = rpb;
-            }
-            return true;
-        }
-        else
-        {
-            return penetration_depth(a, b_rtree, pack, v, pa, pb, max_pen_len);
-        }
-    }
-    else 
-    {
-        DT_BBoxTree a_ltree, a_rtree;
-        pack.m_a.m_nodes[a.m_index].makeChildren(pack.m_a.m_added, a_ltree, a_rtree);
-        if (penetration_depth(a_ltree, b, pack, v, pa, pb, max_pen_len)) 
-        {
-            MT_Point3 rpa, rpb;
-            MT_Scalar rmax_pen_len;
-            if (penetration_depth(a_rtree, b, pack, v, rpa, rpb, rmax_pen_len) &&
-                (max_pen_len < rmax_pen_len))
-            {
-                max_pen_len = rmax_pen_len;
-                pa = rpa;
-                pb = rpb;
-            }
-            return true;
-        }
-        else 
-        {
-            return penetration_depth(a_rtree, b, pack, v, pa, pb, max_pen_len);
-        }
-    }
-}
-
-
-// Returns a lower bound for the distance for quick rejection in closest_points
-inline MT_Scalar distance2(const DT_CBox& a, const MT_Transform& a2w,
-                           const DT_CBox& b, const MT_Transform& b2w)
-{
-    MT_Vector3 v = b2w(b.getCenter()) - a2w(a.getCenter());
-    MT_Scalar dist2 = v.length2();
-    if (dist2 > MT_Scalar(0.0))
-    {
-        MT_Vector3 w = b2w(b.support(-v * b2w.getBasis())) - a2w(a.support(v * a2w.getBasis()));
-        MT_Scalar delta = v.dot(w);
-        return delta > MT_Scalar(0.0) ? delta * delta / dist2 : MT_Scalar(0.0);
-    }
-    return MT_Scalar(0.0);
-}
-
-
-template 
-MT_Scalar closest_points(const DT_BBoxTree& a, const DT_Pack& pack, 
-                         MT_Scalar max_dist2, MT_Point3& pa, MT_Point3& pb) 
-{ 
-    if (a.m_type == DT_BBoxTree::LEAF) 
-    {
-        return closest_points(pack, a.m_index, max_dist2, pa, pb);
-    }
-    else 
-    {
-        DT_BBoxTree a_ltree, a_rtree;
-        pack.m_a.m_nodes[a.m_index].makeChildren(pack.m_a.m_added, a_ltree, a_rtree);
-        MT_Scalar ldist2 = distance2(a_ltree.m_cbox, pack.m_a.m_xform, pack.m_b_cbox, pack.m_a.m_xform);
-        MT_Scalar rdist2 = distance2(a_rtree.m_cbox, pack.m_a.m_xform, pack.m_b_cbox, pack.m_a.m_xform);
-        if (ldist2 < rdist2) 
-        {
-            MT_Scalar dist2 = ldist2 < max_dist2 ? closest_points(a_ltree, pack, max_dist2, pa, pb) : MT_INFINITY;
-            GEN_set_min(max_dist2, dist2);
-            return rdist2 < max_dist2 ? GEN_min(dist2, closest_points(a_rtree, pack, max_dist2, pa, pb)) : dist2;
-        }
-        else
-        {
-            MT_Scalar dist2 = rdist2 < max_dist2 ? closest_points(a_rtree, pack, max_dist2, pa, pb) : MT_INFINITY;
-            GEN_set_min(max_dist2, dist2);  
-            return ldist2 < max_dist2 ? GEN_min(dist2, closest_points(a_ltree, pack, max_dist2, pa, pb)) : dist2;       
-        }
-    }
-}
-
-    
-template 
-MT_Scalar closest_points(const DT_BBoxTree& a, const DT_BBoxTree& b, const DT_DuoPack& pack, 
-                         MT_Scalar max_dist2, MT_Point3& pa, MT_Point3& pb) 
-{   
-    if (a.m_type == DT_BBoxTree::LEAF && b.m_type == DT_BBoxTree::LEAF) 
-    {
-        return closest_points(pack, a.m_index, b.m_index, max_dist2, pa, pb);
-    }
-    else if (a.m_type == DT_BBoxTree::LEAF || 
-             (b.m_type != DT_BBoxTree::LEAF && a.m_cbox.size() < b.m_cbox.size())) 
-    {
-        DT_BBoxTree b_ltree, b_rtree;
-        pack.m_b.m_nodes[b.m_index].makeChildren(pack.m_b.m_added, b_ltree, b_rtree);
-        MT_Scalar ldist2 = distance2(a.m_cbox, pack.m_a.m_xform, b_ltree.m_cbox, pack.m_b.m_xform);
-        MT_Scalar rdist2 = distance2(a.m_cbox, pack.m_a.m_xform, b_rtree.m_cbox, pack.m_b.m_xform);
-        if (ldist2 < rdist2)
-        {
-            MT_Scalar dist2 = ldist2 < max_dist2 ? closest_points(a, b_ltree, pack, max_dist2, pa, pb): MT_INFINITY;;
-            GEN_set_min(max_dist2, dist2);
-            return rdist2 < max_dist2 ? GEN_min(dist2, closest_points(a, b_rtree, pack, max_dist2, pa, pb)) : dist2;        
-        }
-        else
-        {
-            MT_Scalar dist2 =  rdist2 < max_dist2 ? closest_points(a, b_rtree, pack, max_dist2, pa, pb) : MT_INFINITY;;
-            GEN_set_min(max_dist2, dist2);
-            return ldist2 < max_dist2 ? GEN_min(dist2, closest_points(a, b_ltree, pack, max_dist2, pa, pb)) : dist2;
-        }
-    }
-    else
-    {
-        DT_BBoxTree a_ltree, a_rtree;
-        pack.m_a.m_nodes[a.m_index].makeChildren(pack.m_a.m_added, a_ltree, a_rtree);
-        MT_Scalar ldist2 = distance2(a_ltree.m_cbox, pack.m_a.m_xform, b.m_cbox, pack.m_b.m_xform);
-        MT_Scalar rdist2 = distance2(a_rtree.m_cbox, pack.m_a.m_xform, b.m_cbox, pack.m_b.m_xform);
-        if (ldist2 < rdist2) 
-        {
-            MT_Scalar dist2 = ldist2 < max_dist2 ? closest_points(a_ltree, b, pack, max_dist2, pa, pb) : MT_INFINITY;;
-            GEN_set_min(max_dist2, dist2);
-            return rdist2 < max_dist2 ? GEN_min(dist2,closest_points(a_rtree, b, pack, max_dist2, pa, pb)) : dist2;
-        }
-        else
-        {
-            MT_Scalar dist2 = rdist2 < max_dist2 ? closest_points(a_rtree, b, pack, max_dist2, pa, pb) : MT_INFINITY;
-            GEN_set_min(max_dist2, dist2);
-            return ldist2 < max_dist2 ? GEN_min(dist2, closest_points(a_ltree, b, pack, max_dist2, pa, pb)) : dist2;
-        }
-    }
-}
-
-#endif
-
diff --git a/extern/solid/src/complex/DT_CBox.h b/extern/solid/src/complex/DT_CBox.h
deleted file mode 100644
index 7fc7c5df4db..00000000000
--- a/extern/solid/src/complex/DT_CBox.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_CBOX_H
-#define DT_CBOX_H
-
-#include "MT_BBox.h"
-
-struct DT_CBox {
-    DT_CBox() {}
-    DT_CBox(const MT_Point3& center, const MT_Vector3& extent) 
-      : m_center(center),
-        m_extent(extent)
-    {}
-
-    explicit DT_CBox(const MT_BBox& bbox) { set(bbox); }
-
-    const MT_Point3& getCenter() const { return m_center; }
-    const MT_Vector3& getExtent() const { return m_extent; }
-
-    void set(const MT_BBox& bbox)
-    {
-        m_center = bbox.getCenter();
-        m_extent = bbox.getExtent();
-    }
- 
-    MT_BBox get() const
-    {
-        return MT_BBox(m_center - m_extent, m_center + m_extent);
-    }
-
-    MT_Scalar size() const  
-    {
-        return GEN_max(GEN_max(m_extent[0], m_extent[1]), m_extent[2]);
-    }
-
-
-    DT_CBox& operator+=(const DT_CBox& box)
-    {
-        m_center += box.getCenter();
-        m_extent += box.getExtent();
-        return *this;
-    }
-    
-    int longestAxis() const { return m_extent.closestAxis(); }
-        
-    DT_CBox hull(const DT_CBox& b) const 
-    {
-        return DT_CBox(this->get().hull(b.get()));
-    }
-
-    bool overlaps(const DT_CBox& b) const 
-    {
-        return MT_abs(m_center[0] - b.m_center[0]) <= m_extent[0] + b.m_extent[0] &&
-               MT_abs(m_center[1] - b.m_center[1]) <= m_extent[1] + b.m_extent[1] &&
-               MT_abs(m_center[2] - b.m_center[2]) <= m_extent[2] + b.m_extent[2];
-    }
-    
-    bool overlapsLineSegment(const MT_Point3& p, const MT_Point3& q) const 
-    {
-        MT_Vector3 r = q - p;   
-        MT_Vector3 r_abs = r.absolute();
-        
-        if (!overlaps(DT_CBox(p + r * MT_Scalar(0.5), r_abs * MT_Scalar(0.5))))
-        {
-            return false;
-        }
-        
-        MT_Vector3 s = p - m_center;
-
-        if (MT_abs(r[2] * s[1] - r[1] * s[2]) > r_abs[2] * m_extent[1] + r_abs[1] * m_extent[2])
-        {
-            return false;
-        }
-                    
-        if (MT_abs(r[0] * s[2] - r[2] * s[0]) > r_abs[0] * m_extent[2] + r_abs[2] * m_extent[0])
-        {
-            return false;
-        }
-                    
-        if (MT_abs(r[1] * s[0] - r[0] * s[1]) > r_abs[1] * m_extent[0] + r_abs[0] * m_extent[1])
-        {
-            return false;
-        }
-            
-        return true;
-    }
-    
-    MT_Point3 support(const MT_Vector3& v) const 
-    {
-        return m_center + MT_Vector3(v[0] < MT_Scalar(0.0) ? -m_extent[0] : m_extent[0],
-                                     v[1] < MT_Scalar(0.0) ? -m_extent[1] : m_extent[1],
-                                     v[2] < MT_Scalar(0.0) ? -m_extent[2] : m_extent[2]); 
-    
-    }
-
-private:
-    MT_Point3  m_center;
-    MT_Vector3 m_extent;
-};
-
-inline DT_CBox operator+(const DT_CBox& b1, const DT_CBox& b2) 
-{
-    return DT_CBox(b1.getCenter() + b2.getCenter(), 
-                   b1.getExtent() + b2.getExtent());
-}
-
-inline DT_CBox operator-(const DT_CBox& b1, const DT_CBox& b2) 
-{
-    return DT_CBox(b1.getCenter() - b2.getCenter(), 
-                   b1.getExtent() + b2.getExtent());
-}
-
-#endif
diff --git a/extern/solid/src/complex/DT_Complex.cpp b/extern/solid/src/complex/DT_Complex.cpp
deleted file mode 100644
index 023383a8427..00000000000
--- a/extern/solid/src/complex/DT_Complex.cpp
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include 
-#include 
-
-#include "DT_Complex.h"
-#include "DT_Minkowski.h"
-#include "DT_Sphere.h"
-#include "DT_Transform.h"
-
-DT_Complex::DT_Complex(const DT_VertexBase *base) 
-  : m_base(base),
-    m_count(0),
-    m_leaves(0),
-	m_nodes(0)
-{ 
-	assert(base);
-	base->addComplex(this);
-}
-
-
-DT_Complex::~DT_Complex()
-{
-    DT_Index i;
-    for (i = 0; i != m_count; ++i) 
-    {
-        delete m_leaves[i];
-    }
-    delete [] m_leaves;
-    delete [] m_nodes;
-    
-    m_base->removeComplex(this);
-    if (m_base->isOwner()) 
-    {
-        delete m_base;
-    }
-}
-
-void DT_Complex::finish(DT_Count n, const DT_Convex *p[]) 
-{
-	m_count = n;
-
-   
-    assert(n >= 1);
-
-    m_leaves = new const DT_Convex *[n];
-    assert(m_leaves);
-
-    DT_CBox *boxes = new DT_CBox[n];
-    DT_Index *indices = new DT_Index[n];
-    assert(boxes);
-       
-    DT_Index i;
-    for (i = 0; i != n; ++i) 
-    {
-        m_leaves[i] = p[i];
-        boxes[i].set(p[i]->bbox());
-        indices[i] = i;
-    }
-
-    m_cbox = boxes[0];
-    for (i = 1; i != n; ++i) 
-    {
-        m_cbox = m_cbox.hull(boxes[i]);
-    }
-
-    if (n == 1)
-    {
-        m_nodes = 0;
-        m_type = DT_BBoxTree::LEAF;
-    }
-    else 
-    {
-        m_nodes = new DT_BBoxNode[n - 1];
-        assert(m_nodes);
-    
-        int num_nodes = 0;
-        new(&m_nodes[num_nodes++]) DT_BBoxNode(0, n, num_nodes, m_nodes, boxes, indices, m_cbox);
-
-        assert(num_nodes == n - 1);
-        
-        m_type = DT_BBoxTree::INTERNAL;
-    }
-
-    delete [] boxes;
-}
-
-
-MT_BBox DT_Complex::bbox(const MT_Transform& t, MT_Scalar margin) const 
-{
-    MT_Matrix3x3 abs_b = t.getBasis().absolute();  
-    MT_Point3 center = t(m_cbox.getCenter());
-    MT_Vector3 extent(margin + abs_b[0].dot(m_cbox.getExtent()),
-                      margin + abs_b[1].dot(m_cbox.getExtent()),
-                      margin + abs_b[2].dot(m_cbox.getExtent()));
-    
-    return MT_BBox(center - extent, center + extent);
-}
-
-inline DT_CBox computeCBox(const DT_Convex *p)
-{
-    return DT_CBox(p->bbox()); 
-}
-
-inline DT_CBox computeCBox(MT_Scalar margin, const MT_Transform& xform) 
-{
-    const MT_Matrix3x3& basis = xform.getBasis();
-    return DT_CBox(MT_Point3(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0)), 
-                   MT_Vector3(basis[0].length() * margin, 
-                              basis[1].length() * margin, 
-                              basis[2].length() * margin));
-} 
-
-void DT_Complex::refit()
-{
-    DT_RootData rd(m_nodes, m_leaves);
-    DT_Index i = m_count - 1;
-    while (i--)
-    {
-        ::refit(m_nodes[i], rd);
-    }
-    m_cbox = m_type == DT_BBoxTree::LEAF ? computeCBox(m_leaves[0]) : m_nodes[0].hull();
-}
-
-inline bool ray_cast(const DT_RootData& rd, DT_Index index, const MT_Point3& source, const MT_Point3& target, 
-                     MT_Scalar& lambda, MT_Vector3& normal)
-{
-    return rd.m_leaves[index]->ray_cast(source, target, lambda, normal);
-}
-
-bool DT_Complex::ray_cast(const MT_Point3& source, const MT_Point3& target,
-                          MT_Scalar& lambda, MT_Vector3& normal) const 
-{
-    DT_RootData rd(m_nodes, m_leaves);
-
-    return ::ray_cast(DT_BBoxTree(m_cbox, 0, m_type), rd, source, target, lambda, normal);
-}
-
-inline bool intersect(const DT_Pack& pack, DT_Index a_index, MT_Vector3& v) 
-{
-    DT_Transform ta = DT_Transform(pack.m_a.m_xform, *pack.m_a.m_leaves[a_index]);
-    MT_Scalar a_margin = pack.m_a.m_plus;
-    return ::intersect((a_margin > MT_Scalar(0.0) ? 
-                        static_cast(DT_Minkowski(ta, DT_Sphere(a_margin))) :  
-                        static_cast(ta)), 
-                       pack.m_b, v); 
-}
-
-bool intersect(const DT_Complex& a,  const MT_Transform& a2w,  MT_Scalar a_margin, 
-               const DT_Convex& b, MT_Vector3& v) 
-{
-    DT_Pack pack(DT_ObjectData(a.m_nodes, a.m_leaves, a2w, a_margin), b);
-
-    return intersect(DT_BBoxTree(a.m_cbox + pack.m_a.m_added, 0, a.m_type), pack, v);
-}
-
-inline bool intersect(const DT_DuoPack& pack, DT_Index a_index, DT_Index b_index, MT_Vector3& v) 
-{
-    DT_Transform ta = DT_Transform(pack.m_a.m_xform, *pack.m_a.m_leaves[a_index]);
-    MT_Scalar a_margin = pack.m_a.m_plus;
-    DT_Transform tb = DT_Transform(pack.m_b.m_xform, *pack.m_b.m_leaves[b_index]);
-    MT_Scalar b_margin = pack.m_b.m_plus;
-    return ::intersect((a_margin > MT_Scalar(0.0) ?
-                        static_cast(DT_Minkowski(ta, DT_Sphere(a_margin))) : 
-                        static_cast(ta)), 
-                       (b_margin > MT_Scalar(0.0) ? 
-                        static_cast(DT_Minkowski(tb, DT_Sphere(b_margin))) : 
-                        static_cast(tb)), 
-                       v);   
-}
-
-bool intersect(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
-               const DT_Complex& b, const MT_Transform& b2w, MT_Scalar b_margin, MT_Vector3& v) 
-{
-    DT_DuoPack pack(DT_ObjectData(a.m_nodes, a.m_leaves, a2w, a_margin),
-                                                  DT_ObjectData(b.m_nodes, b.m_leaves, b2w, b_margin));
-
-
-    return intersect(DT_BBoxTree(a.m_cbox + pack.m_a.m_added, 0, a.m_type),
-                     DT_BBoxTree(b.m_cbox + pack.m_b.m_added, 0, b.m_type), pack, v);
-}
-
-inline bool common_point(const DT_Pack& pack, DT_Index a_index, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb) 
-{
-    DT_Transform ta = DT_Transform(pack.m_a.m_xform, *pack.m_a.m_leaves[a_index]);
-    MT_Scalar a_margin = pack.m_a.m_plus;
-    return ::common_point((a_margin > MT_Scalar(0.0) ? 
-                           static_cast(DT_Minkowski(ta, DT_Sphere(a_margin))) :
-                           static_cast(ta)), 
-                          pack.m_b, v, pa, pb); 
-}
-    
-bool common_point(const DT_Complex& a,  const MT_Transform& a2w,  MT_Scalar a_margin, 
-                  const DT_Convex& b, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb) 
-{
-     DT_Pack pack(DT_ObjectData(a.m_nodes, a.m_leaves, a2w, a_margin), b);
-
-    return common_point(DT_BBoxTree(a.m_cbox + pack.m_a.m_added, 0, a.m_type), pack, v, pb, pa);
-}
-
-inline bool common_point(const DT_DuoPack& pack, DT_Index a_index, DT_Index b_index, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb) 
-{
-    DT_Transform ta = DT_Transform(pack.m_a.m_xform, *pack.m_a.m_leaves[a_index]);
-    MT_Scalar a_margin = pack.m_a.m_plus;
-    DT_Transform tb = DT_Transform(pack.m_b.m_xform, *pack.m_b.m_leaves[b_index]);
-    MT_Scalar b_margin = pack.m_b.m_plus;
-    return ::common_point((a_margin > MT_Scalar(0.0) ? 
-                           static_cast(DT_Minkowski(ta, DT_Sphere(a_margin))) : 
-                           static_cast(ta)), 
-                          (b_margin > MT_Scalar(0.0) ? 
-                           static_cast(DT_Minkowski(tb, DT_Sphere(b_margin))) : 
-                           static_cast(tb)), 
-                          v, pa, pb);    
-}
-    
-bool common_point(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
-                  const DT_Complex& b, const MT_Transform& b2w, MT_Scalar b_margin, 
-                  MT_Vector3& v, MT_Point3& pa, MT_Point3& pb) 
-{
-    DT_DuoPack pack(DT_ObjectData(a.m_nodes, a.m_leaves, a2w, a_margin),
-                                                  DT_ObjectData(b.m_nodes, b.m_leaves, b2w, b_margin));
-
-    return common_point(DT_BBoxTree(a.m_cbox + pack.m_a.m_added, 0, a.m_type),
-                        DT_BBoxTree(b.m_cbox + pack.m_b.m_added, 0, b.m_type),  pack, v, pa, pb);
-}
-
-inline bool penetration_depth(const DT_HybridPack& pack, DT_Index a_index, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb) 
-{
-    DT_Transform ta = DT_Transform(pack.m_a.m_xform, *pack.m_a.m_leaves[a_index]);
-    return ::hybrid_penetration_depth(ta, pack.m_a.m_plus, pack.m_b, pack.m_margin, v, pa, pb); 
-}
-
-bool penetration_depth(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin, 
-                       const DT_Convex& b, MT_Scalar b_margin, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb) 
-{
-    DT_HybridPack pack(DT_ObjectData(a.m_nodes, a.m_leaves, a2w, a_margin), b, b_margin);
-     
-    MT_Scalar  max_pen_len = MT_Scalar(0.0);
-    return penetration_depth(DT_BBoxTree(a.m_cbox + pack.m_a.m_added, 0, a.m_type), pack, v, pa, pb, max_pen_len);
-}
-
-inline bool penetration_depth(const DT_DuoPack& pack, DT_Index a_index, DT_Index b_index, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb) 
-{
-    DT_Transform ta = DT_Transform(pack.m_a.m_xform, *pack.m_a.m_leaves[a_index]);
-    DT_Transform tb = DT_Transform(pack.m_b.m_xform, *pack.m_b.m_leaves[b_index]);
-    return ::hybrid_penetration_depth(ta, pack.m_a.m_plus, tb, pack.m_a.m_plus, v, pa, pb);  
-}
-
-bool penetration_depth(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
-                       const DT_Complex& b, const MT_Transform& b2w, MT_Scalar b_margin, 
-                       MT_Vector3& v, MT_Point3& pa, MT_Point3& pb) 
-{
-    DT_DuoPack pack(DT_ObjectData(a.m_nodes, a.m_leaves, a2w, a_margin),
-                                                  DT_ObjectData(b.m_nodes, b.m_leaves, b2w, b_margin));
-
-    MT_Scalar  max_pen_len = MT_Scalar(0.0);
-    return penetration_depth(DT_BBoxTree(a.m_cbox + pack.m_a.m_added, 0, a.m_type),
-                             DT_BBoxTree(b.m_cbox + pack.m_b.m_added, 0, b.m_type), pack, v, pa, pb, max_pen_len);
-}
-
-
-
-inline MT_Scalar closest_points(const DT_Pack& pack, DT_Index a_index, MT_Scalar max_dist2, MT_Point3& pa, MT_Point3& pb) 
-{
-    DT_Transform ta = DT_Transform(pack.m_a.m_xform, *pack.m_a.m_leaves[a_index]);
-    MT_Scalar a_margin = pack.m_a.m_plus;
-    return ::closest_points((a_margin > MT_Scalar(0.0) ? 
-                             static_cast(DT_Minkowski(ta, DT_Sphere(a_margin))) :  
-                             static_cast(ta)), 
-                            pack.m_b, max_dist2, pa, pb); 
-}
-
-MT_Scalar closest_points(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
-                         const DT_Convex& b, MT_Point3& pa, MT_Point3& pb)
-{
-    DT_Pack pack(DT_ObjectData(a.m_nodes, a.m_leaves, a2w, a_margin), b);
-
-    return closest_points(DT_BBoxTree(a.m_cbox + pack.m_a.m_added, 0, a.m_type), pack, MT_INFINITY, pa, pb); 
-}
-
-inline MT_Scalar closest_points(const DT_DuoPack& pack, DT_Index a_index, DT_Index b_index, MT_Scalar max_dist2, MT_Point3& pa, MT_Point3& pb) 
-{
-    DT_Transform ta = DT_Transform(pack.m_a.m_xform, *pack.m_a.m_leaves[a_index]);
-    MT_Scalar a_margin = pack.m_a.m_plus;
-    DT_Transform tb = DT_Transform(pack.m_b.m_xform, *pack.m_b.m_leaves[b_index]);
-    MT_Scalar b_margin = pack.m_b.m_plus;
-    return ::closest_points((a_margin > MT_Scalar(0.0) ? 
-                             static_cast(DT_Minkowski(ta, DT_Sphere(a_margin))) : 
-                             static_cast(ta)), 
-                            (b_margin > MT_Scalar(0.0) ? 
-                             static_cast(DT_Minkowski(tb, DT_Sphere(b_margin))) : 
-                             static_cast(tb)), max_dist2, pa, pb);     
-}
-
-MT_Scalar closest_points(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin,
-                         const DT_Complex& b, const MT_Transform& b2w, MT_Scalar b_margin, 
-                         MT_Point3& pa, MT_Point3& pb) 
-{
-    DT_DuoPack pack(DT_ObjectData(a.m_nodes, a.m_leaves, a2w, a_margin),
-                               DT_ObjectData(b.m_nodes, b.m_leaves, b2w, b_margin));
-
-    return closest_points(DT_BBoxTree(a.m_cbox + pack.m_a.m_added, 0, a.m_type),
-                          DT_BBoxTree(b.m_cbox + pack.m_b.m_added, 0, b.m_type), pack, MT_INFINITY, pa, pb);
-}
-
-
diff --git a/extern/solid/src/complex/DT_Complex.h b/extern/solid/src/complex/DT_Complex.h
deleted file mode 100644
index ae08a05d4c9..00000000000
--- a/extern/solid/src/complex/DT_Complex.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_COMPLEX_H
-#define DT_COMPLEX_H
-
-#include 
-
-#include "MT_Transform.h"
-#include "DT_VertexBase.h"
-
-#include "DT_Shape.h"
-#include "DT_CBox.h"
-#include "DT_BBoxTree.h"
-
-class DT_Convex;
-
-class DT_Complex : public DT_Shape  {
-public:
-	DT_Complex(const DT_VertexBase *base);
-	virtual ~DT_Complex();
-	
-	void finish(DT_Count n, const DT_Convex *p[]);
-    
-	virtual DT_ShapeType getType() const { return COMPLEX; }
-
-    virtual MT_BBox bbox(const MT_Transform& t, MT_Scalar margin) const;
-
-	virtual bool ray_cast(const MT_Point3& source, const MT_Point3& target, 
-						  MT_Scalar& lambda, MT_Vector3& normal) const; 
-
-	void refit();
-	
-
-    friend bool intersect(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin, 
-		                  const DT_Convex& b, MT_Vector3& v);
-    
-    friend bool intersect(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin, 
-		                  const DT_Complex& b, const MT_Transform& b2w, MT_Scalar b_margin,
-                          MT_Vector3& v);
-   
-    friend bool common_point(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin, 
-		                     const DT_Convex& b, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb);
-    
-    friend bool common_point(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin, 
-		                     const DT_Complex& b, const MT_Transform& b2w, MT_Scalar b_margin,
-                             MT_Vector3& v, MT_Point3& pa, MT_Point3& pb);
-    
-    friend bool penetration_depth(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin, 
-								  const DT_Convex& b, MT_Scalar b_margin, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb);
-    
-    friend bool penetration_depth(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin, 
-								  const DT_Complex& b, const MT_Transform& b2w, MT_Scalar b_margin,
-								  MT_Vector3& v, MT_Point3& pa, MT_Point3& pb);
-
-    friend MT_Scalar closest_points(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin, 
-		                            const DT_Convex& b, MT_Point3& pa, MT_Point3& pb);
-    
-    friend MT_Scalar closest_points(const DT_Complex& a, const MT_Transform& a2w, MT_Scalar a_margin, 
-		                            const DT_Complex& b, const MT_Transform& b2w, MT_Scalar b_margin,
-									MT_Point3& pa, MT_Point3& pb);
-
-	const DT_VertexBase   *m_base;
-	DT_Count               m_count;
-	const DT_Convex      **m_leaves;
-	DT_BBoxNode           *m_nodes;
-	DT_CBox                m_cbox;
-	DT_BBoxTree::NodeType  m_type;
-};
-
-#endif
-
-
-
diff --git a/extern/solid/src/complex/Makefile b/extern/solid/src/complex/Makefile
deleted file mode 100644
index e8df4df51a3..00000000000
--- a/extern/solid/src/complex/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# $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.
-#
-# The Original Code is: all of this file.
-#
-# Contributor(s): none yet.
-#
-# ***** END GPL LICENSE BLOCK *****
-#
-#
-
-LIBNAME = solid_complex
-DIR = $(OCGDIR)/extern/$(LIBNAME)
-
-CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
-
-CPPFLAGS += -I../../include -I$(NAN_QHULL)/include
-CPPFLAGS += -I../convex
-CPPFLAGS += -DQHULL -DUSE_DOUBLES
-
-include nan_compile.mk 
-
-
diff --git a/extern/solid/src/convex/DT_Accuracy.cpp b/extern/solid/src/convex/DT_Accuracy.cpp
deleted file mode 100644
index 113275b0dbd..00000000000
--- a/extern/solid/src/convex/DT_Accuracy.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "DT_Accuracy.h"
-
-static const MT_Scalar rel_error = MT_Scalar(1.0e-3);
-
-MT_Scalar DT_Accuracy::rel_error2 = rel_error * rel_error;
-MT_Scalar DT_Accuracy::depth_tolerance = MT_Scalar(1.0) + MT_Scalar(2.0) * rel_error; 
-MT_Scalar DT_Accuracy::tol_error = MT_EPSILON;
diff --git a/extern/solid/src/convex/DT_Accuracy.h b/extern/solid/src/convex/DT_Accuracy.h
deleted file mode 100644
index 9759a6fd4c5..00000000000
--- a/extern/solid/src/convex/DT_Accuracy.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_ACCURACY_H
-#define DT_ACCURACY_H
-
-#include "MT_Scalar.h"
-
-class DT_Accuracy {
-public:
-	static MT_Scalar rel_error2; // squared relative error in the computed distance
-	static MT_Scalar depth_tolerance; // terminate EPA if upper_bound <= depth_tolerance * dist2
-	static MT_Scalar tol_error; // error tolerance if the distance is almost zero
-	
-	static void setAccuracy(MT_Scalar rel_error) 
-	{ 
-		rel_error2 = rel_error * rel_error;
-		depth_tolerance = MT_Scalar(1.0) + MT_Scalar(2.0) * rel_error;
-	}	
-   
-	static void setTolerance(MT_Scalar epsilon) 
-	{ 
-		tol_error = epsilon;
-	}
-};
-
-#endif
diff --git a/extern/solid/src/convex/DT_Array.h b/extern/solid/src/convex/DT_Array.h
deleted file mode 100644
index 1694f884e53..00000000000
--- a/extern/solid/src/convex/DT_Array.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_ARRAY_H
-#define DT_ARRAY_H
-
-#if defined (__sgi)
-#include 
-#else
-#include 
-#endif
-
-template 
-class DT_Array {
-public:
-	DT_Array() 
-      :	m_count(0), 
-		m_data(0) 
-	{}
-
-	explicit DT_Array(Size count)
-	  :	m_count(count),
-		m_data(new Data[count]) 
-	{
-		assert(m_data);
-	}
-	
-	DT_Array(Size count, const Data *data) 
-	  :	m_count(count),
-		m_data(new Data[count]) 
-	{
-		assert(m_data);		
-		std::copy(&data[0], &data[count], m_data);
-	}
-	
-	~DT_Array() 
-	{ 
-		delete [] m_data; 
-	}
-	
-	const Data& operator[](int i) const { return m_data[i]; }
-	Data&       operator[](int i)       { return m_data[i]; }
-
-	Size size() const { return m_count; }
-	
-private:
-	DT_Array(const DT_Array&);
-	DT_Array& operator=(const DT_Array&);
-
-	Size  m_count;
-	Data *m_data;
-};
-  
-#endif
-
diff --git a/extern/solid/src/convex/DT_Box.cpp b/extern/solid/src/convex/DT_Box.cpp
deleted file mode 100644
index 0b46f566fe8..00000000000
--- a/extern/solid/src/convex/DT_Box.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "DT_Box.h"
-
-MT_Scalar DT_Box::supportH(const MT_Vector3& v) const 
-{
-    return v.absolute().dot(m_extent);
-}
-
-MT_Point3 DT_Box::support(const MT_Vector3& v) const 
-{
-    return MT_Point3(v[0] < MT_Scalar(0.0) ? -m_extent[0] : m_extent[0],
-                     v[1] < MT_Scalar(0.0) ? -m_extent[1] : m_extent[1],
-                     v[2] < MT_Scalar(0.0) ? -m_extent[2] : m_extent[2]); 
-    
-}
-
-
-bool DT_Box::ray_cast(const MT_Point3& source, const MT_Point3& target,
-					  MT_Scalar& param, MT_Vector3& normal) const 
-{
-	T_Outcode source_bits = outcode(source);
-	T_Outcode target_bits = outcode(target);
-
-	if ((source_bits & target_bits) == 0x0)
-		// None of the side planes separate the ray from the box.
-	{
-		MT_Scalar lambda_enter = MT_Scalar(0.0);
-		MT_Scalar lambda_exit  = param;
-		MT_Vector3 r = target - source;
-		T_Outcode normal_bit = 0x0; // Indicates the axis that is returned as normal.
-		T_Outcode bit = 0x01;
-		int i;
-		for (i = 0; i != 3; ++i)
-		{
-			if (source_bits & bit)
-				// Point of intersection is entering
-			{
-				MT_Scalar lambda = (-source[i] - m_extent[i]) / r[i];
-				if (lambda_enter < lambda)
-				{
-					lambda_enter = lambda;
-					normal_bit = bit;
-				}
-			}
-			else if (target_bits & bit) 
-				// Point of intersection is exiting
-			{
-				MT_Scalar lambda = (-source[i] - m_extent[i]) / r[i];
-				GEN_set_min(lambda_exit, lambda);
-			}
-			bit <<=1;
-			if (source_bits & bit)
-				// Point of intersection is entering
-			{
-				MT_Scalar lambda =  (-source[i] + m_extent[i]) / r[i];
-				if (lambda_enter < lambda)
-				{
-					lambda_enter = lambda;
-					normal_bit = bit;
-				}
-			}
-			else if (target_bits & bit) 
-				// Point of intersection is exiting
-			{
-				MT_Scalar lambda =  (-source[i] + m_extent[i]) / r[i];
-				GEN_set_min(lambda_exit, lambda);
-			}
-			bit <<=1;
-		}
-		if (lambda_enter <= lambda_exit)
-			// The ray intersects the box
-		{
-			param = lambda_enter;
-			normal.setValue(normal_bit == 0x01 ? -MT_Scalar(1.0) : 
-							normal_bit == 0x02 ?  MT_Scalar(1.0) : 
-							MT_Scalar(0.0),
-							normal_bit == 0x04 ? -MT_Scalar(1.0) : 
-							normal_bit == 0x08 ?  MT_Scalar(1.0) : 
-							MT_Scalar(0.0),
-							normal_bit == 0x10 ? -MT_Scalar(1.0) : 
-							normal_bit == 0x20 ?  MT_Scalar(1.0) : 
-							MT_Scalar(0.0));
-			return true;
-		}
-	}
-
-	return false;
-}
-
-
diff --git a/extern/solid/src/convex/DT_Box.h b/extern/solid/src/convex/DT_Box.h
deleted file mode 100644
index ace9634b5e3..00000000000
--- a/extern/solid/src/convex/DT_Box.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_BOX_H
-#define DT_BOX_H
-
-#include "DT_Convex.h"
-
-class DT_Box : public DT_Convex {
-public:
-    DT_Box(MT_Scalar x, MT_Scalar y, MT_Scalar z) : 
-        m_extent(x, y, z) 
-	{}
-
-    DT_Box(const MT_Vector3& e) : 
-		m_extent(e) 
-	{}
-
-    virtual MT_Scalar supportH(const MT_Vector3& v) const;
-    virtual MT_Point3 support(const MT_Vector3& v) const;
-	virtual bool ray_cast(const MT_Point3& source, const MT_Point3& target,
-						  MT_Scalar& param, MT_Vector3& normal) const;
-    
-    const MT_Vector3& getExtent() const { return m_extent; }
-	
-protected:
-	typedef unsigned int T_Outcode;
-	
-	T_Outcode outcode(const MT_Point3& p) const
-	{
-		return (p[0] < -m_extent[0] ? 0x01 : 0x0) |    
-			   (p[0] >  m_extent[0] ? 0x02 : 0x0) |
-			   (p[1] < -m_extent[1] ? 0x04 : 0x0) |    
-			   (p[1] >  m_extent[1] ? 0x08 : 0x0) |
-			   (p[2] < -m_extent[2] ? 0x10 : 0x0) |    
-			   (p[2] >  m_extent[2] ? 0x20 : 0x0);
-	}
-    
-    MT_Vector3 m_extent;
-};
-
-#endif
diff --git a/extern/solid/src/convex/DT_Cone.cpp b/extern/solid/src/convex/DT_Cone.cpp
deleted file mode 100644
index 1dd6a7ddbbe..00000000000
--- a/extern/solid/src/convex/DT_Cone.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "DT_Cone.h"
-
-MT_Point3 DT_Cone::support(const MT_Vector3& v) const 
-{
-    MT_Scalar v_len = v.length();
-
-    if (v[1] > v_len * sinAngle)
-	{
-		return MT_Point3(MT_Scalar(0.0), halfHeight, MT_Scalar(0.0));
-	}
-    else
-	{
-        MT_Scalar s = MT_sqrt(v[0] * v[0] + v[2] * v[2]);
-        if (s != MT_Scalar(0.0))
-		{
-            MT_Scalar d = bottomRadius / s;  
-            return MT_Point3(v[0] * d, -halfHeight, v[2] * d);
-        }
-        else
-		{
-			return MT_Point3(bottomRadius, -halfHeight, MT_Scalar(0.0));
-		}
-    }
-}
-
diff --git a/extern/solid/src/convex/DT_Cone.h b/extern/solid/src/convex/DT_Cone.h
deleted file mode 100644
index 85e416877dd..00000000000
--- a/extern/solid/src/convex/DT_Cone.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_CONE_H
-#define DT_CONE_H
-
-#include "DT_Convex.h"
-
-class DT_Cone : public DT_Convex {
-public:
-	DT_Cone(MT_Scalar r, MT_Scalar h) : 
-        bottomRadius(r), 
-        halfHeight(h * MT_Scalar(0.5)), 
-        sinAngle(r / MT_sqrt(r * r + h * h))
-    {} 
-  
-    virtual MT_Point3 support(const MT_Vector3& v) const;
-  
-protected:
-    MT_Scalar bottomRadius;
-    MT_Scalar halfHeight;
-    MT_Scalar sinAngle;
-};
-
-#endif
diff --git a/extern/solid/src/convex/DT_Convex.cpp b/extern/solid/src/convex/DT_Convex.cpp
deleted file mode 100644
index 3be47f6ed02..00000000000
--- a/extern/solid/src/convex/DT_Convex.cpp
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "DT_Convex.h"
-#include "GEN_MinMax.h"
-
-//#define DEBUG
-#define SAFE_EXIT
-
-#include "DT_GJK.h"
-#include "DT_PenDepth.h"
-
-#include 
-#include 
-
-#include "MT_BBox.h"
-#include "DT_Sphere.h"
-#include "DT_Minkowski.h"
-
-#include "DT_Accuracy.h"
-
-#ifdef STATISTICS
-int num_iterations = 0;
-int num_irregularities = 0;
-#endif
-
-MT_BBox DT_Convex::bbox() const 
-{
-	MT_Point3 min(-supportH(MT_Vector3(-1.0f, 0.0f, 0.0f)),
-                  -supportH(MT_Vector3(0.0f, -1.0f, 0.0f)),
-				  -supportH(MT_Vector3(0.0f, 0.0f, -1.0f)));
-	MT_Point3 max( supportH(MT_Vector3(1.0f, 0.0f, 0.0f)),
-                   supportH(MT_Vector3(0.0f, 1.0f, 0.0f)),
-				   supportH(MT_Vector3(0.0f, 0.0f, 1.0f)));
-
-	
-    return MT_BBox(min, max);
-}
-
-MT_BBox DT_Convex::bbox(const MT_Matrix3x3& basis) const 
-{
-    MT_Point3 min(-supportH(-basis[0]),
-                  -supportH(-basis[1]),
-		          -supportH(-basis[2])); 
-    MT_Point3 max( supportH( basis[0]),
-                   supportH( basis[1]),
-                   supportH( basis[2])); 
-    return MT_BBox(min, max);
-}
-
-MT_BBox DT_Convex::bbox(const MT_Transform& t, MT_Scalar margin) const 
-{
-    MT_Point3 min(t.getOrigin()[0] - supportH(-t.getBasis()[0]) - margin,
-                  t.getOrigin()[1] - supportH(-t.getBasis()[1]) - margin,
-		          t.getOrigin()[2] - supportH(-t.getBasis()[2]) - margin); 
-    MT_Point3 max(t.getOrigin()[0] + supportH( t.getBasis()[0]) + margin,
-                  t.getOrigin()[1] + supportH( t.getBasis()[1]) + margin,
-                  t.getOrigin()[2] + supportH( t.getBasis()[2]) + margin); 
-    return MT_BBox(min, max);
-}
-
-bool DT_Convex::ray_cast(const MT_Point3& source, const MT_Point3& target, MT_Scalar& lambda, MT_Vector3& normal) const
-{
-	// Still working on this one...
-    return false;
-}
-
-bool intersect(const DT_Convex& a, const DT_Convex& b, MT_Vector3& v)
-{
-	DT_GJK gjk;
-
-#ifdef STATISTICS
-    num_iterations = 0;
-#endif
-	MT_Scalar dist2 = MT_INFINITY;
-
-	do
-	{
-		MT_Point3  p = a.support(-v);	
-		MT_Point3  q = b.support(v);
-		MT_Vector3 w = p - q; 
-		
-        if (v.dot(w) > MT_Scalar(0.0)) 
-		{
-			return false;
-		}
- 
-		gjk.addVertex(w);
-
-#ifdef STATISTICS
-        ++num_iterations;
-#endif
-        if (!gjk.closest(v)) 
-		{
-#ifdef STATISTICS
-            ++num_irregularities;
-#endif
-            return false;
-        }
-
-#ifdef SAFE_EXIT
-		MT_Scalar prev_dist2 = dist2;
-#endif
-
-		dist2 = v.length2();
-
-#ifdef SAFE_EXIT
-		if (prev_dist2 - dist2 <= MT_EPSILON * prev_dist2) 
-		{
-			return false;
-		}
-#endif
-    } 
-    while (!gjk.fullSimplex() && dist2 > DT_Accuracy::tol_error * gjk.maxVertex()); 
-
-    v.setValue(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0));
-
-    return true;
-}
-
-
-
-
-bool common_point(const DT_Convex& a, const DT_Convex& b,
-                  MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
-{
-	DT_GJK gjk;
-
-#ifdef STATISTICS
-    num_iterations = 0;
-#endif
-
-	MT_Scalar dist2 = MT_INFINITY;
-
-    do
-	{
-		MT_Point3  p = a.support(-v);	
-		MT_Point3  q = b.support(v);
-		MT_Vector3 w = p - q; 
-		
-        if (v.dot(w) > MT_Scalar(0.0)) 
-		{
-			return false;
-		}
- 
-		gjk.addVertex(w, p, q);
-
-#ifdef STATISTICS
-        ++num_iterations;
-#endif
-        if (!gjk.closest(v)) 
-		{
-#ifdef STATISTICS
-            ++num_irregularities;
-#endif
-            return false;
-        }		
-		
-#ifdef SAFE_EXIT
-		MT_Scalar prev_dist2 = dist2;
-#endif
-
-		dist2 = v.length2();
-
-#ifdef SAFE_EXIT
-		if (prev_dist2 - dist2 <= MT_EPSILON * prev_dist2) 
-		{
-			return false;
-		}
-#endif
-    }
-    while (!gjk.fullSimplex() && dist2 > DT_Accuracy::tol_error * gjk.maxVertex()); 
-    
-	gjk.compute_points(pa, pb);
-
-    v.setValue(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0));
-
-    return true;
-}
-
-
-
-
-
-
-	
-bool penetration_depth(const DT_Convex& a, const DT_Convex& b,
-                       MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
-{
-	DT_GJK gjk;
-
-#ifdef STATISTICS
-    num_iterations = 0;
-#endif
-
-	MT_Scalar dist2 = MT_INFINITY;
-
-    do
-	{
-		MT_Point3  p = a.support(-v);	
-		MT_Point3  q = b.support(v);
-		MT_Vector3 w = p - q; 
-		
-        if (v.dot(w) > MT_Scalar(0.0)) 
-		{
-			return false;
-		}
- 
-		gjk.addVertex(w, p, q);
-
-#ifdef STATISTICS
-        ++num_iterations;
-#endif
-        if (!gjk.closest(v)) 
-		{
-#ifdef STATISTICS
-            ++num_irregularities;
-#endif
-            return false;
-        }		
-		
-#ifdef SAFE_EXIT
-		MT_Scalar prev_dist2 = dist2;
-#endif
-
-		dist2 = v.length2();
-
-#ifdef SAFE_EXIT
-		if (prev_dist2 - dist2 <= MT_EPSILON * prev_dist2) 
-		{
-			return false;
-		}
-#endif
-    }
-    while (!gjk.fullSimplex() && dist2 > DT_Accuracy::tol_error * gjk.maxVertex()); 
-    
-
-	return penDepth(gjk, a, b, v, pa, pb);
-
-}
-
-bool hybrid_penetration_depth(const DT_Convex& a, MT_Scalar a_margin, 
-							  const DT_Convex& b, MT_Scalar b_margin,
-                              MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
-{
-	MT_Scalar margin = a_margin + b_margin;
-	if (margin > MT_Scalar(0.0))
-	{
-		MT_Scalar margin2 = margin * margin;
-
-		DT_GJK gjk;
-
-#ifdef STATISTICS
-		num_iterations = 0;
-#endif
-		MT_Scalar dist2 = MT_INFINITY;
-
-		do
-		{
-			MT_Point3  p = a.support(-v);	
-			MT_Point3  q = b.support(v);
-			
-			MT_Vector3 w = p - q; 
-			
-			MT_Scalar delta = v.dot(w);
-			
-			if (delta > MT_Scalar(0.0) && delta * delta > dist2 * margin2) 
-			{
-				return false;
-			}
-			
-			if (gjk.inSimplex(w) || dist2 - delta <= dist2 * DT_Accuracy::rel_error2)
-			{
-				gjk.compute_points(pa, pb);
-				MT_Scalar s = MT_sqrt(dist2);
-				assert(s > MT_Scalar(0.0));
-				pa -= v * (a_margin / s);
-				pb += v * (b_margin / s);
-				return true;
-			}
-			
-			gjk.addVertex(w, p, q);
-			
-#ifdef STATISTICS
-			++num_iterations;
-#endif
-			if (!gjk.closest(v)) 
-			{
-#ifdef STATISTICS
-				++num_irregularities;
-#endif
-				gjk.compute_points(pa, pb);
-				MT_Scalar s = MT_sqrt(dist2);
-				assert(s > MT_Scalar(0.0));
-				pa -= v * (a_margin / s);
-				pb += v * (b_margin / s);
-				return true;
-			}
-			
-#ifdef SAFE_EXIT
-			MT_Scalar prev_dist2 = dist2;
-#endif
-			
-			dist2 = v.length2();
-			
-#ifdef SAFE_EXIT
-			if (prev_dist2 - dist2 <= MT_EPSILON * prev_dist2) 
-			{ 
-				gjk.backup_closest(v);
-				dist2 = v.length2();
-				gjk.compute_points(pa, pb);
-				MT_Scalar s = MT_sqrt(dist2);
-				assert(s > MT_Scalar(0.0));
-				pa -= v * (a_margin / s);
-				pb += v * (b_margin / s);
-				return true;
-			}
-#endif
-		}
-		while (!gjk.fullSimplex() && dist2 > DT_Accuracy::tol_error * gjk.maxVertex()); 
-		
-	}
-	// Second GJK phase. compute points on the boundary of the offset object
-	
-	return penetration_depth((a_margin > MT_Scalar(0.0) ? 
-							  static_cast(DT_Minkowski(a, DT_Sphere(a_margin))) : 
-							  static_cast(a)), 
-							 (b_margin > MT_Scalar(0.0) ? 
-							  static_cast(DT_Minkowski(b, DT_Sphere(b_margin))) : 
-							  static_cast(b)), v, pa, pb);
-}
-
-
-MT_Scalar closest_points(const DT_Convex& a, const DT_Convex& b, MT_Scalar max_dist2,
-                         MT_Point3& pa, MT_Point3& pb) 
-{
-	MT_Vector3 v(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0));
-	
-    DT_GJK gjk;
-
-#ifdef STATISTICS
-    num_iterations = 0;
-#endif
-
-	MT_Scalar dist2 = MT_INFINITY;
-
-    do
-	{
-		MT_Point3  p = a.support(-v);	
-		MT_Point3  q = b.support(v);
-		MT_Vector3 w = p - q; 
-
-		MT_Scalar delta = v.dot(w);
-		if (delta > MT_Scalar(0.0) && delta * delta > dist2 * max_dist2) 
-		{
-			return MT_INFINITY;
-		}
-
-		if (gjk.inSimplex(w) || dist2 - delta <= dist2 * DT_Accuracy::rel_error2) 
-		{
-            break;
-		}
-
-		gjk.addVertex(w, p, q);
-
-#ifdef STATISTICS
-        ++num_iterations;
-        if (num_iterations > 1000) 
-		{
-			std::cout << "v: " << v << " w: " << w << std::endl;
-		}
-#endif
-        if (!gjk.closest(v)) 
-		{
-#ifdef STATISTICS
-            ++num_irregularities;
-#endif
-            break;
-        }
-
-#ifdef SAFE_EXIT
-		MT_Scalar prev_dist2 = dist2;
-#endif
-
-		dist2 = v.length2();
-
-#ifdef SAFE_EXIT
-		if (prev_dist2 - dist2 <= MT_EPSILON * prev_dist2) 
-		{
-         gjk.backup_closest(v);
-         dist2 = v.length2();
-			break;
-		}
-#endif
-    }
-    while (!gjk.fullSimplex() && dist2 > DT_Accuracy::tol_error * gjk.maxVertex()); 
-
-	assert(!gjk.emptySimplex());
-	
-	if (dist2 <= max_dist2)
-	{
-		gjk.compute_points(pa, pb);
-	}
-	
-	return dist2;
-}
diff --git a/extern/solid/src/convex/DT_Convex.h b/extern/solid/src/convex/DT_Convex.h
deleted file mode 100644
index dd620ac8b98..00000000000
--- a/extern/solid/src/convex/DT_Convex.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_CONVEX_H
-#define DT_CONVEX_H
-
-#include "DT_Shape.h"
-
-#include "MT_Vector3.h"
-#include "MT_Point3.h"
-
-#include "MT_Matrix3x3.h"
-#include "MT_Transform.h"
-
-class DT_Convex : public DT_Shape {
-public:
-    virtual ~DT_Convex() {}
-	virtual DT_ShapeType getType() const { return CONVEX; } 
-    
-	virtual MT_Scalar supportH(const MT_Vector3& v) const {	return v.dot(support(v)); }
-    virtual MT_Point3 support(const MT_Vector3& v) const = 0;
-	virtual MT_BBox bbox() const;
-    virtual MT_BBox bbox(const MT_Matrix3x3& basis) const;
-    virtual MT_BBox bbox(const MT_Transform& t, MT_Scalar margin = MT_Scalar(0.0)) const;
-	virtual bool ray_cast(const MT_Point3& source, const MT_Point3& target, MT_Scalar& param, MT_Vector3& normal) const;
-	
-protected:
-	DT_Convex() {}
-};
-
-
-bool intersect(const DT_Convex& a, const DT_Convex& b, MT_Vector3& v);
-
-bool common_point(const DT_Convex& a, const DT_Convex& b, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb);
-
-MT_Scalar closest_points(const DT_Convex&, const DT_Convex&, MT_Scalar max_dist2, MT_Point3& pa, MT_Point3& pb);
-
-bool penetration_depth(const DT_Convex& a, const DT_Convex& b, MT_Vector3& v, MT_Point3& pa, MT_Point3& pb);
-
-bool hybrid_penetration_depth(const DT_Convex& a, MT_Scalar a_margin, 
-							  const DT_Convex& b, MT_Scalar b_margin,
-                              MT_Vector3& v, MT_Point3& pa, MT_Point3& pb);
-
-#endif
diff --git a/extern/solid/src/convex/DT_Cylinder.cpp b/extern/solid/src/convex/DT_Cylinder.cpp
deleted file mode 100644
index cff5ebcefb1..00000000000
--- a/extern/solid/src/convex/DT_Cylinder.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "DT_Cylinder.h"
-
-MT_Point3 DT_Cylinder::support(const MT_Vector3& v) const 
-{
-    MT_Scalar s = MT_sqrt(v[0] * v[0] + v[2] * v[2]);
-    if (s != MT_Scalar(0.0))
-	{
-        MT_Scalar d = radius / s;  
-        return MT_Point3(v[0] * d, v[1] < 0.0 ? -halfHeight : halfHeight, v[2] * d);
-    }
-    else
-	{
-        return MT_Point3(radius, v[1] < 0.0 ? -halfHeight : halfHeight, MT_Scalar(0.0));
-    }
-}
-  
diff --git a/extern/solid/src/convex/DT_Cylinder.h b/extern/solid/src/convex/DT_Cylinder.h
deleted file mode 100644
index 2a0c07fd579..00000000000
--- a/extern/solid/src/convex/DT_Cylinder.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_CYLINDER_H
-#define DT_CYLINDER_H
-
-#include "DT_Convex.h"
-
-class DT_Cylinder : public DT_Convex {
-public:
-    DT_Cylinder(MT_Scalar r, MT_Scalar h) : 
-        radius(r), 
-        halfHeight(h * MT_Scalar(0.5)) {}
-    
-    virtual MT_Point3 support(const MT_Vector3& v) const;
-    
-protected:
-    MT_Scalar radius;
-    MT_Scalar halfHeight;
-};
-
-#endif
diff --git a/extern/solid/src/convex/DT_Facet.cpp b/extern/solid/src/convex/DT_Facet.cpp
deleted file mode 100644
index 87ae5c3e0be..00000000000
--- a/extern/solid/src/convex/DT_Facet.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "DT_Facet.h"
-
-bool DT_Facet::link(int edge0, DT_Facet *facet, int edge1) 
-{
-    m_adjFacets[edge0] = facet;
-    m_adjEdges[edge0] = edge1;
-    facet->m_adjFacets[edge1] = this;
-    facet->m_adjEdges[edge1] = edge0;
-
-    bool b = m_indices[edge0] == facet->m_indices[incMod3(edge1)] &&
-	m_indices[incMod3(edge0)] == facet->m_indices[edge1];
-    return b;
-}
-
-bool DT_Facet::computeClosest(const MT_Vector3 *verts)
-{
-    const MT_Vector3& p0 = verts[m_indices[0]]; 
-
-    MT_Vector3 v1 = verts[m_indices[1]] - p0;
-    MT_Vector3 v2 = verts[m_indices[2]] - p0;
-    MT_Scalar v1dv1 = v1.length2();
-    MT_Scalar v1dv2 = v1.dot(v2);
-    MT_Scalar v2dv2 = v2.length2();
-    MT_Scalar p0dv1 = p0.dot(v1); 
-    MT_Scalar p0dv2 = p0.dot(v2);
-    
-    m_det = v1dv1 * v2dv2 - v1dv2 * v1dv2; // non-negative
-    m_lambda1 = p0dv2 * v1dv2 - p0dv1 * v2dv2;
-    m_lambda2 = p0dv1 * v1dv2 - p0dv2 * v1dv1; 
-    
-    if (m_det > MT_Scalar(0.0)) {	
-	m_closest = p0 + (m_lambda1 * v1 + m_lambda2 * v2) / m_det;
-	m_dist2 = m_closest.length2();
-	return true;
-    }
-    
-    return false;
-} 
-
-void DT_Facet::silhouette(int index, const MT_Vector3& w, 
-			  DT_EdgeBuffer& edgeBuffer) 
-{
-    if (!m_obsolete) {
-		if (m_closest.dot(w) < m_dist2) {
-			edgeBuffer.push_back(DT_Edge(this, index));
-		}	
-	else {
-	    m_obsolete = true; // Facet is visible 
-	    int next = incMod3(index);
-	    m_adjFacets[next]->silhouette(m_adjEdges[next], w, edgeBuffer);
-	    next = incMod3(next);
-	    m_adjFacets[next]->silhouette(m_adjEdges[next], w, edgeBuffer);
-	}
-    }
-}
-
-
diff --git a/extern/solid/src/convex/DT_Facet.h b/extern/solid/src/convex/DT_Facet.h
deleted file mode 100644
index 873706346b8..00000000000
--- a/extern/solid/src/convex/DT_Facet.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_FACET_H
-#define DT_FACET_H
-
-#include 
-#include 
-
-#include 
-#include 
-
-class DT_Facet;
-
-
-class DT_Edge {
-public:
-    DT_Edge() {}
-    DT_Edge(DT_Facet *facet, int index) : 
-	m_facet(facet), 
-	m_index(index) {}
-
-    DT_Facet *getFacet() const { return m_facet; }
-    int       getIndex() const { return m_index; }
-
-    int getSource() const;
-    int getTarget() const;
-
-private:    
-    DT_Facet *m_facet;
-    int       m_index;
-};
-
-typedef std::vector DT_EdgeBuffer;
-
-
-class DT_Facet {
-public:
-    DT_Facet() {}
-    DT_Facet(int i0, int i1, int i2) 
-	  :	m_obsolete(false) 
-    {
-		m_indices[0] = i0; 
-		m_indices[1] = i1; 
-		m_indices[2] = i2;
-    }
-	
-    int operator[](int i) const { return m_indices[i]; } 
-
-    bool link(int edge0, DT_Facet *facet, int edge1);
-
-    
-    bool isObsolete() const { return m_obsolete; }
-    
-
-    bool computeClosest(const MT_Vector3 *verts);
-    
-    const MT_Vector3& getClosest() const { return m_closest; } 
-    
-    bool isClosestInternal() const
-	{ 
-		return m_lambda1 >= MT_Scalar(0.0) && 
-			m_lambda2 >= MT_Scalar(0.0) && 
-			m_lambda1 + m_lambda2 <= m_det;
-    } 
-
-    MT_Scalar getDist2() const { return m_dist2; }
-	
-    MT_Point3 getClosestPoint(const MT_Point3 *points) const 
-	{
-		const MT_Point3& p0 = points[m_indices[0]];
-		
-		return p0 + (m_lambda1 * (points[m_indices[1]] - p0) + 
-					 m_lambda2 * (points[m_indices[2]] - p0)) / m_det;
-    }
-    
-    void silhouette(const MT_Vector3& w, DT_EdgeBuffer& edgeBuffer) 
-	{
-		edgeBuffer.clear();
-		m_obsolete = true;
-		m_adjFacets[0]->silhouette(m_adjEdges[0], w, edgeBuffer);
-		m_adjFacets[1]->silhouette(m_adjEdges[1], w, edgeBuffer);
-		m_adjFacets[2]->silhouette(m_adjEdges[2], w, edgeBuffer);
-    }
-	
-private:
-    void silhouette(int index, const MT_Vector3& w, DT_EdgeBuffer& edgeBuffer);
-	
-    int         m_indices[3];
-    bool        m_obsolete;
-    DT_Facet   *m_adjFacets[3];
-    int         m_adjEdges[3];
-	
-    MT_Scalar   m_det;
-    MT_Scalar   m_lambda1;
-    MT_Scalar   m_lambda2;
-    MT_Vector3  m_closest;
-    MT_Scalar   m_dist2;
-};
-
-
-inline int incMod3(int i) { return ++i % 3; } 
-
-inline int DT_Edge::getSource() const 
-{
-    return (*m_facet)[m_index];
-}
-
-inline int DT_Edge::getTarget() const 
-{
-    return (*m_facet)[incMod3(m_index)];
-}
-
-#endif
diff --git a/extern/solid/src/convex/DT_GJK.h b/extern/solid/src/convex/DT_GJK.h
deleted file mode 100644
index d8f44acf85e..00000000000
--- a/extern/solid/src/convex/DT_GJK.h
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_GJK_H
-#define DT_GJK_H
-
-//#define USE_BACKUP_PROCEDURE
-#define JOHNSON_ROBUST
-#define FAST_CLOSEST
-
-#include "MT_Point3.h"
-#include "MT_Vector3.h"
-#include "GEN_MinMax.h"
-#include "DT_Accuracy.h"
-
-
-class DT_GJK {
-private:
-	typedef unsigned int T_Bits;
-	inline static bool subseteq(T_Bits a, T_Bits b) { return (a & b) == a; }
-	inline static bool contains(T_Bits a, T_Bits b) { return (a & b) != 0x0; }
-
-public:
-	DT_GJK() :
-		m_bits(0x0),
-		m_all_bits(0x0)
-	{}
-
-	bool emptySimplex() const { return m_bits == 0x0; }
-	bool fullSimplex() const { return m_bits == 0xf; }
-
-	void reset() 
-	{
-		m_bits = 0x0;
-		m_all_bits = 0x0;	
-	}
-
-	bool inSimplex(const MT_Vector3& w) 
-	{
-		int i;
-		T_Bits bit;
-		for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
-		{
-			if (contains(m_all_bits, bit) && w == m_y[i])
-			{
-				return true;
-			}
-		}
-		return false;
-	}
-
-	void addVertex(const MT_Vector3& w) 
-	{
-		assert(!fullSimplex());
-		m_last = 0;
-        m_last_bit = 0x1;
-        while (contains(m_bits, m_last_bit)) 
-		{ 
-			++m_last; 
-			m_last_bit <<= 1; 
-		}
-		m_y[m_last] = w;
-		m_ylen2[m_last] = w.length2();
-        m_all_bits = m_bits | m_last_bit;
-
-		update_cache();
-		compute_det();
-	}
-
-	void addVertex(const MT_Vector3& w, const MT_Point3& p, const MT_Point3& q)
-	{
-		addVertex(w);
-		m_p[m_last] = p;
-		m_q[m_last] = q;
-	}
-
-	int getSimplex(MT_Point3 *pBuf, MT_Point3 *qBuf, MT_Vector3 *yBuf) const 
-	{
-		int num_verts = 0;
-		int i;
-		T_Bits bit;
-		for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1) 
-		{
-			if (contains(m_bits, bit)) 
-			{
-				pBuf[num_verts] = m_p[i];
-				qBuf[num_verts] = m_q[i];
-				yBuf[num_verts] = m_y[i];
-				
-#ifdef DEBUG
-				std::cout << "Point " << i << " = " << m_y[i] << std::endl;
-#endif
-				
-				++num_verts;
-			}
-		}
-		return num_verts;
-    }
-
-	void compute_points(MT_Point3& p1, MT_Point3& p2) 
-	{
-		MT_Scalar sum = MT_Scalar(0.0);
-		p1.setValue(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0));
-		p2.setValue(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0));
-		int i;
-		T_Bits bit;
-		for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1) 
-		{
-			if (contains(m_bits, bit))
-			{
-				sum += m_det[m_bits][i];
-				p1 += m_p[i] * m_det[m_bits][i];
-				p2 += m_q[i] * m_det[m_bits][i];
-			}
-		}
-
-		assert(sum > MT_Scalar(0.0));
-		MT_Scalar s = MT_Scalar(1.0) / sum;
-		p1 *= s;
-		p2 *= s;
-	}
-
-	bool closest(MT_Vector3& v) 
-	{
-#ifdef FAST_CLOSEST
-		T_Bits s;
-		for (s = m_bits; s != 0x0; --s)
-		{
-			if (subseteq(s, m_bits) && valid(s | m_last_bit)) 
-			{
-				m_bits = s | m_last_bit;
-				compute_vector(m_bits, v);
-				return true;
-			}
-		}
-		if (valid(m_last_bit)) 
-		{
-			m_bits = m_last_bit;
-			m_maxlen2 = m_ylen2[m_last];
-			v = m_y[m_last];
-			return true;
-		}
-#else
-		T_Bits s;
-		for (s = m_all_bits; s != 0x0; --s)
-		{
-			if (subseteq(s, m_all_bits) && valid(s)) 
-			{
-				m_bits = s;
-				compute_vector(m_bits, v);
-				return true;
-			}
-		}
-#endif
-		
-		// Original GJK calls the backup procedure at this point.
-#ifdef USE_BACKUP_PROCEDURE
-		backup_closest(MT_Vector3& v); 
-#endif
-		return false;  
-	}
-
-	void backup_closest(MT_Vector3& v)
-	{ 		
-		MT_Scalar min_dist2 = MT_INFINITY;
-		
-      T_Bits s;
-		for (s = m_all_bits; s != 0x0; --s) 
-		{
-			if (subseteq(s, m_all_bits) && proper(s))
-			{	
-				MT_Vector3 u;
-				compute_vector(s, u);
-				MT_Scalar dist2 = u.length2();
-				if (dist2 < min_dist2)
-				{
-					min_dist2 = dist2;
-					m_bits = s;
-					v = u;
-				}
-			}
-		}
-	}
-	
-	MT_Scalar maxVertex() { return m_maxlen2; }
-
-
-private:
-	void update_cache();
-	void compute_det();
-
-	bool valid(T_Bits s) 
-	{
-		int i;
-		T_Bits bit;
-		for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
-		{
-			if (contains(m_all_bits, bit)) 
-			{
-				if (contains(s, bit)) 
-				{
-					if (m_det[s][i] <= MT_Scalar(0.0)) 
-					{
-						return false; 
-					}
-				}
-				else if (m_det[s | bit][i] > MT_Scalar(0.0))
-				{ 
-					return false;
-				}
-			}
-		}
-		return true;
-	}
-
-	bool proper(T_Bits s)
-	{ 
-		int i;
-		T_Bits bit;
-		for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
-		{
-			if (contains(s, bit) && m_det[s][i] <= MT_Scalar(0.0))
-			{
-				return false; 
-			}
-		}
-		return true;
-	}
-
-	void compute_vector(T_Bits s, MT_Vector3& v) 
-	{
-		m_maxlen2 = MT_Scalar(0.0);
-		MT_Scalar sum = MT_Scalar(0.0);
-		v .setValue(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0));
-
-		int i;
-		T_Bits bit;
-		for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1) 
-		{
-			if (contains(s, bit))
-			{
-				sum += m_det[s][i];
-				GEN_set_max(m_maxlen2, m_ylen2[i]);
-				v += m_y[i] * m_det[s][i];
-			}
-		}
-		
-		assert(sum > MT_Scalar(0.0));
-
-		v /= sum;
-	}
- 
-private:
-	MT_Scalar	m_det[16][4]; // cached sub-determinants
-    MT_Vector3	m_edge[4][4];
-
-#ifdef JOHNSON_ROBUST
-    MT_Scalar	m_norm[4][4];
-#endif
-
-	MT_Point3	m_p[4];    // support points of object A in local coordinates 
-	MT_Point3	m_q[4];    // support points of object B in local coordinates 
-	MT_Vector3	m_y[4];   // support points of A - B in world coordinates
-	MT_Scalar	m_ylen2[4];   // Squared lengths support points y
-
-	MT_Scalar	m_maxlen2; // Maximum squared length to a vertex of the current 
-	                      // simplex
-	T_Bits		m_bits;      // identifies current simplex
-	T_Bits		m_last;      // identifies last found support point
-	T_Bits		m_last_bit;  // m_last_bit == 0x1 << last
-	T_Bits		m_all_bits;  // m_all_bits == m_bits  | m_last_bit 
-};
-
-
-
-
-inline void DT_GJK::update_cache() 
-{
-	int i;
-	T_Bits bit;
-    for (i = 0, bit = 0x1; i < 4; ++i, bit <<= 1)
-	{
-        if (contains(m_bits, bit)) 
-		{
-			m_edge[i][m_last] = m_y[i] - m_y[m_last];
-			m_edge[m_last][i] = -m_edge[i][m_last];
-
-#ifdef JOHNSON_ROBUST
-			m_norm[i][m_last] = m_norm[m_last][i] = m_edge[i][m_last].length2();
-#endif
-
-		}
-	}
-}
-
-#ifdef JOHNSON_ROBUST
-
-inline void DT_GJK::compute_det() 
-{
-    m_det[m_last_bit][m_last] = 1;
-
-	int i;
-	T_Bits si;
-    for (i = 0, si = 0x1; i < 4; ++i, si <<= 1) 
-	{
-        if (contains(m_bits, si)) 
-		{
-            T_Bits s2 = si | m_last_bit;
-            m_det[s2][i] = m_edge[m_last][i].dot(m_y[m_last]); 
-            m_det[s2][m_last] = m_edge[i][m_last].dot(m_y[i]);
-
-			int j;
-			T_Bits sj;
-            for (j = 0, sj = 0x1; j < i; ++j, sj <<= 1) 
-			{
-                if (contains(m_bits, sj)) 
-				{
-					int k;
-                    T_Bits s3 = sj | s2;			
-					
-					k = m_norm[i][j] < m_norm[m_last][j] ? i : m_last;
-                    m_det[s3][j] = m_det[s2][i] * m_edge[k][j].dot(m_y[i]) + 
-                                   m_det[s2][m_last] * m_edge[k][j].dot(m_y[m_last]);
-					k = m_norm[j][i] < m_norm[m_last][i] ? j : m_last;
-                    m_det[s3][i] = m_det[sj|m_last_bit][j] * m_edge[k][i].dot(m_y[j]) +  
-                                   m_det[sj|m_last_bit][m_last] * m_edge[k][i].dot(m_y[m_last]);
-					k = m_norm[i][m_last] < m_norm[j][m_last] ? i : j;
-                    m_det[s3][m_last] = m_det[sj|si][j] * m_edge[k][m_last].dot(m_y[j]) + 
-                                        m_det[sj|si][i] * m_edge[k][m_last].dot(m_y[i]);
-                }
-            }
-        }
-    }
-
-    if (m_all_bits == 0xf) 
-	{
-		int k;
-
-		k = m_norm[1][0] < m_norm[2][0] ? (m_norm[1][0] < m_norm[3][0] ? 1 : 3) : (m_norm[2][0] < m_norm[3][0] ? 2 : 3);
-		
-        m_det[0xf][0] = m_det[0xe][1] * m_edge[k][0].dot(m_y[1]) + 
-                        m_det[0xe][2] * m_edge[k][0].dot(m_y[2]) + 
-                        m_det[0xe][3] * m_edge[k][0].dot(m_y[3]);
-
-		k = m_norm[0][1] < m_norm[2][1] ? (m_norm[0][1] < m_norm[3][1] ? 0 : 3) : (m_norm[2][1] < m_norm[3][1] ? 2 : 3);
-		
-        m_det[0xf][1] = m_det[0xd][0] * m_edge[k][1].dot(m_y[0]) + 
-                        m_det[0xd][2] * m_edge[k][1].dot(m_y[2]) +
-                        m_det[0xd][3] * m_edge[k][1].dot(m_y[3]);
-
-		k = m_norm[0][2] < m_norm[1][2] ? (m_norm[0][2] < m_norm[3][2] ? 0 : 3) : (m_norm[1][2] < m_norm[3][2] ? 1 : 3);
-		
-        m_det[0xf][2] = m_det[0xb][0] * m_edge[k][2].dot(m_y[0]) + 
-                        m_det[0xb][1] * m_edge[k][2].dot(m_y[1]) +  
-                        m_det[0xb][3] * m_edge[k][2].dot(m_y[3]);
-
-		k = m_norm[0][3] < m_norm[1][3] ? (m_norm[0][3] < m_norm[2][3] ? 0 : 2) : (m_norm[1][3] < m_norm[2][3] ? 1 : 2);
-		
-        m_det[0xf][3] = m_det[0x7][0] * m_edge[k][3].dot(m_y[0]) + 
-                        m_det[0x7][1] * m_edge[k][3].dot(m_y[1]) + 
-                        m_det[0x7][2] * m_edge[k][3].dot(m_y[2]);
-    }
-}
-
-#else
-
-inline void DT_GJK::compute_det() 
-{
-    m_det[m_last_bit][m_last] = 1;
-
-	int i;
-	T_Bits si;
-    for (i = 0, si = 0x1; i < 4; ++i, si <<= 1) 
-	{
-        if (contains(m_bits, si)) 
-		{
-            T_Bits s2 = si | m_last_bit;
-            m_det[s2][i] = m_edge[m_last][i].dot(m_y[m_last]); 
-            m_det[s2][m_last] = m_edge[i][m_last].dot(m_y[i]);
-
-			int j;
-			T_Bits sj;
-            for (j = 0, sj = 0x1; j < i; ++j, sj <<= 1)
-			{
-                if (contains(m_bits, sj)) 
-				{
-                    T_Bits s3 = sj | s2;
-                    m_det[s3][j] = m_det[s2][i] * m_edge[i][j].dot(m_y[i]) + 
-                                   m_det[s2][m_last] * m_edge[i][j].dot(m_y[m_last]);
-                    m_det[s3][i] = m_det[sj|m_last_bit][j] * m_edge[j][i].dot(m_y[j]) +  
-                                   m_det[sj|m_last_bit][m_last] * m_edge[j][i].dot(m_y[m_last]);
-                    m_det[s3][m_last] = m_det[sj|si][j] * m_edge[j][m_last].dot(m_y[j]) + 
-                                        m_det[sj|si][i] * m_edge[j][m_last].dot(m_y[i]);
-                }
-            }
-        }
-    }
-
-    if (m_all_bits == 0xf) 
-	{
-        m_det[0xf][0] = m_det[0xe][1] * m_edge[1][0].dot(m_y[1]) + 
-                        m_det[0xe][2] * m_edge[1][0].dot(m_y[2]) + 
-                        m_det[0xe][3] * m_edge[1][0].dot(m_y[3]);
-        m_det[0xf][1] = m_det[0xd][0] * m_edge[0][1].dot(m_y[0]) + 
-                        m_det[0xd][2] * m_edge[0][1].dot(m_y[2]) +
-                        m_det[0xd][3] * m_edge[0][1].dot(m_y[3]);
-        m_det[0xf][2] = m_det[0xb][0] * m_edge[0][2].dot(m_y[0]) + 
-                        m_det[0xb][1] * m_edge[0][2].dot(m_y[1]) +  
-                        m_det[0xb][3] * m_edge[0][2].dot(m_y[3]);
-        m_det[0xf][3] = m_det[0x7][0] * m_edge[0][3].dot(m_y[0]) + 
-                        m_det[0x7][1] * m_edge[0][3].dot(m_y[1]) + 
-                        m_det[0x7][2] * m_edge[0][3].dot(m_y[2]);
-    }
-}
-
-#endif
-
-#endif
diff --git a/extern/solid/src/convex/DT_Hull.h b/extern/solid/src/convex/DT_Hull.h
deleted file mode 100644
index a5bf56ae59d..00000000000
--- a/extern/solid/src/convex/DT_Hull.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_HULL_H
-#define DT_HULL_H
-
-#include "DT_Convex.h"
-
-class DT_Hull : public DT_Convex {
-public:
-	DT_Hull(const DT_Convex& lchild, const DT_Convex& rchild) :
-		m_lchild(lchild), 
-		m_rchild(rchild) 
-	{}
-
-	virtual MT_Scalar supportH(const MT_Vector3& v) const 
-	{
-		return GEN_max(m_lchild.supportH(v), m_rchild.supportH(v));
-	}
-
-	virtual MT_Point3 support(const MT_Vector3& v) const 
-	{
-		MT_Point3 lpnt = m_lchild.support(v);
-		MT_Point3 rpnt = m_rchild.support(v);
-		return v.dot(lpnt) > v.dot(rpnt) ? lpnt : rpnt;
-	}
-
-private:
-	const DT_Convex& m_lchild;
-	const DT_Convex& m_rchild;
-};
-
-#endif
diff --git a/extern/solid/src/convex/DT_IndexArray.h b/extern/solid/src/convex/DT_IndexArray.h
deleted file mode 100644
index 95551fa8483..00000000000
--- a/extern/solid/src/convex/DT_IndexArray.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_INDEXARRAY_H
-#define DT_INDEXARRAY_H
-
-#include "SOLID_types.h"
-#include "DT_Array.h"
-
-typedef DT_Array DT_IndexArray;
-
-#endif
-
diff --git a/extern/solid/src/convex/DT_LineSegment.cpp b/extern/solid/src/convex/DT_LineSegment.cpp
deleted file mode 100644
index 6c7ccf6b9b7..00000000000
--- a/extern/solid/src/convex/DT_LineSegment.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "DT_LineSegment.h"
-
-MT_Scalar DT_LineSegment::supportH(const MT_Vector3& v) const
-{
-    return GEN_max(v.dot(m_source), v.dot(m_target));
-}
-
-MT_Point3 DT_LineSegment::support(const MT_Vector3& v) const
-{
-    return v.dot(m_source) > v.dot(m_target) ?	m_source : m_target;
-}
-
-
diff --git a/extern/solid/src/convex/DT_LineSegment.h b/extern/solid/src/convex/DT_LineSegment.h
deleted file mode 100644
index 979ff8a18a9..00000000000
--- a/extern/solid/src/convex/DT_LineSegment.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_LINESEGMENT_H
-#define DT_LINESEGMENT_H
-
-#include "DT_Convex.h"
-
-class DT_LineSegment : public DT_Convex {
-public:
-    DT_LineSegment(const MT_Point3& source, const MT_Point3& target) : 
-	   m_source(source), 
-	   m_target(target) {}
-
-    virtual MT_Scalar supportH(const MT_Vector3& v) const;
-    virtual MT_Point3 support(const MT_Vector3& v) const;
-
-	const MT_Point3& getSource() const { return m_source; }
-	const MT_Point3& getTarget() const { return m_target; }
-
-private:
-	MT_Point3 m_source;
-	MT_Point3 m_target;
-};
-
-#endif
-
-
-
-
-
-
diff --git a/extern/solid/src/convex/DT_Minkowski.h b/extern/solid/src/convex/DT_Minkowski.h
deleted file mode 100644
index e90fed6a8e0..00000000000
--- a/extern/solid/src/convex/DT_Minkowski.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_MINKOWSKI_H
-#define DT_MINKOWSKI_H
-
-#include "DT_Convex.h"
-
-class DT_Minkowski : public DT_Convex {
-public:
-	DT_Minkowski(const DT_Convex& lchild, const DT_Convex& rchild) 
-     : m_lchild(lchild), 
-       m_rchild(rchild) 
-   {}
-
-	virtual MT_Scalar supportH(const MT_Vector3& v) const 
-	{
-		return m_lchild.supportH(v) + m_rchild.supportH(v); 
-	}
-
-	virtual MT_Point3 support(const MT_Vector3& v) const 
-	{
-		return m_lchild.support(v) + (MT_Vector3)m_rchild.support(v); 
-	}
-
-private:
-	const DT_Convex& m_lchild;
-	const DT_Convex& m_rchild;
-};
-
-#endif
diff --git a/extern/solid/src/convex/DT_PenDepth.cpp b/extern/solid/src/convex/DT_PenDepth.cpp
deleted file mode 100644
index e1c5c9a3949..00000000000
--- a/extern/solid/src/convex/DT_PenDepth.cpp
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "DT_PenDepth.h"
-
-#include "MT_Vector3.h"
-#include "MT_Point3.h"
-#include "MT_Quaternion.h"
-#include "DT_Convex.h"
-#include "DT_GJK.h"
-#include "DT_Facet.h"
-
-//#define DEBUG
-
-const int       MaxSupportPoints = 1000;
-const int       MaxFacets         = 2000;
-
-static MT_Point3  pBuf[MaxSupportPoints];
-static MT_Point3  qBuf[MaxSupportPoints];
-static MT_Vector3 yBuf[MaxSupportPoints];
-
-static DT_Facet facetBuf[MaxFacets];
-static int  freeFacet = 0;
-static DT_Facet *facetHeap[MaxFacets];
-static int  num_facets;
-
-class DT_FacetComp {
-public:
-    
-    bool operator()(const DT_Facet *face1, const DT_Facet *face2) 
-	{ 
-		return face1->getDist2() > face2->getDist2();
-    }
-    
-} facetComp;
-
-inline DT_Facet *addFacet(int i0, int i1, int i2,
-						  MT_Scalar lower2, MT_Scalar upper2) 
-{
-    assert(i0 != i1 && i0 != i2 && i1 != i2);
-    if (freeFacet < MaxFacets)
-	{
-		DT_Facet *facet = new(&facetBuf[freeFacet++]) DT_Facet(i0, i1, i2);
-#ifdef DEBUG
-		std::cout << "Facet " << i0 << ' ' << i1 << ' ' << i2;
-#endif
-		if (facet->computeClosest(yBuf)) 
-		{
-			if (facet->isClosestInternal() && 
-				lower2 <= facet->getDist2() && facet->getDist2() <= upper2) 
-			{
-				facetHeap[num_facets++] = facet;
-				std::push_heap(&facetHeap[0], &facetHeap[num_facets], facetComp);
-#ifdef DEBUG
-				std::cout << " accepted" << std::endl;
-#endif
-			}
-			else 
-			{
-#ifdef DEBUG
-				std::cout << " rejected, ";
-				if (!facet->isClosestInternal()) 
-				{
-					std::cout << "closest point not internal";
-				}
-				else if (lower2 > facet->getDist2()) 
-				{
-					std::cout << "facet is closer than orignal facet";
-				}
-				else 
-				{
-					std::cout << "facet is further than upper bound";
-				}
-				std::cout << std::endl;
-#endif
-			}
-			
-			return facet;
-		}
-    }
-    
-    return 0;
-}
-
-inline bool originInTetrahedron(const MT_Vector3& p1, const MT_Vector3& p2, 
-								const MT_Vector3& p3, const MT_Vector3& p4)
-{
-    MT_Vector3 normal1 = (p2 - p1).cross(p3 - p1);
-    MT_Vector3 normal2 = (p3 - p2).cross(p4 - p2);
-    MT_Vector3 normal3 = (p4 - p3).cross(p1 - p3);
-    MT_Vector3 normal4 = (p1 - p4).cross(p2 - p4);
-    
-    return 
-		normal1.dot(p1) > MT_Scalar(0.0) != normal1.dot(p4) > MT_Scalar(0.0) &&
-		normal2.dot(p2) > MT_Scalar(0.0) != normal2.dot(p1) > MT_Scalar(0.0) &&
-		normal3.dot(p3) > MT_Scalar(0.0) != normal3.dot(p2) > MT_Scalar(0.0) &&
-		normal4.dot(p4) > MT_Scalar(0.0) != normal4.dot(p3) > MT_Scalar(0.0);
-}
-
-
-bool penDepth(const DT_GJK& gjk, const DT_Convex& a, const DT_Convex& b,
-			  MT_Vector3& v, MT_Point3& pa, MT_Point3& pb)
-{
-	
-    int num_verts = gjk.getSimplex(pBuf, qBuf, yBuf);
-    
-    switch (num_verts) 
-	{
-	case 1:
-	    // Touching contact. Yes, we have a collision,
-	    // but no penetration.
-	    return false;
-	case 2:	
-	{
-	    // We have a line segment inside the Minkowski sum containing the
-	    // origin. Blow it up by adding three additional support points.
-	    
-	    MT_Vector3 dir  = (yBuf[1] - yBuf[0]).normalized();
-	    int        axis = dir.furthestAxis();
-	    
-	    static MT_Scalar sin_60 = MT_sqrt(MT_Scalar(3.0)) * MT_Scalar(0.5);
-	    
-	    MT_Quaternion rot(dir[0] * sin_60, dir[1] * sin_60, dir[2] * sin_60, MT_Scalar(0.5));
-	    MT_Matrix3x3 rot_mat(rot);
-	    
-	    MT_Vector3 aux1 = dir.cross(MT_Vector3(axis == 0, axis == 1, axis == 2));
-	    MT_Vector3 aux2 = rot_mat * aux1;
-	    MT_Vector3 aux3 = rot_mat * aux2;
-	    
-	    pBuf[2] = a.support(aux1);
-	    qBuf[2] = b.support(-aux1);
-	    yBuf[2] = pBuf[2] - qBuf[2];
-	    
-	    pBuf[3] = a.support(aux2);
-	    qBuf[3] = b.support(-aux2);
-	    yBuf[3] = pBuf[3] - qBuf[3];
-	    
-	    pBuf[4] = a.support(aux3);
-	    qBuf[4] = b.support(-aux3);
-	    yBuf[4] = pBuf[4] - qBuf[4];
-	    
-	    if (originInTetrahedron(yBuf[0], yBuf[2], yBuf[3], yBuf[4])) 
-		{
-			pBuf[1] = pBuf[4];
-			qBuf[1] = qBuf[4];
-			yBuf[1] = yBuf[4];
-	    }
-	    else if (originInTetrahedron(yBuf[1], yBuf[2], yBuf[3], yBuf[4])) 
-		{
-			pBuf[0] = pBuf[4];
-			qBuf[0] = qBuf[4];
-			yBuf[0] = yBuf[4];
-	    } 
-	    else 
-		{
-			// Origin not in initial polytope
-			return false;
-	    }
-	    
-	    num_verts = 4;
-	    
-	    break;
-	}
-	case 3: 
-	{
-	    // We have a triangle inside the Minkowski sum containing
-	    // the origin. First blow it up.
-	    
-	    MT_Vector3 v1     = yBuf[1] - yBuf[0];
-	    MT_Vector3 v2     = yBuf[2] - yBuf[0];
-	    MT_Vector3 vv     = v1.cross(v2);
-	    
-	    pBuf[3] = a.support(vv);
-	    qBuf[3] = b.support(-vv);
-	    yBuf[3] = pBuf[3] - qBuf[3];
-	    pBuf[4] = a.support(-vv);
-	    qBuf[4] = b.support(vv);
-	    yBuf[4] = pBuf[4] - qBuf[4];
-	    
-	   
-	    if (originInTetrahedron(yBuf[0], yBuf[1], yBuf[2], yBuf[4])) 
-		{
-			pBuf[3] = pBuf[4];
-			qBuf[3] = qBuf[4];
-			yBuf[3] = yBuf[4];
-	    }
-	    else if (!originInTetrahedron(yBuf[0], yBuf[1], yBuf[2], yBuf[3]))
-		{ 
-			// Origin not in initial polytope
-			return false;
-	    }
-	    
-	    num_verts = 4;
-	    
-	    break;
-	}
-    }
-    
-    // We have a tetrahedron inside the Minkowski sum containing
-    // the origin (if GJK did it's job right ;-)
-      
-    
-    if (!originInTetrahedron(yBuf[0], yBuf[1], yBuf[2], yBuf[3])) 
-	{
-		//	assert(false);
-		return false;
-	}
-    
-	num_facets = 0;
-    freeFacet = 0;
-
-    DT_Facet *f0 = addFacet(0, 1, 2, MT_Scalar(0.0), MT_INFINITY);
-    DT_Facet *f1 = addFacet(0, 3, 1, MT_Scalar(0.0), MT_INFINITY);
-    DT_Facet *f2 = addFacet(0, 2, 3, MT_Scalar(0.0), MT_INFINITY);
-    DT_Facet *f3 = addFacet(1, 3, 2, MT_Scalar(0.0), MT_INFINITY);
-    
-    if (!f0 || f0->getDist2() == MT_Scalar(0.0) ||
-		!f1 || f1->getDist2() == MT_Scalar(0.0) ||
-		!f2 || f2->getDist2() == MT_Scalar(0.0) ||
-		!f3 || f3->getDist2() == MT_Scalar(0.0)) 
-	{
-		return false;
-    }
-    
-    f0->link(0, f1, 2);
-    f0->link(1, f3, 2);
-    f0->link(2, f2, 0);
-    f1->link(0, f2, 2);
-    f1->link(1, f3, 0);
-    f2->link(1, f3, 1);
-    
-    if (num_facets == 0) 
-	{
-		return false;
-    }
-    
-    // at least one facet on the heap.	
-    
-    DT_EdgeBuffer edgeBuffer(20);
-
-    DT_Facet *facet = 0;
-    
-    MT_Scalar upper_bound2 = MT_INFINITY; 	
-    
-    do {
-        facet = facetHeap[0];
-        std::pop_heap(&facetHeap[0], &facetHeap[num_facets], facetComp);
-        --num_facets;
-		
-		if (!facet->isObsolete()) 
-		{
-			assert(facet->getDist2() > MT_Scalar(0.0));
-			
-			if (num_verts == MaxSupportPoints)
-			{
-#ifdef DEBUG
-				std::cout << "Ouch, no convergence!!!" << std::endl;
-#endif 
-				assert(false);	
-				break;
-			}
-			
-			pBuf[num_verts] = a.support(facet->getClosest());
-			qBuf[num_verts] = b.support(-facet->getClosest());
-			yBuf[num_verts] = pBuf[num_verts] - qBuf[num_verts];
-			
-			int index = num_verts++;
-			MT_Scalar far_dist2 = yBuf[index].dot(facet->getClosest());
-			
-			// Make sure the support mapping is OK.
-			assert(far_dist2 > MT_Scalar(0.0));
-			
-			GEN_set_min(upper_bound2, far_dist2 * far_dist2 / facet->getDist2());
-			
-			if (upper_bound2 <= DT_Accuracy::depth_tolerance * facet->getDist2()
-#define CHECK_NEW_SUPPORT
-#ifdef CHECK_NEW_SUPPORT
-				|| yBuf[index] == yBuf[(*facet)[0]] 
-				|| yBuf[index] == yBuf[(*facet)[1]]
-				|| yBuf[index] == yBuf[(*facet)[2]]
-#endif
-				) 
-			{
-				break;
-			}
-			
-			// Compute the silhouette cast by the new vertex
-			// Note that the new vertex is on the positive side
-			// of the current facet, so the current facet is will
-			// not be in the convex hull. Start local search
-			// from this facet.
-			
-			facet->silhouette(yBuf[index], edgeBuffer);
-			
-			if (edgeBuffer.empty()) 
-			{
-				return false;
-			}
-			
-			DT_EdgeBuffer::const_iterator it = edgeBuffer.begin();
-			DT_Facet *firstFacet = 
-				addFacet((*it).getTarget(), (*it).getSource(),
-						 index, facet->getDist2(), upper_bound2);
-			
-			if (!firstFacet) 
-			{
-				break;
-			}
-			
-			firstFacet->link(0, (*it).getFacet(), (*it).getIndex());
-			DT_Facet *lastFacet = firstFacet;
-			
-			++it;
-			for (; it != edgeBuffer.end(); ++it) 
-			{
-				DT_Facet *newFacet = 
-					addFacet((*it).getTarget(), (*it).getSource(),
-							 index, facet->getDist2(), upper_bound2);
-				
-				if (!newFacet) 
-				{
-					break;
-				}
-				
-				if (!newFacet->link(0, (*it).getFacet(), (*it).getIndex())) 
-				{
-					break;
-				}
-				
-				if (!newFacet->link(2, lastFacet, 1)) 
-				{
-					break;
-				}
-				
-				lastFacet = newFacet;				
-			}
-			if (it != edgeBuffer.end()) 
-			{
-				break;
-			}
-			
-			firstFacet->link(2, lastFacet, 1);
-		}
-    }
-    while (num_facets > 0 && facetHeap[0]->getDist2() <= upper_bound2);
-	
-#ifdef DEBUG    
-    std::cout << "#facets left = " << num_facets << std::endl;
-#endif
-    
-    v = facet->getClosest();
-    pa = facet->getClosestPoint(pBuf);    
-    pb = facet->getClosestPoint(qBuf);    
-    return true;
-}
-
diff --git a/extern/solid/src/convex/DT_PenDepth.h b/extern/solid/src/convex/DT_PenDepth.h
deleted file mode 100644
index 97b3c6c0e0e..00000000000
--- a/extern/solid/src/convex/DT_PenDepth.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_PENDEPTH_H
-#define DT_PENDEPTH_H
-
-#include "MT_Vector3.h"
-#include "MT_Point3.h"
-
-class DT_GJK;
-class DT_Convex;
-
-bool penDepth(const DT_GJK& gjk, const DT_Convex& a, const DT_Convex& b, 
-			  MT_Vector3& v, MT_Point3& pa, MT_Point3& pb);
-
-#endif
diff --git a/extern/solid/src/convex/DT_Point.cpp b/extern/solid/src/convex/DT_Point.cpp
deleted file mode 100644
index 770fe7775b7..00000000000
--- a/extern/solid/src/convex/DT_Point.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "DT_Point.h"
-
-MT_Scalar DT_Point::supportH(const MT_Vector3& v) const
-{
-    return v.dot(m_point);
-}
-
-MT_Point3 DT_Point::support(const MT_Vector3& v) const
-{
-    return m_point;
-}
-
-
diff --git a/extern/solid/src/convex/DT_Point.h b/extern/solid/src/convex/DT_Point.h
deleted file mode 100644
index b35d158ee53..00000000000
--- a/extern/solid/src/convex/DT_Point.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_POINT_H
-#define DT_POINT_H
-
-#include "DT_Convex.h"
-
-class DT_Point : public DT_Convex {
-public:
-    DT_Point(const MT_Point3& point) : m_point(point) {}
-
-    virtual MT_Scalar supportH(const MT_Vector3& v) const;
-    virtual MT_Point3 support(const MT_Vector3& v) const;
-
-private:
-	MT_Point3 m_point;
-};
-
-#endif
-
-
-
-
-
-
diff --git a/extern/solid/src/convex/DT_Polyhedron.cpp b/extern/solid/src/convex/DT_Polyhedron.cpp
deleted file mode 100644
index f48ac6e4b6d..00000000000
--- a/extern/solid/src/convex/DT_Polyhedron.cpp
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "DT_Polyhedron.h"
-
-#ifdef QHULL
-
-extern "C" {
-#include 
-}
-
-#include 
-#include   
-
-typedef std::vector T_VertexBuf;
-typedef std::vector T_IndexBuf;
-typedef std::vector T_MultiIndexBuf;
-
-static char options[] = "qhull Qts i Tv";
-
-#define DK_HIERARCHY
-
-T_IndexBuf *adjacency_graph(DT_Count count, const MT_Point3 *verts, const char *flags)
-{
-	int curlong, totlong, exitcode;
-	
-    facetT *facet;
-    vertexT *vertex;
-    vertexT **vertexp;
-    
-    std::vector > array;
-	T_IndexBuf index;
-    DT_Index i;
-    for (i = 0; i != count; ++i) 
-	{
-		if (flags == 0 || flags[i])
-		{
-            array.push_back(MT::Tuple3(verts[i]));
-			index.push_back(i);
-		}
-    }
-
-    qh_init_A(stdin, stdout, stderr, 0, NULL);
-    if ((exitcode = setjmp(qh errexit))) 
-	{
-		exit(exitcode);
-	}
-    qh_initflags(options);
-    qh_init_B(array[0], array.size(), 3, False);
-    qh_qhull();
-    qh_check_output();
-    
-    T_IndexBuf *indexBuf = new T_IndexBuf[count];
-    FORALLfacets 
-	{
-		setT *vertices = qh_facet3vertex(facet);
-		
-		T_IndexBuf  facetIndices;
-
-		FOREACHvertex_(vertices) 
-		{
-			facetIndices.push_back(index[qh_pointid(vertex->point)]);
-		}
-		int i, j;
-		for (i = 0, j = facetIndices.size()-1; i < (int)facetIndices.size(); j = i++)
-		{
-			indexBuf[facetIndices[j]].push_back(facetIndices[i]);
-		}
-    }
-
-    
-    qh NOerrexit = True;
-    qh_freeqhull(!qh_ALL);
-    qh_memfreeshort(&curlong, &totlong);
-
-	return indexBuf;
-}
-
-T_IndexBuf *simplex_adjacency_graph(DT_Count count, const char *flags)
-{
-	T_IndexBuf *indexBuf = new T_IndexBuf[count];
-
-	DT_Index index[4];
-	
-	DT_Index k = 0;
-	DT_Index i;
-	for (i = 0; i != count; ++i) 
-	{
-		if (flags == 0 || flags[i])
-		{
-			index[k++] = i;
-		}
-	}
-
-	assert(k <= 4);
-
-	for (i = 0; i != k; ++i)
-	{
-		DT_Index j;
-		for (j = 0; j != k; ++j)
-		{
-			if (i != j)
-			{
-				indexBuf[index[i]].push_back(index[j]);
-			}
-		}
-	}
-
-	return indexBuf;
-}
-
-#ifdef DK_HIERARCHY
-
-void prune(DT_Count count, T_MultiIndexBuf *cobound)
-{
-	DT_Index i;
-	for (i = 0; i != count; ++i)
-	{
-		assert(cobound[i].size());
-
-		DT_Index j;
-		for (j = 0; j != cobound[i].size() - 1; ++j)
-		{
-			T_IndexBuf::iterator it = cobound[i][j].begin();
-			while (it != cobound[i][j].end())
-			{
-				T_IndexBuf::iterator jt = 
-					std::find(cobound[i][j+1].begin(), cobound[i][j+1].end(), *it);
-
-				if (jt != cobound[i][j+1].end())
-				{
-					std::swap(*it, cobound[i][j].back());
-					cobound[i][j].pop_back();
-				}
-				else
-				{
-					++it;
-				}
-			}
-		}
-	}	
-}
-
-#endif
-
-DT_Polyhedron::DT_Polyhedron(const DT_VertexBase *base, DT_Count count, const DT_Index *indices)
-{
-	assert(count);
-
-	std::vector vertexBuf;
-	DT_Index i;
-	for (i = 0; i != count; ++i) 
-	{
-		vertexBuf.push_back((*base)[indices[i]]);
-	}
-
-	T_IndexBuf *indexBuf = count > 4 ? adjacency_graph(count, &vertexBuf[0], 0) : simplex_adjacency_graph(count, 0);
-	
-	std::vector pointBuf;
-	
-	for (i = 0; i != count; ++i) 
-	{
-		if (!indexBuf[i].empty()) 
-		{
-			pointBuf.push_back(vertexBuf[i]);
-		}
-	}
-			
-	delete [] indexBuf;
-
-	m_count = pointBuf.size();
-	m_verts = new MT_Point3[m_count];	
-	std::copy(pointBuf.begin(), pointBuf.end(), &m_verts[0]);
-
-	T_MultiIndexBuf *cobound = new T_MultiIndexBuf[m_count];
-    char *flags = new char[m_count];
-	std::fill(&flags[0], &flags[m_count], 1);
-
-	DT_Count num_layers = 0;
-	DT_Count layer_count = m_count;
-	while (layer_count > 4)
-	{
-		T_IndexBuf *indexBuf = adjacency_graph(m_count, m_verts, flags);
-		
-		DT_Index i;
-		for (i = 0; i != m_count; ++i) 
-		{
-			if (flags[i])
-			{
-				assert(!indexBuf[i].empty());
-				cobound[i].push_back(indexBuf[i]);
-			}
-		}
-			
-		++num_layers;
-
-		delete [] indexBuf;
-
-		std::fill(&flags[0], &flags[m_count], 0);
-
-		for (i = 0; i != m_count; ++i)
-		{
-			if (cobound[i].size() == num_layers) 
-			{
-				T_IndexBuf& curr_cobound = cobound[i].back();	
-				if (!flags[i] && curr_cobound.size() <= 8)
-				{	
-					DT_Index j;
-					for (j  = 0; j != curr_cobound.size(); ++j)
-					{
-						flags[curr_cobound[j]] = 1;
-					}
-				}
-			}
-		}
-		
-		layer_count = 0;
-		
-		for (i = 0; i != m_count; ++i)
-		{
-			if (flags[i])
-			{
-				++layer_count;
-			}
-		}	
-	}
-	
-	indexBuf = simplex_adjacency_graph(m_count, flags);
-		
-	for (i = 0; i != m_count; ++i) 
-	{
-		if (flags[i])
-		{
-			assert(!indexBuf[i].empty());
-			cobound[i].push_back(indexBuf[i]);
-		}
-	}
-	
-	++num_layers;
-
-	delete [] indexBuf;
-	delete [] flags;
-		
-
-
-#ifdef DK_HIERARCHY
-	prune(m_count, cobound);
-#endif
-
-	m_cobound = new T_MultiIndexArray[m_count];
-
-	for (i = 0; i != m_count; ++i)
-	{
-		new (&m_cobound[i]) T_MultiIndexArray(cobound[i].size());
-		
-		DT_Index j;
-		for (j = 0; j != cobound[i].size(); ++j)
-		{
-			new (&m_cobound[i][j]) DT_IndexArray(cobound[i][j].size(), &cobound[i][j][0]);
-		}
-	}
-		
-	delete [] cobound;
-
-	m_start_vertex = 0;
-	while (m_cobound[m_start_vertex].size() != num_layers) 
-	{
-		++m_start_vertex;
-		assert(m_start_vertex < m_count);
-	}
-
-	m_curr_vertex = m_start_vertex;
-} 
-
-
-DT_Polyhedron::~DT_Polyhedron() 
-{
-	delete [] m_verts;
-    delete [] m_cobound;
-}
-
-#ifdef DK_HIERARCHY
-
-MT_Scalar DT_Polyhedron::supportH(const MT_Vector3& v) const 
-{
-    m_curr_vertex = m_start_vertex;
-    MT_Scalar d = (*this)[m_curr_vertex].dot(v);
-    MT_Scalar h = d;
-	int curr_layer;
-	for (curr_layer = m_cobound[m_start_vertex].size(); curr_layer != 0; --curr_layer)
-	{
-		const DT_IndexArray& curr_cobound = m_cobound[m_curr_vertex][curr_layer-1];
-        DT_Index i;
-		for (i = 0; i != curr_cobound.size(); ++i) 
-		{
-			d = (*this)[curr_cobound[i]].dot(v);
-			if (d > h)
-			{
-				m_curr_vertex = curr_cobound[i];
-				h = d;
-			}
-		}
-	}
-	
-    return h;
-}
-
-MT_Point3 DT_Polyhedron::support(const MT_Vector3& v) const 
-{
-	m_curr_vertex = m_start_vertex;
-    MT_Scalar d = (*this)[m_curr_vertex].dot(v);
-    MT_Scalar h = d;
-	int curr_layer;
-	for (curr_layer = m_cobound[m_start_vertex].size(); curr_layer != 0; --curr_layer)
-	{
-		const DT_IndexArray& curr_cobound = m_cobound[m_curr_vertex][curr_layer-1];
-        DT_Index i;
-		for (i = 0; i != curr_cobound.size(); ++i) 
-		{
-			d = (*this)[curr_cobound[i]].dot(v);
-			if (d > h)
-			{
-				m_curr_vertex = curr_cobound[i];
-				h = d;
-			}
-		}
-	}
-	
-    return (*this)[m_curr_vertex];
-}
-
-#else
-
-MT_Scalar DT_Polyhedron::supportH(const MT_Vector3& v) const 
-{
-    int last_vertex = -1;
-    MT_Scalar d = (*this)[m_curr_vertex].dot(v);
-    MT_Scalar h = d;
-	
-	for (;;) 
-	{
-        DT_IndexArray& curr_cobound = m_cobound[m_curr_vertex][0];
-        int i = 0, n = curr_cobound.size(); 
-        while (i != n && 
-               (curr_cobound[i] == last_vertex || 
-				(d = (*this)[curr_cobound[i]].dot(v)) - h <= MT_abs(h) * MT_EPSILON)) 
-		{
-            ++i;
-		}
-		
-        if (i == n) 
-		{
-			break;
-		}
-		
-        last_vertex = m_curr_vertex;
-        m_curr_vertex = curr_cobound[i];
-        h = d;
-    }
-    return h;
-}
-
-MT_Point3 DT_Polyhedron::support(const MT_Vector3& v) const 
-{
-	int last_vertex = -1;
-    MT_Scalar d = (*this)[m_curr_vertex].dot(v);
-    MT_Scalar h = d;
-	
-    for (;;)
-	{
-        DT_IndexArray& curr_cobound = m_cobound[m_curr_vertex][0];
-        int i = 0, n = curr_cobound.size();
-        while (i != n && 
-               (curr_cobound[i] == last_vertex || 
-				(d = (*this)[curr_cobound[i]].dot(v)) - h <= MT_abs(h) * MT_EPSILON)) 
-		{
-            ++i;
-		}
-		
-        if (i == n)
-		{
-			break;
-		}
-		
-		last_vertex = m_curr_vertex;
-        m_curr_vertex = curr_cobound[i];
-        h = d;
-    }
-    return (*this)[m_curr_vertex];
-}
-
-#endif
-
-#endif
-
diff --git a/extern/solid/src/convex/DT_Polyhedron.h b/extern/solid/src/convex/DT_Polyhedron.h
deleted file mode 100644
index 58c991bd152..00000000000
--- a/extern/solid/src/convex/DT_Polyhedron.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_POLYHEDRON_H
-#define DT_POLYHEDRON_H
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-# if HAVE_QHULL_QHULL_A_H
-#  define QHULL
-# endif
-#endif
-
-
-#ifdef QHULL
-
-#include "DT_Convex.h"
-#include "DT_IndexArray.h"
-#include "DT_VertexBase.h"
-
-class DT_Polyhedron : public DT_Convex {
-	typedef DT_Array T_MultiIndexArray;
-public:
-	DT_Polyhedron() 
-		: m_verts(0),
-		  m_cobound(0)
-	{}
-		
-	DT_Polyhedron(const DT_VertexBase *base, DT_Count count, const DT_Index *indices);
-
-	virtual ~DT_Polyhedron();
-    
-    virtual MT_Scalar supportH(const MT_Vector3& v) const;
-    virtual MT_Point3 support(const MT_Vector3& v) const;
-
-	const MT_Point3& operator[](int i) const { return m_verts[i]; }
-    DT_Count numVerts() const { return m_count; }
-
-private:
-	DT_Count              m_count;
-	MT_Point3			 *m_verts;
-	T_MultiIndexArray    *m_cobound;
-    DT_Index              m_start_vertex;
-	mutable DT_Index      m_curr_vertex;
-};
-
-#else 
-
-#include "DT_Polytope.h"
-
-typedef DT_Polytope DT_Polyhedron;
-
-#endif
-
-#endif
-
diff --git a/extern/solid/src/convex/DT_Polytope.cpp b/extern/solid/src/convex/DT_Polytope.cpp
deleted file mode 100644
index e757c3bfdb4..00000000000
--- a/extern/solid/src/convex/DT_Polytope.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "DT_Polytope.h"
-
-MT_BBox DT_Polytope::bbox() const 
-{
-	MT_BBox bbox = (*this)[0];
-	DT_Index i;
-    for (i = 1; i < numVerts(); ++i) 
-	{
-        bbox = bbox.hull((*this)[i]);
-    }
-    return bbox;
-}
-
-MT_Scalar DT_Polytope::supportH(const MT_Vector3& v) const 
-{
-    int c = 0;
-    MT_Scalar h = (*this)[0].dot(v), d;
-	DT_Index i;
-    for (i = 1; i < numVerts(); ++i) 
-	{
-        if ((d = (*this)[i].dot(v)) > h) 
-		{ 
-			c = i; 
-			h = d; 
-		}
-    }
-    return h;
-}
-
-MT_Point3 DT_Polytope::support(const MT_Vector3& v) const 
-{
-    int c = 0;
-    MT_Scalar h = (*this)[0].dot(v), d;
-	DT_Index i;
-    for (i = 1; i < numVerts(); ++i)
-	{
-        if ((d = (*this)[i].dot(v)) > h)
-		{ 
-			c = i;
-			h = d; 
-		}
-    }
-    return (*this)[c];
-}
-
-
diff --git a/extern/solid/src/convex/DT_Polytope.h b/extern/solid/src/convex/DT_Polytope.h
deleted file mode 100644
index c715598defe..00000000000
--- a/extern/solid/src/convex/DT_Polytope.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_POLYTOPE_H
-#define DT_POLYTOPE_H
-
-#include "DT_Convex.h"
-#include "DT_IndexArray.h"
-#include "DT_VertexBase.h"
-
-class DT_Polytope : public DT_Convex {
-public:	
-	DT_Polytope() {}
-    DT_Polytope(const DT_VertexBase *base, DT_Count count, const DT_Index *indices) 
-	  : m_base(base), 
-		m_index(count, indices) 
-	{}
- 
-	virtual MT_BBox bbox() const;
-    virtual MT_Scalar supportH(const MT_Vector3& v) const;
-    virtual MT_Point3 support(const MT_Vector3& v) const;
-
-	MT_Point3 operator[](int i) const { return (*m_base)[m_index[i]]; }
-    DT_Count numVerts() const { return m_index.size(); }
-
-protected:
-    const DT_VertexBase *m_base;
-    DT_IndexArray        m_index;
-};
-
-#endif
diff --git a/extern/solid/src/convex/DT_Shape.h b/extern/solid/src/convex/DT_Shape.h
deleted file mode 100644
index d48942fe515..00000000000
--- a/extern/solid/src/convex/DT_Shape.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_SHAPE_H
-#define DT_SHAPE_H
-
-#include 
-
-#include "MT_BBox.h"
-
-#include "MT_Transform.h"
-
-class DT_Object;
-
-enum DT_ShapeType {
-    COMPLEX,
-    CONVEX
-};
-
-class DT_Shape {
-public:
-    virtual ~DT_Shape() {}
-    virtual DT_ShapeType getType() const = 0;
-	virtual MT_BBox bbox(const MT_Transform& t, MT_Scalar margin) const = 0;
-	virtual bool ray_cast(const MT_Point3& source, const MT_Point3& target, MT_Scalar& param, MT_Vector3& normal) const = 0;
-
-protected:
-	DT_Shape()  {}
-};
-
-typedef bool (*Intersect)(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
-						  const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
-						  MT_Vector3&);
-
-typedef bool (*Common_point)(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
-						     const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
-			                 MT_Vector3&, MT_Point3&, MT_Point3&);
-
-typedef bool (*Penetration_depth)(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
-						          const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
-                                  MT_Vector3&, MT_Point3&, MT_Point3&);
-
-typedef MT_Scalar (*Closest_points)(const DT_Shape& a, const MT_Transform& a2w, MT_Scalar a_margin,
-						            const DT_Shape& b, const MT_Transform& b2w, MT_Scalar b_margin,
-									MT_Point3&, MT_Point3&);
-
-#endif
-
-
-
-
-
diff --git a/extern/solid/src/convex/DT_Sphere.cpp b/extern/solid/src/convex/DT_Sphere.cpp
deleted file mode 100644
index 3f2443dcf53..00000000000
--- a/extern/solid/src/convex/DT_Sphere.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#include "DT_Sphere.h"
-#include "GEN_MinMax.h"
-
-MT_Scalar DT_Sphere::supportH(const MT_Vector3& v) const 
-{
-	return m_radius * v.length();
-}
-
-MT_Point3 DT_Sphere::support(const MT_Vector3& v) const 
-{
-   MT_Scalar s = v.length();
-	
-	if (s > MT_Scalar(0.0))
-	{
-		s = m_radius / s;
-		return MT_Point3(v[0] * s, v[1] * s, v[2] * s);
-	}
-	else
-	{
-		return MT_Point3(m_radius, MT_Scalar(0.0), MT_Scalar(0.0));
-	}
-}
-
-bool DT_Sphere::ray_cast(const MT_Point3& source, const MT_Point3& target,
-						 MT_Scalar& param, MT_Vector3& normal) const 
-{
-	MT_Vector3 r = target - source;
-	MT_Scalar  delta = -source.dot(r);  
-	MT_Scalar  r_length2 = r.length2();
-	MT_Scalar  sigma = delta * delta - r_length2 * (source.length2() - m_radius * m_radius);
-
-	if (sigma >= MT_Scalar(0.0))
-		// The line trough source and target intersects the sphere.
-	{
-		MT_Scalar sqrt_sigma = MT_sqrt(sigma);
-		// We need only the sign of lambda2, so the division by the positive 
-		// r_length2 can be left out.
-		MT_Scalar lambda2 = (delta + sqrt_sigma) /* / r_length2 */ ;
-		if (lambda2 >= MT_Scalar(0.0))
-			// The ray points at the sphere
-		{
-			MT_Scalar lambda1 = (delta - sqrt_sigma) / r_length2;
-			if (lambda1 <= param)
-				// The ray hits the sphere, since 
-				// [lambda1, lambda2] overlaps [0, param]. 
-			{
-				if (lambda1 > MT_Scalar(0.0))
-				{
-					param = lambda1;
-					normal = (source + r * lambda1) / m_radius;
-					// NB: division by m_radius to normalize the normal.
-				}
-				else
-				{
-					param = MT_Scalar(0.0);
-					normal.setValue(MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0));
-				}
-						
-				return true;
-			}
-		}
-	}
-
-	return false;
-}
-
-
diff --git a/extern/solid/src/convex/DT_Sphere.h b/extern/solid/src/convex/DT_Sphere.h
deleted file mode 100644
index 92386a66f3a..00000000000
--- a/extern/solid/src/convex/DT_Sphere.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_SPHERE_H
-#define DT_SPHERE_H
-
-#include "DT_Convex.h"
-
-class DT_Sphere : public DT_Convex {
-public:
-   DT_Sphere(MT_Scalar radius) : m_radius(radius) {}
-	
-    virtual MT_Scalar supportH(const MT_Vector3& v) const;
-	virtual MT_Point3 support(const MT_Vector3& v) const;
-	
-	virtual bool ray_cast(const MT_Point3& source, const MT_Point3& target,
-						  MT_Scalar& param, MT_Vector3& normal) const;
-
-protected:
-    MT_Scalar m_radius;
-};
-
-#endif
diff --git a/extern/solid/src/convex/DT_Transform.h b/extern/solid/src/convex/DT_Transform.h
deleted file mode 100644
index a976d48d22b..00000000000
--- a/extern/solid/src/convex/DT_Transform.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_TRANSFORM_H
-#define DT_TRANSFORM_H
-
-#include "DT_Convex.h"
-
-class DT_Transform : public DT_Convex {
-public:
-	DT_Transform(const MT_Transform& xform, const DT_Convex& child) :
-		m_xform(xform), 
-		m_child(child)
-	{}
-
-	virtual MT_Scalar supportH(const MT_Vector3& v) const
-	{
-		return m_child.supportH(v * m_xform.getBasis()) + 
-			   v.dot(m_xform.getOrigin());
-	}
-
-	virtual MT_Point3 support(const MT_Vector3& v) const
-	{
-		return m_xform(m_child.support(v * m_xform.getBasis()));
-	}
-
-private:
-	const MT_Transform& m_xform;
-	const DT_Convex&    m_child;
-};
-
-
-#endif
diff --git a/extern/solid/src/convex/DT_Triangle.cpp b/extern/solid/src/convex/DT_Triangle.cpp
deleted file mode 100644
index 1917910b39d..00000000000
--- a/extern/solid/src/convex/DT_Triangle.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-//#define BACKFACE_CULLING
-
-#include "DT_Triangle.h"
-
-MT_BBox DT_Triangle::bbox() const 
-{
-	return MT_BBox((*this)[0]).hull((*this)[1]).hull((*this)[2]);
-}
-
-MT_Scalar DT_Triangle::supportH(const MT_Vector3& v) const
-{
-    return GEN_max(GEN_max(v.dot((*this)[0]), v.dot((*this)[1])), v.dot((*this)[2]));
-}
-
-MT_Point3 DT_Triangle::support(const MT_Vector3& v) const
-{
-    MT_Vector3 dots(v.dot((*this)[0]), v.dot((*this)[1]), v.dot((*this)[2]));
-
-	return (*this)[dots.maxAxis()];
-}
-
-bool DT_Triangle::ray_cast(const MT_Point3& source, const MT_Point3& target, 
-						   MT_Scalar& param, MT_Vector3& normal) const 
-{
-	MT_Vector3 d1 = (*this)[1] - (*this)[0];
-	MT_Vector3 d2 = (*this)[2] - (*this)[0];
-	MT_Vector3 n = d1.cross(d2);
-	MT_Vector3 r = target - source;
-	MT_Scalar delta = -r.dot(n);
-
-   MT_Scalar rounding_error = GEN_max(GEN_max(MT_abs(n[0]), MT_abs(n[1])), MT_abs(n[2])) * MT_EPSILON; 
-
-#ifdef BACKFACE_CULLING	
-   if (delta > rounding_error)
-#else
-	if (MT_abs(delta) > rounding_error)
-#endif      
-		// The ray is not parallel to the triangle's plane. 
-		// (Coplanar rays are ignored.)
-	{
-		MT_Vector3 b = source - (*this)[0];
-		MT_Scalar lambda = b.dot(n) / delta;
-
-		if (MT_Scalar(0.0) <= lambda && lambda <= param)
-			// The ray intersects the triangle's plane.
-		{
-			MT_Vector3 u = b.cross(r);
-			MT_Scalar mu1 = d2.dot(u) / delta;
-
-			if (MT_Scalar(0.0) <= mu1 && mu1 <= MT_Scalar(1.0)) 
-			{
-				MT_Scalar mu2 = -d1.dot(u) / delta;
-
-				if (MT_Scalar(0.0) <= mu2 && mu1 + mu2 <= MT_Scalar(1.0)) 
-					// The ray intersects the triangle.
-				{
-					param = lambda;
-					// Return a normal that points at the source.
-#ifdef BACKFACE_CULLING
-               normal = n;
-#else
-					normal = delta > MT_Scalar(0.0) ? n : -n;
-#endif
-					return true;
-				}
-			}
-		}
-	}
-
-	return false;
-}
-
-
diff --git a/extern/solid/src/convex/DT_Triangle.h b/extern/solid/src/convex/DT_Triangle.h
deleted file mode 100644
index 4192b5629ac..00000000000
--- a/extern/solid/src/convex/DT_Triangle.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_TRIANGLE_H
-#define DT_TRIANGLE_H
-
-#include "SOLID_types.h"
-
-#include "DT_Convex.h"
-#include "DT_IndexArray.h"
-#include "DT_VertexBase.h"
-
-class DT_Triangle : public DT_Convex {
-public:
-    DT_Triangle(const DT_VertexBase *base, DT_Index i0, DT_Index i1, DT_Index i2) : 
-        m_base(base)
-	{
-		m_index[0] = i0;
-		m_index[1] = i1;
-		m_index[2] = i2;
-	}
-
-    DT_Triangle(const DT_VertexBase *base, const DT_Index *index) : 
-        m_base(base)
-	{
-		m_index[0] = index[0];
-		m_index[1] = index[1];
-		m_index[2] = index[2];
-	}
-
-	virtual MT_BBox bbox() const;
-    virtual MT_Scalar supportH(const MT_Vector3& v) const;
-    virtual MT_Point3 support(const MT_Vector3& v) const;
-	virtual bool ray_cast(const MT_Point3& source, const MT_Point3& target, MT_Scalar& lambda, MT_Vector3& normal) const;
-
-    MT_Point3 operator[](int i) const { return (*m_base)[m_index[i]]; }
-
-private:
-    const DT_VertexBase *m_base;
-    DT_Index             m_index[3];
-};
-
-#endif
diff --git a/extern/solid/src/convex/DT_VertexBase.h b/extern/solid/src/convex/DT_VertexBase.h
deleted file mode 100644
index 37646fdd935..00000000000
--- a/extern/solid/src/convex/DT_VertexBase.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * SOLID - Software Library for Interference Detection
- * 
- * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
- *
- * This library may be distributed under the terms of the Q Public License
- * (QPL) as defined by Trolltech AS of Norway and appearing in the file
- * LICENSE.QPL included in the packaging of this file.
- *
- * This library may be distributed and/or modified under the terms of the
- * GNU General Public License (GPL) version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Commercial use or any other use of this library not covered by either 
- * the QPL or the GPL requires an additional license from Dtecta. 
- * Please contact info@dtecta.com for enquiries about the terms of commercial
- * use of this library.
- */
-
-#ifndef DT_VERTEXBASE_H
-#define DT_VERTEXBASE_H
-
-#include "MT_Point3.h"
-
-#include 
-
-class DT_Complex;
-
-typedef std::vectorDT_ComplexList;
-
-class DT_VertexBase {
-public:
-    explicit DT_VertexBase(const void *base = 0, DT_Size stride = 0, bool owner = false) : 
-        m_base((char *)base),
-		m_stride(stride ? stride : 3 * sizeof(DT_Scalar)),
-		m_owner(owner)
-	{}
-	
-	~DT_VertexBase()
-	{
-		if (m_owner)
-		{
-			delete [] m_base;
-		}
-	}
-    
-    MT_Point3 operator[](DT_Index i) const 
-	{ 
-        return MT_Point3(reinterpret_cast(m_base + i * m_stride));
-    }
-    
-    void setPointer(const void *base, bool owner = false)
-	{
-		m_base = (char *)base; 
-		m_owner = owner;
-	} 
-	
-    const void *getPointer() const { return m_base; }	
-	bool        isOwner() const { return m_owner; }
-    
-	void addComplex(DT_Complex *complex) const { m_complexList.push_back(complex); }
-	void removeComplex(DT_Complex *complex) const
-	{
-		DT_ComplexList::iterator it = std::find(m_complexList.begin(), m_complexList.end(), complex); 
-		if (it != m_complexList.end())
-		{
-			m_complexList.erase(it);
-		}
-	}
-	
-	const DT_ComplexList& getComplexList() const { return m_complexList; }
-	
-private:    
-    char                  *m_base;
-    DT_Size                m_stride;
-	bool                   m_owner;
-	mutable DT_ComplexList m_complexList;
-};
-
-#endif
diff --git a/extern/solid/src/convex/Makefile b/extern/solid/src/convex/Makefile
deleted file mode 100644
index 75fa578a292..00000000000
--- a/extern/solid/src/convex/Makefile
+++ /dev/null
@@ -1,41 +0,0 @@
-#
-# $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.
-#
-# The Original Code is: all of this file.
-#
-# Contributor(s): none yet.
-#
-# ***** END GPL LICENSE BLOCK *****
-#
-#
-
-LIBNAME = solid_convex
-DIR = $(OCGDIR)/extern/$(LIBNAME)
-
-CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
-
-CPPFLAGS += -I../../include -I$(NAN_QHULL)/include
-CPPFLAGS += -DQHULL -DUSE_DOUBLES
-
-include nan_compile.mk 
-
-
diff --git a/intern/bsp/test/Makefile b/intern/bsp/test/Makefile
index eebf7470a0f..91e4497b267 100644
--- a/intern/bsp/test/Makefile
+++ b/intern/bsp/test/Makefile
@@ -47,7 +47,7 @@ SLIBS += $(NAN_MOTO)/lib/$(DEBUG_DIR)libmoto.a
 SLIBS += $(NAN_GHOST)/lib/$(DEBUG_DIR)libghost.a
 SLIBS += $(NAN_STRING)/lib/$(DEBUG_DIR)libstring.a
 
-ifeq ($(OS),$(findstring $(OS), "beos darwin linux freebsd openbsd"))
+ifeq ($(OS),$(findstring $(OS), "darwin linux freebsd openbsd"))
     LLIBS = -L/usr/X11R6/lib -lglut -pthread -lXi -lXmu
 endif
 
diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c
index 7bdca7339fc..3b5f6a0caf9 100644
--- a/intern/guardedalloc/intern/mallocn.c
+++ b/intern/guardedalloc/intern/mallocn.c
@@ -38,8 +38,7 @@
 #include 
 
 /* mmap exception */
-#if defined(AMIGA) || defined(__BeOS)
-#elif defined(WIN32)
+#if defined(WIN32)
 #include 
 #include "mmap_win.h"
 #else
@@ -292,9 +291,6 @@ void *MEM_callocN(unsigned int len, const char *str)
 /* note; mmap returns zero'd memory */
 void *MEM_mapallocN(unsigned int len, const char *str)
 {
-#if defined(AMIGA) || defined(__BeOS)
-	return MEM_callocN(len, str);
-#else
 	MemHead *memh;
 
 	mem_lock_thread();
@@ -329,7 +325,6 @@ void *MEM_mapallocN(unsigned int len, const char *str)
 		print_error("Mapalloc returns nill, fallback to regular malloc: len=%d in %s, total %u\n",len, str, mmap_in_use);
 		return MEM_callocN(len, str);
 	}
-#endif
 }
 
 /* Memory statistics print */
@@ -589,10 +584,6 @@ static void rem_memblock(MemHead *memh)
     totblock--;
     mem_in_use -= memh->len;
    
-#if defined(AMIGA) || defined(__BeOS)
-    free(memh);
-#else   
-   
     if(memh->mmap) {
         mmap_in_use -= memh->len;
         if (munmap(memh, memh->len + sizeof(MemHead) + sizeof(MemTail)))
@@ -603,7 +594,6 @@ static void rem_memblock(MemHead *memh)
 			memset(memh+1, 255, memh->len);
         free(memh);
 	}
-#endif
 }
 
 static void MemorY_ErroR(const char *block, const char *error)
diff --git a/intern/iksolver/test/Makefile b/intern/iksolver/test/Makefile
index 4ab317f9e9f..ed867ba2a73 100644
--- a/intern/iksolver/test/Makefile
+++ b/intern/iksolver/test/Makefile
@@ -46,7 +46,7 @@ LIBS += $(OCGDIR)/intern/$(LIBNAME)/$(DEBUG_DIR)libiksolver.a
 
 SLIBS += $(NAN_MOTO)/lib/$(DEBUG_DIR)libmoto.a
 
-ifeq ($(OS),$(findstring $(OS), "beos darwin linux freebsd openbsd"))
+ifeq ($(OS),$(findstring $(OS), "darwin linux freebsd openbsd"))
     LLIBS = -L/usr/X11R6/lib -lglut -pthread
 endif
 
diff --git a/intern/moto/include/MT_Matrix3x3.h b/intern/moto/include/MT_Matrix3x3.h
index 899a2731588..c6d299d19fd 100644
--- a/intern/moto/include/MT_Matrix3x3.h
+++ b/intern/moto/include/MT_Matrix3x3.h
@@ -98,6 +98,18 @@ public:
         m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m;
     }
 
+    void setValue3x3(const float *m) {
+        m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++;
+        m_el[0][1] = *m++; m_el[1][1] = *m++; m_el[2][1] = *m++;
+        m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m;
+    }
+
+    void setValue3x3(const double *m) {
+        m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++;
+        m_el[0][1] = *m++; m_el[1][1] = *m++; m_el[2][1] = *m++;
+        m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m;
+    }
+
     void setValue(MT_Scalar xx, MT_Scalar xy, MT_Scalar xz, 
                   MT_Scalar yx, MT_Scalar yy, MT_Scalar yz, 
                   MT_Scalar zx, MT_Scalar zy, MT_Scalar zz) {
@@ -194,6 +206,18 @@ public:
         *m++ = m_el[0][2]; *m++ = m_el[1][2]; *m++ = m_el[2][2]; *m   = 0.0;
     }
 
+    void getValue3x3(float *m) const {
+        *m++ = (float) m_el[0][0]; *m++ = (float) m_el[1][0]; *m++ = (float) m_el[2][0];
+        *m++ = (float) m_el[0][1]; *m++ = (float) m_el[1][1]; *m++ = (float) m_el[2][1];
+        *m++ = (float) m_el[0][2]; *m++ = (float) m_el[1][2]; *m++ = (float) m_el[2][2];
+    }
+
+    void getValue3x3(double *m) const {
+        *m++ = m_el[0][0]; *m++ = m_el[1][0]; *m++ = m_el[2][0];
+        *m++ = m_el[0][1]; *m++ = m_el[1][1]; *m++ = m_el[2][1];
+        *m++ = m_el[0][2]; *m++ = m_el[1][2]; *m++ = m_el[2][2];
+    }
+
     MT_Quaternion getRotation() const;
 
     MT_Matrix3x3& operator*=(const MT_Matrix3x3& m); 
diff --git a/intern/string/intern/STR_String.cpp b/intern/string/intern/STR_String.cpp
index dcc52e2a3e7..646b1a853dc 100644
--- a/intern/string/intern/STR_String.cpp
+++ b/intern/string/intern/STR_String.cpp
@@ -559,7 +559,8 @@ STR_String&	STR_String::TrimLeft()
 {
 	int skip;
 	assertd(pData != NULL);
-	for (skip=0; isSpace(pData[skip]); skip++, Len--);
+	for (skip=0; isSpace(pData[skip]); skip++, Len--)
+		{};
 	memmove(pData, pData+skip, Len+1);
 	return *this;
 }
@@ -598,7 +599,8 @@ STR_String&	STR_String::TrimLeft(char *set)
 {
 	int skip;
 	assertd(pData != NULL);
-	for (skip=0; Len && strchr(set, pData[skip]); skip++, Len--);
+	for (skip=0; Len && strchr(set, pData[skip]); skip++, Len--)
+		{};
 	memmove(pData, pData+skip, Len+1);
 	return *this;
 }
diff --git a/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj b/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj
index e66693cc86f..f6a740ee5b0 100644
--- a/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj
+++ b/projectfiles_vc9/blender/BPY_python/BPY_python.vcproj
@@ -43,7 +43,7 @@
 			
 				
 			
+			
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+				
+			
 		
 		
 			
 		
 		
 			
 		
 	
diff --git a/projectfiles_vc9/blender/blenkernel/BKE_blenkernel.vcproj b/projectfiles_vc9/blender/blenkernel/BKE_blenkernel.vcproj
index cc464b9101a..63b2b21971f 100644
--- a/projectfiles_vc9/blender/blenkernel/BKE_blenkernel.vcproj
+++ b/projectfiles_vc9/blender/blenkernel/BKE_blenkernel.vcproj
@@ -43,7 +43,7 @@
 			
 			
 			
 			
 			
 			
+			
+			
 			
@@ -758,6 +762,10 @@
 				RelativePath="..\..\..\source\blender\editors\space_file\file_ops.c"
 				>
 			
+			
+			
 			
@@ -791,11 +799,11 @@
 			Name="space_info"
 			>
 			
 			
 			
 			
 			
 			
+			
+			
 			
@@ -1351,6 +1363,30 @@
 				>
 			
 		
+		
+			
+			
+			
+			
+			
+			
+			
+			
+			
+			
+		
 	
 	
 	
diff --git a/projectfiles_vc9/blender/makesrna/RNA_makesrna.vcproj b/projectfiles_vc9/blender/makesrna/RNA_makesrna.vcproj
index 0f3d2b01030..a19c6dce8b0 100644
--- a/projectfiles_vc9/blender/makesrna/RNA_makesrna.vcproj
+++ b/projectfiles_vc9/blender/makesrna/RNA_makesrna.vcproj
@@ -138,7 +138,7 @@
 			
-			
-			
 			
@@ -684,6 +680,10 @@
 				RelativePath="..\..\..\source\blender\makesrna\intern\rna_main.c"
 				>
 			
+			
+			
 			
@@ -692,6 +692,10 @@
 				RelativePath="..\..\..\source\blender\makesrna\intern\rna_mesh.c"
 				>
 			
+			
+			
 			
@@ -708,6 +712,10 @@
 				RelativePath="..\..\..\source\blender\makesrna\intern\rna_object.c"
 				>
 			
+			
+			
 			
@@ -728,10 +736,6 @@
 				RelativePath="..\..\..\source\blender\makesrna\intern\rna_property.c"
 				>
 			
-			
-			
 			
@@ -780,6 +784,10 @@
 				RelativePath="..\..\..\source\blender\makesrna\intern\rna_ui.c"
 				>
 			
+			
+			
 			
@@ -796,6 +804,10 @@
 				RelativePath="..\..\..\source\blender\makesrna\intern\rna_wm.c"
 				>
 			
+			
+			
 			
diff --git a/projectfiles_vc9/blender/makesrna/RNA_rna.vcproj b/projectfiles_vc9/blender/makesrna/RNA_rna.vcproj
index d99d14c0979..19e47f19d3c 100644
--- a/projectfiles_vc9/blender/makesrna/RNA_rna.vcproj
+++ b/projectfiles_vc9/blender/makesrna/RNA_rna.vcproj
@@ -114,7 +114,7 @@
 				Name="VCCLCompilerTool"
 				Optimization="2"
 				EnableIntrinsicFunctions="true"
-				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\windowmanager;..\..\..\source\blender\editors\include"
+				AdditionalIncludeDirectories="..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\source\blender\imbuf;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\windowmanager;..\..\..\source\blender\editors\include"
 				PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS"
 				MinimalRebuild="true"
 				RuntimeLibrary="0"
@@ -182,6 +182,10 @@
 				RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_armature_gen.c"
 				>
 			
+			
+			
 			
@@ -294,10 +298,6 @@
 				RelativePath="..\..\..\source\blender\makesrna\intern\rna.crna_property_gen.c"
 				>
 			
-			
-			
 			
diff --git a/projectfiles_vc9/blender/nodes/nodes.vcproj b/projectfiles_vc9/blender/nodes/nodes.vcproj
index b8b92ac072b..f7dc938d8f2 100644
--- a/projectfiles_vc9/blender/nodes/nodes.vcproj
+++ b/projectfiles_vc9/blender/nodes/nodes.vcproj
@@ -42,7 +42,7 @@
 			
 			
 			
 			
-			
-			
 			
@@ -601,10 +597,6 @@
 				RelativePath="..\..\..\source\gameengine\Ketsji\KX_SG_NodeRelationships.cpp"
 				>
 			
-			
-			
 			
diff --git a/projectfiles_vc9/gameengine/ketsji/network/KX_network.vcproj b/projectfiles_vc9/gameengine/ketsji/network/KX_network.vcproj
index fc197d0d1f4..c6edae137b7 100644
--- a/projectfiles_vc9/gameengine/ketsji/network/KX_network.vcproj
+++ b/projectfiles_vc9/gameengine/ketsji/network/KX_network.vcproj
@@ -43,7 +43,7 @@
 			
 			
 			
 			 1:
+			col.itemO("OBJECT_OT_vertex_group_copy_to_linked", icon="ICON_BLANK1", text="")
+
+		if context.edit_object:
+			row = layout.row(align=True)
+
+			row.itemO("OBJECT_OT_vertex_group_assign", text="Assign")
+			row.itemO("OBJECT_OT_vertex_group_remove_from", text="Remove")
+			row.itemO("OBJECT_OT_vertex_group_select", text="Select")
+			row.itemO("OBJECT_OT_vertex_group_deselect", text="Deselect")
+
+			layout.itemR(context.tool_settings, "vertex_group_weight", text="Weight")
+
+class DATA_PT_shape_keys(DataButtonsPanel):
+	__idname__ = "DATA_PT_shape_keys"
+	__label__ = "Shape Keys"
+	
+	def poll(self, context):
+		return (context.object and context.object.type in ('MESH', 'LATTICE'))
+
+	def draw(self, context):
+		layout = self.layout
+		ob = context.object
+
+		row = layout.row()
+
+		key = ob.data.shape_keys
+
+		row.template_list(key, "keys", ob, "active_shape_key_index")
+
+		col = row.column(align=True)
+		col.itemO("OBJECT_OT_shape_key_add", icon="ICON_ZOOMIN", text="")
+		col.itemO("OBJECT_OT_shape_key_remove", icon="ICON_ZOOMOUT", text="")
+
+		if context.edit_object:
+			layout.enabled = False
+
+class DATA_PT_uv_texture(DataButtonsPanel):
+	__idname__ = "DATA_PT_uv_texture"
+	__label__ = "UV Texture"
+	
+	def draw(self, context):
+		layout = self.layout
+		me = context.mesh
+
+		row = layout.row()
+
+		row.template_list(me, "uv_textures", me, "active_uv_texture_index")
+
+		col = row.column(align=True)
+		col.itemO("MESH_OT_uv_texture_add", icon="ICON_ZOOMIN", text="")
+		col.itemO("MESH_OT_uv_texture_remove", icon="ICON_ZOOMOUT", text="")
+
+class DATA_PT_vertex_colors(DataButtonsPanel):
+	__idname__ = "DATA_PT_vertex_colors"
+	__label__ = "Vertex Colors"
+	
+	def draw(self, context):
+		layout = self.layout
+		me = context.mesh
+
+		row = layout.row()
+
+		row.template_list(me, "vertex_colors", me, "active_vertex_color_index")
+
+		col = row.column(align=True)
+		col.itemO("MESH_OT_vertex_color_add", icon="ICON_ZOOMIN", text="")
+		col.itemO("MESH_OT_vertex_color_remove", icon="ICON_ZOOMOUT", text="")
+
 bpy.types.register(DATA_PT_mesh)
+bpy.types.register(DATA_PT_materials)
+bpy.types.register(DATA_PT_vertex_groups)
+bpy.types.register(DATA_PT_shape_keys)
+bpy.types.register(DATA_PT_uv_texture)
+bpy.types.register(DATA_PT_vertex_colors)
+
diff --git a/release/ui/buttons_data_modifier.py b/release/ui/buttons_data_modifier.py
index ecb0590f8e5..953fc1f0974 100644
--- a/release/ui/buttons_data_modifier.py
+++ b/release/ui/buttons_data_modifier.py
@@ -23,68 +23,68 @@ class DATA_PT_modifiers(DataButtonsPanel):
 
 			if box:
 				if md.type == 'ARMATURE':
-					self.armature(box, md)
+					self.armature(box, ob, md)
 				if md.type == 'ARRAY':
-					self.array(box, md)
+					self.array(box, ob, md)
 				if md.type == 'BEVEL':
-					self.bevel(box, md)
+					self.bevel(box, ob, md)
 				if md.type == 'BOOLEAN':
-					self.boolean(box, md)
+					self.boolean(box, ob, md)
 				if md.type == 'BUILD':
-					self.build(box, md)
+					self.build(box, ob, md)
 				if md.type == 'CAST':
-					self.cast(box, md)
+					self.cast(box, ob, md)
 				if md.type == 'CLOTH':
-					self.cloth(box, md)
+					self.cloth(box, ob, md)
 				if md.type == 'COLLISION':
-					self.collision(box, md)
+					self.collision(box, ob, md)
 				if md.type == 'CURVE':
-					self.curve(box, md)
+					self.curve(box, ob, md)
 				if md.type == 'DECIMATE':
-					self.decimate(box, md)
+					self.decimate(box, ob, md)
 				if md.type == 'DISPLACE':
-					self.displace(box, md)
+					self.displace(box, ob, md)
 				if md.type == 'EDGE_SPLIT':
-					self.edgesplit(box, md)
+					self.edgesplit(box, ob, md)
 				if md.type == 'EXPLODE':
-					self.explode(box, md)
+					self.explode(box, ob, md)
 				if md.type == 'FLUID_SIMULATION':
-					self.fluid(box, md)
+					self.fluid(box, ob, md)
 				if md.type == 'HOOK':
-					self.hook(box, md)
+					self.hook(box, ob, md)
 				if md.type == 'LATTICE':
-					self.lattice(box, md)
+					self.lattice(box, ob, md)
 				if md.type == 'MASK':
-					self.mask(box, md)
+					self.mask(box, ob, md)
 				if md.type == 'MESH_DEFORM':
-					self.mesh_deform(box, md)
+					self.mesh_deform(box, ob, md)
 				if md.type == 'MIRROR':
-					self.mirror(box, md)
+					self.mirror(box, ob, md)
 				if md.type == 'MULTIRES':
-					self.multires(box, md)
+					self.multires(box, ob, md)
 				if md.type == 'PARTICLE_INSTANCE':
-					self.particleinstance(box, md)
+					self.particleinstance(box, ob, md)
 				if md.type == 'PARTICLE_SYSTEM':
-					self.particlesystem(box, md)
+					self.particlesystem(box, ob, md)
 				if md.type == 'SHRINKWRAP':
-					self.shrinkwrap(box, md)
+					self.shrinkwrap(box, ob, md)
 				if md.type == 'SIMPLE_DEFORM':
-					self.simpledeform(box, md)
+					self.simpledeform(box, ob, md)
 				if md.type == 'SMOOTH':
-					self.smooth(box, md)
+					self.smooth(box, ob, md)
 				if md.type == 'SOFTBODY':
-					self.softbody(box, md)
+					self.softbody(box, ob, md)
 				if md.type == 'SUBSURF':
-					self.subsurf(box, md)
+					self.subsurf(box, ob, md)
 				if md.type == 'UV_PROJECT':
-					self.uvproject(box, md)
+					self.uvproject(box, ob, md)
 				if md.type == 'WAVE':
-					self.wave(box, md)
+					self.wave(box, ob, md)
 							
-	def armature(self, layout, md):
+	def armature(self, layout, ob, md):
 		layout.itemR(md, "object")
 		row = layout.row()
-		row.itemR(md, "vertex_group")
+		row.item_pointerR(md, "vertex_group", ob, "vertex_groups")
 		row.itemR(md, "invert")
 		flow = layout.column_flow()
 		flow.itemR(md, "use_vertex_groups", text="Vertex Groups")
@@ -92,7 +92,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
 		flow.itemR(md, "quaternion")
 		flow.itemR(md, "multi_modifier")
 		
-	def array(self, layout, md):
+	def array(self, layout, ob, md):
 		layout.itemR(md, "fit_type")
 		if md.fit_type == 'FIXED_COUNT':
 			layout.itemR(md, "count")
@@ -141,7 +141,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
 		col.itemR(md, "start_cap")
 		col.itemR(md, "end_cap")
 	
-	def bevel(self, layout, md):
+	def bevel(self, layout, ob, md):
 		row = layout.row()
 		row.itemR(md, "width")
 		row.itemR(md, "only_vertices")
@@ -156,11 +156,11 @@ class DATA_PT_modifiers(DataButtonsPanel):
 			row = layout.row()
 			row.itemR(md, "edge_weight_method", expand=True)
 			
-	def boolean(self, layout, md):
+	def boolean(self, layout, ob, md):
 		layout.itemR(md, "operation")
 		layout.itemR(md, "object")
 		
-	def build(self, layout, md):
+	def build(self, layout, ob, md):
 		split = layout.split()
 		
 		col = split.column()
@@ -175,7 +175,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
 			
 		
 			
-	def cast(self, layout, md):
+	def cast(self, layout, ob, md):
 		layout.itemR(md, "cast_type")
 		col = layout.column_flow()
 		col.itemR(md, "x")
@@ -184,26 +184,26 @@ class DATA_PT_modifiers(DataButtonsPanel):
 		col.itemR(md, "factor")
 		col.itemR(md, "radius")
 		col.itemR(md, "size")
-		layout.itemR(md, "vertex_group")
+		layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
 		#Missing: "OB" and "From Radius"
 		
-	def cloth(self, layout, md):
+	def cloth(self, layout, ob, md):
 		layout.itemL(text="See Cloth panel.")
 		
-	def collision(self, layout, md):
+	def collision(self, layout, ob, md):
 		layout.itemL(text="See Collision panel.")
 		
-	def curve(self, layout, md):
+	def curve(self, layout, ob, md):
 		layout.itemR(md, "object")
-		layout.itemR(md, "vertex_group")
+		layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
 		layout.itemR(md, "deform_axis")
 		
-	def decimate(self, layout, md):
+	def decimate(self, layout, ob, md):
 		layout.itemR(md, "ratio")
 		layout.itemR(md, "face_count")
 		
-	def displace(self, layout, md):
-		layout.itemR(md, "vertex_group")
+	def displace(self, layout, ob, md):
+		layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
 		layout.itemR(md, "texture")
 		layout.itemR(md, "midlevel")
 		layout.itemR(md, "strength")
@@ -211,10 +211,10 @@ class DATA_PT_modifiers(DataButtonsPanel):
 		layout.itemR(md, "texture_coordinates")
 		if md.texture_coordinates == 'OBJECT':
 			layout.itemR(md, "texture_coordinate_object", text="Object")
-		if md.texture_coordinates == 'UV':
-			layout.itemR(md, "uv_layer")
+		if md.texture_coordinates == 'UV' and ob.type == 'MESH':
+			layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers")
 	
-	def edgesplit(self, layout, md):
+	def edgesplit(self, layout, ob, md):
 		split = layout.split()
 		
 		col = split.column()
@@ -225,8 +225,8 @@ class DATA_PT_modifiers(DataButtonsPanel):
 		col = split.column()
 		col.itemR(md, "use_sharp", text="Sharp Edges")
 		
-	def explode(self, layout, md):
-		layout.itemR(md, "vertex_group")
+	def explode(self, layout, ob, md):
+		layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
 		layout.itemR(md, "protect")
 		layout.itemR(md, "split_edges")
 		layout.itemR(md, "unborn")
@@ -234,31 +234,31 @@ class DATA_PT_modifiers(DataButtonsPanel):
 		layout.itemR(md, "dead")
 		# Missing: "Refresh" and "Clear Vertex Group" ?
 		
-	def fluid(self, layout, md):
+	def fluid(self, layout, ob, md):
 		layout.itemL(text="See Fluidsim panel.")
 		
-	def hook(self, layout, md):
+	def hook(self, layout, ob, md):
 		layout.itemR(md, "falloff")
 		layout.itemR(md, "force", slider=True)
 		layout.itemR(md, "object")
-		layout.itemR(md, "vertex_group")
+		layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
 		# Missing: "Reset" and "Recenter"
 		
-	def lattice(self, layout, md):
+	def lattice(self, layout, ob, md):
 		layout.itemR(md, "object")
-		layout.itemR(md, "vertex_group")
+		layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
 		
-	def mask(self, layout, md):
+	def mask(self, layout, ob, md):
 		layout.itemR(md, "mode")
 		if md.mode == 'ARMATURE':
 			layout.itemR(md, "armature")
 		if md.mode == 'VERTEX_GROUP':
-			layout.itemR(md, "vertex_group")
+			layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
 		layout.itemR(md, "inverse")
 		
-	def mesh_deform(self, layout, md):
+	def mesh_deform(self, layout, ob, md):
 		layout.itemR(md, "object")
-		layout.itemR(md, "vertex_group")
+		layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
 		layout.itemR(md, "invert")
 
 		layout.itemS()
@@ -267,7 +267,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
 		row.itemR(md, "precision")
 		row.itemR(md, "dynamic")
 		
-	def mirror(self, layout, md):
+	def mirror(self, layout, ob, md):
 		layout.itemR(md, "merge_limit")
 		split = layout.split()
 		
@@ -285,12 +285,12 @@ class DATA_PT_modifiers(DataButtonsPanel):
 		
 		layout.itemR(md, "mirror_object")
 		
-	def multires(self, layout, md):
+	def multires(self, layout, ob, md):
 		layout.itemR(md, "subdivision_type")
 		layout.itemO("OBJECT_OT_multires_subdivide", text="Subdivide")
 		layout.itemR(md, "level")
 	
-	def particleinstance(self, layout, md):
+	def particleinstance(self, layout, ob, md):
 		layout.itemR(md, "object")
 		layout.itemR(md, "particle_system_number")
 		
@@ -302,12 +302,12 @@ class DATA_PT_modifiers(DataButtonsPanel):
 		col.itemR(md, "alive")
 		col.itemR(md, "dead")
 		
-	def particlesystem(self, layout, md):
+	def particlesystem(self, layout, ob, md):
 		layout.itemL(text="See Particle panel.")
 		
-	def shrinkwrap(self, layout, md):
+	def shrinkwrap(self, layout, ob, md):
 		layout.itemR(md, "target")
-		layout.itemR(md, "vertex_group")
+		layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
 		layout.itemR(md, "offset")
 		layout.itemR(md, "subsurf_levels")
 		layout.itemR(md, "mode")
@@ -329,9 +329,9 @@ class DATA_PT_modifiers(DataButtonsPanel):
 			layout.itemR(md, "keep_above_surface")
 		# To-Do: Validate if structs
 		
-	def simpledeform(self, layout, md):
+	def simpledeform(self, layout, ob, md):
 		layout.itemR(md, "mode")
-		layout.itemR(md, "vertex_group")
+		layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
 		layout.itemR(md, "origin")
 		layout.itemR(md, "relative")
 		layout.itemR(md, "factor")
@@ -340,7 +340,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
 			layout.itemR(md, "lock_x_axis")
 			layout.itemR(md, "lock_y_axis")
 	
-	def smooth(self, layout, md):
+	def smooth(self, layout, ob, md):
 		split = layout.split()
 		sub = split.column()
 		sub.itemR(md, "x")
@@ -350,12 +350,12 @@ class DATA_PT_modifiers(DataButtonsPanel):
 		sub.itemR(md, "factor")
 		sub.itemR(md, "repeat")
 		
-		layout.itemR(md, "vertex_group")
+		layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
 		
-	def softbody(self, layout, md):
+	def softbody(self, layout, ob, md):
 		layout.itemL(text="See Softbody panel.")
 	
-	def subsurf(self, layout, md):
+	def subsurf(self, layout, ob, md):
 		layout.itemR(md, "subdivision_type")
 		col = layout.column_flow()
 		col.itemR(md, "levels", text="Preview")
@@ -363,16 +363,17 @@ class DATA_PT_modifiers(DataButtonsPanel):
 		col.itemR(md, "optimal_draw", text="Optimal Display")
 		col.itemR(md, "subsurf_uv")
 	
-	def uvproject(self, layout, md):
-		layout.itemR(md, "uv_layer")
-		layout.itemR(md, "projectors")
-		layout.itemR(md, "image")
-		layout.itemR(md, "horizontal_aspect_ratio")
-		layout.itemR(md, "vertical_aspect_ratio")
-		layout.itemR(md, "override_image")
-		#"Projectors" don't work.
+	def uvproject(self, layout, ob, md):
+		if ob.type == 'MESH':
+			layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers")
+			layout.itemR(md, "projectors")
+			layout.itemR(md, "image")
+			layout.itemR(md, "horizontal_aspect_ratio")
+			layout.itemR(md, "vertical_aspect_ratio")
+			layout.itemR(md, "override_image")
+			#"Projectors" don't work.
 		
-	def wave(self, layout, md):
+	def wave(self, layout, ob, md):
 		split = layout.split()
 		
 		sub = split.column()
@@ -398,11 +399,11 @@ class DATA_PT_modifiers(DataButtonsPanel):
 		col.itemR(md, "start_position_y")
 		
 		layout.itemR(md, "start_position_object")
-		layout.itemR(md, "vertex_group")
+		layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
 		layout.itemR(md, "texture")
 		layout.itemR(md, "texture_coordinates")
-		if md.texture_coordinates == 'MAP_UV':
-			layout.itemR(md, "uv_layer")
+		if md.texture_coordinates == 'MAP_UV' and ob.type == 'MESH':
+			layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers")
 		if md.texture_coordinates == 'OBJECT':
 			layout.itemR(md, "texture_coordinates_object")
 		
@@ -412,4 +413,4 @@ class DATA_PT_modifiers(DataButtonsPanel):
 		col.itemR(md, "width", slider=True)
 		col.itemR(md, "narrowness", slider=True)
 
-bpy.types.register(DATA_PT_modifiers)
\ No newline at end of file
+bpy.types.register(DATA_PT_modifiers)
diff --git a/release/ui/buttons_data_text.py b/release/ui/buttons_data_text.py
index bce16e78a40..5f4cdd3f838 100644
--- a/release/ui/buttons_data_text.py
+++ b/release/ui/buttons_data_text.py
@@ -27,10 +27,10 @@ class DATA_PT_shape_text(DataButtonsPanel):
 		split = layout.split(percentage=0.65)
 
 		if ob:
-			split.template_ID(context, ob, "data")
+			split.template_ID(ob, "data")
 			split.itemS()
 		elif curve:
-			split.template_ID(context, space, "pin_id")
+			split.template_ID(space, "pin_id")
 			split.itemS()
 
 		if curve:
diff --git a/release/ui/buttons_material.py b/release/ui/buttons_material.py
index 124fba83608..8b0ef82b628 100644
--- a/release/ui/buttons_material.py
+++ b/release/ui/buttons_material.py
@@ -40,10 +40,10 @@ class MATERIAL_PT_material(MaterialButtonsPanel):
 		split = layout.split(percentage=0.65)
 
 		if ob and slot:
-			split.template_ID(context, slot, "material", new="MATERIAL_OT_new")
+			split.template_ID(slot, "material", new="MATERIAL_OT_new")
 			split.itemR(ob, "active_material_index", text="Active")
 		elif mat:
-			split.template_ID(context, space, "pin_id")
+			split.template_ID(space, "pin_id")
 			split.itemS()
 
 		if mat:
diff --git a/release/ui/buttons_object_constraint.py b/release/ui/buttons_object_constraint.py
index f4507f9149d..f2b0b986ab9 100644
--- a/release/ui/buttons_object_constraint.py
+++ b/release/ui/buttons_object_constraint.py
@@ -67,7 +67,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
 				row.itemR(con, "target_space", text="")
 
 			if target and owner:
-				row.itemL(icon=8) # XXX
+				row.itemL(icon="ICON_ARROW_LEFTRIGHT")
 
 			if owner:
 				row.itemR(con, "owner_space", text="")
@@ -77,13 +77,14 @@ class ConstraintButtonsPanel(bpy.types.Panel):
 		
 		if con.target and subtargets:
 			if con.target.type == "ARMATURE":
-				layout.itemR(con, "subtarget", text="Bone") # XXX autocomplete
+				layout.item_pointerR(con, "subtarget", con.target.data, "bones", text="Bone")
 				
-				row = layout.row()
-				row.itemL(text="Head/Tail:")
-				row.itemR(con, "head_tail", text="")
+				if con.type == 'COPY_LOCATION':
+					row = layout.row()
+					row.itemL(text="Head/Tail:")
+					row.itemR(con, "head_tail", text="")
 			elif con.target.type in ("MESH", "LATTICE"):
-				layout.itemR(con, "subtarget", text="Vertex Group") # XXX autocomplete
+				layout.item_pointerR(con, "subtarget", con.target, "vertex_groups", text="Vertex Group")
 	
 	def child_of(self, layout, con):
 		self.target_template(layout, con)
@@ -528,23 +529,23 @@ class OBJECT_PT_constraints(ConstraintButtonsPanel):
 class BONE_PT_constraints(ConstraintButtonsPanel):
 	__idname__ = "BONE_PT_constraints"
 	__label__ = "Bone Constraints"
-	__context__ = "constraint"
+	__context__ = "bone"
 
 	def poll(self, context):
 		ob = context.object
-		return (ob and ob.type == "ARMATURE")
+		return (ob and ob.type == "ARMATURE" and context.bone)
 		
 	def draw(self, context):
 		ob = context.object
-		pchan = ob.pose.pose_channels[0] # XXX
+		pchan = ob.pose.pose_channels[context.bone.name]
 		layout = self.layout
 
-		#row = layout.row()
-		#row.item_menu_enumO("BONE_OT_constraint_add", "type")
-		#row.itemL();
+		row = layout.row()
+		row.item_menu_enumO("OBJECT_OT_constraint_add", "type")
+		row.itemL();
 
 		for con in pchan.constraints:
 			self.draw_constraint(con)
 
 bpy.types.register(OBJECT_PT_constraints)
-bpy.types.register(BONE_PT_constraints)
\ No newline at end of file
+bpy.types.register(BONE_PT_constraints)
diff --git a/release/ui/buttons_particle.py b/release/ui/buttons_particle.py
index 571cafb709d..49ceaf6aae1 100644
--- a/release/ui/buttons_particle.py
+++ b/release/ui/buttons_particle.py
@@ -7,6 +7,7 @@ def particle_panel_enabled(psys):
 def particle_panel_poll(context):
 	psys = context.particle_system
 	if psys==None:	return False
+	if psys.settings==None:  return False
 	return psys.settings.type in ('EMITTER', 'REACTOR', 'HAIR')
 
 class ParticleButtonsPanel(bpy.types.Panel):
@@ -29,75 +30,51 @@ class PARTICLE_PT_particles(ParticleButtonsPanel):
 		ob = context.object
 		psys = context.particle_system
 
-		split = layout.split(percentage=0.65)
-
-		if psys:
-			split.template_ID(context, psys, "settings")
-
-			#if ob:
-			#	split.itemR(ob, "active_particle_system_index", text="Active")
+		if ob:
+			row = layout.row()
+
+			row.template_list(ob, "particle_systems", ob, "active_particle_system_index")
+
+			col = row.column(align=True)
+			col.itemO("OBJECT_OT_particle_system_add", icon="ICON_ZOOMIN", text="")
+			col.itemO("OBJECT_OT_particle_system_remove", icon="ICON_ZOOMOUT", text="")
 
 		if psys:
+			split = layout.split(percentage=0.65)
+			
+			split.template_ID(psys, "settings", new="PARTICLE_OT_new")
+			
 			#row = layout.row()
-			#row.itemL(text="Particle system datablock")
 			#row.itemL(text="Viewport")
 			#row.itemL(text="Render")
 			
 			part = psys.settings
-			ptype = psys.settings.type
 			
-			if ptype not in ('EMITTER', 'REACTOR', 'HAIR'):
-				layout.itemL(text="No settings for fluid particles")
-				return
-			
-			row = layout.row()
-			row.enabled = particle_panel_enabled(psys)
-			row.itemR(part, "type")
-			row.itemR(psys, "seed")
-			
-			row = layout.row()
-			if part.type=='HAIR':
-				if psys.editable==True:
-					row.itemO("PARTICLE_OT_editable_set", text="Free Edit")
-				else:
-					row.itemO("PARTICLE_OT_editable_set", text="Make Editable")
-				subrow = row.row()
-				subrow.enabled = particle_panel_enabled(psys)
-				subrow.itemR(part, "hair_step")
-			elif part.type=='REACTOR':
-				row.itemR(psys, "reactor_target_object")
-				row.itemR(psys, "reactor_target_particle_system", text="Particle System")
-		
-		if psys:
-			#row = layout.row()
-			#row.itemL(text="Particle system datablock")
-			#row.itemL(text="Viewport")
-			#row.itemL(text="Render")
-			
-			part = psys.settings
-			ptype = psys.settings.type
-			
-			if ptype not in ('EMITTER', 'REACTOR', 'HAIR'):
-				layout.itemL(text="No settings for fluid particles")
-				return
-			
-			row = layout.row()
-			row.enabled = particle_panel_enabled(psys)
-			row.itemR(part, "type", expand=True)
-			
-			
-			row = layout.row()
-			if part.type=='HAIR':
-				if psys.editable==True:
-					row.itemO("PARTICLE_OT_editable_set", text="Free Edit")
-				else:
-					row.itemO("PARTICLE_OT_editable_set", text="Make Editable")
-				subrow = row.row()
-				subrow.enabled = particle_panel_enabled(psys)
-				subrow.itemR(part, "hair_step")
-			elif part.type=='REACTOR':
-				row.itemR(psys, "reactor_target_object")
-				row.itemR(psys, "reactor_target_particle_system", text="Particle System")
+			if part:
+				ptype = psys.settings.type
+				if ptype not in ('EMITTER', 'REACTOR', 'HAIR'):
+					layout.itemL(text="No settings for fluid particles")
+					return
+					
+				split = layout.split(percentage=0.65)
+				
+				split.enabled = particle_panel_enabled(psys)
+				split.itemR(part, "type")
+				split.itemR(psys, "seed")
+				
+				split = layout.split(percentage=0.65)
+				if part.type=='HAIR':
+					if psys.editable==True:
+						split.itemO("PARTICLE_OT_editable_set", text="Free Edit")
+					else:
+						split.itemO("PARTICLE_OT_editable_set", text="Make Editable")
+					row = split.row()
+					row.enabled = particle_panel_enabled(psys)
+					row.itemR(part, "hair_step")
+				elif part.type=='REACTOR':
+					split.enabled = particle_panel_enabled(psys)
+					split.itemR(psys, "reactor_target_object")
+					split.itemR(psys, "reactor_target_particle_system", text="Particle System")
 		
 class PARTICLE_PT_emission(ParticleButtonsPanel):
 	__idname__= "PARTICLE_PT_emission"
@@ -112,9 +89,7 @@ class PARTICLE_PT_emission(ParticleButtonsPanel):
 		layout.enabled = particle_panel_enabled(psys)
 		
 		row = layout.row()
-		#col.itemL(text="TODO: Rate instead of amount")
 		row.itemR(part, "amount")
-		row.itemR(psys, "seed")
 		
 		split = layout.split()
 		
@@ -150,10 +125,12 @@ class PARTICLE_PT_emission(ParticleButtonsPanel):
 class PARTICLE_PT_cache(ParticleButtonsPanel):
 	__idname__= "PARTICLE_PT_cache"
 	__label__ = "Cache"
+	__default_closed__ = True
 	
 	def poll(self, context):
 		psys = context.particle_system
 		if psys==None:	return False
+		if psys.settings==None:  return False
 		return psys.settings.type in ('EMITTER', 'REACTOR')
 
 	def draw(self, context):
@@ -163,15 +140,42 @@ class PARTICLE_PT_cache(ParticleButtonsPanel):
 		part = psys.settings
 		cache = psys.point_cache
 		
-		#if cache.baked==True:
-			#layout.itemO("PARTICLE_OT_free_bake", text="BAKE")
-		#else:
 		row = layout.row()
-			#row.itemO("PARTICLE_OT_bake", text="BAKE")
-		row.itemR(cache, "start_frame")
-		row.itemR(cache, "end_frame")
-			
-			#layout.row().itemL(text="No simulation frames in disk cache.")
+		row.itemR(cache, "name")
+		
+		row = layout.row()
+		
+		if cache.baked == True:
+			row.itemO("PTCACHE_OT_free_bake_particle_system", text="Free Bake")
+		else:
+			row.item_booleanO("PTCACHE_OT_cache_particle_system", "bake", True, text="Bake")
+		
+		subrow = row.row()
+		subrow.enabled = (cache.frames_skipped or cache.outdated) and particle_panel_enabled(psys)
+		subrow.itemO("PTCACHE_OT_cache_particle_system", text="Calculate to Current Frame")
+		
+		row = layout.row()
+		row.enabled = particle_panel_enabled(psys)
+		row.itemO("PTCACHE_OT_bake_from_particles_cache", text="Current Cache to Bake")
+		row.itemR(cache, "step");
+	
+		row = layout.row()
+		row.enabled = particle_panel_enabled(psys)
+		row.itemR(cache, "quick_cache")
+		row.itemR(cache, "disk_cache")
+		
+		layout.itemL(text=cache.info)
+		
+		layout.itemS()
+		
+		row = layout.row()
+		row.item_booleanO("PTCACHE_OT_bake_all", "bake", True, text="Bake All Dynamics")
+		row.itemO("PTCACHE_OT_free_bake_all", text="Free All Bakes")
+		layout.itemO("PTCACHE_OT_bake_all", text="Update All Dynamics to current frame")
+		
+		# for particles these are figured out automatically
+		#row.itemR(cache, "start_frame")
+		#row.itemR(cache, "end_frame")
 
 class PARTICLE_PT_initial(ParticleButtonsPanel):
 	__idname__= "PARTICLE_PT_initial"
@@ -184,8 +188,6 @@ class PARTICLE_PT_initial(ParticleButtonsPanel):
 		part = psys.settings
 		
 		layout.enabled = particle_panel_enabled(psys)
-		
-		#layout.row().itemL(text="")
 				
 		layout.row().itemL(text="Direction:")
 	
@@ -296,7 +298,10 @@ class PARTICLE_PT_render(ParticleButtonsPanel):
 	__label__ = "Render"
 	
 	def poll(self, context):
-		return (context.particle_system != None)
+		psys = context.particle_system
+		if psys==None: return False
+		if psys.settings==None: return False
+		return True;
 		
 	def draw(self, context):
 		layout = self.layout
@@ -304,7 +309,9 @@ class PARTICLE_PT_render(ParticleButtonsPanel):
 		psys = context.particle_system
 		part = psys.settings
 		
-		layout.itemR(part, "material")
+		row = layout.row()
+		row.itemR(part, "material")
+		row.itemR(psys, "parent");
 		
 		split = layout.split()
 			
@@ -362,27 +369,14 @@ class PARTICLE_PT_render(ParticleButtonsPanel):
 			row = layout.row()
 			col = row.column()
 			
-			
-#			subrow = col.row()
-#			subrow.active = part.render_strand == False
-#			subrow.itemR(part, "render_adaptive")
-#			col = row.column(align=True)
-#			subrow = col.row()
-#			subrow.active = part.render_adaptive or part.render_strand == True
-#			subrow.itemR(part, "adaptive_angle")
-#			subrow = col.row()
-#			subrow.active = part.render_adaptive == True and part.render_strand == False
-#			subrow.itemR(part, "adaptive_pix")
-			
 			if part.type=='HAIR' and part.render_strand==True and part.child_type=='FACES':
 				layout.itemR(part, "enable_simplify")
 				if part.enable_simplify==True:
-					box = layout.box()
-					row = box.row()
+					row = layout.row()
 					row.itemR(part, "simplify_refsize")
 					row.itemR(part, "simplify_rate")
 					row.itemR(part, "simplify_transition")
-					row = box.row()
+					row = layout.row()
 					row.itemR(part, "viewport")
 					subrow = row.row()
 					subrow.active = part.viewport==True
@@ -438,9 +432,13 @@ class PARTICLE_PT_render(ParticleButtonsPanel):
 class PARTICLE_PT_draw(ParticleButtonsPanel):
 	__idname__= "PARTICLE_PT_draw"
 	__label__ = "Display"
+	__default_closed__ = True
 	
 	def poll(self, context):
-		return (context.particle_system != None)
+		psys = context.particle_system
+		if psys==None: return False
+		if psys.settings==None: return False
+		return True;
 	
 	def draw(self, context):
 		layout = self.layout
@@ -490,6 +488,7 @@ class PARTICLE_PT_draw(ParticleButtonsPanel):
 class PARTICLE_PT_children(ParticleButtonsPanel):
 	__idname__= "PARTICLE_PT_children"
 	__label__ = "Children"
+	__default_closed__ = True
 
 	def draw(self, context):
 		layout = self.layout
@@ -557,6 +556,7 @@ class PARTICLE_PT_children(ParticleButtonsPanel):
 class PARTICLE_PT_vertexgroups(ParticleButtonsPanel):
 	__idname__= "PARTICLE_PT_vertexgroups"
 	__label__ = "Vertexgroups"
+	__default_closed__ = True
 
 	def draw(self, context):
 		layout = self.layout
diff --git a/release/ui/buttons_physic_cloth.py b/release/ui/buttons_physic_cloth.py
index bd65392ad63..a06c644322a 100644
--- a/release/ui/buttons_physic_cloth.py
+++ b/release/ui/buttons_physic_cloth.py
@@ -43,7 +43,54 @@ class Physic_PT_cloth(PhysicButtonsPanel):
 			col.itemR(cloth, "goal_spring", text="Stiffness")
 			col.itemR(cloth, "goal_friction", text="Friction")
 		"""
+
+class PHYSICS_PT_cloth_cache(PhysicButtonsPanel):
+	__idname__= "PHYSICS_PT_cloth_cache"
+	__label__ = "Cache"
+	__default_closed__ = True
+
+	def draw(self, context):
+		layout = self.layout
+
+		cache = context.cloth.point_cache
+		
+		row = layout.row()
+		row.itemR(cache, "name")
+		
+		row = layout.row()
+		row.itemR(cache, "start_frame")
+		row.itemR(cache, "end_frame")
+		
+		row = layout.row()
+		
+		if cache.baked == True:
+			row.itemO("PTCACHE_OT_free_bake_cloth", text="Free Bake")
+		else:
+			row.item_booleanO("PTCACHE_OT_cache_cloth", "bake", True, text="Bake")
+		
+		subrow = row.row()
+		subrow.enabled = cache.frames_skipped or cache.outdated
+		subrow.itemO("PTCACHE_OT_cache_cloth", text="Calculate to Current Frame")
+			
+		row = layout.row()
+		#row.enabled = particle_panel_enabled(psys)
+		row.itemO("PTCACHE_OT_bake_from_cloth_cache", text="Current Cache to Bake")
+		row.itemR(cache, "step");
 	
+		row = layout.row()
+		#row.enabled = particle_panel_enabled(psys)
+		row.itemR(cache, "quick_cache")
+		row.itemR(cache, "disk_cache")
+		
+		layout.itemL(text=cache.info)
+		
+		layout.itemS()
+		
+		row = layout.row()
+		row.itemO("PTCACHE_OT_bake_all", "bake", True, text="Bake All Dynamics")
+		row.itemO("PTCACHE_OT_free_bake_all", text="Free All Bakes")
+		layout.itemO("PTCACHE_OT_bake_all", text="Update All Dynamics to current frame")
+		
 class Physic_PT_cloth_collision(PhysicButtonsPanel):
 	__idname__ = "Physic_PT_clothcollision"
 	__label__ = "Cloth Collision"
@@ -102,5 +149,6 @@ class Physic_PT_cloth_stiffness(PhysicButtonsPanel):
 		sub.itemR(cloth, "bending_stiffness_max", text="Max")
 		
 bpy.types.register(Physic_PT_cloth)
+bpy.types.register(PHYSICS_PT_cloth_cache)
 bpy.types.register(Physic_PT_cloth_collision)
 bpy.types.register(Physic_PT_cloth_stiffness)
diff --git a/release/ui/buttons_texture.py b/release/ui/buttons_texture.py
index de166cef796..31908d5ec9c 100644
--- a/release/ui/buttons_texture.py
+++ b/release/ui/buttons_texture.py
@@ -43,7 +43,7 @@ class TEXTURE_PT_texture(TextureButtonsPanel):
 
 		if ma or la or wo:
 			if slot:
-				split.template_ID(context, slot, "texture", new="TEXTURE_OT_new")
+				split.template_ID(slot, "texture", new="TEXTURE_OT_new")
 			else:
 				split.itemS()
 
@@ -54,7 +54,7 @@ class TEXTURE_PT_texture(TextureButtonsPanel):
 			elif wo:
 				split.itemR(wo, "active_texture_index", text="Active")
 		elif tex:
-			split.template_ID(context, space, "pin_id")
+			split.template_ID(space, "pin_id")
 			split.itemS()
 
 		layout.itemS()
diff --git a/release/ui/buttons_world.py b/release/ui/buttons_world.py
index d9516cb7900..39b5eca04ff 100644
--- a/release/ui/buttons_world.py
+++ b/release/ui/buttons_world.py
@@ -37,9 +37,9 @@ class WORLD_PT_world(WorldButtonsPanel):
 		split = layout.split(percentage=0.65)
 
 		if scene:
-			split.template_ID(context, scene, "world", new="WORLD_OT_new")
+			split.template_ID(scene, "world", new="WORLD_OT_new")
 		elif world:
-			split.template_ID(context, space, "pin_id")
+			split.template_ID(space, "pin_id")
 
 		split.itemS()
 
diff --git a/release/ui/space_buttons.py b/release/ui/space_buttons.py
new file mode 100644
index 00000000000..cae9a813433
--- /dev/null
+++ b/release/ui/space_buttons.py
@@ -0,0 +1,36 @@
+
+import bpy
+
+class Buttons_HT_header(bpy.types.Header):
+	__space_type__ = "BUTTONS_WINDOW"
+	__idname__ = "BUTTONS_HT_header"
+
+	def draw(self, context):
+		layout = self.layout
+		
+		so = context.space_data
+		scene = context.scene
+
+		layout.template_header()
+
+		if context.area.show_menus:
+			row = layout.row(align=True)
+			row.itemM("Buttons_MT_view", text="View")
+			
+		row = layout.row()
+		row.itemR(so, "buttons_context", expand=True, text="")
+		row.itemR(scene, "current_frame")
+
+class Buttons_MT_view(bpy.types.Menu):
+	__space_type__ = "BUTTONS_WINDOW"
+	__label__ = "View"
+
+	def draw(self, context):
+		layout = self.layout
+		so = context.space_data
+
+		col = layout.column()
+		col.itemR(so, "panel_alignment", expand=True)
+
+bpy.types.register(Buttons_HT_header)
+bpy.types.register(Buttons_MT_view)
diff --git a/release/ui/space_filebrowser.py b/release/ui/space_filebrowser.py
new file mode 100644
index 00000000000..820134d3e87
--- /dev/null
+++ b/release/ui/space_filebrowser.py
@@ -0,0 +1,65 @@
+
+import bpy
+
+
+class FILEBROWSER_HT_header(bpy.types.Header):
+	__space_type__ = "FILE_BROWSER"
+	__idname__ = "FILEBROWSER_HT_header"
+
+	def draw(self, context):
+		st = context.space_data
+		layout = self.layout
+		
+		params = st.params 
+		layout.template_header()
+
+		if context.area.show_menus:
+			row = layout.row()
+			row.itemM("FILEBROWSER_MT_directory")
+			row.itemM("FILEBROWSER_MT_bookmarks")
+			
+		row = layout.row(align=True)
+		row.itemO("FILE_OT_parent", text="", icon='ICON_FILE_PARENT')
+		row.itemO("FILE_OT_refresh", text="", icon='ICON_FILE_REFRESH')
+
+		layout.itemR(params, "display", expand=True, text="")
+		layout.itemR(params, "sort", expand=True, text="")
+		
+		layout.itemR(params, "hide_dot")
+		layout.itemR(params, "do_filter")
+		
+		row = layout.row(align=True)
+		row.itemR(params, "filter_folder", text="");
+		row.itemR(params, "filter_blender", text="");
+		row.itemR(params, "filter_image", text="");
+		row.itemR(params, "filter_movie", text="");
+		row.itemR(params, "filter_script", text="");
+		row.itemR(params, "filter_font", text="");
+		row.itemR(params, "filter_sound", text="");
+		row.itemR(params, "filter_text", text="");
+
+		row.active = params.do_filter
+
+class FILEBROWSER_MT_directory(bpy.types.Menu):
+	__space_type__ = "FILE_BROWSER"
+	__label__ = "Directory"
+
+	def draw(self, context):
+		layout = self.layout
+
+		layout.itemO("FILE_OT_refresh", text="Refresh", icon='ICON_FILE_REFRESH')
+		layout.itemO("FILE_OT_parent", text="Parent", icon='ICON_FILE_PARENT')
+		
+class FILEBROWSER_MT_bookmarks(bpy.types.Menu):
+	__space_type__ = "FILE_BROWSER"
+	__label__ = "Bookmarks"
+
+	def draw(self, context):
+		layout = self.layout
+
+		layout.itemO("FILE_OT_add_bookmark", text="Add current directory", icon='ICON_BOOKMARKS')
+
+		
+bpy.types.register(FILEBROWSER_HT_header)
+bpy.types.register(FILEBROWSER_MT_directory)
+bpy.types.register(FILEBROWSER_MT_bookmarks)
diff --git a/release/ui/space_image.py b/release/ui/space_image.py
index 3623b914942..49ef18705c4 100644
--- a/release/ui/space_image.py
+++ b/release/ui/space_image.py
@@ -9,6 +9,7 @@ class IMAGE_MT_view(bpy.types.Menu):
 		layout = self.layout
 		sima = context.space_data
 		uv = sima.uv_editor
+		settings = context.scene.tool_settings
 
 		show_uvedit = sima.show_uvedit
 
@@ -17,8 +18,8 @@ class IMAGE_MT_view(bpy.types.Menu):
 		layout.itemS()
 
 		layout.itemR(sima, "update_automatically")
-		# XXX if show_uvedit:
-		# XXX	layout.itemR(uv, "local_view") # "UV Local View", Numpad /
+		if show_uvedit:
+			layout.itemR(settings, "uv_local_view") # Numpad /
 
 		layout.itemS()
 
@@ -95,9 +96,9 @@ class IMAGE_MT_image(bpy.types.Menu):
 				else:
 					layout.itemO("IMAGE_OT_pack")
 
-				# only for dirty && specific image types : XXX poll?
-				#if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY))
-				if False:
+				# only for dirty && specific image types, perhaps
+				# this could be done in operator poll too
+				if ima.dirty:
 					if ima.source in ("FILE", "GENERATED") and ima.type != "MULTILAYER":
 						layout.item_booleanO("IMAGE_OT_pack", "as_png", True, text="Pack As PNG")
 
@@ -156,7 +157,7 @@ class IMAGE_MT_uvs(bpy.types.Menu):
 		layout = self.layout
 		sima = context.space_data
 		uv = sima.uv_editor
-		scene = context.scene
+		settings = context.scene.tool_settings
 
 		layout.itemR(uv, "snap_to_pixels")
 		layout.itemR(uv, "constrain_to_image_bounds")
@@ -177,18 +178,18 @@ class IMAGE_MT_uvs(bpy.types.Menu):
 
 		layout.itemS()
 
-		layout.itemM(context, "IMAGE_MT_uvs_transform")
-		layout.itemM(context, "IMAGE_MT_uvs_mirror")
-		layout.itemM(context, "IMAGE_MT_uvs_weldalign")
+		layout.itemM("IMAGE_MT_uvs_transform")
+		layout.itemM("IMAGE_MT_uvs_mirror")
+		layout.itemM("IMAGE_MT_uvs_weldalign")
 
 		layout.itemS()
 
-		# XXX layout.itemR(scene, "proportional_editing")
-		layout.item_menu_enumR(scene, "proportional_editing_falloff")
+		layout.itemR(settings, "proportional_editing")
+		layout.item_menu_enumR(settings, "proportional_editing_falloff")
 
 		layout.itemS()
 
-		layout.itemM(context, "IMAGE_MT_uvs_showhide")
+		layout.itemM("IMAGE_MT_uvs_showhide")
 
 class IMAGE_HT_header(bpy.types.Header):
 	__space_type__ = "IMAGE_EDITOR"
@@ -196,29 +197,33 @@ class IMAGE_HT_header(bpy.types.Header):
 	def draw(self, context):
 		sima = context.space_data
 		ima = sima.image
+		iuser = sima.image_user
 		layout = self.layout
+		settings = context.scene.tool_settings
 
 		show_render = sima.show_render
 		show_paint = sima.show_paint
 		show_uvedit = sima.show_uvedit
 
-		layout.template_header(context)
+		layout.template_header()
 
 		# menus
 		if context.area.show_menus:
 			row = layout.row()
-			row.itemM(context, "IMAGE_MT_view")
+			row.itemM("IMAGE_MT_view")
 
 			if show_uvedit:
-				row.itemM(context, "IMAGE_MT_select")
+				row.itemM("IMAGE_MT_select")
 
-			# XXX menuname= (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))? "Image*": "Image";
-			row.itemM(context, "IMAGE_MT_image")
+			if ima and ima.dirty:
+				row.itemM("IMAGE_MT_image", text="Image*")
+			else:
+				row.itemM("IMAGE_MT_image", text="Image")
 
 			if show_uvedit:
-				row.itemM(context, "IMAGE_MT_uvs")
+				row.itemM("IMAGE_MT_uvs")
 
-		layout.template_ID(context, sima, "image", new="IMAGE_OT_new", open="IMAGE_OT_open")
+		layout.template_ID(sima, "image", new="IMAGE_OT_new", open="IMAGE_OT_open")
 
 		"""
 		/* image select */
@@ -250,526 +255,33 @@ class IMAGE_HT_header(bpy.types.Header):
 
 		# uv editing
 		if show_uvedit:
-			pass
-		
-		"""
-		/* uv editing */
-		if(show_uvedit) {
-			/* pivot */
-			uiDefIconTextButS(block, ICONTEXTROW, B_NOP, ICON_ROTATE,
-					"Pivot: %t|Bounding Box Center %x0|Median Point %x3|2D Cursor %x1",
-					xco,yco,XIC+10,YIC, &ar->v2d.around, 0, 3.0, 0, 0,
-					"Rotation/Scaling Pivot (Hotkeys: Comma, Shift Comma, Period)");
-			xco+= XIC + 18;
-			
-			/* selection modes */
-			uiDefIconButBitS(block, TOG, UV_SYNC_SELECTION, B_REDR, ICON_EDIT, xco,yco,XIC,YIC, &scene->toolsettings->uv_flag, 0, 0, 0, 0, "Sync UV and Mesh Selection");
-			xco+= XIC+8;
-
-			if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
-				uiBlockBeginAlign(block);
-				
-				uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_REDR, ICON_VERTEXSEL,
-					xco,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode");
-				uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_REDR, ICON_EDGESEL,
-					xco+=XIC,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Edge select mode");
-				uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_REDR, ICON_FACESEL,
-					xco+=XIC,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Face select mode");
-
-				uiBlockEndAlign(block);
-			}
-			else {
-				uiBlockBeginAlign(block);
-
-				uiDefIconButS(block, ROW, B_REDR, ICON_VERTEXSEL,
-					xco,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_VERTEX, 0, 0, "Vertex select mode");
-				uiDefIconButS(block, ROW, B_REDR, ICON_EDGESEL,
-					xco+=XIC,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_EDGE, 0, 0, "Edge select mode");
-				uiDefIconButS(block, ROW, B_REDR, ICON_FACESEL,
-					xco+=XIC,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_FACE, 0, 0, "Face select mode");
-				uiDefIconButS(block, ROW, B_REDR, ICON_LINKEDSEL,
-					xco+=XIC,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_ISLAND, 0, 0, "Island select mode");
-
-				uiBlockEndAlign(block);
-
-				/* would use these if const's could go in strings 
-				 * SI_STICKY_LOC SI_STICKY_DISABLE SI_STICKY_VERTEX */
-				but = uiDefIconTextButC(block, ICONTEXTROW, B_REDR, ICON_STICKY_UVS_LOC,
-						"Sticky UV Selection: %t|Disable%x1|Shared Location%x0|Shared Vertex%x2",
-						xco+=XIC+10,yco,XIC+10,YIC, &(sima->sticky), 0, 3.0, 0, 0,
-						"Sticky UV Selection (Hotkeys: Shift C, Alt C, Ctrl C)");
-			}
-
-			xco+= XIC + 16;
-			
-			/* snap options, identical to options in 3d view header */
-			uiBlockBeginAlign(block);
-
-			if (scene->snap_flag & SCE_SNAP) {
-				uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEO,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Use Snap or Grid (Shift Tab).");
-				xco+= XIC;
-				uiDefButS(block, MENU, B_NOP, "Mode%t|Closest%x0|Center%x1|Median%x2",xco,yco,70,YIC, &scene->snap_target, 0, 0, 0, 0, "Snap Target Mode.");
-				xco+= 70;
-			}
-			else {
-				uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEAR,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab).");	
-				xco+= XIC;
-			}
-
-			uiBlockEndAlign(block);
-			xco+= 8;
-
-			/* uv layers */
-			{
-				Object *obedit= CTX_data_edit_object(C);
-				char menustr[34*MAX_MTFACE];
-				static int act;
-				
-				image_menu_uvlayers(obedit, menustr, &act);
-
-				but = uiDefButI(block, MENU, B_NOP, menustr ,xco,yco,85,YIC, &act, 0, 0, 0, 0, "Active UV Layer for editing.");
-				// uiButSetFunc(but, do_image_buttons_set_uvlayer_callback, &act, NULL);
-				
-				xco+= 85;
-			}
-
-			xco+= 8;
-		}
-		"""
-
-		if ima:
-			"""
-			RenderResult *rr;
-		
-			/* render layers and passes */
-			rr= BKE_image_get_renderresult(scene, ima);
-			if(rr) {
-				uiBlockBeginAlign(block);
-#if 0
-				uiblock_layer_pass_buttons(block, rr, &sima->iuser, B_REDR, xco, 0, 160);
-#endif
-				uiBlockEndAlign(block);
-				xco+= 166;
-			}
-			"""
-
-			# painting
-			layout.itemR(sima, "image_painting", text="")
-
-			# draw options
-			row = layout.row(align=True)
-			row.itemR(sima, "draw_channels", text="", expand=True)
-
-			row = layout.row(align=True)
-			if ima.type == "COMPOSITE":
-				row.itemO("IMAGE_OT_record_composite", icon="ICON_REC")
-			if ima.type == "COMPOSITE" and ima.source in ("MOVIE", "SEQUENCE"):
-				row.itemO("IMAGE_OT_play_composite", icon="ICON_PLAY")
-		
-		layout.itemR(sima, "update_automatically", text="")
-
-class IMAGE_PT_game_properties(bpy.types.Panel):
-	__space_type__ = "IMAGE_EDITOR"
-	__region_type__ = "UI"
-	__label__ = "Game Properties"
-
-	def draw(self, context):
-		sima = context.space_data
-		layout = self.layout
-
-		ima = sima.image
-
-		if ima:
-			split = layout.split()
-
-			col = split.column(align=True)
-			col.itemR(ima, "animated")
-
-			subcol = col.column()
-			subcol.itemR(ima, "animation_start", text="Start")
-			subcol.itemR(ima, "animation_end", text="End")
-			subcol.itemR(ima, "animation_speed", text="Speed")
-			subcol.active = ima.animated
-
-			col = split.column()
-			col.itemR(ima, "tiles")
-
-			subrow = col.row(align=True)
-			subrow.itemR(ima, "tiles_x", text="X")
-			subrow.itemR(ima, "tiles_y", text="Y")
-			subrow.active = ima.tiles
-
-			col.itemS()
-			col.itemR(ima, "clamp_x")
-			col.itemR(ima, "clamp_y")
-
-			col.itemR(ima, "mapping", expand=True)
-
-bpy.types.register(IMAGE_MT_view)
-bpy.types.register(IMAGE_MT_select)
-bpy.types.register(IMAGE_MT_image)
-bpy.types.register(IMAGE_MT_uvs_showhide)
-bpy.types.register(IMAGE_MT_uvs_transform)
-bpy.types.register(IMAGE_MT_uvs_mirror)
-bpy.types.register(IMAGE_MT_uvs_weldalign)
-bpy.types.register(IMAGE_MT_uvs)
-bpy.types.register(IMAGE_HT_header)
-bpy.types.register(IMAGE_PT_game_properties)
-
-
-import bpy
-
-class IMAGE_MT_view(bpy.types.Menu):
-	__space_type__ = "IMAGE_EDITOR"
-	__label__ = "View"
-
-	def draw(self, context):
-		layout = self.layout
-		sima = context.space_data
-		uv = sima.uv_editor
-
-		show_uvedit = sima.show_uvedit
-
-		layout.itemO("IMAGE_OT_properties") # icon
-
-		layout.itemS()
-
-		layout.itemR(sima, "update_automatically")
-		# XXX if show_uvedit:
-		# XXX	layout.itemR(uv, "local_view") # "UV Local View", Numpad /
-
-		layout.itemS()
-
-		layout.itemO("IMAGE_OT_view_zoom_in")
-		layout.itemO("IMAGE_OT_view_zoom_out")
-
-		layout.itemS()
-
-		ratios = [[1, 8], [1, 4], [1, 2], [1, 1], [2, 1], [4, 1], [8, 1]];
-
-		for a, b in ratios:
-			text = "Zoom %d:%d" % (a, b)
-			layout.item_floatO("IMAGE_OT_view_zoom_ratio", "ratio", a/b, text=text)
-
-		layout.itemS()
-
-		if show_uvedit:
-			layout.itemO("IMAGE_OT_view_selected")
-
-		layout.itemO("IMAGE_OT_view_all")
-		layout.itemO("SCREEN_OT_screen_full_area")
-
-class IMAGE_MT_select(bpy.types.Menu):
-	__space_type__ = "IMAGE_EDITOR"
-	__label__ = "Select"
-
-	def draw(self, context):
-		layout = self.layout
-
-		layout.itemO("UV_OT_select_border")
-		layout.item_booleanO("UV_OT_select_border", "pinned", True)
-
-		layout.itemS()
-		
-		layout.itemO("UV_OT_select_all_toggle")
-		layout.itemO("UV_OT_select_invert")
-		layout.itemO("UV_OT_unlink_selection")
-		
-		layout.itemS()
-
-		layout.itemO("UV_OT_select_pinned")
-		layout.itemO("UV_OT_select_linked")
-
-class IMAGE_MT_image(bpy.types.Menu):
-	__space_type__ = "IMAGE_EDITOR"
-	__label__ = "Image"
-
-	def draw(self, context):
-		layout = self.layout
-		sima = context.space_data
-		ima = sima.image
-
-		layout.itemO("IMAGE_OT_new")
-		layout.itemO("IMAGE_OT_open")
-
-		show_render = sima.show_render
-
-		if ima:
-			if show_render:
-				layout.itemO("IMAGE_OT_replace")
-				layout.itemO("IMAGE_OT_reload")
-
-			layout.itemO("IMAGE_OT_save")
-			layout.itemO("IMAGE_OT_save_as")
-
-			if ima.source == "SEQUENCE":
-				layout.itemO("IMAGE_OT_save_sequence")
-
-			if not show_render:
-				layout.itemS()
-
-				if ima.packed_file:
-					layout.itemO("IMAGE_OT_unpack")
-				else:
-					layout.itemO("IMAGE_OT_pack")
-
-				# only for dirty && specific image types : XXX poll?
-				#if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY))
-				if False:
-					if ima.source in ("FILE", "GENERATED") and ima.type != "MULTILAYER":
-						layout.item_booleanO("IMAGE_OT_pack", "as_png", True, text="Pack As PNG")
+			uvedit = sima.uv_editor
 
 			layout.itemS()
 
-			layout.itemR(sima, "image_painting")
+			layout.itemR(uvedit, "pivot", text="")
+			layout.itemR(settings, "uv_sync_selection", text="")
 
-class IMAGE_MT_uvs_showhide(bpy.types.Menu):
-	__space_type__ = "IMAGE_EDITOR"
-	__label__ = "Show/Hide Faces"
-
-	def draw(self, context):
-		layout = self.layout
-
-		layout.itemO("UV_OT_reveal")
-		layout.itemO("UV_OT_hide")
-		layout.item_booleanO("UV_OT_hide", "unselected", True)
-
-class IMAGE_MT_uvs_transform(bpy.types.Menu):
-	__space_type__ = "IMAGE_EDITOR"
-	__label__ = "Transform"
-
-	def draw(self, context):
-		layout = self.layout
-
-		layout.item_enumO("TFM_OT_transform", "mode", "TRANSLATION")
-		layout.item_enumO("TFM_OT_transform", "mode", "ROTATION")
-		layout.item_enumO("TFM_OT_transform", "mode", "RESIZE")
-
-class IMAGE_MT_uvs_mirror(bpy.types.Menu):
-	__space_type__ = "IMAGE_EDITOR"
-	__label__ = "Mirror"
-
-	def draw(self, context):
-		layout = self.layout
-
-		layout.item_enumO("UV_OT_mirror", "axis", "MIRROR_X") # "X Axis", M, 
-		layout.item_enumO("UV_OT_mirror", "axis", "MIRROR_Y") # "Y Axis", M, 
-
-class IMAGE_MT_uvs_weldalign(bpy.types.Menu):
-	__space_type__ = "IMAGE_EDITOR"
-	__label__ = "Weld/Align"
-
-	def draw(self, context):
-		layout = self.layout
-
-		layout.itemO("UV_OT_weld") # W, 1
-		layout.items_enumO("UV_OT_align", "axis") # W, 2/3/4
-
-
-class IMAGE_MT_uvs(bpy.types.Menu):
-	__space_type__ = "IMAGE_EDITOR"
-	__label__ = "UVs"
-
-	def draw(self, context):
-		layout = self.layout
-		sima = context.space_data
-		uv = sima.uv_editor
-		scene = context.scene
-
-		layout.itemR(uv, "snap_to_pixels")
-		layout.itemR(uv, "constrain_to_image_bounds")
-
-		layout.itemS()
-
-		layout.itemR(uv, "live_unwrap")
-		layout.itemO("UV_OT_unwrap")
-		layout.item_booleanO("UV_OT_pin", "clear", True, text="Unpin")
-		layout.itemO("UV_OT_pin")
-
-		layout.itemS()
-
-		layout.itemO("UV_OT_pack_islands")
-		layout.itemO("UV_OT_average_islands_scale")
-		layout.itemO("UV_OT_minimize_stretch")
-		layout.itemO("UV_OT_stitch")
-
-		layout.itemS()
-
-		layout.itemM(context, "IMAGE_MT_uvs_transform")
-		layout.itemM(context, "IMAGE_MT_uvs_mirror")
-		layout.itemM(context, "IMAGE_MT_uvs_weldalign")
-
-		layout.itemS()
-
-		# XXX layout.itemR(scene, "proportional_editing")
-		layout.item_menu_enumR(scene, "proportional_editing_falloff")
-
-		layout.itemS()
-
-		layout.itemM(context, "IMAGE_MT_uvs_showhide")
-
-class IMAGE_HT_header(bpy.types.Header):
-	__space_type__ = "IMAGE_EDITOR"
-
-	def draw(self, context):
-		sima = context.space_data
-		ima = sima.image
-		layout = self.layout
-
-		show_render = sima.show_render
-		show_paint = sima.show_paint
-		show_uvedit = sima.show_uvedit
-
-		layout.template_header(context)
-
-		# menus
-		if context.area.show_menus:
-			row = layout.row()
-			row.itemM(context, "IMAGE_MT_view")
-
-			if show_uvedit:
-				row.itemM(context, "IMAGE_MT_select")
-
-			# XXX menuname= (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))? "Image*": "Image";
-			row.itemM(context, "IMAGE_MT_image")
-
-			if show_uvedit:
-				row.itemM(context, "IMAGE_MT_uvs")
-
-		layout.template_ID(context, sima, "image", new="IMAGE_OT_new", open="IMAGE_OT_open")
-
-		"""
-		/* image select */
-
-		pinflag= (show_render)? 0: UI_ID_PIN;
-		xco= uiDefIDPoinButs(block, CTX_data_main(C), NULL, (ID*)sima->image, ID_IM, &sima->pin, xco, yco,
-			sima_idpoin_handle, UI_ID_BROWSE|UI_ID_BROWSE_RENDER|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_OPEN|UI_ID_DELETE|pinflag);
-		xco += 8;
-		"""
-
-		"""
-		if(ima && !ELEM3(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_VIEWER) && ima->ok) {
-			/* XXX this should not be a static var */
-			static int headerbuttons_packdummy;
-			
-			headerbuttons_packdummy = 0;
-
-			if (ima->packedfile) {
-				headerbuttons_packdummy = 1;
-			}
-			if (ima->packedfile && ibuf && (ibuf->userflags & IB_BITMAPDIRTY))
-				uiDefIconButBitI(block, TOG, 1, 0 /* XXX B_SIMA_REPACK */, ICON_UGLYPACKAGE,	xco,yco,XIC,YIC, &headerbuttons_packdummy, 0, 0, 0, 0, "Re-Pack this image as PNG");
-			else
-				uiDefIconButBitI(block, TOG, 1, 0 /* XXX B_SIMAPACKIMA */, ICON_PACKAGE,	xco,yco,XIC,YIC, &headerbuttons_packdummy, 0, 0, 0, 0, "Pack/Unpack this image");
-				
-			xco+= XIC+8;
-		}
-		"""
-
-		# uv editing
-		if show_uvedit:
+			if settings.uv_sync_selection:
+				layout.itemR(settings, "mesh_selection_mode", text="", expand=True)
+			else:
+				layout.itemR(settings, "uv_selection_mode", text="", expand=True)
+				layout.itemR(uvedit, "sticky_selection_mode", text="")
 			pass
-		
-		"""
-		/* uv editing */
-		if(show_uvedit) {
-			/* pivot */
-			uiDefIconTextButS(block, ICONTEXTROW, B_NOP, ICON_ROTATE,
-					"Pivot: %t|Bounding Box Center %x0|Median Point %x3|2D Cursor %x1",
-					xco,yco,XIC+10,YIC, &ar->v2d.around, 0, 3.0, 0, 0,
-					"Rotation/Scaling Pivot (Hotkeys: Comma, Shift Comma, Period)");
-			xco+= XIC + 18;
-			
-			/* selection modes */
-			uiDefIconButBitS(block, TOG, UV_SYNC_SELECTION, B_REDR, ICON_EDIT, xco,yco,XIC,YIC, &scene->toolsettings->uv_flag, 0, 0, 0, 0, "Sync UV and Mesh Selection");
-			xco+= XIC+8;
 
-			if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
-				uiBlockBeginAlign(block);
-				
-				uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_REDR, ICON_VERTEXSEL,
-					xco,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode");
-				uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_REDR, ICON_EDGESEL,
-					xco+=XIC,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Edge select mode");
-				uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_REDR, ICON_FACESEL,
-					xco+=XIC,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Face select mode");
+			row = layout.row(align=True)
+			row.itemR(settings, "snap", text="")
+			if settings.snap:
+				row.itemR(settings, "snap_mode", text="")
 
-				uiBlockEndAlign(block);
-			}
-			else {
-				uiBlockBeginAlign(block);
-
-				uiDefIconButS(block, ROW, B_REDR, ICON_VERTEXSEL,
-					xco,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_VERTEX, 0, 0, "Vertex select mode");
-				uiDefIconButS(block, ROW, B_REDR, ICON_EDGESEL,
-					xco+=XIC,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_EDGE, 0, 0, "Edge select mode");
-				uiDefIconButS(block, ROW, B_REDR, ICON_FACESEL,
-					xco+=XIC,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_FACE, 0, 0, "Face select mode");
-				uiDefIconButS(block, ROW, B_REDR, ICON_LINKEDSEL,
-					xco+=XIC,yco,XIC,YIC, &scene->toolsettings->uv_selectmode, 1.0, UV_SELECT_ISLAND, 0, 0, "Island select mode");
-
-				uiBlockEndAlign(block);
-
-				/* would use these if const's could go in strings 
-				 * SI_STICKY_LOC SI_STICKY_DISABLE SI_STICKY_VERTEX */
-				but = uiDefIconTextButC(block, ICONTEXTROW, B_REDR, ICON_STICKY_UVS_LOC,
-						"Sticky UV Selection: %t|Disable%x1|Shared Location%x0|Shared Vertex%x2",
-						xco+=XIC+10,yco,XIC+10,YIC, &(sima->sticky), 0, 3.0, 0, 0,
-						"Sticky UV Selection (Hotkeys: Shift C, Alt C, Ctrl C)");
-			}
-
-			xco+= XIC + 16;
-			
-			/* snap options, identical to options in 3d view header */
-			uiBlockBeginAlign(block);
-
-			if (scene->snap_flag & SCE_SNAP) {
-				uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEO,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Use Snap or Grid (Shift Tab).");
-				xco+= XIC;
-				uiDefButS(block, MENU, B_NOP, "Mode%t|Closest%x0|Center%x1|Median%x2",xco,yco,70,YIC, &scene->snap_target, 0, 0, 0, 0, "Snap Target Mode.");
-				xco+= 70;
-			}
-			else {
-				uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEAR,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab).");	
-				xco+= XIC;
-			}
-
-			uiBlockEndAlign(block);
-			xco+= 8;
-
-			/* uv layers */
-			{
-				Object *obedit= CTX_data_edit_object(C);
-				char menustr[34*MAX_MTFACE];
-				static int act;
-				
-				image_menu_uvlayers(obedit, menustr, &act);
-
-				but = uiDefButI(block, MENU, B_NOP, menustr ,xco,yco,85,YIC, &act, 0, 0, 0, 0, "Active UV Layer for editing.");
-				// uiButSetFunc(but, do_image_buttons_set_uvlayer_callback, &act, NULL);
-				
-				xco+= 85;
-			}
-
-			xco+= 8;
-		}
-		"""
+			"""
+			mesh = context.edit_object.data
+			row.item_pointerR(mesh, "active_uv_layer", mesh, "uv_layers")
+			"""
 
 		if ima:
-			"""
-			RenderResult *rr;
-		
-			/* render layers and passes */
-			rr= BKE_image_get_renderresult(scene, ima);
-			if(rr) {
-				uiBlockBeginAlign(block);
-#if 0
-				uiblock_layer_pass_buttons(block, rr, &sima->iuser, B_REDR, xco, 0, 160);
-#endif
-				uiBlockEndAlign(block);
-				xco+= 166;
-			}
-			"""
+			# layers
+			layout.template_image_layers(ima, iuser)
 
 			# painting
 			layout.itemR(sima, "image_painting", text="")
@@ -791,6 +303,10 @@ class IMAGE_PT_game_properties(bpy.types.Panel):
 	__region_type__ = "UI"
 	__label__ = "Game Properties"
 
+	def poll(self, context):
+		sima = context.space_data
+		return (sima and sima.image)
+
 	def draw(self, context):
 		sima = context.space_data
 		layout = self.layout
@@ -800,28 +316,74 @@ class IMAGE_PT_game_properties(bpy.types.Panel):
 		if ima:
 			split = layout.split()
 
-			col = split.column(align=True)
-			col.itemR(ima, "animated")
+			col = split.column()
 
-			subcol = col.column()
+			subcol = col.column(align=True)
+			subcol.itemR(ima, "clamp_x")
+			subcol.itemR(ima, "clamp_y")
+
+			col.itemR(ima, "mapping", expand=True)
+			col.itemR(ima, "tiles")
+
+			col = split.column()
+
+			subcol = col.column(align=True)
+			subcol.itemR(ima, "animated")
+
+			subcol = subcol.column()
 			subcol.itemR(ima, "animation_start", text="Start")
 			subcol.itemR(ima, "animation_end", text="End")
 			subcol.itemR(ima, "animation_speed", text="Speed")
 			subcol.active = ima.animated
 
-			col = split.column()
-			col.itemR(ima, "tiles")
-
 			subrow = col.row(align=True)
 			subrow.itemR(ima, "tiles_x", text="X")
 			subrow.itemR(ima, "tiles_y", text="Y")
-			subrow.active = ima.tiles
+			subrow.active = ima.tiles or ima.animated
 
-			col.itemS()
-			col.itemR(ima, "clamp_x")
-			col.itemR(ima, "clamp_y")
+class IMAGE_PT_view_properties(bpy.types.Panel):
+	__space_type__ = "IMAGE_EDITOR"
+	__region_type__ = "UI"
+	__label__ = "View Properties"
 
-			col.itemR(ima, "mapping", expand=True)
+	def poll(self, context):
+		sima = context.space_data
+		return (sima and (sima.image or sima.show_uvedit))
+
+	def draw(self, context):
+		sima = context.space_data
+		layout = self.layout
+
+		ima = sima.image
+		show_uvedit = sima.show_uvedit
+		uvedit = sima.uv_editor
+
+		split = layout.split()
+
+		col = split.column()
+		if ima:
+			col.itemR(ima, "display_aspect")
+
+			col = split.column()
+			col.itemR(sima, "draw_repeated", text="Repeat")
+			if show_uvedit:
+				col.itemR(uvedit, "normalized_coordinates", text="Normalized")
+		elif show_uvedit:
+			col.itemR(uvedit, "normalized_coordinates", text="Normalized")
+
+		if show_uvedit:
+			col = layout.column()
+			row = col.row()
+			row.itemR(uvedit, "edge_draw_type", expand=True)
+			row = col.row()
+			row.itemR(uvedit, "draw_smooth_edges", text="Smooth")
+			row.itemR(uvedit, "draw_modified_edges", text="Modified")
+
+			row = col.row()
+			row.itemR(uvedit, "draw_stretch", text="Stretch")
+			row.itemR(uvedit, "draw_stretch_type", text="")
+			#col.itemR(uvedit, "draw_edges")
+			#col.itemR(uvedit, "draw_faces")
 
 bpy.types.register(IMAGE_MT_view)
 bpy.types.register(IMAGE_MT_select)
@@ -833,4 +395,5 @@ bpy.types.register(IMAGE_MT_uvs_weldalign)
 bpy.types.register(IMAGE_MT_uvs)
 bpy.types.register(IMAGE_HT_header)
 bpy.types.register(IMAGE_PT_game_properties)
+bpy.types.register(IMAGE_PT_view_properties)
 
diff --git a/release/ui/space_info.py b/release/ui/space_info.py
new file mode 100644
index 00000000000..de3346711e9
--- /dev/null
+++ b/release/ui/space_info.py
@@ -0,0 +1,119 @@
+
+import bpy
+
+class INFO_HT_header(bpy.types.Header):
+	__space_type__ = "USER_PREFERENCES"
+	__idname__ = "INFO_HT_header"
+
+	def draw(self, context):
+		st = context.space_data
+		layout = self.layout
+		
+		layout.template_header()
+
+		if context.area.show_menus:
+			row = layout.row()
+			row.itemM("INFO_MT_file")
+			row.itemM("INFO_MT_add")
+			row.itemM("INFO_MT_timeline")
+			row.itemM("INFO_MT_game")
+			row.itemM("INFO_MT_render")
+			row.itemM("INFO_MT_help")
+
+		layout.template_ID(context.window, "screen") #, new="SCREEN_OT_new", open="SCREEN_OT_unlink")
+		layout.template_ID(context.screen, "scene") #, new="SCENE_OT_new", unlink="SCENE_OT_unlink")
+
+		layout.itemS()
+
+		layout.template_operator_search()
+		layout.template_running_jobs()
+			
+class INFO_MT_file(bpy.types.Menu):
+	__space_type__ = "USER_PREFERENCES"
+	__label__ = "File"
+
+	def draw(self, context):
+		layout = self.layout
+
+		layout.operator_context = "EXEC_AREA"
+		layout.itemO("WM_OT_read_homefile")
+		layout.operator_context = "INVOKE_AREA"
+		layout.itemO("WM_OT_open_mainfile")
+
+		layout.itemS()
+
+		layout.operator_context = "EXEC_AREA"
+		layout.itemO("WM_OT_save_mainfile")
+		layout.operator_context = "INVOKE_AREA"
+		layout.itemO("WM_OT_save_as_mainfile")
+
+		layout.itemS()
+
+		layout.itemM("INFO_MT_file_external_data")
+
+class INFO_MT_file_external_data(bpy.types.Menu):
+	__space_type__ = "USER_PREFERENCES"
+	__label__ = "External Data"
+
+	def draw(self, context):
+		layout = self.layout
+
+		layout.itemO("FILE_OT_pack_all", text="Pack into .blend file")
+		layout.itemO("FILE_OT_unpack_all", text="Unpack into Files...")
+
+		layout.itemS()
+
+		layout.itemO("FILE_OT_make_paths_relative")
+		layout.itemO("FILE_OT_make_paths_absolute")
+		layout.itemO("FILE_OT_report_missing_files")
+		layout.itemO("FILE_OT_find_missing_files")
+
+class INFO_MT_add(bpy.types.Menu):
+	__space_type__ = "USER_PREFERENCES"
+	__label__ = "Add"
+
+	def draw(self, context):
+		layout = self.layout
+		layout.itemL(text="Nothing yet")
+
+class INFO_MT_timeline(bpy.types.Menu):
+	__space_type__ = "USER_PREFERENCES"
+	__label__ = "Timeline"
+
+	def draw(self, context):
+		layout = self.layout
+		layout.itemL(text="Nothing yet")
+
+class INFO_MT_game(bpy.types.Menu):
+	__space_type__ = "USER_PREFERENCES"
+	__label__ = "Game"
+
+	def draw(self, context):
+		layout = self.layout
+		layout.itemL(text="Nothing yet")
+
+class INFO_MT_render(bpy.types.Menu):
+	__space_type__ = "USER_PREFERENCES"
+	__label__ = "Render"
+
+	def draw(self, context):
+		layout = self.layout
+		layout.itemL(text="Nothing yet")
+
+class INFO_MT_help(bpy.types.Menu):
+	__space_type__ = "USER_PREFERENCES"
+	__label__ = "Help"
+
+	def draw(self, context):
+		layout = self.layout
+		layout.itemL(text="Nothing yet")
+
+bpy.types.register(INFO_HT_header)
+bpy.types.register(INFO_MT_file)
+bpy.types.register(INFO_MT_file_external_data)
+bpy.types.register(INFO_MT_add)
+bpy.types.register(INFO_MT_timeline)
+bpy.types.register(INFO_MT_game)
+bpy.types.register(INFO_MT_render)
+bpy.types.register(INFO_MT_help)
+
diff --git a/release/ui/space_logic.py b/release/ui/space_logic.py
index 71d94c86bf3..f862f6e2667 100644
--- a/release/ui/space_logic.py
+++ b/release/ui/space_logic.py
@@ -5,6 +5,10 @@ class LOGIC_PT_physics(bpy.types.Panel):
 	__region_type__ = "UI"
 	__label__ = "Physics"
 
+	def poll(self, context):
+		ob = context.active_object
+		return ob and ob.game
+
 	def draw(self, context):
 		layout = self.layout
 		ob = context.active_object
@@ -56,6 +60,10 @@ class LOGIC_PT_collision_bounds(bpy.types.Panel):
 	__space_type__ = "LOGIC_EDITOR"
 	__region_type__ = "UI"
 	__label__ = "Collision Bounds"
+
+	def poll(self, context):
+		ob = context.active_object
+		return ob and ob.game
 	
 	def draw_header(self, context):
 		layout = self.layout
diff --git a/release/ui/space_outliner.py b/release/ui/space_outliner.py
index f039eb3f7c3..5a6ee5ea2aa 100644
--- a/release/ui/space_outliner.py
+++ b/release/ui/space_outliner.py
@@ -10,11 +10,11 @@ class OUTLINER_HT_header(bpy.types.Header):
 		sce = context.scene
 		layout = self.layout
 
-		layout.template_header(context)
+		layout.template_header()
 
 		if context.area.show_menus:
 			row = layout.row(align=True)
-			row.itemM(context, "OUTLINER_MT_view")
+			row.itemM("OUTLINER_MT_view")
 			
 		row = layout.row()
 		row.itemR(so, "display_mode", text="")
diff --git a/release/ui/space_sequencer.py b/release/ui/space_sequencer.py
index 94858db81ad..b64e7d8e0c4 100644
--- a/release/ui/space_sequencer.py
+++ b/release/ui/space_sequencer.py
@@ -15,21 +15,21 @@ class SEQUENCER_HT_header(bpy.types.Header):
 		st = context.space_data
 		layout = self.layout
 
-		layout.template_header(context)
+		layout.template_header()
 		
 		if context.area.show_menus:
 			row = layout.row()
-			row.itemM(context, "SEQUENCER_MT_view")
+			row.itemM("SEQUENCER_MT_view")
 			
 			row.itemR(st, "display_mode")
 			
 			layout.itemS()
 			
 			if st.display_mode == 'SEQUENCER':
-				row.itemM(context, "SEQUENCER_MT_select")
-				row.itemM(context, "SEQUENCER_MT_marker")
-				row.itemM(context, "SEQUENCER_MT_add")
-				row.itemM(context, "SEQUENCER_MT_strip")
+				row.itemM("SEQUENCER_MT_select")
+				row.itemM("SEQUENCER_MT_marker")
+				row.itemM("SEQUENCER_MT_add")
+				row.itemM("SEQUENCER_MT_strip")
 				layout.itemS()
 				row.itemO("SEQUENCER_OT_reload")
 			else:
@@ -151,7 +151,7 @@ class SEQUENCER_MT_add(bpy.types.Menu):
 		layout.itemO("SEQUENCER_OT_sound_strip_add", text="Sound (Ram)")
 		layout.item_booleanO("SEQUENCER_OT_sound_strip_add", "hd", True, text="Sound (Streaming)") # FFMPEG ONLY
 		
-		layout.itemM(context, "SEQUENCER_MT_add_effect")
+		layout.itemM("SEQUENCER_MT_add_effect")
 
 
 class SEQUENCER_MT_add_effect(bpy.types.Menu):
diff --git a/release/ui/space_text.py b/release/ui/space_text.py
index 42e5347ce6a..07e43f32054 100644
--- a/release/ui/space_text.py
+++ b/release/ui/space_text.py
@@ -1,10 +1,6 @@
 
 import bpy
 
-# temporary
-ICON_TEXT = 120
-ICON_HELP = 1
-
 class TEXT_HT_header(bpy.types.Header):
 	__space_type__ = "TEXT_EDITOR"
 	__idname__ = "TEXT_HT_header"
@@ -14,14 +10,14 @@ class TEXT_HT_header(bpy.types.Header):
 		text = st.text
 		layout = self.layout
 
-		layout.template_header(context)
+		layout.template_header()
 
 		if context.area.show_menus:
 			row = layout.row()
-			row.itemM(context, "TEXT_MT_text")
+			row.itemM("TEXT_MT_text")
 			if text:
-				row.itemM(context, "TEXT_MT_edit")
-				row.itemM(context, "TEXT_MT_format")
+				row.itemM("TEXT_MT_edit")
+				row.itemM("TEXT_MT_format")
 
 		if text and text.modified:
 			row = layout.row()
@@ -33,7 +29,7 @@ class TEXT_HT_header(bpy.types.Header):
 		row.itemR(st, "word_wrap", text="")
 		row.itemR(st, "syntax_highlight", text="")
 
-		layout.template_ID(context, st, "text", new="TEXT_OT_new", open="TEXT_OT_open", unlink="TEXT_OT_unlink")
+		layout.template_ID(st, "text", new="TEXT_OT_new", unlink="TEXT_OT_unlink")
 
 		if text:
 			row = layout.row()
@@ -217,9 +213,9 @@ class TEXT_MT_edit(bpy.types.Menu):
 
 		layout.itemS()
 
-		layout.itemM(context, "TEXT_MT_edit_view")
-		layout.itemM(context, "TEXT_MT_edit_select")
-		layout.itemM(context, "TEXT_MT_edit_markers")
+		layout.itemM("TEXT_MT_edit_view")
+		layout.itemM("TEXT_MT_edit_select")
+		layout.itemM("TEXT_MT_edit_markers")
 
 		layout.itemS()
 
@@ -228,7 +224,7 @@ class TEXT_MT_edit(bpy.types.Menu):
 
 		layout.itemS()
 
-		layout.itemM(context, "TEXT_MT_edit_to3d")
+		layout.itemM("TEXT_MT_edit_to3d")
 
 bpy.types.register(TEXT_HT_header)
 bpy.types.register(TEXT_PT_properties)
diff --git a/source/Makefile b/source/Makefile
index 2df57f58c73..62eb25acbc1 100644
--- a/source/Makefile
+++ b/source/Makefile
@@ -115,25 +115,16 @@ ifneq ($(NAN_NO_KETSJI),true)
     COMLIB += $(OCGDIR)/gameengine/ketsji/$(DEBUG_DIR)libketsji.a
     COMLIB += $(OCGDIR)/gameengine/blconverter/$(DEBUG_DIR)libblconverter.a
     COMLIB += $(OCGDIR)/gameengine/blconverter/$(DEBUG_DIR)libblconverter.a
-    COMLIB += $(NAN_SOLID)/lib/libsolid.a
-    COMLIB += $(NAN_SOLID)/lib/libsolid_broad.a
-    COMLIB += $(NAN_SOLID)/lib/libsolid_complex.a
-    COMLIB += $(NAN_SOLID)/lib/libsolid_convex.a
-    COMLIB += $(OCGDIR)/gameengine/blphys/sumo/$(DEBUG_DIR)libsumo.a
     COMLIB += $(OCGDIR)/gameengine/blphys/fuzzics/$(DEBUG_DIR)libfuzzics.a
     COMLIB += $(NAN_QHULL)/lib/libqhull.a
     COMLIB += $(OCGDIR)/gameengine/blphys/dummy/$(DEBUG_DIR)libdummy.a
     COMLIB += $(OCGDIR)/gameengine/blphys/common/$(DEBUG_DIR)libcommon.a
-#    COMLIB += $(OCGDIR)/gameengine/blphys/sumo/$(DEBUG_DIR)libsumo.a
     COMLIB += $(OCGDIR)/gameengine/blphys/dummy/$(DEBUG_DIR)libdummy.a
     COMLIB += $(OCGDIR)/gameengine/ketsji/$(DEBUG_DIR)libketsji.a
     COMLIB += $(OCGDIR)/gameengine/blphys/common/$(DEBUG_DIR)libcommon.a
-#    COMLIB += $(OCGDIR)/gameengine/blphys/blode/$(DEBUG_DIR)libblode.a
-#    COMLIB += $(OCGDIR)/gameengine/blphys/sumo/$(DEBUG_DIR)libsumo.a
     COMLIB += $(OCGDIR)/gameengine/blphys/dummy/$(DEBUG_DIR)libdummy.a
     COMLIB += $(OCGDIR)/gameengine/blphys/blbullet/$(DEBUG_DIR)libblbullet.a
     COMLIB += $(OCGDIR)/gameengine/blphys/common/$(DEBUG_DIR)libcommon.a
-#    COMLIB += $(OCGDIR)/gameengine/blphys/sumo/$(DEBUG_DIR)libsumo.a
     COMLIB += $(OCGDIR)/gameengine/blphys/dummy/$(DEBUG_DIR)libdummy.a
     COMLIB += $(OCGDIR)/gameengine/ketsji/$(DEBUG_DIR)libketsji.a
     COMLIB += $(OCGDIR)/gameengine/logic/$(DEBUG_DIR)liblogic.a
@@ -143,8 +134,6 @@ ifneq ($(NAN_NO_KETSJI),true)
     COMLIB += $(OCGDIR)/gameengine/expression/$(DEBUG_DIR)libexpression.a
     COMLIB += $(OCGDIR)/gameengine/scenegraph/$(DEBUG_DIR)libscenegraph.a
     COMLIB += $(OCGDIR)/gameengine/videotex/$(DEBUG_DIR)libvideotex.a
-#    COMLIB += $(OCGDIR)/sumo/$(DEBUG_DIR)libfuzzics.a
-#    COMLIB += $(OCGDIR)/sumo/$(DEBUG_DIR)libsolid.a
     COMLIB += $(NAN_MOTO)/lib/libmoto.a
     COMLIB += $(NAN_SND_LIBS)
     COMLIB += $(OCGDIR)/kernel/gen_system/$(DEBUG_DIR)libgen_system.a
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index a53b15673e2..a9e3d50211f 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -37,7 +37,6 @@ ADD_SUBDIRECTORY(imbuf/intern/cineon)
 ADD_SUBDIRECTORY(gpu)
 ADD_SUBDIRECTORY(makesdna)
 ADD_SUBDIRECTORY(makesrna)
-ADD_SUBDIRECTORY(radiosity)
 ADD_SUBDIRECTORY(readblenfile)
 ADD_SUBDIRECTORY(render)
 ADD_SUBDIRECTORY(blenfont)
diff --git a/source/blender/Makefile b/source/blender/Makefile
index 64eb1a2614b..31636f838c3 100644
--- a/source/blender/Makefile
+++ b/source/blender/Makefile
@@ -31,7 +31,7 @@
 include nan_definitions.mk
 
 DIRS = windowmanager editors blenloader readblenfile
-DIRS += avi imbuf render radiosity blenlib blenkernel blenpluginapi
+DIRS += avi imbuf render blenlib blenkernel blenpluginapi
 DIRS += makesdna makesrna
 DIRS += python nodes gpu
 DIRS += blenfont
diff --git a/source/blender/SConscript b/source/blender/SConscript
index 691fbf9b494..a064850c170 100644
--- a/source/blender/SConscript
+++ b/source/blender/SConscript
@@ -13,7 +13,6 @@ SConscript(['avi/SConscript',
             'imbuf/intern/cineon/SConscript',
             'makesdna/SConscript',
             'makesrna/SConscript',
-            'radiosity/SConscript',
             'readblenfile/SConscript',
             'render/SConscript',
             'nodes/SConscript',
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index e871de490f3..2ee31a17fa6 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -90,6 +90,21 @@ void BLF_kerning(float space);
 void BLF_enable(int option);
 void BLF_disable(int option);
 
+/*
+ * Shadow options, level is the blur level, can be 3, 5 or 0 and
+ * the other argument are the rgba color.
+ * Take care that shadow need to be enable using BLF_enable!!.
+ */
+void BLF_shadow(int level, float r, float g, float b, float a);
+
+/*
+ * Set the offset for shadow text, this is the current cursor
+ * position plus this offset, don't need call BLF_position before
+ * this function, the current position is calculate only on
+ * BLF_draw, so it's safe call this whenever you like.
+ */
+void BLF_shadow_offset(int x, int y);
+
 /*
  * Search the path directory to the locale files, this try all
  * the case for Linux, Win and Mac.
@@ -119,6 +134,8 @@ void BLF_dir_free(char **dirs, int count);
 #define BLF_CLIPPING (1<<1)
 #define BLF_FONT_KERNING (1<<2)
 #define BLF_USER_KERNING (1<<3)
+#define BLF_SHADOW (1<<4)
+#define BLF_OVERLAP_CHAR (1<<5)
 
 /* font->mode. */
 #define BLF_MODE_TEXTURE 0
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index f06c7fb0d28..9dad5a4bfa0 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -500,3 +500,28 @@ void BLF_kerning(float space)
 	if (font)
 		font->kerning= space;
 }
+
+void BLF_shadow(int level, float r, float g, float b, float a)
+{
+	FontBLF *font;
+
+	font= global_font[global_font_cur];
+	if (font) {
+		font->shadow= level;
+		font->shadow_col[0]= r;
+		font->shadow_col[1]= g;
+		font->shadow_col[2]= b;
+		font->shadow_col[3]= a;
+	}
+}
+
+void BLF_shadow_offset(int x, int y)
+{
+	FontBLF *font;
+
+	font= global_font[global_font_cur];
+	if (font) {
+		font->shadow_x= x;
+		font->shadow_y= y;
+	}
+}
diff --git a/source/blender/blenfont/intern/blf_dir.c b/source/blender/blenfont/intern/blf_dir.c
index 88b0105a292..92dfe8457b0 100644
--- a/source/blender/blenfont/intern/blf_dir.c
+++ b/source/blender/blenfont/intern/blf_dir.c
@@ -1,5 +1,5 @@
 /**
- * $Id: blf_dir.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index ee4ba0ee71a..a3c5232cc76 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -146,20 +146,22 @@ void blf_font_draw(FontBLF *font, char *str)
 
 			if (FT_Get_Kerning(font->face, g_prev_index, glyph_index, FT_KERNING_UNFITTED, &delta) == 0) {
 				pen_x += delta.x >> 6;
-/*
-				if (pen_x < old_pen_x)
-					pen_x= old_pen_x;
-*/
+
+				if (font->flags & BLF_OVERLAP_CHAR) {
+					if (pen_x < old_pen_x)
+						pen_x= old_pen_x;
+				}
 			}
 		}
 
 		if (font->flags & BLF_USER_KERNING) {
 			old_pen_x= pen_x;
 			pen_x += font->kerning;
-/*
-			if (pen_x < old_pen_x)
-				pen_x= old_pen_x;
-*/
+
+			if (font->flags & BLF_OVERLAP_CHAR) {
+				if (pen_x < old_pen_x)
+					pen_x= old_pen_x;
+			}
 		}
 
 		/* do not return this loop if clipped, we want every character tested */
@@ -228,20 +230,22 @@ void blf_font_boundbox(FontBLF *font, char *str, rctf *box)
 
 			if (FT_Get_Kerning(font->face, g_prev_index, glyph_index, FT_KERNING_UNFITTED, &delta) == 0) {
 				pen_x += delta.x >> 6;
-/*
-				if (pen_x < old_pen_x)
-					old_pen_x= pen_x;
-*/
+
+				if (font->flags & BLF_OVERLAP_CHAR) {
+					if (pen_x < old_pen_x)
+						pen_x= old_pen_x;
+				}
 			}
 		}
 
 		if (font->flags & BLF_USER_KERNING) {
 			old_pen_x= pen_x;
 			pen_x += font->kerning;
-/*
-			if (pen_x < old_pen_x)
-				old_pen_x= pen_x;
-*/
+
+			if (font->flags & BLF_OVERLAP_CHAR) {
+				if (pen_x < old_pen_x)
+					pen_x= old_pen_x;
+			}
 		}
 
 		gbox.xmin= g->box.xmin + pen_x;
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 33a435cc5be..a637774d7bf 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -496,8 +496,20 @@ int blf_glyph_texture_render(FontBLF *font, GlyphBLF *g, float x, float y)
 	GLint cur_tex;
 	float dx, dx1;
 	float y1, y2;
+	float xo, yo;
+	float color[4];
 
 	gt= g->tex_data;
+	xo= 0.0f;
+	yo= 0.0f;
+
+	if (font->flags & BLF_SHADOW) {
+		xo= x;
+		yo= y;
+		x += font->shadow_x;
+		y += font->shadow_y;
+	}
+
 	dx= floor(x + gt->pos_x);
 	dx1= dx + gt->width;
 	y1= y + gt->pos_y;
@@ -518,6 +530,27 @@ int blf_glyph_texture_render(FontBLF *font, GlyphBLF *g, float x, float y)
 	if (cur_tex != gt->tex)
 		glBindTexture(GL_TEXTURE_2D, gt->tex);
 
+	if (font->flags & BLF_SHADOW) {
+		glGetFloatv(GL_CURRENT_COLOR, color);
+		glColor4fv(font->shadow_col);
+
+		if (font->shadow == 3)
+			blf_texture3_draw(gt->uv, dx, y1, dx1, y2);
+		else if (font->shadow == 5)
+			blf_texture5_draw(gt->uv, dx, y1, dx1, y2);
+		else
+			blf_texture_draw(gt->uv, dx, y1, dx1, y2);
+
+		glColor4fv(color);
+		x= xo;
+		y= yo;
+
+		dx= floor(x + gt->pos_x);
+		dx1= dx + gt->width;
+		y1= y + gt->pos_y;
+		y2= y + gt->pos_y - gt->height;
+	}
+
 	if (font->blur==3)
 		blf_texture3_draw(gt->uv, dx, y1, dx1, y2);
 	else if (font->blur==5)
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index af237690b58..c9bdc428ebb 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -1,5 +1,5 @@
 /**
- * $Id: blf_internal.h 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index ba988c522f0..5382ac19aae 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -1,5 +1,5 @@
 /**
- * $Id: blf_internal_types.h 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -154,6 +154,16 @@ typedef struct FontBLF {
 	
 	/* blur: 3 or 5 large kernel */
 	int blur;
+
+	/* shadow level. */
+	int shadow;
+
+	/* and shadow offset. */
+	int shadow_x;
+	int shadow_y;
+
+	/* shadow color. */
+	float shadow_col[4];
 	
 	/* this is the matrix that we load before rotate/scale/translate. */
 	float mat[4][4];
diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c
index 757a18f0165..024172d6db4 100644
--- a/source/blender/blenfont/intern/blf_lang.c
+++ b/source/blender/blenfont/intern/blf_lang.c
@@ -1,5 +1,5 @@
 /**
- * $Id: blf_lang.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index e09be838f06..4270c677338 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -46,6 +46,7 @@
 #include "DNA_meshdata_types.h"
 #include "DNA_modifier_types.h"
 #include "DNA_object_types.h"
+#include "DNA_scene_types.h"
 
 #include "BKE_collision.h"
 
@@ -245,8 +246,8 @@ void bvhtree_update_from_cloth ( ClothModifierData *clmd, int moving );
 void bvhselftree_update_from_cloth ( ClothModifierData *clmd, int moving );
 
 // needed for editmesh.c
-void cloth_write_cache ( Object *ob, ClothModifierData *clmd, float framenr );
-int cloth_read_cache ( Object *ob, ClothModifierData *clmd, float framenr );
+void cloth_write_cache( Object *ob, ClothModifierData *clmd, int framenr );
+int cloth_read_cache( Scene *scene, Object *ob, ClothModifierData *clmd, float framenr, int *old_framenr );
 
 // needed for button_object.c
 void cloth_clear_cache ( Object *ob, ClothModifierData *clmd, float framenr );
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 1845665a96d..f536e117b7b 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -1,5 +1,5 @@
 /**
- * $Id: BKE_context.h 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -131,6 +131,7 @@ void CTX_wm_menu_set(bContext *C, struct ARegion *menu);
    - the dir listbase consits of LinkData items */
 
 PointerRNA CTX_data_pointer_get(const bContext *C, const char *member);
+PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type);
 ListBase CTX_data_collection_get(const bContext *C, const char *member);
 ListBase CTX_data_dir_get(const bContext *C);
 void CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb);
diff --git a/source/blender/blenkernel/BKE_exotic.h b/source/blender/blenkernel/BKE_exotic.h
index 11dc1f41109..5c47eeabfe8 100644
--- a/source/blender/blenkernel/BKE_exotic.h
+++ b/source/blender/blenkernel/BKE_exotic.h
@@ -47,7 +47,6 @@ int BKE_read_exotic(struct Scene *scene, char *name);
 
 void write_dxf(struct Scene *scene, char *str);
 void write_vrml(struct Scene *scene, char *str);
-void write_videoscape(struct Scene *scene, char *str);
 void write_stl(struct Scene *scene, char *str);
 
 #endif
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 581285be21c..1892c8e71a4 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -1,5 +1,5 @@
 /**
- * $Id: BDR_gpencil.h 19541 2009-04-05 06:54:47Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index 38a1d9b13b7..382754ee2b2 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -39,6 +39,8 @@ struct Material;
 struct ID;
 struct Object;
 
+/* materials */
+
 void init_def_material(void);
 void free_material(struct Material *sc); 
 void test_object_materials(struct ID *id);
@@ -47,15 +49,22 @@ struct Material *add_material(char *name);
 struct Material *copy_material(struct Material *ma);
 void make_local_material(struct Material *ma);
 
+void automatname(struct Material *);
+
+/* material slots */
+
 struct Material ***give_matarar(struct Object *ob);
 short *give_totcolp(struct Object *ob);
 struct Material *give_current_material(struct Object *ob, int act);
 struct ID *material_from(struct Object *ob, int act);
 void assign_material(struct Object *ob, struct Material *ma, int act);
-void new_material_to_objectdata(struct Object *ob);
 
 int find_material_index(struct Object *ob, struct Material *ma);
 
+void object_add_material_slot(struct Object *ob);
+void object_remove_material_slot(struct Object *ob);
+
+/* rendering */
 
 void init_render_material(struct Material *, int, float *);
 void init_render_materials(int, float *);
@@ -64,12 +73,8 @@ void end_render_materials(void);
 
 int material_in_material(struct Material *parmat, struct Material *mat);
 
-void automatname(struct Material *);
-void delete_material_index(struct Object *ob);            
-
 void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col);
 
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h
index 2d5acc51b7b..efd930d375a 100644
--- a/source/blender/blenkernel/BKE_packedFile.h
+++ b/source/blender/blenkernel/BKE_packedFile.h
@@ -31,31 +31,43 @@
 #ifndef BKE_PACKEDFILE_H
 #define BKE_PACKEDFILE_H
 
-#define RET_OK 0
-#define RET_ERROR 1
+#define RET_OK		0
+#define RET_ERROR	1
 
-struct PackedFile;
-struct VFont;
 struct bSample;
 struct bSound;
 struct Image;
+struct Main;
+struct PackedFile;
+struct ReportList;
+struct VFont;
 
-struct PackedFile * newPackedFile(char * filename);
-struct PackedFile * newPackedFileMemory(void *mem, int memlen);
+/* pack */
+struct PackedFile *newPackedFile(struct ReportList *reports, char *filename);
+struct PackedFile *newPackedFileMemory(void *mem, int memlen);
+
+void packAll(struct Main *bmain, struct ReportList *reports);
+
+/* unpack */
+char *unpackFile(struct ReportList *reports, char *abs_name, char *local_name, struct PackedFile *pf, int how);
+int unpackVFont(struct ReportList *reports, struct VFont *vfont, int how);
+int unpackSample(struct ReportList *reports, struct bSample *sample, int how);
+int unpackImage(struct ReportList *reports, struct Image *ima, int how);
+void unpackAll(struct Main *bmain, struct ReportList *reports, int how);
+
+int writePackedFile(struct ReportList *reports, char *filename, struct PackedFile *pf, int guimode);
+
+/* free */
+void freePackedFile(struct PackedFile *pf);
+
+/* info */
+int countPackedFiles(struct Main *bmain);
+int checkPackedFile(char *filename, struct PackedFile *pf);
+
+/* read */
+int seekPackedFile(struct PackedFile *pf, int offset, int whence);
+void rewindPackedFile(struct PackedFile *pf);
+int readPackedFile(struct PackedFile *pf, void *data, int size);
 
-int seekPackedFile(struct PackedFile * pf, int offset, int whence);
-void rewindPackedFile(struct PackedFile * pf);
-int readPackedFile(struct PackedFile * pf, void * data, int size);
-int countPackedFiles(void);
-void freePackedFile(struct PackedFile * pf);
-void packAll(void);
-int writePackedFile(char * filename, struct PackedFile *pf, int guimode);
-int checkPackedFile(char * filename, struct PackedFile * pf);
-char * unpackFile(char * abs_name, char * local_name, struct PackedFile * pf, int how);
-int unpackVFont(struct VFont * vfont, int how);
-int unpackSample(struct bSample *sample, int how);
-int unpackImage(struct Image * ima, int how);
-void unpackAll(int how);
-	
 #endif
 
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 4efd9a7f8ba..73f0195d1d8 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -217,6 +217,8 @@ char *psys_menu_string(struct Object *ob, int for_sb);
 
 struct ParticleSystem *psys_get_current(struct Object *ob);
 short psys_get_current_num(struct Object *ob);
+void psys_set_current_num(Object *ob, int index);
+struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys);
 //struct ParticleSystem *psys_get(struct Object *ob, int index);
 struct ParticleData *psys_get_selected_particle(struct ParticleSystem *psys, int *index);
 struct ParticleKey *psys_get_selected_key(struct ParticleSystem *psys, int pa_index, int *key_index);
@@ -249,6 +251,8 @@ void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int tim
 void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor);
 struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct ParticleSystem *psys);
 
+void object_add_particle_system(struct Scene *scene, struct Object *ob);
+void object_remove_particle_system(struct Scene *scene, struct Object *ob);
 struct ParticleSettings *psys_new_settings(char *name, struct Main *main);
 struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part);
 void psys_flush_particle_settings(struct Scene *scene, struct ParticleSettings *part, int recalc);
@@ -290,10 +294,13 @@ void psys_get_reactor_target(struct Object *ob, struct ParticleSystem *psys, str
 void psys_init_effectors(struct Scene *scene, struct Object *obsrc, struct Group *group, struct ParticleSystem *psys);
 void psys_end_effectors(struct ParticleSystem *psys);
 
+void psys_get_pointcache_start_end(struct Scene *scene, struct ParticleSystem *psys, int *sfra, int *efra);
+
 void particle_system_update(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
 
 /* ----------- functions needed only inside particlesystem ------------ */
 /* particle.c */
+void psys_interpolate_particle(short type, struct ParticleKey keys[4], float dt, struct ParticleKey *result, int velocity);
 void psys_key_to_object(struct Object *ob, struct ParticleKey *key, float imat[][4]);
 //void psys_key_to_geometry(struct DerivedMesh *dm, struct ParticleData *pa, struct ParticleKey *key);
 //void psys_key_from_geometry(struct DerivedMesh *dm, struct ParticleData *pa, struct ParticleKey *key);
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index 8ef3ff4d4b7..3f1c45d28ec 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -31,6 +31,8 @@
 
 #include "DNA_ID.h"
 
+#include "MEM_guardedalloc.h"
+
 /* Point cache clearing option, for BKE_ptcache_id_clear, before
  * and after are non inclusive (they wont remove the cfra) */
 #define PTCACHE_CLEAR_ALL		0
@@ -42,6 +44,7 @@
 #define PTCACHE_RESET_DEPSGRAPH		0
 #define PTCACHE_RESET_BAKED			1
 #define PTCACHE_RESET_OUTDATED		2
+#define PTCACHE_RESET_FREE			3
 
 /* Add the blendfile name after blendcache_ */
 #define PTCACHE_EXT ".bphys"
@@ -56,6 +59,11 @@
 #define PTCACHE_TYPE_PARTICLES	1
 #define PTCACHE_TYPE_CLOTH		2
 
+/* PTCache read return code */
+#define PTCACHE_READ_EXACT				1
+#define PTCACHE_READ_INTERPOLATED		2
+#define PTCACHE_READ_OLD				3
+
 /* Structs */
 struct Object;
 struct Scene;
@@ -80,6 +88,40 @@ typedef struct PTCacheID {
 	struct PointCache *cache;
 } PTCacheID;
 
+typedef struct PTCacheWriter {
+	struct PTCacheID *pid;
+	int cfra;
+	int totelem;
+
+	void (*set_elem)(int index, void *calldata, float *data);
+	void *calldata;
+} PTCacheWriter;
+
+typedef struct PTCacheReader {
+	struct Scene *scene;
+	struct PTCacheID *pid;
+	float cfra;
+	int totelem;
+
+	void (*set_elem)(int elem_index, void *calldata, float *data);
+	void (*interpolate_elem)(int index, void *calldata, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2);
+	void *calldata;
+
+	int *old_frame;
+} PTCacheReader;
+
+typedef struct PTCacheBaker {
+	struct Scene *scene;
+	int bake;
+	int render;
+	int quick_step;
+	struct PTCacheID *pid;
+	int (*break_test)(void *data);
+	void *break_data;
+	void (*progressbar)(void *data, int num);
+	void *progresscontext;
+} PTCacheBaker;
+
 /* Creating ID's */
 void BKE_ptcache_id_from_softbody(PTCacheID *pid, struct Object *ob, struct SoftBody *sb);
 void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct ParticleSystem *psys);
@@ -93,9 +135,9 @@ void BKE_ptcache_remove(void);
 /* ID specific functions */
 void	BKE_ptcache_id_clear(PTCacheID *id, int mode, int cfra);
 int		BKE_ptcache_id_exist(PTCacheID *id, int cfra);
-int		BKE_ptcache_id_reset(PTCacheID *id, int mode);
+int		BKE_ptcache_id_reset(struct Scene *scene, PTCacheID *id, int mode);
 void	BKE_ptcache_id_time(PTCacheID *pid, struct Scene *scene, float cfra, int *startframe, int *endframe, float *timescale);
-int		BKE_ptcache_object_reset(struct Object *ob, int mode);
+int		BKE_ptcache_object_reset(struct Scene *scene, struct Object *ob, int mode);
 
 /* File reading/writing */
 PTCacheFile	*BKE_ptcache_file_open(PTCacheID *id, int mode, int cfra);
@@ -103,6 +145,12 @@ void         BKE_ptcache_file_close(PTCacheFile *pf);
 int          BKE_ptcache_file_read_floats(PTCacheFile *pf, float *f, int tot);
 int          BKE_ptcache_file_write_floats(PTCacheFile *pf, float *f, int tot);
 
+void BKE_ptcache_update_info(PTCacheID *pid);
+
+/* General cache reading/writing */
+int			 BKE_ptcache_read_cache(PTCacheReader *reader);
+int			 BKE_ptcache_write_cache(PTCacheWriter *writer);
+
 /* Continue physics */
 void BKE_ptcache_set_continue_physics(struct Scene *scene, int enable);
 int BKE_ptcache_get_continue_physics(void);
@@ -112,4 +160,9 @@ struct PointCache *BKE_ptcache_add(void);
 void BKE_ptcache_free(struct PointCache *cache);
 struct PointCache *BKE_ptcache_copy(struct PointCache *cache);
 
+/* Baking */
+void BKE_ptcache_quick_cache_all(struct Scene *scene);
+void BKE_ptcache_make_cache(struct PTCacheBaker* baker);
+void BKE_ptcache_toggle_disk_cache(struct PTCacheID *pid);
+
 #endif
diff --git a/source/blender/blenkernel/BKE_report.h b/source/blender/blenkernel/BKE_report.h
index 60e48004fb1..1bb7152fbf3 100644
--- a/source/blender/blenkernel/BKE_report.h
+++ b/source/blender/blenkernel/BKE_report.h
@@ -1,5 +1,5 @@
 /**
- * $Id: BKE_report.h 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -34,7 +34,10 @@ extern "C" {
 
 #include "DNA_listBase.h"
 
-/* Reporting Information and Errors */
+/* Reporting Information and Errors
+ *
+ * These functions also accept NULL in case no error reporting
+ * is needed. */
 
 typedef enum ReportType {
 	RPT_DEBUG					= 0,
diff --git a/source/blender/blenkernel/BKE_sequence.h b/source/blender/blenkernel/BKE_sequence.h
index 93f68f00d2f..65a3b0216fe 100644
--- a/source/blender/blenkernel/BKE_sequence.h
+++ b/source/blender/blenkernel/BKE_sequence.h
@@ -1,5 +1,5 @@
 /**
- * $Id: BKE_sequence.h 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h
index 6584af085cd..419f0f5beeb 100644
--- a/source/blender/blenkernel/BKE_utildefines.h
+++ b/source/blender/blenkernel/BKE_utildefines.h
@@ -130,7 +130,7 @@
 #define IN_RANGE(a, b, c) ((b < c)? ((bid.newid ) (a)= (void *)(a)->id.newid
 
 #define FORM MAKE_ID('F','O','R','M')
-#define DDG1 MAKE_ID('3','D','G','1')
-#define DDG2 MAKE_ID('3','D','G','2')
-#define DDG3 MAKE_ID('3','D','G','3')
-#define DDG4 MAKE_ID('3','D','G','4')
-
-#define GOUR MAKE_ID('G','O','U','R')
 
 #define BLEN MAKE_ID('B','L','E','N')
 #define DER_ MAKE_ID('D','E','R','_')
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 30dcb383ef6..441e17f3318 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -43,6 +43,7 @@ static short id_has_animdata (ID *id)
 		case ID_OB:
 		case ID_CU:
 		case ID_KE:
+		case ID_PA:
 		case ID_MA: case ID_TE: case ID_NT:
 		case ID_LA: case ID_CA: case ID_WO:
 		case ID_SCE:
@@ -883,6 +884,9 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
 	/* meshes */
 	// TODO...
 	
+	/* particles */
+	EVAL_ANIM_IDS(main->particle.first, ADT_RECALC_ANIM);
+	
 	/* objects */
 		/* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets 
 		 * this tagged by Depsgraph on framechange 
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 5fc7d18689d..d3d21018c1c 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -221,7 +221,6 @@ static void clear_global(void)
 {
 //	extern short winqueue_break;	/* screen.c */
 
-// XXX	freeAllRad();
 	fastshade_free_render();	/* lamps hang otherwise */
 	free_main(G.main);			/* free all lib data */
 	
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 57ef920f75b..706eece108c 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -1220,7 +1220,7 @@ void CDDM_calc_edges(DerivedMesh *dm)
 	BLI_edgehashIterator_free(ehi);
 
 	/* free old CustomData and assign new one */
-	CustomData_free(&dm->edgeData, dm->numVertData);
+	CustomData_free(&dm->edgeData, dm->numEdgeData);
 	dm->edgeData = edgeData;
 	dm->numEdgeData = numEdges;
 
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index e98d7bb01a4..08caea565aa 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -33,6 +33,7 @@
 #include "DNA_mesh_types.h"
 #include "DNA_object_force.h"
 #include "DNA_scene_types.h"
+#include "DNA_particle_types.h"
 
 #include "BKE_deform.h"
 #include "BKE_DerivedMesh.h"
@@ -42,6 +43,7 @@
 #include "BKE_object.h"
 #include "BKE_modifier.h"
 #include "BKE_utildefines.h"
+#include "BKE_particle.h"
 
 #include "BKE_pointcache.h"
 
@@ -339,43 +341,88 @@ void bvhselftree_update_from_cloth(ClothModifierData *clmd, int moving)
 }
 
 int modifiers_indexInObject(Object *ob, ModifierData *md_seek);
-
-int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr)
+static void cloth_write_state(int index, Cloth *cloth, float *data)
 {
-	PTCacheID pid;
-	PTCacheFile *pf;
-	Cloth *cloth = clmd->clothObject;
-	unsigned int a, ret = 1;
+	ClothVertex *vert = cloth->verts + index;
+
+	memcpy(data, vert->x, 3 * sizeof(float));
+	memcpy(data + 3, vert->xconst, 3 * sizeof(float));
+	memcpy(data + 6, vert->v, 3 * sizeof(float));
+}
+static void cloth_read_state(int index, Cloth *cloth, float *data)
+{
+	ClothVertex *vert = cloth->verts + index;
 	
-	if(!cloth)
-		return 0;
-	
-	BKE_ptcache_id_from_cloth(&pid, ob, clmd);
-	pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_READ, framenr);
-	if(pf) {
-		for(a = 0; a < cloth->numverts; a++) {
-			if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].x, 3)) {
-				ret = 0;
-				break;
-			}
-			if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].xconst, 3)) {
-				ret = 0;
-				break;
-			}
-			if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].v, 3)) {
-				ret = 0;
-				break;
-			}
-		}
-		
-		BKE_ptcache_file_close(pf);
+	memcpy(vert->x, data, 3 * sizeof(float));
+	memcpy(vert->xconst, data + 3, 3 * sizeof(float));
+	memcpy(vert->v, data + 6, 3 * sizeof(float));
+}
+static void cloth_cache_interpolate(int index, Cloth *cloth, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2)
+{
+	ClothVertex *vert = cloth->verts + index;
+	ParticleKey keys[4];
+	float dfra;
+
+	if(cfra1 == cfra2) {
+		cloth_read_state(index, cloth, data1);
+		return;
 	}
-	else
-		ret = 0;
-	
-	return ret;
+
+	memcpy(keys[1].co, data1, 3 * sizeof(float));
+	memcpy(keys[1].vel, data1 + 6, 3 * sizeof(float));
+
+	memcpy(keys[2].co, data2, 3 * sizeof(float));
+	memcpy(keys[2].vel, data2 + 6, 3 * sizeof(float));
+
+	dfra = cfra2 - cfra1;
+
+	VecMulf(keys[1].vel, dfra);
+	VecMulf(keys[2].vel, dfra);
+
+	psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
+
+	VecMulf(keys->vel, 1.0f / dfra);
+
+	memcpy(vert->x, keys->co, 3 * sizeof(float));
+	memcpy(vert->v, keys->vel, 3 * sizeof(float));
+
+	/* not sure what to do with this - jahka */
+	memcpy(vert->xconst, data1 + 3, 3 * sizeof(float));
+}
+void cloth_write_cache(Object *ob, ClothModifierData *clmd, int cfra)
+{
+	PTCacheWriter writer;
+	PTCacheID pid;
+
+	BKE_ptcache_id_from_cloth(&pid, ob, clmd);
+
+	writer.calldata = clmd->clothObject;
+	writer.cfra = cfra;
+	writer.set_elem = cloth_write_state;
+	writer.pid = &pid;
+	writer.totelem = clmd->clothObject->numverts;
+
+	BKE_ptcache_write_cache(&writer);
 }
 
+int cloth_read_cache(Scene *scene, Object *ob, ClothModifierData *clmd, float cfra, int *old_framenr)
+{
+	PTCacheReader reader;
+	PTCacheID pid;
+	
+	BKE_ptcache_id_from_cloth(&pid, ob, clmd);
+
+	reader.calldata = clmd->clothObject;
+	reader.cfra = cfra;
+	reader.interpolate_elem = cloth_cache_interpolate;
+	reader.old_frame = old_framenr;
+	reader.pid = &pid;
+	reader.scene = scene;
+	reader.set_elem = cloth_read_state;
+	reader.totelem = clmd->clothObject->numverts;
+
+	return BKE_ptcache_read_cache(&reader);
+}
 void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr)
 {
 	PTCacheID pid;
@@ -389,30 +436,6 @@ void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr)
 	BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_AFTER, framenr);
 }
 
-void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr)
-{
-	Cloth *cloth = clmd->clothObject;
-	PTCacheID pid;
-	PTCacheFile *pf;
-	unsigned int a;
-	
-	if(!cloth)
-		return;
-	
-	BKE_ptcache_id_from_cloth(&pid, ob, clmd);
-	pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_WRITE, framenr);
-	if(!pf)
-		return;
-	
-	for(a = 0; a < cloth->numverts; a++) {
-		BKE_ptcache_file_write_floats(pf, cloth->verts[a].x, 3);
-		BKE_ptcache_file_write_floats(pf, cloth->verts[a].xconst, 3);
-		BKE_ptcache_file_write_floats(pf, cloth->verts[a].v, 3);
-	}
-	
-	BKE_ptcache_file_close(pf);
-}
-
 static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr)
 {
 	PointCache *cache;
@@ -486,6 +509,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
 	PTCacheID pid;
 	float timescale;
 	int framedelta, framenr, startframe, endframe;
+	int cache_result, old_framenr;
 
 	clmd->scene= scene;	/* nice to pass on later :) */
 	framenr= (int)scene->r.cfra;
@@ -499,6 +523,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
 	if(!result) {
 		cache->flag &= ~PTCACHE_SIMULATION_VALID;
 		cache->simframe= 0;
+		cache->last_exact= 0;
 		return dm;
 	}
 	
@@ -510,6 +535,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
 		if(result->getNumVerts(result) != clmd->clothObject->numverts) {
 			cache->flag &= ~PTCACHE_SIMULATION_VALID;
 			cache->simframe= 0;
+			cache->last_exact= 0;
 			return result;
 		}
 	}
@@ -521,6 +547,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
 	if(BKE_ptcache_get_continue_physics()) {
 		cache->flag &= ~PTCACHE_SIMULATION_VALID;
 		cache->simframe= 0;
+		cache->last_exact= 0;
 
 		/* do simulation */
 		if(!do_init_cloth(ob, clmd, result, framenr))
@@ -536,6 +563,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
 	if(framenr < startframe) {
 		cache->flag &= ~PTCACHE_SIMULATION_VALID;
 		cache->simframe= 0;
+		cache->last_exact= 0;
 		return result;
 	}
 	else if(framenr > endframe) {
@@ -552,7 +580,9 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
 		return result;
 
 	/* try to read from cache */
-	if(cloth_read_cache(ob, clmd, framenr)) {
+	cache_result = cloth_read_cache(scene, ob, clmd, framenr, &old_framenr);
+
+	if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
 		cache->flag |= PTCACHE_SIMULATION_VALID;
 		cache->simframe= framenr;
 
@@ -561,25 +591,40 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
 
 		return result;
 	}
+	else if(cache_result==PTCACHE_READ_OLD) {
+		BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE);
+
+		implicit_set_positions(clmd);
+
+		cache->flag |= PTCACHE_SIMULATION_VALID;
+		cache->simframe= old_framenr;
+	}
 	else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) {
 		/* if baked and nothing in cache, do nothing */
 		cache->flag &= ~PTCACHE_SIMULATION_VALID;
 		cache->simframe= 0;
+		cache->last_exact= 0;
 		return result;
 	}
 
 	if(framenr == startframe) {
+		if(cache->flag & PTCACHE_REDO_NEEDED) {
+			BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
+			do_init_cloth(ob, clmd, result, framenr);
+		}
 		cache->flag |= PTCACHE_SIMULATION_VALID;
 		cache->simframe= framenr;
 
 		/* don't write cache on first frame, but on second frame write
 		 * cache for frame 1 and 2 */
 	}
-	else if(framedelta == 1) {
+	else {
 		/* if on second frame, write cache for first frame */
-		if(framenr == startframe+1)
+		if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
 			cloth_write_cache(ob, clmd, startframe);
 
+		clmd->sim_parms->timescale *= framenr - cache->simframe;
+
 		/* do simulation */
 		cache->flag |= PTCACHE_SIMULATION_VALID;
 		cache->simframe= framenr;
@@ -587,16 +632,13 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
 		if(!do_step_cloth(ob, clmd, result, framenr)) {
 			cache->flag &= ~PTCACHE_SIMULATION_VALID;
 			cache->simframe= 0;
+			cache->last_exact= 0;
 		}
 		else
 			cloth_write_cache(ob, clmd, framenr);
 
 		cloth_to_object (ob, clmd, result);
 	}
-	else {
-		cache->flag &= ~PTCACHE_SIMULATION_VALID;
-		cache->simframe= 0;
-	}
 
 	return result;
 }
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index a43389a2ef6..88e73a00ba7 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -3028,7 +3028,7 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
 	if (VALID_CONS_TARGET(ct)) {
 		float loc[3], eul[3], size[3];
 		float dvec[3], sval[3];
-		short i;
+		int i;
 		
 		/* obtain target effect */
 		switch (data->from) {
@@ -3075,7 +3075,7 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
 		switch (data->to) {
 			case 2: /* scaling */
 				for (i=0; i<3; i++)
-					size[i]= data->to_min[i] + (sval[data->map[i]] * (data->to_max[i] - data->to_min[i])); 
+					size[i]= data->to_min[i] + (sval[(int)data->map[i]] * (data->to_max[i] - data->to_min[i])); 
 				break;
 			case 1: /* rotation */
 				for (i=0; i<3; i++) {
@@ -3085,7 +3085,7 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
 					tmax= data->to_max[i];
 					
 					/* all values here should be in degrees */
-					eul[i]= tmin + (sval[data->map[i]] * (tmax - tmin)); 
+					eul[i]= tmin + (sval[(int)data->map[i]] * (tmax - tmin)); 
 					
 					/* now convert final value back to radians */
 					eul[i] = (float)(eul[i] / 180 * M_PI);
@@ -3094,7 +3094,7 @@ static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
 			default: /* location */
 				/* get new location */
 				for (i=0; i<3; i++)
-					loc[i]= (data->to_min[i] + (sval[data->map[i]] * (data->to_max[i] - data->to_min[i])));
+					loc[i]= (data->to_min[i] + (sval[(int)data->map[i]] * (data->to_max[i] - data->to_min[i])));
 				
 				/* add original location back on (so that it can still be moved) */
 				VecAddf(loc, cob->matrix[3], loc);
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 6afbcf4950c..fbad585d9b7 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -1,5 +1,5 @@
 /**
- * $Id: context.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -358,6 +358,9 @@ static int ctx_data_collection_get(const bContext *C, const char *member, ListBa
 		return 1;
 	}
 
+	list->first= NULL;
+	list->last= NULL;
+
 	return 0;
 }
 
@@ -365,15 +368,20 @@ PointerRNA CTX_data_pointer_get(const bContext *C, const char *member)
 {
 	bContextDataResult result;
 
-	if(ctx_data_get((bContext*)C, member, &result)) {
+	if(ctx_data_get((bContext*)C, member, &result))
 		return result.ptr;
-	}
-	else {
-		PointerRNA ptr;
-		memset(&ptr, 0, sizeof(ptr));
-		return ptr;
-	}
+	else
+		return PointerRNA_NULL;
+}
 
+PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
+{
+	PointerRNA ptr = CTX_data_pointer_get(C, member);
+
+	if(ptr.data && ptr.type == type)
+		return ptr;
+	
+	return PointerRNA_NULL;
 }
 
 ListBase CTX_data_collection_get(const bContext *C, const char *member)
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 8bb34bde122..a36b825293e 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -559,7 +559,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
 
 			dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation");
 
-			if(psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE)
+			if(!psys_check_enabled(ob, psys))
 				continue;
 
 			if(part->phystype==PART_PHYS_KEYED && psys->keyed_ob &&
@@ -1831,7 +1831,7 @@ static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime)
 }
 
 /* node was checked to have lasttime != curtime , and is of type ID_OB */
-static void flush_pointcache_reset(DagNode *node, int curtime, int reset)
+static void flush_pointcache_reset(Scene *scene, DagNode *node, int curtime, int reset)
 {
 	DagAdjList *itA;
 	Object *ob;
@@ -1844,13 +1844,13 @@ static void flush_pointcache_reset(DagNode *node, int curtime, int reset)
 				ob= (Object*)(node->ob);
 
 				if(reset || (ob->recalc & OB_RECALC)) {
-					if(BKE_ptcache_object_reset(ob, PTCACHE_RESET_DEPSGRAPH))
+					if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH))
 						ob->recalc |= OB_RECALC_DATA;
 
-					flush_pointcache_reset(itA->node, curtime, 1);
+					flush_pointcache_reset(scene, itA->node, curtime, 1);
 				}
 				else
-					flush_pointcache_reset(itA->node, curtime, 0);
+					flush_pointcache_reset(scene, itA->node, curtime, 0);
 			}
 		}
 	}
@@ -1908,13 +1908,13 @@ void DAG_scene_flush_update(Scene *sce, unsigned int lay, int time)
 				ob= (Object*)(itA->node->ob);
 
 				if(ob->recalc & OB_RECALC) {
-					if(BKE_ptcache_object_reset(ob, PTCACHE_RESET_DEPSGRAPH))
+					if(BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH))
 						ob->recalc |= OB_RECALC_DATA;
 
-					flush_pointcache_reset(itA->node, lasttime, 1);
+					flush_pointcache_reset(sce, itA->node, lasttime, 1);
 				}
 				else
-					flush_pointcache_reset(itA->node, lasttime, 0);
+					flush_pointcache_reset(sce, itA->node, lasttime, 0);
 			}
 		}
 	}
@@ -2132,7 +2132,7 @@ void DAG_object_flush_update(Scene *sce, Object *ob, short flag)
 	if(ob==NULL || sce->theDag==NULL) return;
 
 	ob->recalc |= flag;
-	BKE_ptcache_object_reset(ob, PTCACHE_RESET_DEPSGRAPH);
+	BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH);
 	
 	/* all users of this ob->data should be checked */
 	/* BUT! displists for curves are still only on cu */
@@ -2147,7 +2147,7 @@ void DAG_object_flush_update(Scene *sce, Object *ob, short flag)
 					for (obt=G.main->object.first; obt; obt= obt->id.next) {
 						if (obt != ob && obt->data==ob->data) {
 							obt->recalc |= OB_RECALC_DATA;
-							BKE_ptcache_object_reset(obt, PTCACHE_RESET_DEPSGRAPH);
+							BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
 						}
 					}
 				}
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 736165a8a98..cdf4b90cee1 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -315,13 +315,19 @@ static void init_fastshade_shadeinput(Render *re)
 
 static Render *fastshade_get_render(Scene *scene)
 {
-	Render *re= RE_GetRender("_Shade View_");
-	if(re==NULL) {
-		re= RE_NewRender("_Shade View_");
-	
-		RE_Database_Baking(re, scene, 0, 0);	/* 0= no faces */
+	/* XXX ugly global still, but we can't do preview while rendering */
+	if(G.rendering==0) {
+		
+		Render *re= RE_GetRender("_Shade View_");
+		if(re==NULL) {
+			re= RE_NewRender("_Shade View_");
+		
+			RE_Database_Baking(re, scene, 0, 0);	/* 0= no faces */
+		}
+		return re;
 	}
-	return re;
+	
+	return NULL;
 }
 
 /* called on file reading */
@@ -611,18 +617,20 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un
 
 void shadeMeshMCol(Scene *scene, Object *ob, Mesh *me)
 {
+	Render *re= fastshade_get_render(scene);
 	int a;
 	char *cp;
 	unsigned int *mcol= (unsigned int*)me->mcol;
 	
-	Render *re= fastshade_get_render(scene);
-	mesh_create_shadedColors(re, ob, 1, &mcol, NULL);
-	me->mcol= (MCol*)mcol;
+	if(re) {
+		mesh_create_shadedColors(re, ob, 1, &mcol, NULL);
+		me->mcol= (MCol*)mcol;
 
-	/* swap bytes */
-	for(cp= (char *)me->mcol, a= 4*me->totface; a>0; a--, cp+=4) {
-		SWAP(char, cp[0], cp[3]);
-		SWAP(char, cp[1], cp[2]);
+		/* swap bytes */
+		for(cp= (char *)me->mcol, a= 4*me->totface; a>0; a--, cp+=4) {
+			SWAP(char, cp[0], cp[3]);
+			SWAP(char, cp[1], cp[2]);
+		}
 	}
 }
 
@@ -641,6 +649,8 @@ void shadeDispList(Scene *scene, Base *base)
 	int a, need_orco;
 	
 	re= fastshade_get_render(scene);
+	if(re==NULL)
+		return;
 	
 	dl = find_displist(&ob->disp, DL_VERTCOL);
 	if (dl) {
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 9858025af5a..eaa2d541638 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -29,6 +29,8 @@
  * ***** END GPL LICENSE BLOCK *****
  */
 
+#include "BLI_storage.h" /* _LARGEFILE_SOURCE */
+
 #include 
 #include 
 
diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c
index 929d3f942dc..4e7e76dfae3 100644
--- a/source/blender/blenkernel/intern/exotic.c
+++ b/source/blender/blenkernel/intern/exotic.c
@@ -27,48 +27,9 @@
  *
  * - Blender Foundation
  *
- * ***** END GPL LICENSE BLOCK *****
- *  
- *  eigen videoscape formaat:
- *
- * 
- * lamp:
- *		3DG2
-		aantal_lampen
-		
-		type
-		spsi spbl
-		r, g, b, energy
-		locx, locy, locz
-		vecx, vecy, vecz
-
-		
-	curve / nurbs:
-		3DG3
-		5 of 11 (curve of surf)
-		aantal_nurbs
-		extr1 extr2
-		
-		mat[0][0] mat[0][1] mat[0][2] mat[0][3]
-		mat[1][0] mat[1][1] mat[1][2] mat[1][3]
-		...		
-		
-		type
-		pntsu, pntsv
-		resolu, resolv
-		orderu, orderv
-		flagu, flagv
-		
-		(als type==nurb) x y z w
-						 x y z w
-						 ...
-		(als type==bez)  xyz xyz xyz h1 h2 h3
-						 xyz xyz xyz h1 h2 h3
-						 ...
- *  
- * 
- */
+ * ***** END GPL LICENSE BLOCK *****/
 
+#include "BLI_storage.h"
 
 #include  /* isdigit, isspace */
 #include 
@@ -482,385 +443,6 @@ static void read_stl_mesh_ascii(Scene *scene, char *str)
 #undef STLREADLINE
 #undef STLREADVERT
 
-static void read_videoscape_mesh(Scene *scene, char *str)
-{
-	Object *ob;
-	Mesh *me;
-	MVert *mvert;
-	MFace *mface;
-	Material *ma;
-	FILE *fp;
-	float *vertdata, *vd, min[3], max[3], cent[3], ftemp;
-	unsigned int color[32], col;
-	int totcol, a, b, verts, tottria=0, totquad=0, totedge=0, poly, nr0, nr, first;
-	int end;
-	char s[50];
-	
-	fp= fopen(str, "rb");
-	if(fp==NULL) {
-		//XXX error("Can't read file");
-		return;
-	}
-	
-	fscanf(fp, "%40s", s);
-	
-	fscanf(fp, "%d\n", &verts);
-	if(verts<=0) {
-		fclose(fp);
-		//XXX error("Read error");
-		return;
-	}
-	
-	if(verts>MESH_MAX_VERTS) {
-		//XXX error("too many vertices");
-		fclose(fp);
-		return;
-	}
-	
-	INIT_MINMAX(min, max);
-	vd= vertdata= MEM_mallocN(sizeof(float)*3*verts, "videoscapelezer");
-	
-	for(a=0; a0) {
-		end= fscanf(fp,"%d", &poly);
-		if(end<=0) break;
-	
-		if(poly==3) tottria++;
-		else if(poly==4) totquad++;
-		else totedge+= poly;
-	
-		for(a=0;a=totcol && totcol<32) {
-			color[totcol]= col;
-			totcol++;
-		}
-	}
-
-	/* new object */
-	ob= add_object(scene, OB_MESH);
-	me= ob->data;
-	me->totvert= verts;
-	me->totface= totedge+tottria+totquad;
-	
-	me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC,
-	                                NULL, me->totvert);
-	me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC,
-	                                NULL, me->totface);
-	
-	/* colors */
-	if(totcol) {
-		ob->mat= MEM_callocN(sizeof(void *)*totcol, "ob->mat");
-		me->mat= MEM_callocN(sizeof(void *)*totcol, "me->mat");
-		me->totcol= totcol;
-		ob->totcol= (unsigned char) me->totcol;
-		ob->actcol= 1;
-	}
-	
-	/* materials */
-	for(a=0; amat.first;
-		while(ma) {
-			if(ma->mtex[0]==0) {
-				col= rgb_to_cpack(ma->r, ma->g, ma->b);
-				if(color[a]==col) {
-					me->mat[a]= ma;
-					ma->id.us++;
-					break;
-				}
-			}
-			ma= ma->id.next;
-		}
-		if(ma==0) {
-			ma= add_material("ext");
-			me->mat[a]= ma;
-			cpack_to_rgb(color[a], cent, cent+1, cent+2);
-			ma->r= cent[0];
-			ma->g= cent[1];
-			ma->b= cent[2];
-			automatname(ma);
-		}
-	}
-	
-	/* verts */
-	
-	cent[0]= (min[0]+max[0])/2.0f;
-	cent[1]= (min[1]+max[1])/2.0f;
-	cent[2]= (min[2]+max[2])/2.0f;
-	VECCOPY(ob->loc, cent);
-	
-	a= me->totvert;
-	vd= vertdata;
-	mvert= me->mvert;
-	while(a--) {
-		VecSubf(mvert->co, vd, cent);
-		mvert++;
-		vd+= 3;
-	}
-	
-	/* faces */
-	if(me->totface) {
-		rewind(fp);
-	
-		fscanf(fp, "%40s", s);
-		fscanf(fp, "%d\n", &verts);
-		/* fake read */
-		for(a=0;atotface;
-		mface= me->mface;
-		while(a--) {
-			end= fscanf(fp,"%d", &poly);
-			if(end<=0) break;
-	
-			if(poly==3 || poly==4) {
-				fscanf(fp,"%d", &nr);
-				mface->v1= MIN2(nr, me->totvert-1);
-				fscanf(fp,"%d", &nr);
-				mface->v2= MIN2(nr, me->totvert-1);
-				fscanf(fp,"%d", &nr);
-				mface->v3= MIN2(nr, me->totvert-1);
-				if(poly==4) {
-					if( fscanf(fp,"%d", &nr) <=0 ) break;
-					mface->v4= MIN2(nr, me->totvert-1);
-				}
-				
-				test_index_face(mface, NULL, 0, poly);
-				
-				mface++;
-			}
-			else {
-				if( fscanf(fp,"%d", &nr0) <=0) break;
-				first= nr0;
-				for(b=1; btotvert-1);
-					mface->v1= nr;
-					mface->v2= nr0;
-					nr0= nr;
-					mface++;
-					a--;
-				}
-				mface->v1= first;
-				mface->v2= nr;
-				mface++;
-				if(end<=0) break;
-			}
-			end= fscanf(fp,"%i", &col);
-			col &= 0xF0F0F0;
-			if(end<=0) break;
-			
-			for(b=0; bmat_nr= b;
-					break;
-				}
-			}
-		}
-	}
-	
-	fclose(fp);
-	MEM_freeN(vertdata);
-	
-	mesh_add_normals_flags(me);
-	make_edges(me, 0);
-
-	//XXX waitcursor(1);
-}
-
-static void read_videoscape_lamp(Scene *scene, char *str)
-{
-	Object *ob;
-	Lamp *la;
-	FILE *fp;
-	float vec[3], q1[4];
-	int tot, val;
-	char s[50];
-	
-	fp= fopen(str, "rb");
-	if(fp==NULL) {
-		//XXX error("Can't read file");
-		return;
-	}
-
-	fscanf(fp, "%40s", s);
-	fscanf(fp, "%d\n", &tot);
-	
-	while(tot--) {
-		ob= add_object(scene, OB_LAMP);
-		la= ob->data;
-		
-		fscanf(fp, "%d\n", &val);
-		la->type= val;
-		if(la->type==1) la->type= LA_SPOT;
-		else if(la->type==2) la->type= LA_SUN;
-		
-		fscanf(fp, "%f %f\n", &la->spotsize, &la->spotblend);
-		
-		fscanf(fp, "%f %f %f %f\n", &la->r, &la->g, &la->b, &la->energy);		
-		
-		fscanf(fp, "%f %f %f\n", ob->loc, ob->loc+1, ob->loc+2);
-		val= fscanf(fp, "%f %f %f\n", vec, vec+1, vec+2);
-		vectoquat(vec, 5, 2, q1);
-		QuatToEul(q1, ob->rot);
-		
-		if(val<=0) break;
-		
-	}
-	fclose(fp);
-}
-
-static void read_videoscape_nurbs(Scene *scene, char *str)
-{
-	Object *ob;
-	Curve *cu;
-	Nurb *nu;
-	BezTriple *bezt;
-	BPoint *bp;
-	FILE *fp;
-	float tmat[4][4], omat[3][3], imat[3][3], mat[3][3];
-	int a, tot, type, val;
-	char s[50];
-
-	fp= fopen(str, "rb");
-	if(fp==NULL) {
-		//XXX error("Can't read file");
-		return;
-	}
-
-	fscanf(fp, "%40s", s);
-	fscanf(fp, "%d\n", &type);
-	
-	if(type==5) ob= add_object(scene, OB_SURF);
-	else ob= add_object(scene, OB_CURVE);
-	cu= ob->data;
-	
-	fscanf(fp, "%d\n", &tot);
-	fscanf(fp, "%d %d\n", &type, &val);
-	
-	cu->ext1= 0.002f*type;
-	cu->ext2= 0.002f*val;
-
-	for(a=0; a<4; a++) fscanf(fp, "%e %e %e %e\n", tmat[a], tmat[a]+1, tmat[a]+2, tmat[a]+3);
-
-	VECCOPY(ob->loc, tmat[3]);
-
-	Mat3CpyMat4(omat, tmat);
-	Mat3ToEul(omat, ob->rot);
-	EulToMat3(ob->rot, mat);
-	Mat3Inv(imat, mat);
-	Mat3MulMat3((float ( * )[3])tmat, imat, omat);
-	
-	while(tot--) {
-		nu= (Nurb*)MEM_callocN(sizeof(Nurb),"nu from exotic");
-		BLI_addtail(&cu->nurb, nu);
-		
-		fscanf(fp, "%d\n", &type);
-		nu->type= type;
-
-		fscanf(fp, "%d %d\n", &type, &val);
-		nu->pntsu= type; nu->pntsv= val;
-		fscanf(fp, "%d %d\n", &type, &val);
-		nu->resolu= type; nu->resolv= val;
-		fscanf(fp, "%d %d\n", &type, &val);
-		nu->orderu= type; nu->orderv= val;
-		fscanf(fp, "%d %d\n", &type, &val);
-		nu->flagu= type; nu->flagv= val;
-		
-		if( (nu->type & 7)==CU_BEZIER) {
-			a= nu->pntsu;
-			nu->bezt= bezt= MEM_callocN(a*sizeof(BezTriple), "bezt from exotic");
-			while(a--) {
-				fscanf(fp, "%f %f %f ", bezt->vec[0], bezt->vec[0]+1, bezt->vec[0]+2);
-				Mat4MulVecfl(tmat, bezt->vec[0]);
-				fscanf(fp, "%f %f %f ", bezt->vec[1], bezt->vec[1]+1, bezt->vec[1]+2);
-				Mat4MulVecfl(tmat, bezt->vec[1]);
-				fscanf(fp, "%f %f %f ", bezt->vec[2], bezt->vec[2]+1, bezt->vec[2]+2);
-				Mat4MulVecfl(tmat, bezt->vec[2]);
-				fscanf(fp, "%d %d\n", &type, &val);
-				bezt->h1= type;
-				bezt->h2= val;
-				bezt++;
-			}
-		}
-		else {
-			a= nu->pntsu*nu->pntsv;
-			if(a) {
-				nu->bp= bp= MEM_callocN(a*sizeof(BPoint), "bp from exotic");
-				while(a--) {
-					fscanf(fp, "%f %f %f %f\n", bp->vec, bp->vec+1, bp->vec+2, bp->vec+3);
-					Mat4MulVecfl(tmat, bp->vec);
-					bp++;
-				}
-				
-				val= KNOTSU(nu);
-				nu->knotsu= MEM_mallocN(sizeof(float)*val, "knots");
-				for(a=0; aknotsu+a);
-				
-				if(nu->pntsv>1) {
-					val= KNOTSV(nu);
-					nu->knotsv= MEM_mallocN(sizeof(float)*val, "knots");
-					for(a=0; aknotsv+a);
-				}
-			}
-			else {
-				BLI_remlink(&cu->nurb, nu);
-				MEM_freeN(nu);
-			}
-		}
-	}
-	fclose(fp);
-}
-
-static void read_videoscape(Scene *scene, char *str)
-{
-	int file, type;
-	unsigned int val;
-	unsigned short numlen;
-	char name[FILE_MAXDIR+FILE_MAXFILE], head[FILE_MAXDIR+FILE_MAXFILE], tail[FILE_MAXFILE];
-	
-	strcpy(name, str);
-
-	while( TRUE ) {
-		file= open(name, O_BINARY|O_RDONLY);
-		if(file<=0) break;
-		else {
-			read(file, &type, 4);
-			close(file);
-			
-			if(type==DDG1) read_videoscape_mesh(scene, name);
-			else if(type==DDG2) read_videoscape_lamp(scene, name);
-			else if(type==DDG3) read_videoscape_nurbs(scene, name);
-		}
-
-		val = BLI_stringdec(name, head, tail, &numlen);
-		BLI_stringenc(name, head, tail, numlen, val + 1);
-
-	}
-}
-
-
 /* ***************** INVENTOR ******************* */
 
 
@@ -2204,16 +1786,7 @@ int BKE_read_exotic(Scene *scene, char *name)
 			if ((*s0 != FORM) && (strncmp(str, "BLEN", 4) != 0) && !BLI_testextensie(name,".blend.gz")) {
 
 				//XXX waitcursor(1);
-				
-				if(ELEM4(*s0, DDG1, DDG2, DDG3, DDG4)) {
-					if(0) { // XXX obedit) {
-						//XXX error("Unable to perform function in EditMode");
-					} else {
-						read_videoscape(scene, name);
-						retval = 1;
-					}
-				}
-				else if(strncmp(str, "#Inventor V1.0", 14)==0) {
+				if(strncmp(str, "#Inventor V1.0", 14)==0) {
 					if( strncmp(str+15, "ascii", 5)==0) {
 						read_inventor(scene, name, &lbase);
 						displist_to_objects(scene, &lbase);				
@@ -2385,167 +1958,6 @@ void write_stl(Scene *scene, char *str)
 	//XXX waitcursor(0);
 }
 
-static void write_videoscape_mesh(Scene *scene, Object *ob, char *str)
-{
-	Mesh *me= ob->data;
-	EditMesh *em = BKE_mesh_get_editmesh(me);
-	Material *ma;
-	MFace *mface;
-	FILE *fp;
-	EditVert *eve;
-	EditFace *evl;
-	unsigned int kleur[32];
-	float co[3];
-	int a;
-	intptr_t tot;
-	char *cp;
-	
-	if(ob && ob->type==OB_MESH);
-	else {
-		return;
-	}
-
-	kleur[0]= 0x00C0C0C0;
-
-	cp= (char *)kleur;
-	for(a=0; atotcol; a++, cp+=4) {
-		
-		ma= give_current_material(ob, a+1);
-		if(ma) {
-			cp[0]= (unsigned char) (255.0*ma->emit);
-			cp[1]= (unsigned char) (255.0*ma->b);
-			cp[2]= (unsigned char) (255.0*ma->g);
-			cp[3]= (unsigned char) (255.0*ma->r);
-			if(ENDIAN_ORDER==L_ENDIAN) SWITCH_INT(kleur[a]);
-		}
-		else kleur[a]= 0x00C0C0C0;
-	
-		if(a>30) break;
-	}
-	
-	fp= fopen(str, "wb");
-	if(fp==NULL) return;
-
-	fprintf(fp,"3DG1\n");
-
-	if(em) {
-
-		fprintf(fp, "%d\n", em->totvert);
-	
-		tot= 0;
-		eve= em->verts.first;
-		while(eve) {
-			VECCOPY(co, eve->co);
-			Mat4MulVecfl(ob->obmat, co);
-			fprintf(fp, "%f %f %f\n", co[0], co[1], co[2] );
-			eve->tmp.l = tot;
-			tot++;
-			eve= eve->next;
-		}
-		evl= em->faces.first;
-		while(evl) {
-
-			if(evl->v4==0) {
-				fprintf(fp, "3 %ld %ld %ld 0x%x\n", 
-						(intptr_t) evl->v1->tmp.l,
-						(intptr_t) evl->v2->tmp.l,
-						(intptr_t) evl->v3->tmp.l, 
-						kleur[evl->mat_nr]);
-			}
-			else {
-				fprintf(fp, "4 %ld %ld %ld %ld 0x%x\n", 
-						(intptr_t) evl->v1->tmp.l, 
-						(intptr_t) evl->v2->tmp.l, 
-						(intptr_t) evl->v3->tmp.l, 
-						(intptr_t) evl->v4->tmp.l, 
-						kleur[evl->mat_nr]);
-			}
-			evl= evl->next;
-		}
-	}
-	else {
-		DerivedMesh *dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
-		
-		me= ob->data;
-		
-		fprintf(fp, "%d\n", me->totvert);
-		
-		mface= me->mface;
-		for(a=0; atotvert; a++) {
-			dm->getVertCo(dm, a, co);
-			Mat4MulVecfl(ob->obmat, co);
-			fprintf(fp, "%f %f %f\n", co[0], co[1], co[2] );
-		}
-		for(a=0; atotface; a++, mface++) {
-			if(mface->v4==0) {
-				fprintf(fp, "3 %d %d %d 0x%x\n", mface->v1, mface->v2, mface->v3, kleur[(int)mface->mat_nr]);
-			}
-			else {
-				fprintf(fp, "4 %d %d %d %d 0x%x\n", mface->v1, mface->v2, mface->v3, mface->v4, kleur[(int)mface->mat_nr]);
-			}
-		}
-
-		dm->release(dm);
-	}
-	
-	fclose(fp);
-
-	if (em) BKE_mesh_end_editmesh(me, em);
-	
-}
-
-
-void write_videoscape(Scene *scene, char *str)
-{
-	Base *base;
-	int file, val, lampdone=0;
-	unsigned short numlen;
-	char head[FILE_MAXFILE], tail[FILE_MAXFILE];
-	
-	if(BLI_testextensie(str,".trace")) str[ strlen(str)-6]= 0;
-	if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0;
-	if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0;
-	if(BLI_testextensie(str,".obj")==0) strcat(str, ".obj");
-
-	file= open(str,O_BINARY|O_RDONLY);
-	close(file);
-	//XXX saveover()
-	// if(file>-1) if(!during_script() && saveover(str)==0) return;
-
-	strcpy(temp_dir, str);
-
-	base= scene->base.first;
-	while(base) {
-		if((base->flag & SELECT) && (base->lay & scene->lay))  {
-			if(base->object->type==OB_MESH) {
-				write_videoscape_mesh(scene, base->object, str);
-				val = BLI_stringdec(str, head, tail, &numlen);
-				BLI_stringenc(str, head, tail, numlen, val + 1);
-			}
-			else if(base->object->type==OB_CURVE || base->object->type==OB_SURF) {
-				/* write_videoscape_nurbs(base->object, str); */
-				/* val = stringdec(str, head, tail, &numlen); */
-				/* stringenc(str, head, tail, numlen, val + 1); */
-			}
-			else if(lampdone==0 && base->object->type==OB_LAMP) {
-				/* lampdone= 1; */
-				/* write_videoscape_lamps(str); */
-				/* val = stringdec(str, head, tail, &numlen); */
-				/* stringenc(str, head, tail, numlen, val + 1); */
-			}
-		}
-		base= base->next;
-	}
-	
-	
-	/* remove when higher numbers exist */
-	while(remove(str)==0) {
-		
-		val = BLI_stringdec(str, head, tail, &numlen);
-		BLI_stringenc(str, head, tail, numlen, val + 1);
-	}
-}
-
 /* ******************************* WRITE VRML ***************************** */
 
 static void replace_chars(char *str1, char *str2)
diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c
index 9eefd48cae4..54008185f72 100644
--- a/source/blender/blenkernel/intern/fluidsim.c
+++ b/source/blender/blenkernel/intern/fluidsim.c
@@ -28,6 +28,8 @@
  * ***** END GPL LICENSE BLOCK *****
  */
 
+#include "BLI_storage.h" /* _LARGEFILE_SOURCE */
+
 #include "MEM_guardedalloc.h"
 
 #include "DNA_mesh_types.h"
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index 60a7ffc28d9..70901778585 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -333,11 +333,11 @@ static VFontData *vfont_get_data(VFont *vfont)
 					BLI_addtail(&ttfdata, tmpfnt);
 				}
 			} else {
-				pf= newPackedFile(vfont->name);
+				pf= newPackedFile(NULL, vfont->name);
 				
 				if(!tmpfnt)
 				{
-					tpf= newPackedFile(vfont->name);
+					tpf= newPackedFile(NULL, vfont->name);
 					
 					// Add temporary packed file to globals
 					tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font");
@@ -385,8 +385,8 @@ VFont *load_vfont(char *name)
 		strcpy(dir, name);
 		BLI_splitdirstring(dir, filename);
 
-		pf= newPackedFile(name);
-		tpf= newPackedFile(name);		
+		pf= newPackedFile(NULL, name);
+		tpf= newPackedFile(NULL, name);		
 		
 		is_builtin= 0;
 	}
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 6086aa58d40..dd8f44c71d5 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -1,5 +1,5 @@
 /**
- * $Id: gpencil.c 19758 2009-04-16 13:10:08Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 3be47778674..54366aadd92 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -230,16 +230,16 @@ void IDP_ResizeArray(IDProperty *prop, int newlen)
 	 */
 	newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;
 
-	newarr = MEM_callocN(idp_size_table[prop->subtype]*newsize, "idproperty array resized");
+	newarr = MEM_callocN(idp_size_table[(int)prop->subtype]*newsize, "idproperty array resized");
 	if (newlen >= prop->len) {
 		/* newlen is bigger*/
-		memcpy(newarr, prop->data.pointer, prop->len*idp_size_table[prop->subtype]);
+		memcpy(newarr, prop->data.pointer, prop->len*idp_size_table[(int)prop->subtype]);
 		idp_resize_group_array(prop, newlen, newarr);
 	}
 	else {
 		/* newlen is smaller*/
 		idp_resize_group_array(prop, newlen, newarr);
-		memcpy(newarr, prop->data.pointer, newlen*prop->len*idp_size_table[prop->subtype]);
+		memcpy(newarr, prop->data.pointer, newlen*prop->len*idp_size_table[(int)prop->subtype]);
 	}
 
 	MEM_freeN(prop->data.pointer);
@@ -546,7 +546,7 @@ int IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2)
 		return BSTR_EQ(IDP_String(prop1), IDP_String(prop2));
 	else if(prop1->type == IDP_ARRAY) {
 		if(prop1->len == prop2->len && prop1->subtype == prop2->subtype)
-			return memcmp(IDP_Array(prop1), IDP_Array(prop2), idp_size_table[prop1->subtype]*prop1->len);
+			return memcmp(IDP_Array(prop1), IDP_Array(prop2), idp_size_table[(int)prop1->subtype]*prop1->len);
 		else
 			return 0;
 	}
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 8eef9984c92..ef0984bf93d 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -1431,7 +1431,7 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal)
 		/* try to repack file */
 		if(ima->packedfile) {
 			PackedFile *pf;
-			pf = newPackedFile(ima->name);
+			pf = newPackedFile(NULL, ima->name);
 			if (pf) {
 				freePackedFile(ima->packedfile);
 				ima->packedfile = pf;
@@ -1750,7 +1750,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
 			
 			/* make packed file for autopack */
 			if ((ima->packedfile == NULL) && (G.fileflags & G_AUTOPACK))
-				ima->packedfile = newPackedFile(str);
+				ima->packedfile = newPackedFile(NULL, str);
 		}
 		
 		if(ima->flag & IMA_DO_PREMUL)
@@ -1812,7 +1812,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser)
 	Render *re= NULL;
 	RenderResult *rr= NULL;
 	
-	if(iuser->scene) {
+	if(iuser && iuser->scene) {
 		re= RE_GetRender(iuser->scene->id.name);
 		rr= RE_GetResult(re);
 	}
diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c
index 40c98c1d9cc..fc5213d5532 100644
--- a/source/blender/blenkernel/intern/implicit.c
+++ b/source/blender/blenkernel/intern/implicit.c
@@ -1600,6 +1600,10 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
 		
 		if(clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED)
 		{
+			float temp = clmd->sim_parms->stepsPerFrame;
+			/* not too nice hack, but collisions need this correction -jahka */
+			clmd->sim_parms->stepsPerFrame /= clmd->sim_parms->timescale;
+
 			// collisions 
 			// itstart();
 			
@@ -1614,7 +1618,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
 			
 			// call collision function
 			// TODO: check if "step" or "step+dt" is correct - dg
-			result = cloth_bvh_objcollision(ob, clmd, step, dt);
+			result = cloth_bvh_objcollision(ob, clmd, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale);
 			
 			// correct velocity again, just to be sure we had to change it due to adaptive collisions
 			for(i = 0; i < numverts; i++)
@@ -1637,6 +1641,9 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
 				}
 			}
 			
+			/* restore original stepsPerFrame */
+			clmd->sim_parms->stepsPerFrame = temp;
+			
 			// X = Xnew;
 			cp_lfvector(id->X, id->Xnew, numverts);
 			
@@ -1654,7 +1661,6 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
 				
 				simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv, id->M, id->bigI);
 			}
-			
 		}
 		else
 		{
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index b410c521dea..57b88bb0b3f 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -615,7 +615,7 @@ int find_material_index(Object *ob, Material *ma)
 	return 0;	   
 }
 
-void new_material_to_objectdata(Object *ob)
+void object_add_material_slot(Object *ob)
 {
 	Material *ma;
 	
@@ -854,7 +854,7 @@ void automatname(Material *ma)
 }
 
 
-void delete_material_index(Object *ob)
+void object_remove_material_slot(Object *ob)
 {
 	Material *mao, ***matarar;
 	Object *obt;
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index bf3d27cafbf..80a9f173d6a 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -3543,7 +3543,7 @@ static void displaceModifier_updateDepgraph(
 	}
 }
 
-static void validate_layer_name(const CustomData *data, int type, char *name)
+static void validate_layer_name(const CustomData *data, int type, char *name, char *outname)
 {
 	int index = -1;
 
@@ -3556,8 +3556,10 @@ static void validate_layer_name(const CustomData *data, int type, char *name)
 		* deleted, so assign the active layer to name
 		*/
 		index = CustomData_get_active_layer_index(data, CD_MTFACE);
-		strcpy(name, data->layers[index].name);
+		strcpy(outname, data->layers[index].name);
 	}
+	else
+		strcpy(outname, name);
 }
 
 static void get_texture_coords(DisplaceModifierData *dmd, Object *ob,
@@ -3583,12 +3585,11 @@ static void get_texture_coords(DisplaceModifierData *dmd, Object *ob,
 			char *done = MEM_callocN(sizeof(*done) * numVerts,
 					"get_texture_coords done");
 			int numFaces = dm->getNumFaces(dm);
+			char uvname[32];
 			MTFace *tf;
 
-			validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name);
-
-			tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE,
-					dmd->uvlayer_name);
+			validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name, uvname);
+			tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
 
 			/* verts are given the UV from the first face that uses them */
 			for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
@@ -3884,6 +3885,7 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
 	Projector projectors[MOD_UVPROJECT_MAXPROJECTORS];
 	int num_projectors = 0;
 	float aspect;
+	char uvname[32];
 	
 	if(umd->aspecty != 0) aspect = umd->aspectx / umd->aspecty;
 	else aspect = 1.0f;
@@ -3898,12 +3900,11 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
 	if(!dm->getFaceDataArray(dm, CD_MTFACE)) return dm;
 
 	/* make sure we're using an existing layer */
-	validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name);
+	validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name, uvname);
 
 	/* make sure we are not modifying the original UV layer */
 	tface = CustomData_duplicate_referenced_layer_named(&dm->faceData,
-			CD_MTFACE,
-   umd->uvlayer_name);
+			CD_MTFACE, uvname);
 
 	numVerts = dm->getNumVerts(dm);
 
@@ -5185,12 +5186,11 @@ static void wavemod_get_texture_coords(WaveModifierData *wmd, Object *ob,
 			char *done = MEM_callocN(sizeof(*done) * numVerts,
 					"get_texture_coords done");
 			int numFaces = dm->getNumFaces(dm);
+			char uvname[32];
 			MTFace *tf;
 
-			validate_layer_name(&dm->faceData, CD_MTFACE, wmd->uvlayer_name);
-
-			tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE,
-					wmd->uvlayer_name);
+			validate_layer_name(&dm->faceData, CD_MTFACE, wmd->uvlayer_name, uvname);
+			tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
 
 			/* verts are given the UV from the first face that uses them */
 			for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
@@ -6295,6 +6295,9 @@ CustomDataMask particleSystemModifier_requiredDataMask(Object *ob, ModifierData
 	MTex *mtex;
 	int i;
 
+	if(!psmd->psys->part)
+		return 0;
+
 	ma= give_current_material(ob, psmd->psys->part->omat);
 	if(ma) {
 		for(i=0; ivdata, lvl->totvert);
 			CustomData_free(&mr->fdata, lvl->totface);
-			MEM_freeN(mr->edge_flags);
-			MEM_freeN(mr->edge_creases);
+			if(mr->edge_flags)
+				MEM_freeN(mr->edge_flags);
+			if(mr->edge_creases)
+				MEM_freeN(mr->edge_creases);
 		}
 
 		while(lvl) {
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index 22e4e8a8309..4d88556d8bf 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -61,8 +61,9 @@
 #include "BKE_image.h"
 #include "BKE_font.h"
 #include "BKE_packedFile.h"
+#include "BKE_report.h"
 
-int seekPackedFile(PackedFile * pf, int offset, int whence)
+int seekPackedFile(PackedFile *pf, int offset, int whence)
 {
 	int oldseek = -1, seek = 0;
 
@@ -92,12 +93,12 @@ int seekPackedFile(PackedFile * pf, int offset, int whence)
 	return(oldseek);
 }
 	
-void rewindPackedFile(PackedFile * pf)
+void rewindPackedFile(PackedFile *pf)
 {
 	seekPackedFile(pf, 0, SEEK_SET);
 }
 
-int readPackedFile(PackedFile * pf, void * data, int size)
+int readPackedFile(PackedFile *pf, void *data, int size)
 { 
 	if ((pf != NULL) && (size >= 0) && (data != NULL)) {
 		if (size + pf->seek > pf->size) {
@@ -118,66 +119,55 @@ int readPackedFile(PackedFile * pf, void * data, int size)
 	return(size);
 }
 
-int countPackedFiles()
+int countPackedFiles(Main *bmain)
 {
-	int count = 0;
 	Image *ima;
 	VFont *vf;
 	bSample *sample;
+	int count = 0;
 	
 	// let's check if there are packed files...
-	ima = G.main->image.first;
-	while (ima) {
-		if (ima->packedfile) {
+	for(ima=bmain->image.first; ima; ima=ima->id.next)
+		if(ima->packedfile)
 			count++;
-		}
-		ima= ima->id.next;
-	}
 
-	vf = G.main->vfont.first;
-	while (vf) {
-		if (vf->packedfile) {
+	for(vf=bmain->vfont.first; vf; vf=vf->id.next)
+		if(vf->packedfile)
 			count++;
-		}
-		vf = vf->id.next;
-	}
 
-	sample = samples->first;
-	while (sample) {
-		if (sample->packedfile) {
-			count++;
-		}
-		sample = sample->id.next;
-	}
+	if(samples)
+		for(sample=samples->first; sample; sample=sample->id.next)
+			if(sample->packedfile)
+				count++;
 
-	return(count);
+	return count;
 }
 
-void freePackedFile(PackedFile * pf)
+void freePackedFile(PackedFile *pf)
 {
-	if (pf) {
+	if(pf) {
 		MEM_freeN(pf->data);
 		MEM_freeN(pf);
-	} else {
-		printf("freePackedFile: Trying to free a NULL pointer\n");
 	}
+	else
+		printf("freePackedFile: Trying to free a NULL pointer\n");
 }
 	
-PackedFile * newPackedFileMemory(void *mem, int memlen)
+PackedFile *newPackedFileMemory(void *mem, int memlen)
 {
-	PackedFile * pf = MEM_callocN(sizeof(*pf), "PackedFile");
+	PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile");
 	pf->data = mem;
 	pf->size = memlen;
 	
 	return pf;
 }
 
-PackedFile * newPackedFile(char * filename)
+PackedFile *newPackedFile(ReportList *reports, char *filename)
 {
-	PackedFile * pf = NULL;
+	PackedFile *pf = NULL;
 	int file, filelen;
 	char name[FILE_MAXDIR+FILE_MAXFILE];
-	void * data;
+	void *data;
 	
 	//XXX waitcursor(1);
 	
@@ -191,7 +181,7 @@ PackedFile * newPackedFile(char * filename)
 
 	file= open(name, O_BINARY|O_RDONLY);
 	if (file <= 0) {
-		// error("Can't open file: %s", name);
+		BKE_reportf(reports, RPT_ERROR, "Can't open file: %s", name);
 	} else {
 		filelen = BLI_filesize(file);
 
@@ -214,36 +204,24 @@ PackedFile * newPackedFile(char * filename)
 	return (pf);
 }
 
-void packAll()
+void packAll(Main *bmain, ReportList *reports)
 {
 	Image *ima;
 	VFont *vf;
 	bSample *sample;
 	
-	ima = G.main->image.first;
-	while (ima) {
-		if (ima->packedfile == NULL) {
-			ima->packedfile = newPackedFile(ima->name);
-		}
-		ima= ima->id.next;
-	}
-	
-	vf = G.main->vfont.first;
-	while (vf) {
-		if (vf->packedfile == NULL) {
-			vf->packedfile = newPackedFile(vf->name);
-		}
-		vf = vf->id.next;
-	}
+	for(ima=bmain->image.first; ima; ima=ima->id.next)
+		if(ima->packedfile == NULL)
+			ima->packedfile = newPackedFile(reports, ima->name);
 
+	for(vf=bmain->vfont.first; vf; vf=vf->id.next)
+		if(vf->packedfile == NULL)
+			vf->packedfile = newPackedFile(reports, vf->name);
 
-	sample = samples->first;
-	while (sample) {
-		if (sample->packedfile == NULL) {
-			sound_set_packedfile(sample, newPackedFile(sample->name));
-		}
-		sample = sample->id.next;
-	}
+	if(samples)
+		for(sample=samples->first; sample; sample=sample->id.next)
+			if(sample->packedfile == NULL)
+				sound_set_packedfile(sample, newPackedFile(reports, sample->name));
 }
 
 
@@ -252,10 +230,10 @@ void packAll()
 // attempt to create a function that generates an unique filename
 // this will work when all funtions in fileops.c understand relative filenames...
 
-char * find_new_name(char * name)
+char *find_new_name(char *name)
 {
 	char tempname[FILE_MAXDIR + FILE_MAXFILE];
-	char * newname;
+	char *newname;
 	
 	if (fop_exists(name)) {
 		for (number = 1; number <= 999; number++) {
@@ -274,13 +252,13 @@ char * find_new_name(char * name)
 	
 */
 
-int writePackedFile(char * filename, PackedFile *pf, int guimode)
+int writePackedFile(ReportList *reports, char *filename, PackedFile *pf, int guimode)
 {
 	int file, number, remove_tmp = FALSE;
 	int ret_value = RET_OK;
 	char name[FILE_MAXDIR + FILE_MAXFILE];
 	char tempname[FILE_MAXDIR + FILE_MAXFILE];
-/*  	void * data; */
+/*  	void *data; */
 	
 	if (guimode); //XXX  waitcursor(1);
 	
@@ -305,23 +283,23 @@ int writePackedFile(char * filename, PackedFile *pf, int guimode)
 	file = open(name, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666);
 	if (file >= 0) {
 		if (write(file, pf->data, pf->size) != pf->size) {
-			if(guimode) ; //XXX error("Error writing file: %s", name);
+			BKE_reportf(reports, RPT_ERROR, "Error writing file: %s", name);
 			ret_value = RET_ERROR;
 		}
 		close(file);
 	} else {
-		if(guimode); //XXX error("Error creating file: %s", name);
+		BKE_reportf(reports, RPT_ERROR, "Error creating file: %s", name);
 		ret_value = RET_ERROR;
 	}
 	
 	if (remove_tmp) {
 		if (ret_value == RET_ERROR) {
 			if (BLI_rename(tempname, name) != 0) {
-				if(guimode); //XXX error("Error restoring tempfile. Check files: '%s' '%s'", tempname, name);
+				BKE_reportf(reports, RPT_ERROR, "Error restoring tempfile. Check files: '%s' '%s'", tempname, name);
 			}
 		} else {
 			if (BLI_delete(tempname, 0, 0) != 0) {
-				if(guimode); //XXX error("Error deleting '%s' (ignored)");
+				BKE_reportf(reports, RPT_ERROR, "Error deleting '%s' (ignored)", tempname);
 			}
 		}
 	}
@@ -342,7 +320,7 @@ PF_NOFILE		- the original file doens't exist
 
 */
 
-int checkPackedFile(char * filename, PackedFile * pf)
+int checkPackedFile(char *filename, PackedFile *pf)
 {
 	struct stat st;
 	int ret_val, i, len, file;
@@ -390,68 +368,23 @@ int checkPackedFile(char * filename, PackedFile * pf)
 
 /*
 
-unpackFile() looks at the existing files (abs_name, local_name) and a packed file.
-If how == PF_ASK it offers the user a couple of options what to do with the packed file.
+   unpackFile() looks at the existing files (abs_name, local_name) and a packed file.
 
-It returns a char * to the existing file name / new file name or NULL when
+It returns a char *to the existing file name / new file name or NULL when
 there was an error or when the user desides to cancel the operation.
 
 */
 
-char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how)
+char *unpackFile(ReportList *reports, char *abs_name, char *local_name, PackedFile *pf, int how)
 {
-	char menu[6 * (FILE_MAXDIR + FILE_MAXFILE + 100)];
+	char menu[6 *(FILE_MAXDIR + FILE_MAXFILE + 100)];
 	char line[FILE_MAXDIR + FILE_MAXFILE + 100];
-	char * newname = NULL, * temp = NULL;
+	char *newname = NULL, *temp = NULL;
 	
 	// char newabs[FILE_MAXDIR + FILE_MAXFILE];
 	// char newlocal[FILE_MAXDIR + FILE_MAXFILE];
 	
 	if (pf != NULL) {
-		if (how == PF_ASK) {
-			sprintf(menu, "UnPack file%%t|Remove Pack %%x%d", PF_REMOVE);
-			
-			if (strcmp(abs_name, local_name)) {
-				switch (checkPackedFile(local_name, pf)) {
-					case PF_NOFILE:
-						sprintf(line, "|Create %s%%x%d", local_name, PF_WRITE_LOCAL);
-						strcat(menu, line);
-						break;
-					case PF_EQUAL:
-						sprintf(line, "|Use %s (identical)%%x%d", local_name, PF_USE_LOCAL);
-						strcat(menu, line);
-						break;
-					case PF_DIFFERS:
-						sprintf(line, "|Use %s (differs)%%x%d", local_name, PF_USE_LOCAL);
-						strcat(menu, line);
-						sprintf(line, "|Overwrite %s%%x%d", local_name, PF_WRITE_LOCAL);
-						strcat(menu, line);
-						break;
-				}
-				// sprintf(line, "|%%x%d", PF_INVALID);
-				// strcat(menu, line);
-			}
-			
-			switch (checkPackedFile(abs_name, pf)) {
-				case PF_NOFILE:
-					sprintf(line, "|Create %s%%x%d", abs_name, PF_WRITE_ORIGINAL);
-					strcat(menu, line);
-					break;
-				case PF_EQUAL:
-					sprintf(line, "|Use %s (identical)%%x%d", abs_name, PF_USE_ORIGINAL);
-					strcat(menu, line);
-					break;
-				case PF_DIFFERS:
-					sprintf(line, "|Use %s (differs)%%x%d", abs_name, PF_USE_ORIGINAL);
-					strcat(menu, line);
-					sprintf(line, "|Overwrite %s%%x%d", abs_name, PF_WRITE_ORIGINAL);
-					strcat(menu, line);
-					break;
-			}
-			
-			//XXX how = pupmenu(menu);
-		}
-		
 		switch (how) {
 			case -1:
 			case PF_KEEP:
@@ -467,7 +400,7 @@ char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how)
 				}
 				// else fall through and create it
 			case PF_WRITE_LOCAL:
-				if (writePackedFile(local_name, pf, 1) == RET_OK) {
+				if (writePackedFile(reports, local_name, pf, 1) == RET_OK) {
 					temp = local_name;
 				}
 				break;
@@ -479,7 +412,7 @@ char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how)
 				}
 				// else fall through and create it
 			case PF_WRITE_ORIGINAL:
-				if (writePackedFile(abs_name, pf, 1) == RET_OK) {
+				if (writePackedFile(reports, abs_name, pf, 1) == RET_OK) {
 					temp = abs_name;
 				}
 				break;
@@ -498,10 +431,10 @@ char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how)
 }
 
 
-int unpackVFont(VFont * vfont, int how)
+int unpackVFont(ReportList *reports, VFont *vfont, int how)
 {
 	char localname[FILE_MAXDIR + FILE_MAXFILE], fi[FILE_MAXFILE];
-	char * newname;
+	char *newname;
 	int ret_value = RET_ERROR;
 	
 	if (vfont != NULL) {
@@ -510,7 +443,7 @@ int unpackVFont(VFont * vfont, int how)
 		
 		sprintf(localname, "//fonts/%s", fi);
 		
-		newname = unpackFile(vfont->name, localname, vfont->packedfile, how);
+		newname = unpackFile(reports, vfont->name, localname, vfont->packedfile, how);
 		if (newname != NULL) {
 			ret_value = RET_OK;
 			freePackedFile(vfont->packedfile);
@@ -523,10 +456,10 @@ int unpackVFont(VFont * vfont, int how)
 	return (ret_value);
 }
 
-int unpackSample(bSample *sample, int how)
+int unpackSample(ReportList *reports, bSample *sample, int how)
 {
 	char localname[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX];
-	char * newname;
+	char *newname;
 	int ret_value = RET_ERROR;
 	PackedFile *pf;
 	
@@ -535,7 +468,7 @@ int unpackSample(bSample *sample, int how)
 		BLI_splitdirstring(localname, fi);
 		sprintf(localname, "//samples/%s", fi);
 		
-		newname = unpackFile(sample->name, localname, sample->packedfile, how);
+		newname = unpackFile(reports, sample->name, localname, sample->packedfile, how);
 		if (newname != NULL) {
 			strcpy(sample->name, newname);
 			MEM_freeN(newname);
@@ -553,10 +486,10 @@ int unpackSample(bSample *sample, int how)
 	return(ret_value);
 }
 
-int unpackImage(Image * ima, int how)
+int unpackImage(ReportList *reports, Image *ima, int how)
 {
 	char localname[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX];
-	char * newname;
+	char *newname;
 	int ret_value = RET_ERROR;
 	
 	if (ima != NULL) {
@@ -564,7 +497,7 @@ int unpackImage(Image * ima, int how)
 		BLI_splitdirstring(localname, fi);
 		sprintf(localname, "//textures/%s", fi);
 			
-		newname = unpackFile(ima->name, localname, ima->packedfile, how);
+		newname = unpackFile(reports, ima->name, localname, ima->packedfile, how);
 		if (newname != NULL) {
 			ret_value = RET_OK;
 			freePackedFile(ima->packedfile);
@@ -578,33 +511,23 @@ int unpackImage(Image * ima, int how)
 	return(ret_value);
 }
 
-void unpackAll(int how)
+void unpackAll(Main *bmain, ReportList *reports, int how)
 {
 	Image *ima;
 	VFont *vf;
 	bSample *sample;
-		
-	ima = G.main->image.first;
-	while (ima) {
-		if (ima->packedfile) {
-			unpackImage(ima, how);
-		}
-		ima= ima->id.next;
-	}
-	
-	vf = G.main->vfont.first;
-	while (vf) {
-		if (vf->packedfile) {
-			unpackVFont(vf, how);
-		}
-		vf = vf->id.next;
-	}
 
-	sample = samples->first;
-	while (sample) {
-		if (sample->packedfile) {
-			unpackSample(sample, how);
-		}
-		sample = sample->id.next;
-	}
+	for(ima=bmain->image.first; ima; ima=ima->id.next)
+		if(ima->packedfile)
+			unpackImage(reports, ima, how);
+
+	for(vf=bmain->vfont.first; vf; vf=vf->id.next)
+		if(vf->packedfile)
+			unpackVFont(reports, vf, how);
+
+	if(samples)
+		for(sample=samples->first; sample; sample=sample->id.next)
+			if(sample->packedfile)
+				unpackSample(reports, sample, how);
 }
+
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 34e69b2d736..5bf9335d211 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -222,6 +222,34 @@ short psys_get_current_num(Object *ob)
 	
 	return i;
 }
+void psys_set_current_num(Object *ob, int index)
+{
+	ParticleSystem *psys;
+	short i;
+
+	if(ob==0) return;
+
+	for(psys=ob->particlesystem.first, i=0; psys; psys=psys->next, i++) {
+		if(i == index)
+			psys->flag |= PSYS_CURRENT;
+		else
+			psys->flag &= ~PSYS_CURRENT;
+	}
+}
+Object *psys_find_object(Scene *scene, ParticleSystem *psys)
+{
+	Base *base = scene->base.first;
+	ParticleSystem *tpsys;
+
+	for(base = scene->base.first; base; base = base->next) {
+		for(tpsys = base->object->particlesystem.first; psys; psys=psys->next) {
+			if(tpsys == psys)
+				return base->object;
+		}
+	}
+
+	return NULL;
+}
 /* change object's active particle system */
 void psys_change_act(void *ob_v, void *act_v)
 {
@@ -293,7 +321,7 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys)
 	ParticleSystemModifierData *psmd;
 	Mesh *me;
 
-	if(psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE)
+	if(psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE || !psys->part)
 		return 0;
 
 	if(ob->type == OB_MESH) {
@@ -864,7 +892,7 @@ static void weighted_particle_vector(float *v1, float *v2, float *v3, float *v4,
 	vec[1]= weights[0]*v1[1] + weights[1]*v2[1] + weights[2]*v3[1] + weights[3]*v4[1];
 	vec[2]= weights[0]*v1[2] + weights[1]*v2[2] + weights[2]*v3[2] + weights[3]*v4[2];
 }
-static void interpolate_particle(short type, ParticleKey keys[4], float dt, ParticleKey *result, int velocity)
+void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, ParticleKey *result, int velocity)
 {
 	float t[4];
 
@@ -2569,7 +2597,7 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
 			}
 
 			/* now we should have in chronologiacl order k1<=k2<=t<=k3<=k4 with keytime between [0,1]->[k2,k3] (k1 & k4 used for cardinal & bspline interpolation)*/
-			interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */
+			psys_interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */
 				: ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL)
 				,keys, keytime, &result, 0);
 
@@ -2901,6 +2929,61 @@ void psys_mat_hair_to_global(Object *ob, DerivedMesh *dm, short from, ParticleDa
 /************************************************/
 /*			ParticleSettings handling			*/
 /************************************************/
+void object_add_particle_system(Scene *scene, Object *ob)
+{
+	ParticleSystem *psys;
+	ModifierData *md;
+	ParticleSystemModifierData *psmd;
+
+	if(!ob || ob->type != OB_MESH)
+		return;
+
+	psys = ob->particlesystem.first;
+	for(; psys; psys=psys->next)
+		psys->flag &= ~PSYS_CURRENT;
+
+	psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
+	psys->pointcache = BKE_ptcache_add();
+	BLI_addtail(&ob->particlesystem, psys);
+
+	psys->part = psys_new_settings("PSys", NULL);
+
+	md= modifier_new(eModifierType_ParticleSystem);
+	sprintf(md->name, "ParticleSystem %i", BLI_countlist(&ob->particlesystem));
+	psmd= (ParticleSystemModifierData*) md;
+	psmd->psys=psys;
+	BLI_addtail(&ob->modifiers, md);
+
+	psys->totpart=0;
+	psys->flag = PSYS_ENABLED|PSYS_CURRENT;
+	psys->cfra=bsystem_time(scene,ob,scene->r.cfra+1,0.0);
+
+	DAG_scene_sort(scene);
+	DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+}
+void object_remove_particle_system(Scene *scene, Object *ob)
+{
+	ParticleSystem *psys = psys_get_current(ob);
+	ParticleSystemModifierData *psmd;
+
+	if(!psys)
+		return;
+
+	/* clear modifier */
+	psmd= psys_get_modifier(ob, psys);
+	BLI_remlink(&ob->modifiers, psmd);
+	modifier_free((ModifierData *)psmd);
+
+	/* clear particle system */
+	BLI_remlink(&ob->particlesystem, psys);
+	psys_free(ob,psys);
+
+	if(ob->particlesystem.first)
+		((ParticleSystem *) ob->particlesystem.first)->flag |= PSYS_CURRENT;
+
+	DAG_scene_sort(scene);
+	DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+}
 static void default_particle_settings(ParticleSettings *part)
 {
 	int i;
@@ -2987,6 +3070,9 @@ ParticleSettings *psys_new_settings(char *name, Main *main)
 {
 	ParticleSettings *part;
 
+	if(main==NULL)
+		main = G.main;
+
 	part= alloc_libblock(&main->particle, ID_PA, name);
 	
 	default_particle_settings(part);
@@ -3062,7 +3148,6 @@ void make_local_particlesettings(ParticleSettings *part)
 		}
 	}
 }
-
 void psys_flush_particle_settings(Scene *scene, ParticleSettings *part, int recalc)
 {
 	Base *base = scene->base.first;
@@ -3495,7 +3580,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
 			QuatInterpol(state->rot,keys[1].rot,keys[2].rot,keytime);
 		}
 
-		interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */
+		psys_interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */
 			: ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL)
 			,keys, keytime, state, 1);
 
@@ -3702,6 +3787,8 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy
 			if((pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN)==0)
 				|| (pa->alive==PARS_DEAD && (part->flag & PART_DIED)==0))
 				return 0;
+
+		state->time = MIN2(state->time, pa->dietime);
 	}
 
 	if(psys->flag & PSYS_KEYED){
@@ -3776,7 +3863,7 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy
 							VecMulf(keys[1].vel, dfra / frs_sec);
 							VecMulf(keys[2].vel, dfra / frs_sec);
 							
-							interpolate_particle(-1, keys, keytime, state, 1);
+							psys_interpolate_particle(-1, keys, keytime, state, 1);
 							
 							/* convert back to real velocity */
 							VecMulf(state->vel, frs_sec / dfra);
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 52f13eeadb8..591b6ca9be5 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -29,6 +29,8 @@
  * ***** END GPL LICENSE BLOCK *****
  */
 
+#include "BLI_storage.h" /* _LARGEFILE_SOURCE */
+
 #include 
 #include 
 #include 
@@ -104,7 +106,8 @@ static int get_current_display_percentage(ParticleSystem *psys)
 {
 	ParticleSettings *part=psys->part;
 
-	if(psys->renderdata || (part->child_nbr && part->childtype)) 
+	if(psys->renderdata || (part->child_nbr && part->childtype)
+		|| (psys->pointcache->flag & PTCACHE_BAKING))
 		return 100;
 
 	if(part->phystype==PART_PHYS_KEYED){
@@ -2195,57 +2198,91 @@ void psys_get_reactor_target(Object *ob, ParticleSystem *psys, Object **target_o
 /************************************************/
 /*			Point Cache							*/
 /************************************************/
-
-static void write_particles_to_cache(Object *ob, ParticleSystem *psys, int cfra)
+void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra, int *efra)
 {
-	PTCacheID pid;
-	PTCacheFile *pf;
-	ParticleData *pa;
-	int i, totpart= psys->totpart;
+	ParticleSettings *part = psys->part;
 
-	if(totpart == 0)
-		return;
-
-	BKE_ptcache_id_from_particles(&pid, ob, psys);
-	pf= BKE_ptcache_file_open(&pid, PTCACHE_FILE_WRITE, cfra);
-	if(!pf)
-		return;
-
-	/* assuming struct consists of tightly packed floats */
-	for(i=0, pa=psys->particles; istate, sizeof(ParticleKey)/sizeof(float));
-	
-	BKE_ptcache_file_close(pf);
+	*sfra = MAX2(1, (int)part->sta);
+	*efra = MIN2((int)(part->end + part->lifetime + 1.0), scene->r.efra);
 }
-
-static int get_particles_from_cache(Object *ob, ParticleSystem *psys, int cfra)
+static void particle_write_state(int index, ParticleSystem *psys, float *data)
 {
-	PTCacheID pid;
-	PTCacheFile *pf;
-	ParticleData *pa;
-	int i, totpart= psys->totpart;
+	memcpy(data, (float *)(&(psys->particles+index)->state), sizeof(ParticleKey));
+}
+static void particle_read_state(int index, void *psys_ptr, float *data)
+{
+	ParticleSystem *psys= psys_ptr;
+	ParticleData *pa = psys->particles + index;
+	ParticleKey *key = (ParticleKey *)data;
 
-	if(totpart == 0)
-		return 0;
+	if(key->time > pa->state.time)
+		copy_particle_key(&pa->prev_state, &pa->state, 1);
 
-	BKE_ptcache_id_from_particles(&pid, ob, psys);
-	pf= BKE_ptcache_file_open(&pid, PTCACHE_FILE_READ, cfra);
-	if(!pf)
-		return 0;
+	copy_particle_key(&pa->state, key, 1);
+}
+static void particle_cache_interpolate(int index, void *psys_ptr, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2)
+{
+	ParticleSystem *psys= psys_ptr;
+	ParticleData *pa = psys->particles + index;
+	ParticleKey keys[4];
+	float dfra, cfra1f = (float)cfra1, cfra2f(float);
 
-	/* assuming struct consists of tightly packed floats */
-	for(i=0, pa=psys->particles; istate.time)
-			copy_particle_key(&pa->prev_state,&pa->state,1);
-		if(!BKE_ptcache_file_read_floats(pf, (float*)&pa->state, sizeof(ParticleKey)/sizeof(float))) {
-			BKE_ptcache_file_close(pf);
-			return 0;
-		}
+	cfra = MIN2(cfra, pa->dietime);
+	cfra1 = MIN2(cfra1, pa->dietime);
+	cfra2 = MIN2(cfra2, pa->dietime);
+
+	keys[1] = *((ParticleKey*)data1);
+	keys[2] = *((ParticleKey*)data2);
+
+	if(cfra1 == cfra2) {
+		copy_particle_key(&pa->state, &keys[1], 1);
+		return;
 	}
 
-	BKE_ptcache_file_close(pf);
+	dfra = cfra2 - cfra1;
 
-	return 1;
+	VecMulf(keys[1].vel, dfra / frs_sec);
+	VecMulf(keys[2].vel, dfra / frs_sec);
+
+	psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
+
+	VecMulf(pa->state.vel, frs_sec / dfra);
+
+	pa->state.time = cfra;
+}
+static void write_particles_to_cache(Object *ob, ParticleSystem *psys, int cfra)
+{
+	PTCacheWriter writer;
+	PTCacheID pid;
+
+	BKE_ptcache_id_from_particles(&pid, ob, psys);
+
+	writer.calldata = psys;
+	writer.cfra = cfra;
+	writer.set_elem = particle_write_state;
+	writer.pid = &pid;
+	writer.totelem = psys->totpart;
+
+	BKE_ptcache_write_cache(&writer);
+}
+
+static int get_particles_from_cache(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int *old_frame)
+{
+	PTCacheReader reader;
+	PTCacheID pid;
+	
+	BKE_ptcache_id_from_particles(&pid, ob, psys);
+
+	reader.calldata = psys;
+	reader.cfra = cfra;
+	reader.interpolate_elem = particle_cache_interpolate;
+	reader.old_frame = old_frame;
+	reader.pid = &pid;
+	reader.scene = scene;
+	reader.set_elem = particle_read_state;
+	reader.totelem = psys->totpart;
+
+	return BKE_ptcache_read_cache(&reader);
 }
 
 /************************************************/
@@ -2372,6 +2409,8 @@ static void add_to_effectors(ListBase *lb, Scene *scene, Object *ob, Object *obs
 		Object *tob;
 
 		for(i=0; epsys; epsys=epsys->next,i++){
+			if(!psys_check_enabled(ob, epsys))
+				continue;
 			type=0;
 			if(epsys!=psys || (psys->part->flag & PART_SELF_EFFECT)){
 				epart=epsys->part;
@@ -4085,7 +4124,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic
 
 		/* main loop: calculate physics for all particles */
 		for(p=0, pa=psys->particles; pflag & PARS_UNEXIST) continue;
+			if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue;
 
 			copy_particle_key(&pa->prev_state,&pa->state,1);
 			
@@ -4110,25 +4149,26 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic
 			if(pa->alive==PARS_UNBORN
 				|| pa->alive==PARS_KILLED
 				|| ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED)
-				|| birthtime >= cfra){
+				|| birthtime >= psys->cfra){
 				reset_particle(scene, pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot);
 			}
 
 			pa_dfra = dfra;
 			pa_dtime = dtime;
 
-			if(birthtime <= cfra && birthtime >= psys->cfra){
+
+			if(dietime <= cfra && psys->cfra < dietime){
+				/* particle dies some time between this and last step */
+				pa_dfra = dietime - ((birthtime > psys->cfra) ? birthtime : psys->cfra);
+				pa_dtime = pa_dfra * timestep;
+				pa->alive = PARS_DYING;
+			}
+			else if(birthtime <= cfra && birthtime >= psys->cfra){
 				/* particle is born some time between this and last step*/
 				pa->alive = PARS_ALIVE;
 				pa_dfra = cfra - birthtime;
 				pa_dtime = pa_dfra*timestep;
 			}
-			else if(dietime <= cfra && psys->cfra < dietime){
-				/* particle dies some time between this and last step */
-				pa_dfra = dietime - psys->cfra;
-				pa_dtime = pa_dfra * timestep;
-				pa->alive = PARS_DYING;
-			}
 			else if(dietime < cfra){
 				/* nothing to be done when particle is dead */
 			}
@@ -4335,7 +4375,7 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps
 			pa->alive = PARS_UNBORN;
 		else if(dietime <= cfra){
 			if(dietime > psys->cfra){
-				state.time = pa->dietime;
+				state.time = dietime;
 				psys_get_particle_state(scene, ob,psys,p,&state,1);
 				push_reaction(ob,psys,p,PART_EVENT_DEATH,&state);
 			}
@@ -4520,7 +4560,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
 	int totpart, oldtotpart, totchild, oldtotchild, p;
 	float disp, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0;
 	int init= 0, distr= 0, alloc= 0, usecache= 0, only_children_changed= 0;
-	int framenr, framedelta, startframe, endframe;
+	int framenr, framedelta, startframe, endframe, old_framenr;
 
 	part= psys->part;
 	cache= psys->pointcache;
@@ -4528,6 +4568,10 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
 	framenr= (int)scene->r.cfra;
 	framedelta= framenr - cache->simframe;
 
+	/* set suitable cache range automatically */
+	if((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0)
+		psys_get_pointcache_start_end(scene, psys, &cache->startframe, &cache->endframe);
+
 	BKE_ptcache_id_from_particles(&pid, ob, psys);
 	BKE_ptcache_id_time(&pid, scene, 0.0f, &startframe, &endframe, NULL);
 
@@ -4600,9 +4644,13 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
 
 	if(init) {
 		if(distr) {
-			if(alloc)
+			if(alloc) {
 				realloc_particles(ob, psys, totpart);
 
+				if(usecache)
+					BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0);
+			}
+
 			distribute_particles(scene, ob, psys, part->from);
 
 			if((psys->part->type == PART_HAIR) && !(psys->flag & PSYS_HAIR_DONE))
@@ -4616,9 +4664,11 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
 			free_keyed_keys(psys);
 
 			initialize_all_particles(ob, psys, psmd);
+			
 
-			if(alloc)
+			if(alloc) {
 				reset_all_particles(scene, ob, psys, psmd, 0.0, cfra, oldtotpart);
+			}
 		}
 
 		/* flag for possible explode modifiers after this system */
@@ -4627,46 +4677,59 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
 
 	/* try to read from the cache */
 	if(usecache) {
-		if(get_particles_from_cache(ob, psys, framenr)) {
-			if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) {
-				psys_count_keyed_targets(ob,psys);
-				set_keyed_keys(scene, ob, psys);
-			}
+		int result = get_particles_from_cache(scene, ob, psys, (float)framenr, &old_framenr);
+
+		if(result == PTCACHE_READ_EXACT || result == PTCACHE_READ_INTERPOLATED) {
+			//if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) {
+			//	psys_count_keyed_targets(ob,psys);
+			//	set_keyed_keys(scene, ob, psys);
+			//}
 
 			cached_step(scene, ob, psmd, psys, cfra);
 			psys->cfra=cfra;
 			psys->recalc = 0;
 
-			if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) {
-				psys_update_path_cache(scene, ob, psmd, psys, framenr);
-			}
+			//if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) {
+			//	psys_update_path_cache(scene, ob, psmd, psys, framenr);
+			//}
 
 			cache->simframe= framenr;
 			cache->flag |= PTCACHE_SIMULATION_VALID;
 
+			if(result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
+				write_particles_to_cache(ob, psys, cfra);
+
 			return;
 		}
+		else if(result==PTCACHE_READ_OLD) {
+			/* set old cfra */
+			psys->cfra = (float)old_framenr;
+
+			for(p=0, pa=psys->particles; ptime > psys->cfra)
+					pa->alive = PARS_UNBORN;
+				else if(pa->dietime <= psys->cfra)
+					pa->alive = PARS_DEAD;
+				else
+					pa->alive = PARS_ALIVE;
+			}
+		}
 		else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) {
 			psys_reset(psys, PSYS_RESET_CACHE_MISS);
 			psys->cfra=cfra;
 			psys->recalc = 0;
 			return;
 		}
-
-		if(framenr != startframe && framedelta != 1) {
-			psys_reset(psys, PSYS_RESET_CACHE_MISS);
-			psys->cfra = cfra;
-			psys->recalc = 0;
-			return;
-		}
 	}
 	else {
 		cache->flag &= ~PTCACHE_SIMULATION_VALID;
 		cache->simframe= 0;
+		cache->last_exact= 0;
 	}
 
 	/* if on second frame, write cache for first frame */
-	if(usecache && framenr == startframe+1)
+	if(usecache && psys->cfra == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
 		write_particles_to_cache(ob, psys, startframe);
 
 	if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED)
@@ -4768,8 +4831,7 @@ static void psys_to_softbody(Scene *scene, Object *ob, ParticleSystem *psys)
 static int hair_needs_recalc(ParticleSystem *psys)
 {
 	if((psys->flag & PSYS_EDITED)==0 &&
-		((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_REDO)) {
-		psys->recalc &= ~PSYS_RECALC_REDO;
+		((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_RESET)) {
 		return 1;
 	}
 
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index b00755f7135..64473d07151 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -51,9 +51,11 @@
 #include "BKE_object.h"
 #include "BKE_particle.h"
 #include "BKE_pointcache.h"
+#include "BKE_scene.h"
 #include "BKE_softbody.h"
 #include "BKE_utildefines.h"
 
+#include "BLI_blenlib.h"
 
 /* needed for directory lookup */
 #ifndef WIN32
@@ -213,21 +215,29 @@ static int BKE_ptcache_id_filename(PTCacheID *pid, char *filename, int cfra, sho
 	filename[0] = '\0';
 	newname = filename;
 	
-	/*if (!G.relbase_valid) return 0; *//* save blend file before using pointcache */
+	if (!G.relbase_valid) return 0; /* save blend file before using disk pointcache */
 	
 	/* start with temp dir */
 	if (do_path) {
 		len = ptcache_path(pid, filename);
 		newname += len;
 	}
-	idname = (pid->ob->id.name+2);
-	/* convert chars to hex so they are always a valid filename */
-	while('\0' != *idname) {
-		snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++));
-		newname+=2;
-		len += 2;
+	if(strcmp(pid->cache->name, "")==0) {
+		idname = (pid->ob->id.name+2);
+		/* convert chars to hex so they are always a valid filename */
+		while('\0' != *idname) {
+			snprintf(newname, MAX_PTCACHE_FILE, "%02X", (char)(*idname++));
+			newname+=2;
+			len += 2;
+		}
 	}
-	
+	else {
+		int temp = strlen(pid->cache->name); 
+		strcpy(newname, pid->cache->name); 
+		newname+=temp;
+		len += temp;
+	}
+
 	if (do_ext) {
 		snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
 		len += 16;
@@ -247,7 +257,7 @@ PTCacheFile *BKE_ptcache_file_open(PTCacheID *pid, int mode, int cfra)
 	if(pid->ob->id.lib && mode == PTCACHE_FILE_WRITE)
 		return NULL;
 
-	/*if (!G.relbase_valid) return NULL; *//* save blend file before using pointcache */
+	if (!G.relbase_valid) return NULL; /* save blend file before using disk pointcache */
 	
 	BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
 
@@ -286,6 +296,427 @@ int BKE_ptcache_file_write_floats(PTCacheFile *pf, float *f, int tot)
 	return (fwrite(f, sizeof(float), tot, pf->fp) == tot);
 }
 
+static int ptcache_pid_elemsize(PTCacheID *pid)
+{
+	if(pid->type==PTCACHE_TYPE_SOFTBODY)
+		return 0; // TODO
+	else if(pid->type==PTCACHE_TYPE_PARTICLES)
+		return sizeof(ParticleKey);
+	else if(pid->type==PTCACHE_TYPE_CLOTH)
+		return 9 * sizeof(float);
+
+	return 0;
+}
+static int ptcache_pid_totelem(PTCacheID *pid)
+{
+	if(pid->type==PTCACHE_TYPE_SOFTBODY)
+		return 0; // TODO
+	else if(pid->type==PTCACHE_TYPE_PARTICLES) {
+		ParticleSystem *psys = pid->data;
+		return psys->totpart;
+	}
+	else if(pid->type==PTCACHE_TYPE_CLOTH)
+		return 0; // TODO
+
+	return 0;
+}
+
+void BKE_ptcache_update_info(PTCacheID *pid)
+{
+	PointCache *cache = pid->cache;
+	int totframes = 0;
+	char mem_info[64];
+
+	if(cache->flag & PTCACHE_DISK_CACHE) {
+		int cfra = cache->startframe;
+
+		for(; cfra<=cache->endframe; cfra++) {
+			if(BKE_ptcache_id_exist(pid, cfra))
+				totframes++;
+		}
+
+		sprintf(mem_info, "%i frames on disk", totframes);
+	}
+	else {
+		PTCacheMem *pm = cache->mem_cache.first;		
+		float framesize = 0.0f, bytes = 0.0f;
+		int mb;
+
+		if(pm)
+			framesize = (float)ptcache_pid_elemsize(pid) * (float)pm->totpoint;
+		
+		for(; pm; pm=pm->next)
+			totframes++;
+
+		bytes = totframes * framesize;
+
+		mb = (bytes > 1024.0f * 1024.0f);
+
+		sprintf(mem_info, "%i frames in memory (%.1f %s)",
+			totframes,
+			bytes / (mb ? 1024.0f * 1024.0f : 1024.0f),
+			mb ? "Mb" : "kb");
+	}
+
+	if(cache->flag & PTCACHE_OUTDATED) {
+		sprintf(cache->info, "%s, cache is outdated!", mem_info);
+	}
+	else if(cache->flag & PTCACHE_FRAMES_SKIPPED) {
+		sprintf(cache->info, "%s, not exact since frame %i.", mem_info, cache->last_exact);
+	}
+	else
+		sprintf(cache->info, "%s.", mem_info);
+}
+/* reads cache from disk or memory */
+/* possible to get old or interpolated result */
+int BKE_ptcache_read_cache(PTCacheReader *reader)
+{
+	PTCacheID *pid = reader->pid;
+	PTCacheFile *pf=NULL, *pf2=NULL;
+	PTCacheMem *pm=NULL, *pm2=NULL;
+	int totelem = reader->totelem;
+	float cfra = reader->cfra;
+	int cfrai = (int)cfra;
+	int elemsize = ptcache_pid_elemsize(pid);
+	int i, incr = elemsize / sizeof(float);
+	float frs_sec = reader->scene->r.frs_sec;
+	int cfra1=0, cfra2;
+	int ret = 0;
+
+	if(totelem == 0)
+		return 0;
+
+
+	/* first check if we have the actual frame cached */
+	if(cfra == (float)cfrai) {
+		if(pid->cache->flag & PTCACHE_DISK_CACHE) {
+			pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
+		}
+		else {
+			pm = pid->cache->mem_cache.first;
+
+			for(; pm; pm=pm->next) {
+				if(pm->frame == cfrai)
+					break;
+			}
+		}
+	}
+
+	/* if found, use exact frame */
+	if(pf || pm) {
+		float *data;
+
+		if(pm)
+			data = pm->data;
+		else
+			data = MEM_callocN(elemsize, "pointcache read data");
+
+		for(i=0; iset_elem(i, reader->calldata, data);
+			}
+			else {
+				reader->set_elem(i, reader->calldata, data);
+				data += incr;
+			}
+		}
+
+		if(pf) {
+			BKE_ptcache_file_close(pf);
+			MEM_freeN(data);
+		}
+
+		ret = PTCACHE_READ_EXACT;
+	}
+
+	if(ret)
+		;
+	/* no exact cache frame found so try to find cached frames around cfra */
+	else if(pid->cache->flag & PTCACHE_DISK_CACHE) {
+		pf=NULL;
+		while(cfrai > pid->cache->startframe && !pf) {
+			cfrai--;
+			pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
+			cfra1 = cfrai;
+		}
+
+		if(reader->old_frame)
+			*(reader->old_frame) = cfrai;
+
+		cfrai = (int)cfra;
+		while(cfrai < pid->cache->endframe && !pf2) {
+			cfrai++;
+			pf2= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
+			cfra2 = cfrai;
+		}
+	}
+	else if(pid->cache->mem_cache.first){
+		pm = pid->cache->mem_cache.first;
+
+		while(pm->next && pm->next->frame < cfra)
+			pm= pm->next;
+
+		if(pm) {
+			if(reader->old_frame)
+				*(reader->old_frame) = pm->frame;
+			cfra1 = pm->frame;
+		}
+
+		pm2 = pid->cache->mem_cache.last;
+
+		if(pm2 && pm2->frame < cfra)
+			pm2 = NULL;
+		else {
+			while(pm2->prev && pm2->prev->frame > cfra)
+				pm2= pm2->prev;
+
+			if(pm2)
+				cfra2 = pm2->frame;
+		}
+	}
+
+	if(ret)
+		;
+	else if((pf && pf2) || (pm && pm2)) {
+		/* interpolate from nearest frames if cache isn't outdated */
+		float *data1, *data2;
+
+		if(pm) {
+			data1 = pm->data;
+			data2 = pm2->data;
+		}
+		else {
+			data1 = MEM_callocN(elemsize, "pointcache read data1");
+			data2 = MEM_callocN(elemsize, "pointcache read data2");
+		}
+
+		for(i=0; iinterpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2);
+			}
+			else {
+				reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2);
+				data1 += incr;
+				data2 += incr;
+			}
+		}
+
+		if(pf) {
+			BKE_ptcache_file_close(pf);
+			BKE_ptcache_file_close(pf2);
+			MEM_freeN(data1);
+			MEM_freeN(data2);
+		}
+
+		ret = PTCACHE_READ_INTERPOLATED;
+	}
+	else if(pf || pm) {
+		/* use last valid cache frame */
+		float *data;
+
+		/* don't read cache if allready simulated past cached frame */
+		if(cfra1 && cfra1 <= pid->cache->simframe) {
+			if(pf)
+				BKE_ptcache_file_close(pf);
+			if(pf2)
+				BKE_ptcache_file_close(pf2);
+
+			return 0;
+		}
+
+		if(pm)
+			data = pm->data;
+		else
+			data = MEM_callocN(elemsize, "pointcache read data");
+
+		for(i=0; iset_elem(i, reader->calldata, data);
+			}
+			else {
+				reader->set_elem(i, reader->calldata, data);
+				data += incr;
+			}
+		}
+
+		if(pf) {
+			BKE_ptcache_file_close(pf);
+			MEM_freeN(data);
+		}
+		if(pf2)
+			BKE_ptcache_file_close(pf2);
+
+		ret = PTCACHE_READ_OLD;
+	}
+
+	if(pf)
+		BKE_ptcache_file_close(pf);
+	if(pf2)
+		BKE_ptcache_file_close(pf2);
+
+	if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) {
+		/* clear invalid cache frames so that better stuff can be simulated */
+		if(pid->cache->flag & PTCACHE_OUTDATED) {
+			BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfra);
+		}
+		else if(pid->cache->flag & PTCACHE_FRAMES_SKIPPED) {
+			if(cfra <= pid->cache->last_exact)
+				pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
+
+			BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfra,pid->cache->last_exact));
+		}
+	}
+
+	return ret;
+}
+/* writes cache to disk or memory */
+int BKE_ptcache_write_cache(PTCacheWriter *writer)
+{
+	PointCache *cache = writer->pid->cache;
+	PTCacheFile *pf= NULL;
+	int elemsize = ptcache_pid_elemsize(writer->pid);
+	int i, incr = elemsize / sizeof(float);
+	int add = 0, overwrite = 0, ocfra;
+	float temp[14];
+
+	if(writer->totelem == 0 || writer->cfra <= 0)
+		return 0;
+
+	if(cache->flag & PTCACHE_DISK_CACHE) {
+		/* allways start from scratch on the first frame */
+		if(writer->cfra == cache->startframe) {
+			BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra);
+			cache->flag &= ~PTCACHE_REDO_NEEDED;
+			add = 1;
+		}
+		else {
+			int cfra = cache->endframe;
+			/* find last cached frame */
+			while(cfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, cfra))
+				cfra--;
+
+			/* find second last cached frame */
+			ocfra = cfra-1;
+			while(ocfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, ocfra))
+				ocfra--;
+
+			if(writer->cfra > cfra) {
+				if(ocfra >= cache->startframe && cfra - ocfra < cache->step)
+					overwrite = 1;
+				else
+					add = 1;
+			}
+		}
+
+		if(add || overwrite) {
+			if(overwrite)
+				BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_FRAME, ocfra);
+
+			pf = BKE_ptcache_file_open(writer->pid, PTCACHE_FILE_WRITE, writer->cfra);
+			if(!pf)
+				return 0;
+
+			for(i=0; itotelem; i++) {
+				writer->set_elem(i, writer->calldata, &temp);
+				BKE_ptcache_file_write_floats(pf, &temp, incr);
+			}
+		}
+	}
+	else {
+		PTCacheMem *pm;
+		PTCacheMem *pm2;
+		float *pmdata;
+
+		pm2 = cache->mem_cache.first;
+		
+		/* allways start from scratch on the first frame */
+		if(writer->cfra == cache->startframe) {
+			BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra);
+			cache->flag &= ~PTCACHE_REDO_NEEDED;
+			add = 1;
+		}
+		else {
+			pm2 = cache->mem_cache.last;
+
+			if(pm2 && writer->cfra > pm2->frame) {
+				if(pm2 && pm2->prev && pm2->frame - pm2->prev->frame < cache->step)
+					overwrite = 1;
+				else
+					add = 1;
+			}
+		}
+
+		if(overwrite) {
+			pm = cache->mem_cache.last;
+			pmdata = pm->data;
+
+			for(i=0; itotelem; i++, pmdata+=incr) {
+				writer->set_elem(i, writer->calldata, &temp);
+				memcpy(pmdata, &temp, elemsize);
+			}
+
+			pm->frame = writer->cfra;
+		}
+		else if(add) {
+			pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
+			pm->data = MEM_callocN(elemsize * writer->totelem, "Pointcache mem data");
+			pmdata = pm->data;
+
+			for(i=0; itotelem; i++, pmdata+=incr) {
+				writer->set_elem(i, writer->calldata, &temp);
+				memcpy(pmdata, &temp, elemsize);
+			}
+
+			pm->frame = writer->cfra;
+			pm->totpoint = writer->totelem;
+
+			BLI_addtail(&cache->mem_cache, pm);
+		}
+	}
+
+	if(add || overwrite) {
+		if(writer->cfra - cache->last_exact == 1
+			|| writer->cfra == cache->startframe) {
+			cache->last_exact = writer->cfra;
+			cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
+		}
+		else
+			cache->flag |= PTCACHE_FRAMES_SKIPPED;
+	}
+	
+	if(pf)
+		BKE_ptcache_file_close(pf);
+
+	BKE_ptcache_update_info(writer->pid);
+
+	return 1;
+}
 /* youll need to close yourself after!
  * mode - PTCACHE_CLEAR_ALL, 
 
@@ -317,62 +748,116 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
 	case PTCACHE_CLEAR_ALL:
 	case PTCACHE_CLEAR_BEFORE:	
 	case PTCACHE_CLEAR_AFTER:
-		ptcache_path(pid, path);
-		
-		len = BKE_ptcache_id_filename(pid, filename, cfra, 0, 0); /* no path */
-		
-		dir = opendir(path);
-		if (dir==NULL)
-			return;
+		if(pid->cache->flag & PTCACHE_DISK_CACHE) {
+			ptcache_path(pid, path);
+			
+			len = BKE_ptcache_id_filename(pid, filename, cfra, 0, 0); /* no path */
+			
+			dir = opendir(path);
+			if (dir==NULL)
+				return;
 
-		snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index);
-		
-		while ((de = readdir(dir)) != NULL) {
-			if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
-				if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
-					if (mode == PTCACHE_CLEAR_ALL) {
-						BLI_join_dirfile(path_full, path, de->d_name);
-						BLI_delete(path_full, 0, 0);
-					} else {
-						/* read the number of the file */
-						int frame, len2 = strlen(de->d_name);
-						char num[7];
+			snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, pid->stack_index);
+			
+			while ((de = readdir(dir)) != NULL) {
+				if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
+					if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */
+						if (mode == PTCACHE_CLEAR_ALL) {
+							pid->cache->last_exact = 0;
+							BLI_join_dirfile(path_full, path, de->d_name);
+							BLI_delete(path_full, 0, 0);
+						} else {
+							/* read the number of the file */
+							int frame, len2 = strlen(de->d_name);
+							char num[7];
 
-						if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
-							BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
-							frame = atoi(num);
-							
-							if((mode==PTCACHE_CLEAR_BEFORE && frame < cfra)	|| 
-							   (mode==PTCACHE_CLEAR_AFTER && frame > cfra)	) {
+							if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
+								BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
+								frame = atoi(num);
 								
-								BLI_join_dirfile(path_full, path, de->d_name);
-								BLI_delete(path_full, 0, 0);
+								if((mode==PTCACHE_CLEAR_BEFORE && frame < cfra)	|| 
+								(mode==PTCACHE_CLEAR_AFTER && frame > cfra)	) {
+									
+									BLI_join_dirfile(path_full, path, de->d_name);
+									BLI_delete(path_full, 0, 0);
+								}
 							}
 						}
 					}
 				}
 			}
+			closedir(dir);
+		}
+		else {
+			PTCacheMem *pm= pid->cache->mem_cache.first;
+			PTCacheMem *link= NULL;
+
+			if(mode == PTCACHE_CLEAR_ALL) {
+				pid->cache->last_exact = 0;
+				for(; pm; pm=pm->next)
+					MEM_freeN(pm->data);
+				BLI_freelistN(&pid->cache->mem_cache);
+			} else {
+				while(pm) {
+					if((mode==PTCACHE_CLEAR_BEFORE && pm->frame < cfra)	|| 
+					(mode==PTCACHE_CLEAR_AFTER && pm->frame > cfra)	) {
+						link = pm;
+						pm = pm->next;
+						MEM_freeN(link->data);
+						BLI_freelinkN(&pid->cache->mem_cache, link);
+					}
+					else
+						pm = pm->next;
+				}
+			}
 		}
-		closedir(dir);
 		break;
 		
 	case PTCACHE_CLEAR_FRAME:
-		len = BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); /* no path */
-		BLI_delete(filename, 0, 0);
+		if(pid->cache->flag & PTCACHE_DISK_CACHE) {
+			if(BKE_ptcache_id_exist(pid, cfra)) {
+				BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); /* no path */
+				BLI_delete(filename, 0, 0);
+			}
+		}
+		else {
+			PTCacheMem *pm = pid->cache->mem_cache.first;
+
+			for(; pm; pm=pm->next) {
+				if(pm->frame == cfra) {
+					MEM_freeN(pm->data);
+					BLI_freelinkN(&pid->cache->mem_cache, pm);
+					break;
+				}
+			}
+		}
 		break;
 	}
+
+	BKE_ptcache_update_info(pid);
 }
 
 int BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
 {
-	char filename[MAX_PTCACHE_FILE];
-
 	if(!pid->cache)
 		return 0;
 	
-	BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
+	if(pid->cache->flag & PTCACHE_DISK_CACHE) {
+		char filename[MAX_PTCACHE_FILE];
+		
+		BKE_ptcache_id_filename(pid, filename, cfra, 1, 1);
 
-	return BLI_exists(filename);
+		return BLI_exists(filename);
+	}
+	else {
+		PTCacheMem *pm = pid->cache->mem_cache.first;
+
+		for(; pm; pm=pm->next) {
+			if(pm->frame==cfra)
+				return 1;
+		}
+		return 0;
+	}
 }
 
 void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
@@ -381,6 +866,9 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra
 	PointCache *cache;
 	float offset, time, nexttime;
 
+	/* TODO: this has to be sorter out once bsystem_time gets redone, */
+	/*       now caches can handle interpolating etc. too - jahka */
+
 	/* time handling for point cache:
 	 * - simulation time is scaled by result of bsystem_time
 	 * - for offsetting time only time offset is taken into account, since
@@ -414,10 +902,10 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra
 	}
 }
 
-int BKE_ptcache_id_reset(PTCacheID *pid, int mode)
+int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
 {
 	PointCache *cache;
-	int reset, clear;
+	int reset, clear, after;
 
 	if(!pid->cache)
 		return 0;
@@ -425,14 +913,17 @@ int BKE_ptcache_id_reset(PTCacheID *pid, int mode)
 	cache= pid->cache;
 	reset= 0;
 	clear= 0;
+	after= 0;
 
 	if(mode == PTCACHE_RESET_DEPSGRAPH) {
 		if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) {
-			reset= 1;
-			clear= 1;
+			if(cache->flag & PTCACHE_QUICK_CACHE)
+				clear= 1;
+
+			after= 1;
 		}
-		else
-			cache->flag |= PTCACHE_OUTDATED;
+
+		cache->flag |= PTCACHE_OUTDATED;
 	}
 	else if(mode == PTCACHE_RESET_BAKED) {
 		if(!BKE_ptcache_get_continue_physics()) {
@@ -451,8 +942,9 @@ int BKE_ptcache_id_reset(PTCacheID *pid, int mode)
 	}
 
 	if(reset) {
-		cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_SIMULATION_VALID);
+		cache->flag &= ~(PTCACHE_REDO_NEEDED|PTCACHE_SIMULATION_VALID);
 		cache->simframe= 0;
+		cache->last_exact= 0;
 
 		if(pid->type == PTCACHE_TYPE_CLOTH)
 			cloth_free_modifier(pid->ob, pid->data);
@@ -463,11 +955,13 @@ int BKE_ptcache_id_reset(PTCacheID *pid, int mode)
 	}
 	if(clear)
 		BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
+	else if(after)
+		BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA);
 
-	return (reset || clear);
+	return (reset || clear || after);
 }
 
-int BKE_ptcache_object_reset(Object *ob, int mode)
+int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
 {
 	PTCacheID pid;
 	ParticleSystem *psys;
@@ -479,7 +973,7 @@ int BKE_ptcache_object_reset(Object *ob, int mode)
 
 	if(ob->soft) {
 		BKE_ptcache_id_from_softbody(&pid, ob, ob->soft);
-		reset |= BKE_ptcache_id_reset(&pid, mode);
+		reset |= BKE_ptcache_id_reset(scene, &pid, mode);
 	}
 
 	for(psys=ob->particlesystem.first; psys; psys=psys->next) {
@@ -488,23 +982,23 @@ int BKE_ptcache_object_reset(Object *ob, int mode)
 		if(psys->soft) {
 			BKE_ptcache_id_from_softbody(&pid, ob, psys->soft);
 			if(mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) 
-				reset |= BKE_ptcache_id_reset(&pid, mode);
+				reset |= BKE_ptcache_id_reset(scene, &pid, mode);
 			else
 				skip = 1;
 		}
-		else if((psys->recalc & PSYS_RECALC_RESET)==0)
+		else if(psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD)
 			skip = 1;
 
 		if(skip == 0) {
 			BKE_ptcache_id_from_particles(&pid, ob, psys);
-			reset |= BKE_ptcache_id_reset(&pid, mode);
+			reset |= BKE_ptcache_id_reset(scene, &pid, mode);
 		}
 	}
 
 	for(md=ob->modifiers.first; md; md=md->next) {
 		if(md->type == eModifierType_Cloth) {
 			BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md);
-			reset |= BKE_ptcache_id_reset(&pid, mode);
+			reset |= BKE_ptcache_id_reset(scene, &pid, mode);
 		}
 	}
 
@@ -564,7 +1058,7 @@ void BKE_ptcache_set_continue_physics(Scene *scene, int enable)
 
 		if(CONTINUE_PHYSICS == 0) {
 			for(ob=G.main->object.first; ob; ob=ob->id.next)
-				if(BKE_ptcache_object_reset(ob, PTCACHE_RESET_OUTDATED))
+				if(BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED))
 					DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
 		}
 	}
@@ -584,12 +1078,21 @@ PointCache *BKE_ptcache_add()
 	cache= MEM_callocN(sizeof(PointCache), "PointCache");
 	cache->startframe= 1;
 	cache->endframe= 250;
+	cache->step= 10;
 
 	return cache;
 }
 
 void BKE_ptcache_free(PointCache *cache)
 {
+	PTCacheMem *pm = cache->mem_cache.first;
+	if(pm) {
+		for(; pm; pm=pm->next)
+			MEM_freeN(pm->data);
+
+		BLI_freelistN(&cache->mem_cache);
+	}
+
 	MEM_freeN(cache);
 }
 
@@ -605,3 +1108,276 @@ PointCache *BKE_ptcache_copy(PointCache *cache)
 	return ncache;
 }
 
+
+
+/* Baking */
+static int count_quick_cache(Scene *scene, int *quick_step)
+{
+	Base *base = scene->base.first;
+	PTCacheID *pid;
+	ListBase pidlist;
+	int autocache_count= 0;
+
+	for(base = scene->base.first; base; base = base->next) {
+		if(base->object) {
+			BKE_ptcache_ids_from_object(&pidlist, base->object);
+
+			for(pid=pidlist.first; pid; pid=pid->next) {
+				if((pid->cache->flag & PTCACHE_BAKED)
+					|| (pid->cache->flag & PTCACHE_QUICK_CACHE)==0)
+					continue;
+
+				if(pid->cache->flag & PTCACHE_OUTDATED || (pid->cache->flag & PTCACHE_SIMULATION_VALID)==0) {
+					if(!autocache_count)
+						*quick_step = pid->cache->step;
+					else
+						*quick_step = MIN2(*quick_step, pid->cache->step);
+
+					autocache_count++;
+				}
+			}
+
+			BLI_freelistN(&pidlist);
+		}
+	}
+
+	return autocache_count;
+}
+void BKE_ptcache_quick_cache_all(Scene *scene)
+{
+	PTCacheBaker baker;
+
+	baker.bake=0;
+	baker.break_data=NULL;
+	baker.break_test=NULL;
+	baker.pid=NULL;
+	baker.progressbar=NULL;
+	baker.progresscontext=NULL;
+	baker.render=0;
+	baker.scene=scene;
+
+	if(count_quick_cache(scene, &baker.quick_step))
+		BKE_ptcache_make_cache(&baker);
+}
+
+/* if bake is not given run simulations to current frame */
+void BKE_ptcache_make_cache(PTCacheBaker* baker)
+{
+	Scene *scene = baker->scene;
+	Base *base;
+	ListBase pidlist;
+	PTCacheID *pid = baker->pid;
+	PointCache *cache;
+	float frameleno = scene->r.framelen;
+	int cfrao = CFRA;
+	int startframe = MAXFRAME;
+	int endframe = CFRA;
+	int bake = baker->bake;
+	int render = baker->render;
+	int step = baker->quick_step;
+
+	G.afbreek = 0;
+
+	/* set caches to baking mode and figure out start frame */
+	if(pid) {
+		/* cache/bake a single object */
+		cache = pid->cache;
+		if((cache->flag & PTCACHE_BAKED)==0) {
+			if(pid->type==PTCACHE_TYPE_PARTICLES)
+				psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe);
+
+			if(bake || cache->flag & PTCACHE_REDO_NEEDED)
+				BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
+
+			startframe = MAX2(cache->last_exact, cache->startframe);
+
+			if(bake) {
+				endframe = cache->endframe;
+				cache->flag |= PTCACHE_BAKING;
+			}
+			else {
+				endframe = MIN2(endframe, cache->endframe);
+			}
+
+			cache->flag &= ~PTCACHE_BAKED;
+		}
+	}
+	else for(base=scene->base.first; base; base= base->next) {
+		/* cache/bake everything in the scene */
+		BKE_ptcache_ids_from_object(&pidlist, base->object);
+
+		for(pid=pidlist.first; pid; pid=pid->next) {
+			cache = pid->cache;
+			if((cache->flag & PTCACHE_BAKED)==0) {
+				if(pid->type==PTCACHE_TYPE_PARTICLES)
+					psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe);
+
+				if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0)
+					&& ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake))
+					BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
+
+				startframe = MIN2(startframe, cache->startframe);
+
+				if(bake || render) {
+					cache->flag |= PTCACHE_BAKING;
+
+					if(bake)
+						endframe = MAX2(endframe, cache->endframe);
+				}
+
+				cache->flag &= ~PTCACHE_BAKED;
+
+			}
+		}
+		BLI_freelistN(&pidlist);
+	}
+
+	CFRA= startframe;
+	scene->r.framelen = 1.0;
+
+	for(; CFRA <= endframe; CFRA+=step) {
+		float prog;
+
+		if(bake)
+			prog = (int)(100.0 * (float)(CFRA - startframe)/(float)(endframe-startframe));
+		else
+			prog = CFRA;
+
+		/* NOTE: baking should not redraw whole ui as this slows things down */
+		if(baker->progressbar)
+			baker->progressbar(baker->progresscontext, prog);
+		
+		scene_update_for_newframe(scene, scene->lay);
+
+		/* NOTE: breaking baking should leave calculated frames in cache, not clear it */
+		if(baker->break_test && baker->break_test(baker->break_data))
+			break;
+	}
+
+	/* clear baking flag */
+	if(pid) {
+		cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
+		cache->flag |= PTCACHE_SIMULATION_VALID;
+		if(bake)
+			cache->flag |= PTCACHE_BAKED;
+	}
+	else for(base=scene->base.first; base; base= base->next) {
+		BKE_ptcache_ids_from_object(&pidlist, base->object);
+
+		for(pid=pidlist.first; pid; pid=pid->next) {
+			cache = pid->cache;
+
+			if(step > 1)
+				cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
+			else
+				cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
+
+			cache->flag |= PTCACHE_SIMULATION_VALID;
+
+			if(bake)
+				cache->flag |= PTCACHE_BAKED;
+		}
+		BLI_freelistN(&pidlist);
+	}
+
+	scene->r.framelen = frameleno;
+	CFRA = cfrao;
+	scene_update_for_newframe(scene, scene->lay);
+
+	/* TODO: call redraw all windows somehow */
+}
+
+void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
+	PointCache *cache = pid->cache;
+	PTCacheFile *pf;
+	PTCacheMem *pm;
+	int totelem=0;
+	int float_count=0;
+	int tot;
+	int last_exact = cache->last_exact;
+
+	if (!G.relbase_valid){
+		cache->flag &= ~PTCACHE_DISK_CACHE;
+		return;
+	}
+
+	totelem = ptcache_pid_totelem(pid);
+	float_count = ptcache_pid_elemsize(pid) / sizeof(float);
+
+	if(totelem==0 || float_count==0)
+		return;
+
+	tot = totelem*float_count;
+
+	/* MEM -> DISK */
+	if(cache->flag & PTCACHE_DISK_CACHE) {
+		pm = cache->mem_cache.first;
+
+		BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
+
+		for(; pm; pm=pm->next) {
+			pf = BKE_ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame);
+
+			if(pf) {
+				if(fwrite(pm->data, sizeof(float), tot, pf->fp) != tot) {
+					printf("Error writing to disk cache\n");
+					
+					cache->flag &= ~PTCACHE_DISK_CACHE;
+
+					BKE_ptcache_file_close(pf);
+					return;
+				}
+				BKE_ptcache_file_close(pf);
+			}
+			else
+				printf("Error creating disk cache file\n");
+		}
+
+		cache->flag &= ~PTCACHE_DISK_CACHE;
+		BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
+		cache->flag |= PTCACHE_DISK_CACHE;
+	}
+	/* DISK -> MEM */
+	else {
+		int cfra;
+		int sfra = cache->startframe;
+		int efra = cache->endframe;
+
+		BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
+
+		for(cfra=sfra; cfra <= efra; cfra++) {
+			pf = BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
+
+			if(pf) {
+				pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
+				pm->data = MEM_callocN(sizeof(float)*tot, "Pointcache mem data");
+
+				if(fread(pm->data, sizeof(float), tot, pf->fp)!= tot) {
+					printf("Error reading from disk cache\n");
+
+					cache->flag |= PTCACHE_DISK_CACHE;
+
+					MEM_freeN(pm->data);
+					MEM_freeN(pm);
+					BKE_ptcache_file_close(pf);
+					return;
+				}
+
+				pm->frame = cfra;
+				pm->totpoint = totelem;
+
+				BLI_addtail(&pid->cache->mem_cache, pm);
+
+				BKE_ptcache_file_close(pf);
+			}
+		}
+
+		cache->flag |= PTCACHE_DISK_CACHE;
+		BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
+		cache->flag &= ~PTCACHE_DISK_CACHE;
+	}
+	
+	cache->last_exact = last_exact;
+
+	BKE_ptcache_update_info(pid);
+}
diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c
index 1d97eccb9f3..8de8cf8d0f4 100644
--- a/source/blender/blenkernel/intern/report.c
+++ b/source/blender/blenkernel/intern/report.c
@@ -1,5 +1,5 @@
 /**
- * $Id: report.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -65,8 +65,8 @@ void BKE_reports_init(ReportList *reports, int flag)
 
 	memset(reports, 0, sizeof(ReportList));
 
-	reports->storelevel= RPT_WARNING;
-	reports->printlevel= RPT_WARNING;
+	reports->storelevel= RPT_INFO;
+	reports->printlevel= RPT_INFO;
 	reports->flag= flag;
 }
 
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 156bdae9b00..23da5c66850 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -142,8 +142,6 @@ void free_scene(Scene *sce)
 
 	BLI_freelistN(&sce->base);
 	seq_free_editing(sce->ed);
-	if(sce->radio) MEM_freeN(sce->radio);
-	sce->radio= 0;
 	
 #ifndef DISABLE_PYTHON
 	BPY_free_scriptlink(&sce->scriptlink);
@@ -205,9 +203,6 @@ Scene *add_scene(char *name)
 
 	sce= alloc_libblock(&G.main->scene, ID_SCE, name);
 	sce->lay= 1;
-	sce->selectmode= SCE_SELECT_VERTEX;
-	sce->editbutsize= 0.1;
-	sce->autokey_mode= U.autokey_mode;
 	
 	sce->r.mode= R_GAMMA;
 	sce->r.cfra= 1;
@@ -277,6 +272,10 @@ Scene *add_scene(char *name)
 	sce->toolsettings->select_thresh= 0.01f;
 	sce->toolsettings->jointrilimit = 0.8f;
 
+	sce->toolsettings->selectmode= SCE_SELECT_VERTEX;
+	sce->toolsettings->normalsize= 0.1;
+	sce->toolsettings->autokey_mode= U.autokey_mode;
+
 	sce->toolsettings->skgen_resolution = 100;
 	sce->toolsettings->skgen_threshold_internal 	= 0.01f;
 	sce->toolsettings->skgen_threshold_external 	= 0.01f;
diff --git a/source/blender/blenkernel/intern/sequence.c b/source/blender/blenkernel/intern/sequence.c
index bb0665a5b0f..7fc262b4796 100644
--- a/source/blender/blenkernel/intern/sequence.c
+++ b/source/blender/blenkernel/intern/sequence.c
@@ -1,5 +1,5 @@
 /**
-* $Id: sequence.c 17508 2008-11-20 00:34:24Z campbellbarton $
+* $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h
index d2fb62141de..d0b106b59c3 100644
--- a/source/blender/blenlib/BLI_listbase.h
+++ b/source/blender/blenlib/BLI_listbase.h
@@ -1,5 +1,5 @@
 /*
- * $Id: BLI_blenlib.h 17433 2008-11-12 21:16:53Z blendix $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -26,7 +26,7 @@
  *
  * ***** END GPL LICENSE BLOCK *****
  * 
- * $Id: $ 
+ * $Id$ 
 */
 
 #ifndef BLI_LISTBASE_H
diff --git a/source/blender/blenlib/BLI_noise.h b/source/blender/blenlib/BLI_noise.h
index 9f72c5e7b54..0886eb3a8a5 100644
--- a/source/blender/blenlib/BLI_noise.h
+++ b/source/blender/blenlib/BLI_noise.h
@@ -1,5 +1,5 @@
 /*
- * $Id: BLI_blenlib.h 17433 2008-11-12 21:16:53Z blendix $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h
index c7026b21494..c36a41af84b 100644
--- a/source/blender/blenlib/BLI_rect.h
+++ b/source/blender/blenlib/BLI_rect.h
@@ -1,5 +1,5 @@
 /*
- * $Id: BLI_blenlib.h 17433 2008-11-12 21:16:53Z blendix $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/blenlib/BLI_storage.h b/source/blender/blenlib/BLI_storage.h
index d7bf3bd13f8..fa44bb36e15 100644
--- a/source/blender/blenlib/BLI_storage.h
+++ b/source/blender/blenlib/BLI_storage.h
@@ -25,15 +25,20 @@
  *
  * ***** END GPL LICENSE BLOCK *****
  */
+
 #ifndef BLI_STORAGE_H
 #define BLI_STORAGE_H
 
+/* NOTE: these have to be defined before including unistd.h! */
 #ifndef __APPLE__
 #ifndef WIN32
-#define _LARGEFILE_SOURCE 1
+#ifndef _LARGEFILE_SOURCE
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
 #define _FILE_OFFSET_BITS 64
 #endif
 #endif
+#endif
 
 struct direntry;
 
diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index 4e5bf650196..bf93dc19cc5 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -1,5 +1,5 @@
 /*
- * $Id: BLI_blenlib.h 17433 2008-11-12 21:16:53Z blendix $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -26,7 +26,7 @@
  *
  * ***** END GPL LICENSE BLOCK *****
  *
- * $Id: $ 
+ * $Id$ 
 */
 
 #ifndef BLI_STRING_H
diff --git a/source/blender/blenlib/BLI_util.h b/source/blender/blenlib/BLI_util.h
index 30c9fc353b3..a138ea780ea 100644
--- a/source/blender/blenlib/BLI_util.h
+++ b/source/blender/blenlib/BLI_util.h
@@ -50,6 +50,7 @@ void BLI_make_existing_file(char *name);
 void BLI_split_dirfile(char *string, char *dir, char *file);
 void BLI_split_dirfile_basic(const char *string, char *dir, char *file);
 void BLI_join_dirfile(char *string, const char *dir, const char *file);
+void BLI_getlastdir(const char* dir, char *last, int maxlen);
 int BLI_testextensie(const char *str, const char *ext);
 void BLI_uniquename(struct ListBase *list, void *vlink, char defname[], char delim, short name_offs, short len);
 void BLI_newname(char * name, int add);
diff --git a/source/blender/blenlib/intern/dynamiclist.c b/source/blender/blenlib/intern/dynamiclist.c
index fbb87124bba..4fe654cffb6 100644
--- a/source/blender/blenlib/intern/dynamiclist.c
+++ b/source/blender/blenlib/intern/dynamiclist.c
@@ -3,7 +3,7 @@
  * various string, file, list operations.
  *
  *
- * $Id: util.c 17433 2008-11-12 21:16:53Z blendix $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/blenlib/intern/dynamiclist.h b/source/blender/blenlib/intern/dynamiclist.h
index aba3eda0696..e8c93fbcf23 100644
--- a/source/blender/blenlib/intern/dynamiclist.h
+++ b/source/blender/blenlib/intern/dynamiclist.h
@@ -1,5 +1,5 @@
 /**
- * $Id: BLI_dynamiclist.h 13161 2008-01-07 19:13:47Z hos $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c
index e0fd5c37494..1064c8ac1bf 100644
--- a/source/blender/blenlib/intern/listbase.c
+++ b/source/blender/blenlib/intern/listbase.c
@@ -3,7 +3,7 @@
  * various string, file, list operations.
  *
  *
- * $Id: util.c 17433 2008-11-12 21:16:53Z blendix $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/blenlib/intern/psfont.c b/source/blender/blenlib/intern/psfont.c
index 39d38e4cf3a..269e674a62f 100644
--- a/source/blender/blenlib/intern/psfont.c
+++ b/source/blender/blenlib/intern/psfont.c
@@ -837,7 +837,7 @@ static int decodetype1(PackedFile * pf, char *outname)
 		while(newfgets(oneline, LINELEN, pf)) {
 			hptr = (char *)oneline;
 			while(*hptr) {
-				if(hextab[*hptr] != NOTHEX)
+				if(hextab[(int)*hptr] != NOTHEX)
 					hexdat[hexbytes++] = *hptr;
 				hptr++;
 			}
@@ -853,7 +853,7 @@ static int decodetype1(PackedFile * pf, char *outname)
 		bptr = bindat;
 		c = datbytes;
 		while(c--) {
-			*bptr++  = (hextab[hptr[0]]<<4)+hextab[hptr[1]];
+			*bptr++  = (hextab[(int)hptr[0]]<<4)+hextab[(int)hptr[1]];
 			hptr += 2;
 		}
 
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index 688a4ab901b..3204d5f74e1 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -62,13 +62,6 @@
 #include 
 #endif
 
-#ifdef __BeOS
-struct statfs {
-	int f_bsize;
-	int f_bfree;
-};
-#endif
-
 #ifdef __APPLE__
 /* For statfs */
 #include 
@@ -77,7 +70,7 @@ struct statfs {
 
 
 #include 
-#if !defined(__BeOS) && !defined(WIN32)
+#if !defined(WIN32)
 #include 			/* tape comando's */
 #endif
 #include 			/* strcpy etc.. */
@@ -201,9 +194,6 @@ double BLI_diskfree(char *dir)
 #if defined (__FreeBSD__) || defined (linux) || defined (__OpenBSD__) || defined (__APPLE__) 
 	if (statfs(name, &disk)) return(-1);
 #endif
-#ifdef __BeOS
-	return -1;
-#endif
 
 #if defined (__sun__) || defined (__sun) || defined (__sgi)
 	if (statvfs(name, &disk)) return(-1);	
@@ -228,7 +218,7 @@ void BLI_builddir(char *dirname, char *relname)
 {
 	struct dirent *fname;
 	struct dirlink *dlink;
-	int rellen, newnum = 0, seen_ = 0, seen__ = 0;
+	int rellen, newnum = 0, ignore;
 	char buf[256];
 	DIR *dir;
 
@@ -248,21 +238,17 @@ void BLI_builddir(char *dirname, char *relname)
 	if ( (dir = (DIR *)opendir(".")) ){
 		while ((fname = (struct dirent*) readdir(dir)) != NULL) {
 			
-			if(hide_dot && fname->d_name[0]=='.' && fname->d_name[1]!='.' && fname->d_name[1]!=0);
+			if(hide_dot && fname->d_name[0]=='.' && fname->d_name[1]!='.' && fname->d_name[1]!=0) {
+			}
+			else if ( ( (fname->d_name[0] == '.') && (fname->d_name[1] == 0) ) ||
+					  ( (fname->d_name[0] == '.') && (fname->d_name[1] == '.') && (fname->d_name[2] == 0)) ) {
+				/* ignore '.' and '..' */
+			}
 			else {
-				
 				dlink = (struct dirlink *)malloc(sizeof(struct dirlink));
 				if (dlink){
 					strcpy(buf+rellen,fname->d_name);
-	
 					dlink->name = BLI_strdup(buf);
-	
-					if (dlink->name[0] == '.') {
-						if (dlink->name[1] == 0) seen_ = 1;
-						else if (dlink->name[1] == '.') {
-							if (dlink->name[2] == 0) seen__ = 1;
-						}
-					}
 					BLI_addhead(dirbase,dlink);
 					newnum++;
 				}
@@ -270,30 +256,6 @@ void BLI_builddir(char *dirname, char *relname)
 		}
 		
 		if (newnum){
-#ifndef WIN32		
-			if (seen_ == 0) {	/* Cachefs PATCH */
-				dlink = (struct dirlink *)malloc(sizeof(struct dirlink));
-				strcpy(buf+rellen,"./.");
-				dlink->name = BLI_strdup(buf);
-				BLI_addhead(dirbase,dlink);
-				newnum++;
-			}
-			if (seen__ == 0) {	/* MAC PATCH */
-				dlink = (struct dirlink *)malloc(sizeof(struct dirlink));
-				strcpy(buf+rellen,"./..");
-				dlink->name = BLI_strdup(buf);
-				BLI_addhead(dirbase,dlink);
-				newnum++;
-			}
-#else // WIN32
-			if (seen_ == 0) {	/* should only happen for root paths like "C:\" */
-				dlink = (struct dirlink *)malloc(sizeof(struct dirlink));
-				strcpy(buf+rellen,".");
-				dlink->name = BLI_strdup(buf);
-				BLI_addhead(dirbase,dlink);
-				newnum++;
-			}
-#endif			
 
 			if (files) files=(struct direntry *)realloc(files,(totnum+newnum) * sizeof(struct direntry));
 			else files=(struct direntry *)malloc(newnum * sizeof(struct direntry));
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index fa4bcbc26bc..4cd04aa232c 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -3,7 +3,7 @@
  * various string, file, list operations.
  *
  *
- * $Id: util.c 17433 2008-11-12 21:16:53Z blendix $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c
index df4ad4e7c75..b9d4daaf5b2 100644
--- a/source/blender/blenlib/intern/util.c
+++ b/source/blender/blenlib/intern/util.c
@@ -736,11 +736,27 @@ void BLI_splitdirstring(char *di, char *fi)
 	}
 }
 
-char *BLI_gethome(void) {
-	#ifdef __BeOS
-		return "/boot/home/";		/* BeOS 4.5: doubleclick at icon doesnt give home env */
+void BLI_getlastdir(const char* dir, char *last, int maxlen)
+{
+	char *s = dir;
+	char *lslash = NULL;
+	char *prevslash = NULL;
+	while (*s) {
+		if ((*s == '\\') || (*s == '/')) {
+			prevslash = lslash;
+			lslash = s;
+		}
+		s++;
+	}
+	if (prevslash) {
+		BLI_strncpy(last, prevslash+1, maxlen);
+	} else {
+		BLI_strncpy(last, dir, maxlen);
+	}
+}
 
-	#elif !defined(WIN32)
+char *BLI_gethome(void) {
+	#if !defined(WIN32)
 		return getenv("HOME");
 
 	#else /* Windows */
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index 0c8b8a6b31d..1f276913ea8 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -32,6 +32,8 @@
 #include 
 #endif
 
+#include "BLI_storage.h" /* _LARGEFILE_SOURCE */
+
 #include 
 #include 
 #include 
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 1502b475350..c89f515f319 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2878,6 +2878,16 @@ static void direct_link_material(FileData *fd, Material *ma)
 
 static void direct_link_pointcache(FileData *fd, PointCache *cache)
 {
+	if((cache->flag & PTCACHE_DISK_CACHE)==0) {
+		PTCacheMem *pm;
+
+		link_list(fd, &cache->mem_cache);
+
+		pm = cache->mem_cache.first;
+
+		for(; pm; pm=pm->next)
+			pm->data = newdataadr(fd, pm->data);
+	}
 	cache->flag &= ~(PTCACHE_SIMULATION_VALID|PTCACHE_BAKE_EDIT_ACTIVE);
 	cache->simframe= 0;
 }
@@ -2889,7 +2899,9 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
 	part= main->particle.first;
 	while(part) {
 		if(part->id.flag & LIB_NEEDLINK) {
+			if (part->adt) lib_link_animdata(fd, &part->id, part->adt);
 			part->ipo= newlibadr_us(fd, part->id.lib, part->ipo); // XXX depreceated - old animation system
+			
 			part->dup_ob = newlibadr(fd, part->id.lib, part->dup_ob);
 			part->dup_group = newlibadr(fd, part->id.lib, part->dup_group);
 			part->eff_group = newlibadr(fd, part->id.lib, part->eff_group);
@@ -2902,6 +2914,7 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
 
 static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
 {
+	part->adt= newdataadr(fd, part->adt);
 	part->pd= newdataadr(fd, part->pd);
 	part->pd2= newdataadr(fd, part->pd2);
 }
@@ -3142,10 +3155,8 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
 		direct_link_dverts(fd, lvl->totvert, CustomData_get(&mesh->mr->vdata, 0, CD_MDEFORMVERT));
 		direct_link_customdata(fd, &mesh->mr->fdata, lvl->totface);
 		
-		if(!mesh->mr->edge_flags)
-			mesh->mr->edge_flags= MEM_callocN(sizeof(short)*lvl->totedge, "Multires Edge Flags");
-		if(!mesh->mr->edge_creases)
-			mesh->mr->edge_creases= MEM_callocN(sizeof(char)*lvl->totedge, "Multires Edge Creases");
+		mesh->mr->edge_flags= newdataadr(fd, mesh->mr->edge_flags);
+		mesh->mr->edge_creases= newdataadr(fd, mesh->mr->edge_creases);
 
 		mesh->mr->verts = newdataadr(fd, mesh->mr->verts);
 			
@@ -3933,8 +3944,6 @@ static void direct_link_scene(FileData *fd, Scene *sce)
 	direct_link_keyingsets(fd, &sce->keyingsets);
 	
 	sce->basact= newdataadr(fd, sce->basact);
-
-	sce->radio= newdataadr(fd, sce->radio);
 	
 	sce->toolsettings= newdataadr(fd, sce->toolsettings);
 	if(sce->toolsettings) {
@@ -5586,21 +5595,6 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
 				/* temporarily hide it */
 				ar->flag = RGN_FLAG_HIDDEN;
 				break;
-				
-			case SPACE_FILE:
-				/* channel (bookmarks/directories) region */
-				ar= MEM_callocN(sizeof(ARegion), "area region from do_versions");
-				BLI_addtail(lb, ar);
-				ar->regiontype= RGN_TYPE_CHANNELS;
-				ar->alignment= RGN_ALIGN_LEFT;
-				ar->v2d.scroll= V2D_SCROLL_RIGHT;
-				/* button UI region */
-				ar= MEM_callocN(sizeof(ARegion), "area region from do_versions");
-				BLI_addtail(lb, ar);
-				ar->regiontype= RGN_TYPE_UI;
-				ar->alignment= RGN_ALIGN_TOP;
-				break;
-
 #if 0
 			case SPACE_BUTS:
 				/* context UI region */
@@ -7096,22 +7090,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 	
 
 	if(main->versionfile <= 234) {
-		Scene *sce;
 		World *wo;
 		bScreen *sc;
-		int set_zbuf_sel=0;
 		
 		// force sumo engine to be active
 		for (wo = main->world.first; wo; wo= wo->id.next) {
 			if(wo->physicsEngine==0) wo->physicsEngine = 2;
 		}
 		
-		for (sce= main->scene.first; sce; sce= sce->id.next) {
-			if(sce->selectmode==0) {
-				sce->selectmode= SCE_SELECT_VERTEX;
-				set_zbuf_sel= 1;
-			}
-		}
 		for (sc= main->screen.first; sc; sc= sc->id.next) {
 			ScrArea *sa;
 			for (sa= sc->areabase.first; sa; sa= sa->next) {
@@ -7119,7 +7105,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 				for (sl= sa->spacedata.first; sl; sl= sl->next) {
 					if(sl->spacetype==SPACE_VIEW3D) {
 						View3D *v3d= (View3D *)sl;
-						if(set_zbuf_sel) v3d->flag |= V3D_ZBUF_SELECT;
+						v3d->flag |= V3D_ZBUF_SELECT;
 					}
 					else if(sl->spacetype==SPACE_TEXT) {
 						SpaceText *st= (SpaceText *)sl;
@@ -7154,16 +7140,10 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 	}
 	if(main->versionfile <= 236) {
 		Object *ob;
-		Scene *sce= main->scene.first;
 		Camera *cam= main->camera.first;
 		Material *ma;
 		bScreen *sc;
 
-		while(sce) {
-			if(sce->editbutsize==0.0) sce->editbutsize= 0.1f;
-			
-			sce= sce->id.next;
-		}
 		while(cam) {
 			if(cam->ortho_scale==0.0) {
 				cam->ortho_scale= 256.0f/cam->lens;
@@ -8789,15 +8769,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 			}
 		}
 	}
-	/* autokey mode settings now used from scene, but need to be initialised off userprefs */
-	if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 8)) {
-		Scene *sce;
-		
-		for (sce= main->scene.first; sce; sce= sce->id.next) {
-			if (sce->autokey_mode == 0)
-				sce->autokey_mode= U.autokey_mode;
-		}
-	}
 
 	if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 9)) {
 		Lamp *la= main->lamp.first;
@@ -8990,6 +8961,34 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 	
 	}
 
+	if (main->versionfile < 249 && main->subversionfile < 2) {
+		Scene *sce= main->scene.first;
+		Sequence *seq;
+		Editing *ed;
+		
+		while(sce) {
+			ed= sce->ed;
+			if(ed) {
+				SEQP_BEGIN(ed, seq) {
+					if (seq->strip && seq->strip->proxy){
+						if (sce->r.size != 100.0) {
+							seq->strip->proxy->size
+								= sce->r.size;
+						} else {
+							seq->strip->proxy->size
+								= 25.0;
+						}
+						seq->strip->proxy->quality =90;
+					}
+				}
+				SEQ_END
+			}
+			
+			sce= sce->id.next;
+		}
+
+	}
+
 	if (main->versionfile < 250) {
 		bScreen *screen;
 		Scene *scene;
@@ -8998,6 +8997,9 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 		Scene *sce;
 		Tex *tx;
 		ParticleSettings *part;
+		Object *ob;
+		PTCacheID *pid;
+		ListBase pidlist;
 		
 		for(screen= main->screen.first; screen; screen= screen->id.next) {
 			do_versions_windowmanager_2_50(screen);
@@ -9009,12 +9011,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 		 */
 		//do_versions_ipos_to_animato(main);
 		
-		/* struct audio data moved to renderdata */
+		/* toolsettings */
 		for(scene= main->scene.first; scene; scene= scene->id.next) {
 			scene->r.audio = scene->audio;
 			
-			if(!scene->toolsettings->uv_selectmode)
+			if(!scene->toolsettings->uv_selectmode) {
 				scene->toolsettings->uv_selectmode= UV_SELECT_VERTEX;
+				scene->toolsettings->vgroup_weight= 1.0f;
+			}
 		}
 		
 		/* shader, composit and texture node trees have id.name empty, put something in
@@ -9040,7 +9044,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 			me->drawflag= ME_DRAWEDGES|ME_DRAWFACES|ME_DRAWCREASES;
 		}
 
-		/* particle settings conversion */
+		/* particle draw and render types */
 		for(part= main->particle.first; part; part= part->id.next) {
 			if(part->draw_as) {
 				if(part->draw_as == PART_DRAW_DOT) {
@@ -9056,6 +9060,16 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 				}
 			}
 		}
+		/* set old pointcaches to have disk cache flag */
+		for(ob = main->object.first; ob; ob= ob->id.next) {
+
+			BKE_ptcache_ids_from_object(&pidlist, ob);
+
+			for(pid=pidlist.first; pid; pid=pid->next)
+				pid->cache->flag |= PTCACHE_DISK_CACHE;
+
+			BLI_freelistN(&pidlist);
+		}
 	}
 
 	/* TODO: should be moved into one of the version blocks once this branch moves to trunk and we can
@@ -9063,6 +9077,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 	{
 		Object *ob;
 		Material *ma;
+		Scene *sce;
+		ToolSettings *ts;
 		int i;
 
 		for(ob = main->object.first; ob; ob = ob->id.next) {
@@ -9135,37 +9151,17 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 				ma->mode &= ~MA_HALO;
 			}
 		}
-	}
-	
-	if (main->versionfile < 249 && main->subversionfile < 2) {
-		Scene *sce= main->scene.first;
-		Sequence *seq;
-		Editing *ed;
-		
-		while(sce) {
-			ed= sce->ed;
-			if(ed) {
-				SEQP_BEGIN(ed, seq) {
-					if (seq->strip && seq->strip->proxy){
-						if (sce->r.size != 100.0) {
-							seq->strip->proxy->size
-								= sce->r.size;
-						} else {
-							seq->strip->proxy->size
-								= 25.0;
-						}
-						seq->strip->proxy->quality =90;
-					}
-				}
-				SEQ_END
+
+		for(sce = main->scene.first; sce; sce = sce->id.next) {
+			ts= sce->toolsettings;
+			if(ts->normalsize == 0.0) {
+				ts->normalsize= 0.1f;
+				ts->selectmode= SCE_SELECT_VERTEX;
+				ts->autokey_mode= U.autokey_mode;
 			}
-			
-			sce= sce->id.next;
 		}
-
 	}
 
-
 	/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
 	/* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */
 
@@ -9517,6 +9513,8 @@ static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSetting
 	expand_doit(fd, mainvar, part->dup_group);
 	expand_doit(fd, mainvar, part->eff_group);
 	expand_doit(fd, mainvar, part->bb_ob);
+	
+	expand_animdata(fd, mainvar, part->adt);
 }
 
 static void expand_group(FileData *fd, Main *mainvar, Group *group)
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index f8112406e80..c433232d084 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -382,6 +382,7 @@ static void writedata(WriteData *wd, int filecode, int len, void *adr)	/* do not
 /*These functions are used by blender's .blend system for file saving/loading.*/
 void IDP_WriteProperty_OnlyData(IDProperty *prop, void *wd);
 void IDP_WriteProperty(IDProperty *prop, void *wd);
+static void write_animdata(WriteData *wd, AnimData *adt); // XXX code needs reshuffling, but not before NLA SoC is merged back into 2.5
 
 static void IDP_WriteArray(IDProperty *prop, void *wd)
 {
@@ -549,6 +550,25 @@ static void write_userdef(WriteData *wd)
 	}
 }
 
+/* TODO: replace *cache with *cachelist once it's coded */
+#define PTCACHE_WRITE_PSYS	0
+#define PTCACHE_WRITE_CLOTH	1
+static void write_pointcaches(WriteData *wd, PointCache *cache, int type)
+{
+	writestruct(wd, DATA, "PointCache", 1, cache);
+
+	if((cache->flag & PTCACHE_DISK_CACHE)==0) {
+		PTCacheMem *pm = cache->mem_cache.first;
+
+		for(; pm; pm=pm->next) {
+			writestruct(wd, DATA, "PTCacheMem", 1, pm);
+			if(type==PTCACHE_WRITE_PSYS)
+				writestruct(wd, DATA, "ParticleKey", pm->totpoint, pm->data);
+			else if(type==PTCACHE_WRITE_CLOTH)
+				writedata(wd, DATA, 9 * sizeof(float) * pm->totpoint, pm->data);
+		}
+	}
+}
 static void write_particlesettings(WriteData *wd, ListBase *idbase)
 {
 	ParticleSettings *part;
@@ -559,6 +579,7 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
 			/* write LibData */
 			writestruct(wd, ID_PA, "ParticleSettings", 1, part);
 			if (part->id.properties) IDP_WriteProperty(part->id.properties, wd);
+			if (part->adt) write_animdata(wd, part->adt);
 			writestruct(wd, DATA, "PartDeflect", 1, part->pd);
 			writestruct(wd, DATA, "PartDeflect", 1, part->pd2);
 		}
@@ -585,8 +606,8 @@ static void write_particlesystems(WriteData *wd, ListBase *particles)
 		}
 		if(psys->child) writestruct(wd, DATA, "ChildParticle", psys->totchild ,psys->child);
 		writestruct(wd, DATA, "SoftBody", 1, psys->soft);
-		if(psys->soft) writestruct(wd, DATA, "PointCache", 1, psys->soft->pointcache);
-		writestruct(wd, DATA, "PointCache", 1, psys->pointcache);
+		if(psys->soft) write_pointcaches(wd, psys->soft->pointcache, PTCACHE_WRITE_PSYS);
+		write_pointcaches(wd, psys->pointcache, PTCACHE_WRITE_PSYS);
 	}
 }
 
@@ -1007,7 +1028,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase, int write_undo)
 			
 			writestruct(wd, DATA, "ClothSimSettings", 1, clmd->sim_parms);
 			writestruct(wd, DATA, "ClothCollSettings", 1, clmd->coll_parms);
-			writestruct(wd, DATA, "PointCache", 1, clmd->point_cache);
+			write_pointcaches(wd, clmd->point_cache, PTCACHE_WRITE_CLOTH);
 		} 
 		else if(md->type==eModifierType_Fluidsim) {
 			FluidsimModifierData *fluidmd = (FluidsimModifierData*) md;
@@ -1584,7 +1605,6 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
 			base= base->next;
 		}
 		
-		writestruct(wd, DATA, "Radio", 1, sce->radio);
 		writestruct(wd, DATA, "ToolSettings", 1, sce->toolsettings);
 		if(sce->toolsettings->vpaint)
 			writestruct(wd, DATA, "VPaint", 1, sce->toolsettings->vpaint);
diff --git a/source/blender/blenpluginapi/intern/Makefile b/source/blender/blenpluginapi/intern/Makefile
index 51905cad8ec..20a61e9a25c 100644
--- a/source/blender/blenpluginapi/intern/Makefile
+++ b/source/blender/blenpluginapi/intern/Makefile
@@ -33,10 +33,6 @@ DIR = $(OCGDIR)/blender/$(LIBNAME)
 
 include nan_compile.mk
 
-ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris"))
-    CFLAGS += -shared
-endif
-
 CFLAGS += $(LEVEL_1_C_WARNINGS)
 
 # path to our own external headerfiles. On win2k this needs to be
diff --git a/source/blender/editors/animation/Makefile b/source/blender/editors/animation/Makefile
index 19b62891b63..a7f36aa58ac 100644
--- a/source/blender/editors/animation/Makefile
+++ b/source/blender/editors/animation/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/animation/anim_channels.c b/source/blender/editors/animation/anim_channels.c
index c52ade1bba8..05d50f98e8e 100644
--- a/source/blender/editors/animation/anim_channels.c
+++ b/source/blender/editors/animation/anim_channels.c
@@ -1,5 +1,5 @@
 /**
- * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index cfbd6d2bced..d0e83eeaec7 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -1,5 +1,5 @@
 /**
- * $Id: drawaction.c 17746 2008-12-08 11:19:44Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/armature/BIF_generate.h b/source/blender/editors/armature/BIF_generate.h
index 2d46cfa41e6..bde079c45fb 100644
--- a/source/blender/editors/armature/BIF_generate.h
+++ b/source/blender/editors/armature/BIF_generate.h
@@ -1,5 +1,5 @@
 /**
- * $Id: BIF_generate.h 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/armature/BIF_retarget.h b/source/blender/editors/armature/BIF_retarget.h
index 56f7e4cdd5d..c39f410424a 100644
--- a/source/blender/editors/armature/BIF_retarget.h
+++ b/source/blender/editors/armature/BIF_retarget.h
@@ -1,5 +1,5 @@
 /**
- * $Id: BIF_retarget.h 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/armature/Makefile b/source/blender/editors/armature/Makefile
index 6c7ce81a8a1..0291bcb1830 100644
--- a/source/blender/editors/armature/Makefile
+++ b/source/blender/editors/armature/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/armature/editarmature_generate.c b/source/blender/editors/armature/editarmature_generate.c
index a50f767cf14..6d271375c64 100644
--- a/source/blender/editors/armature/editarmature_generate.c
+++ b/source/blender/editors/armature/editarmature_generate.c
@@ -1,5 +1,5 @@
 /**
- * $Id: editarmature_generate.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index 1b879569e9c..fb030b91ce1 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -1,5 +1,5 @@
 /**
- * $Id: editarmature_sketch.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -243,6 +243,7 @@ void BIF_makeListTemplates(bContext *C)
 {
 	Object *obedit = CTX_data_edit_object(C);
 	Scene *scene = CTX_data_scene(C);
+	ToolSettings *ts = CTX_data_tool_settings(C);
 	Base *base;
 	int index = 0;
 
@@ -263,7 +264,7 @@ void BIF_makeListTemplates(bContext *C)
 			index++;
 			BLI_ghash_insert(TEMPLATES_HASH, SET_INT_IN_POINTER(index), ob);
 			
-			if (ob == scene->toolsettings->skgen_template)
+			if (ob == ts->skgen_template)
 			{
 				TEMPLATES_CURRENT = index;
 			}
@@ -305,8 +306,9 @@ char *BIF_listTemplates(bContext *C)
 
 int   BIF_currentTemplate(bContext *C)
 {
-	Scene *scene = CTX_data_scene(C);
-	if (TEMPLATES_CURRENT == 0 && scene->toolsettings->skgen_template != NULL)
+	ToolSettings *ts = CTX_data_tool_settings(C);
+
+	if (TEMPLATES_CURRENT == 0 && ts->skgen_template != NULL)
 	{
 		GHashIterator ghi;
 		BLI_ghashIterator_init(&ghi, TEMPLATES_HASH);
@@ -316,7 +318,7 @@ int   BIF_currentTemplate(bContext *C)
 			Object *ob = BLI_ghashIterator_getValue(&ghi);
 			int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi));
 			
-			if (ob == scene->toolsettings->skgen_template)
+			if (ob == ts->skgen_template)
 			{
 				TEMPLATES_CURRENT = key;
 				break;
@@ -360,8 +362,8 @@ RigGraph* sk_makeTemplateGraph(bContext *C, Object *ob)
 
 int BIF_nbJointsTemplate(bContext *C)
 {
-	Scene *scene = CTX_data_scene(C);
-	RigGraph *rg = sk_makeTemplateGraph(C, scene->toolsettings->skgen_template);
+	ToolSettings *ts = CTX_data_tool_settings(C);
+	RigGraph *rg = sk_makeTemplateGraph(C, ts->skgen_template);
 	
 	if (rg)
 	{
@@ -375,7 +377,7 @@ int BIF_nbJointsTemplate(bContext *C)
 
 char * BIF_nameBoneTemplate(bContext *C)
 {
-	Scene *scene = CTX_data_scene(C);
+	ToolSettings *ts = CTX_data_tool_settings(C);
 	SK_Sketch *stk = GLOBAL_sketch;
 	RigGraph *rg;
 	int index = 0;
@@ -385,7 +387,7 @@ char * BIF_nameBoneTemplate(bContext *C)
 		index = stk->active_stroke->nb_points;
 	}
 	
-	rg = sk_makeTemplateGraph(C, scene->toolsettings->skgen_template);
+	rg = sk_makeTemplateGraph(C, ts->skgen_template);
 	
 	if (rg == NULL)
 	{
@@ -418,14 +420,14 @@ void  BIF_freeTemplates(bContext *C)
 
 void  BIF_setTemplate(bContext *C, int index)
 {
-	Scene *scene = CTX_data_scene(C);
+	ToolSettings *ts = CTX_data_tool_settings(C);
 	if (index > 0)
 	{
-		scene->toolsettings->skgen_template = BLI_ghash_lookup(TEMPLATES_HASH, SET_INT_IN_POINTER(index));
+		ts->skgen_template = BLI_ghash_lookup(TEMPLATES_HASH, SET_INT_IN_POINTER(index));
 	}
 	else
 	{
-		scene->toolsettings->skgen_template = NULL;
+		ts->skgen_template = NULL;
 		
 		if (TEMPLATE_RIGG != NULL)
 		{
@@ -439,19 +441,19 @@ void  BIF_setTemplate(bContext *C, int index)
 
 void sk_autoname(bContext *C, ReebArc *arc)
 {
-	Scene *scene = CTX_data_scene(C);
-	if (scene->toolsettings->skgen_retarget_options & SK_RETARGET_AUTONAME)
+	ToolSettings *ts = CTX_data_tool_settings(C);
+	if (ts->skgen_retarget_options & SK_RETARGET_AUTONAME)
 	{
 		if (arc == NULL)
 		{
-			char *num = scene->toolsettings->skgen_num_string;
+			char *num = ts->skgen_num_string;
 			int i = atoi(num);
 			i++;
 			BLI_snprintf(num, 8, "%i", i);
 		}
 		else
 		{
-			char *side = scene->toolsettings->skgen_side_string;
+			char *side = ts->skgen_side_string;
 			int valid = 0;
 			int caps = 0;
 			
@@ -525,7 +527,7 @@ ReebArc *sk_strokeToArc(SK_Stroke *stk, float imat[][4], float tmat[][3])
 
 void sk_retargetStroke(bContext *C, SK_Stroke *stk)
 {
-	Scene *scene = CTX_data_scene(C);
+	ToolSettings *ts = CTX_data_tool_settings(C);
 	Object *obedit = CTX_data_edit_object(C);
 	float imat[4][4];
 	float tmat[3][3];
@@ -541,7 +543,7 @@ void sk_retargetStroke(bContext *C, SK_Stroke *stk)
 	
 	sk_autoname(C, arc);
 	
-	rg = sk_makeTemplateGraph(C, scene->toolsettings->skgen_template);
+	rg = sk_makeTemplateGraph(C, ts->skgen_template);
 
 	BIF_retargetArc(C, arc, rg);
 	
@@ -1408,10 +1410,10 @@ void sk_startStroke(SK_Sketch *sketch)
 
 void sk_endStroke(bContext *C, SK_Sketch *sketch)
 {
-	Scene *scene = CTX_data_scene(C);
+	ToolSettings *ts = CTX_data_tool_settings(C);
 	sk_shrinkStrokeBuffer(sketch->active_stroke);
 
-	if (scene->toolsettings->bone_sketching & BONE_SKETCHING_ADJUST)
+	if (ts->bone_sketching & BONE_SKETCHING_ADJUST)
 	{
 		sk_endOverdraw(sketch);
 	}
@@ -1521,10 +1523,10 @@ int sk_addStrokeDrawPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_Dra
 
 int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
 {
-	Scene *scene = CTX_data_scene(C);
+	ToolSettings *ts = CTX_data_tool_settings(C);
 	int point_added = 0;
 
-	if (scene->snap_mode == SCE_SNAP_MODE_VOLUME)
+	if (ts->snap_mode == SCE_SNAP_MODE_VOLUME)
 	{
 		ListBase depth_peels;
 		DepthPeel *p1, *p2;
@@ -1557,7 +1559,7 @@ int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Strok
 				p1->flag = 1;
 	
 				/* if peeling objects, take the first and last from each object */			
-				if (scene->snap_flag & SCE_SNAP_PEEL_OBJECT)
+				if (ts->snap_flag & SCE_SNAP_PEEL_OBJECT)
 				{
 					DepthPeel *peel;
 					for (peel = p1->next; peel; peel = peel->next)
@@ -1627,7 +1629,7 @@ int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Strok
 		int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
 
 		/* snap to strokes */
-		// if (scene->snap_mode == SCE_SNAP_MODE_VERTEX) /* snap all the time to strokes */
+		// if (ts->snap_mode == SCE_SNAP_MODE_VERTEX) /* snap all the time to strokes */
 		for (snap_stk = sketch->strokes.first; snap_stk; snap_stk = snap_stk->next)
 		{
 			SK_Point *spt = NULL;
@@ -1713,7 +1715,7 @@ int sk_addStrokeSnapPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_Dra
 
 void sk_addStrokePoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short snap)
 {
-	Scene *scene = CTX_data_scene(C);
+	ToolSettings *ts = CTX_data_tool_settings(C);
 	int point_added = 0;
 	
 	if (snap)
@@ -1726,7 +1728,7 @@ void sk_addStrokePoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawDa
 		point_added = sk_addStrokeDrawPoint(C, sketch, stk, dd);
 	}
 	
-	if (stk == sketch->active_stroke && scene->toolsettings->bone_sketching & BONE_SKETCHING_ADJUST)
+	if (stk == sketch->active_stroke && ts->bone_sketching & BONE_SKETCHING_ADJUST)
 	{
 		sk_updateOverdraw(C, sketch, stk, dd);
 	}
@@ -1951,7 +1953,7 @@ static int iteratorStopped(void *arg)
 void sk_convertStroke(bContext *C, SK_Stroke *stk)
 {
 	Object *obedit = CTX_data_edit_object(C);
-	Scene *scene = CTX_data_scene(C);
+	ToolSettings *ts = CTX_data_tool_settings(C);
 	bArmature *arm = obedit->data;
 	SK_Point *head;
 	EditBone *parent = NULL;
@@ -1990,17 +1992,17 @@ void sk_convertStroke(bContext *C, SK_Stroke *stk)
 
 					initStrokeIterator(iter, stk, head_index, i);
 					
-					if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
+					if (ts->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
 					{
-						bone = subdivideArcBy(scene->toolsettings, arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
+						bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
 					}
-					else if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
+					else if (ts->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
 					{
-						bone = subdivideArcBy(scene->toolsettings, arm, arm->edbo, iter, invmat, tmat, nextLengthSubdivision);
+						bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextLengthSubdivision);
 					}
-					else if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
+					else if (ts->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
 					{
-						bone = subdivideArcBy(scene->toolsettings, arm, arm->edbo, iter, invmat, tmat, nextFixedSubdivision);
+						bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextFixedSubdivision);
 					}
 				}
 				
@@ -2042,14 +2044,14 @@ void sk_convertStroke(bContext *C, SK_Stroke *stk)
 
 void sk_convert(bContext *C, SK_Sketch *sketch)
 {
-	Scene *scene = CTX_data_scene(C);
+	ToolSettings *ts = CTX_data_tool_settings(C);
 	SK_Stroke *stk;
 	
 	for (stk = sketch->strokes.first; stk; stk = stk->next)
 	{
 		if (stk->selected == 1)
 		{
-			if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
+			if (ts->bone_sketching_convert == SK_CONVERT_RETARGET)
 			{
 				sk_retargetStroke(C, stk);
 			}
@@ -2693,7 +2695,7 @@ void sk_selectStroke(bContext *C, SK_Sketch *sketch, short mval[2], int extend)
 	rect.ymin= mval[1]-5;
 	rect.ymax= mval[1]+5;
 		
-	hits= view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
+	hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
 
 	if (hits>0)
 	{
@@ -2743,6 +2745,7 @@ void sk_queueRedrawSketch(SK_Sketch *sketch)
 
 void sk_drawSketch(Scene *scene, SK_Sketch *sketch, int with_names)
 {
+	ToolSettings *ts= scene->toolsettings;
 	SK_Stroke *stk;
 	
 	glDisable(GL_DEPTH_TEST);
@@ -2779,7 +2782,7 @@ void sk_drawSketch(Scene *scene, SK_Sketch *sketch, int with_names)
 		
 			if (stk->selected == 1)
 			{
-				sk_drawStrokeSubdivision(scene->toolsettings, stk);
+				sk_drawStrokeSubdivision(ts, stk);
 			}
 		}
 	
@@ -2794,9 +2797,9 @@ void sk_drawSketch(Scene *scene, SK_Sketch *sketch, int with_names)
 		{
 			SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
 			
-			if (scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK)
+			if (ts->bone_sketching & BONE_SKETCHING_QUICK)
 			{
-				sk_drawStrokeSubdivision(scene->toolsettings, sketch->active_stroke);
+				sk_drawStrokeSubdivision(ts, sketch->active_stroke);
 			}
 			
 			if (last != NULL)
@@ -2839,7 +2842,7 @@ void sk_drawSketch(Scene *scene, SK_Sketch *sketch, int with_names)
 
 int sk_finish_stroke(bContext *C, SK_Sketch *sketch)
 {
-	Scene *scene = CTX_data_scene(C);
+	ToolSettings *ts = CTX_data_tool_settings(C);
 
 	if (sketch->active_stroke != NULL)
 	{
@@ -2847,9 +2850,9 @@ int sk_finish_stroke(bContext *C, SK_Sketch *sketch)
 		
 		sk_endStroke(C, sketch);
 		
-		if (scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK)
+		if (ts->bone_sketching & BONE_SKETCHING_QUICK)
 		{
-			if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
+			if (ts->bone_sketching_convert == SK_CONVERT_RETARGET)
 			{
 				sk_retargetStroke(C, stk);
 			}
@@ -3196,11 +3199,11 @@ static int sketch_draw_preview(bContext *C, wmOperator *op, wmEvent *event)
 int ED_operator_sketch_mode_active_stroke(bContext *C)
 {
 	Object *obedit = CTX_data_edit_object(C);
-	Scene *scene = CTX_data_scene(C);
+	ToolSettings *ts = CTX_data_tool_settings(C);
 	
 	if (obedit && 
 		obedit->type == OB_ARMATURE && 
-		scene->toolsettings->bone_sketching & BONE_SKETCHING &&
+		ts->bone_sketching & BONE_SKETCHING &&
 		GLOBAL_sketch != NULL &&
 		GLOBAL_sketch->active_stroke != NULL)
 	{
@@ -3215,12 +3218,12 @@ int ED_operator_sketch_mode_active_stroke(bContext *C)
 int ED_operator_sketch_mode_gesture(bContext *C)
 {
 	Object *obedit = CTX_data_edit_object(C);
-	Scene *scene = CTX_data_scene(C);
+	ToolSettings *ts = CTX_data_tool_settings(C);
 	
 	if (obedit && 
 		obedit->type == OB_ARMATURE && 
-		scene->toolsettings->bone_sketching & BONE_SKETCHING &&
-		(scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK) == 0 &&
+		ts->bone_sketching & BONE_SKETCHING &&
+		(ts->bone_sketching & BONE_SKETCHING_QUICK) == 0 &&
 		GLOBAL_sketch != NULL &&
 		GLOBAL_sketch->active_stroke == NULL)
 	{
@@ -3235,12 +3238,12 @@ int ED_operator_sketch_mode_gesture(bContext *C)
 int ED_operator_sketch_full_mode(bContext *C)
 {
 	Object *obedit = CTX_data_edit_object(C);
-	Scene *scene = CTX_data_scene(C);
+	ToolSettings *ts = CTX_data_tool_settings(C);
 	
 	if (obedit && 
 		obedit->type == OB_ARMATURE && 
-		scene->toolsettings->bone_sketching & BONE_SKETCHING && 
-		(scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK) == 0)
+		ts->bone_sketching & BONE_SKETCHING && 
+		(ts->bone_sketching & BONE_SKETCHING_QUICK) == 0)
 	{
 		return 1;
 	}
@@ -3253,11 +3256,11 @@ int ED_operator_sketch_full_mode(bContext *C)
 int ED_operator_sketch_mode(bContext *C)
 {
 	Object *obedit = CTX_data_edit_object(C);
-	Scene *scene = CTX_data_scene(C);
+	ToolSettings *ts = CTX_data_tool_settings(C);
 	
 	if (obedit && 
 		obedit->type == OB_ARMATURE && 
-		scene->toolsettings->bone_sketching & BONE_SKETCHING)
+		ts->bone_sketching & BONE_SKETCHING)
 	{
 		return 1;
 	}
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 4a0ee474f25..d74c8dbd0e1 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -1,5 +1,5 @@
 /**
- * $Id: meshlaplacian.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/armature/meshlaplacian.h b/source/blender/editors/armature/meshlaplacian.h
index ff921e93909..00c0aefaec7 100644
--- a/source/blender/editors/armature/meshlaplacian.h
+++ b/source/blender/editors/armature/meshlaplacian.h
@@ -1,5 +1,5 @@
 /**
- * $Id: meshlaplacian.h 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/curve/Makefile b/source/blender/editors/curve/Makefile
index 6b1f628f231..6449700e50b 100644
--- a/source/blender/editors/curve/Makefile
+++ b/source/blender/editors/curve/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h
index a73a54323ee..2146855a75e 100644
--- a/source/blender/editors/curve/curve_intern.h
+++ b/source/blender/editors/curve/curve_intern.h
@@ -49,7 +49,6 @@ void FONT_OT_case_toggle(struct wmOperatorType *ot);
 void FONT_OT_case_set(struct wmOperatorType *ot);
 void FONT_OT_style_toggle(struct wmOperatorType *ot);
 void FONT_OT_style_set(struct wmOperatorType *ot);
-void FONT_OT_material_set(struct wmOperatorType *ot);
 
 void FONT_OT_text_copy(struct wmOperatorType *ot);
 void FONT_OT_text_cut(struct wmOperatorType *ot);
diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c
index 5292d86d3c9..66cde772f3e 100644
--- a/source/blender/editors/curve/curve_ops.c
+++ b/source/blender/editors/curve/curve_ops.c
@@ -106,7 +106,6 @@ void ED_operatortypes_curve(void)
 	WM_operatortype_append(FONT_OT_case_set);
 	WM_operatortype_append(FONT_OT_style_toggle);
 	WM_operatortype_append(FONT_OT_style_set);
-	WM_operatortype_append(FONT_OT_material_set);
 
 	WM_operatortype_append(FONT_OT_text_copy);
 	WM_operatortype_append(FONT_OT_text_cut);
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 466908c562c..5283aacf39e 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -189,7 +189,7 @@ static short swap_selection_bpoint(BPoint *bp)
 		return select_bpoint(bp, SELECT, 1, VISIBLE);
 }
 
-short isNurbsel(Nurb *nu)
+int isNurbsel(Nurb *nu)
 {
 	BezTriple *bezt;
 	BPoint *bp;
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 5389db9e2ee..9f2bd6f26f9 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -700,50 +700,6 @@ void FONT_OT_style_toggle(wmOperatorType *ot)
 	RNA_def_enum(ot->srna, "style", style_items, CU_BOLD, "Style", "Style to set selection to.");
 }
 
-/******************* set material operator ********************/
-
-static int set_material_exec(bContext *C, wmOperator *op)
-{
-	Scene *scene= CTX_data_scene(C);
-	Object *obedit= CTX_data_edit_object(C);
-	Curve *cu= obedit->data;
-	EditFont *ef= cu->editfont;
-	int i, mat_nr, selstart, selend;
-
-	if(!BKE_font_getselection(obedit, &selstart, &selend))
-		return OPERATOR_CANCELLED;
-
-	if(RNA_property_is_set(op->ptr, "index"))
-		mat_nr= RNA_int_get(op->ptr, "index");
-	else
-		mat_nr= obedit->actcol;
-
-	for(i=selstart; i<=selend; i++)
-		ef->textbufinfo[i].mat_nr = mat_nr;
-
-	DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
-	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
-
-	return OPERATOR_FINISHED;
-}
-
-void FONT_OT_material_set(wmOperatorType *ot)
-{
-	/* identifiers */
-	ot->name= "Set Material";
-	ot->idname= "FONT_OT_material_set";
-	
-	/* api callbacks */
-	ot->exec= set_material_exec;
-	ot->poll= ED_operator_editfont;
-	
-	/* flags */
-	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
-	/* properties */
-	RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Material Index", "Material slot index.", 0, INT_MAX);
-}
-
 /******************* copy text operator ********************/
 
 static void copy_selection(Object *obedit)
diff --git a/source/blender/editors/datafiles/Bfont.c b/source/blender/editors/datafiles/Bfont.c
index 4080a0d369f..cd45debcbe4 100644
--- a/source/blender/editors/datafiles/Bfont.c
+++ b/source/blender/editors/datafiles/Bfont.c
@@ -1,6 +1,6 @@
 /* DataToC output of file  */
 /*
- * $Id: Bfont.c 125 2002-11-25 12:02:15Z mein $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/datafiles/Makefile b/source/blender/editors/datafiles/Makefile
index 4162125623e..d7bb4e7222f 100644
--- a/source/blender/editors/datafiles/Makefile
+++ b/source/blender/editors/datafiles/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/gpencil/Makefile b/source/blender/editors/gpencil/Makefile
index f4c1cd246f4..9bc5f491a83 100644
--- a/source/blender/editors/gpencil/Makefile
+++ b/source/blender/editors/gpencil/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index bad86c170ab..c0c1cbc7ac6 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -1,5 +1,5 @@
 /**
- * $Id: gpencil.c 19758 2009-04-16 13:10:08Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/include/BIF_gl.h b/source/blender/editors/include/BIF_gl.h
index 014201648c9..c1b3b056d62 100644
--- a/source/blender/editors/include/BIF_gl.h
+++ b/source/blender/editors/include/BIF_gl.h
@@ -1,5 +1,5 @@
 /**
- * $Id: BIF_gl.h 10455 2007-04-04 13:18:41Z campbellbarton $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h
index c619ee80f70..2cebc6a572a 100644
--- a/source/blender/editors/include/ED_curve.h
+++ b/source/blender/editors/include/ED_curve.h
@@ -30,6 +30,7 @@
 
 struct Base;
 struct bContext;
+struct Nurb;
 struct Object;
 struct Scene;
 struct Text;
@@ -52,6 +53,8 @@ void	mouse_nurb		(struct bContext *C, short mval[2], int extend);
 
 struct Nurb *add_nurbs_primitive(struct bContext *C, int type, int newname);
 
+int		isNurbsel		(struct Nurb *nu);;
+
 /* editfont.h */
 void	undo_push_font	(struct bContext *C, char *name);
 void	make_editText	(struct Object *obedit);
diff --git a/source/blender/editors/include/ED_datafiles.h b/source/blender/editors/include/ED_datafiles.h
index c1802c2952b..5d24b93418b 100644
--- a/source/blender/editors/include/ED_datafiles.h
+++ b/source/blender/editors/include/ED_datafiles.h
@@ -1,5 +1,5 @@
 /**
- * $Id: ED_datafiles.h 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h
index 34aefa91225..01882ecd9bc 100644
--- a/source/blender/editors/include/ED_fileselect.h
+++ b/source/blender/editors/include/ED_fileselect.h
@@ -29,34 +29,8 @@
 #define ED_FILES_H
 
 struct SpaceFile;
-
-#define FILE_SHORTDISPLAY	1
-#define FILE_LONGDISPLAY	2
-#define FILE_IMGDISPLAY		3
-
-typedef struct FileSelectParams {
-	char title[24]; /* title, also used for the text of the execute button */
-	char dir[240]; /* directory */
-	char file[80]; /* file */
-
-	short flag; /* settings for filter, hiding files and display mode */
-	short sort; /* sort order */
-	short display; /* display mode flag */
-	short filter; /* filter when (flags & FILE_FILTER) is true */
-
-	/* XXX - temporary, better move to filelist */
-	short active_bookmark;
-	int	active_file;
-	int selstate;
-
-	/* XXX --- still unused -- */
-	short f_fp; /* show font preview */
-	char fp_str[8]; /* string to use for font preview */
-	
-	char *pupmenu; /* allows menu for save options - result stored in menup */
-	short menu; /* currently selected option in pupmenu */
-	/* XXX --- end unused -- */
-} FileSelectParams;
+struct ARegion;
+struct FileSelectParams;
 
 #define FILE_LAYOUT_HOR 1
 #define FILE_LAYOUT_VER 2
@@ -93,7 +67,7 @@ typedef struct FileLayout
 	float column_widths[MAX_FILE_COLUMN];
 } FileLayout;
 
-FileSelectParams* ED_fileselect_get_params(struct SpaceFile *sfile);
+struct FileSelectParams* ED_fileselect_get_params(struct SpaceFile *sfile);
 
 short ED_fileselect_set_params(struct SpaceFile *sfile, const char *title, const char *path, 
 						   short flag, short display, short filter, short sort);
diff --git a/source/blender/editors/include/ED_fluidsim.h b/source/blender/editors/include/ED_fluidsim.h
index bda879173c3..586f16f42aa 100644
--- a/source/blender/editors/include/ED_fluidsim.h
+++ b/source/blender/editors/include/ED_fluidsim.h
@@ -1,7 +1,7 @@
 /**
  * BKE_fluidsim.h 
  *	
- * $Id: LBM_fluidsim.h 17433 2008-11-12 21:16:53Z blendix $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h
index 81420ac95e5..e104bce90f6 100644
--- a/source/blender/editors/include/ED_keyframes_draw.h
+++ b/source/blender/editors/include/ED_keyframes_draw.h
@@ -1,5 +1,5 @@
 /**
- * $Id: BDR_drawaction.h 17579 2008-11-26 11:01:56Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index fbb469f8d43..9d063910aa9 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -1,5 +1,5 @@
 /**
- * $Id: BIF_keyframing.h 17216 2008-10-29 11:20:02Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -178,9 +178,9 @@ void ANIM_OT_remove_driver_button(struct wmOperatorType *ot);
 
 /* Auto-Keying macros for use by various tools */
 	/* check if auto-keyframing is enabled (per scene takes presidence) */
-#define IS_AUTOKEY_ON(scene)	((scene) ? (scene->autokey_mode & AUTOKEY_ON) : (U.autokey_mode & AUTOKEY_ON))
+#define IS_AUTOKEY_ON(scene)	((scene) ? (scene->toolsettings->autokey_mode & AUTOKEY_ON) : (U.autokey_mode & AUTOKEY_ON))
 	/* check the mode for auto-keyframing (per scene takes presidence)  */
-#define IS_AUTOKEY_MODE(scene, mode) 	((scene) ? (scene->autokey_mode == AUTOKEY_MODE_##mode) : (U.autokey_mode == AUTOKEY_MODE_##mode))
+#define IS_AUTOKEY_MODE(scene, mode) 	((scene) ? (scene->toolsettings->autokey_mode == AUTOKEY_MODE_##mode) : (U.autokey_mode == AUTOKEY_MODE_##mode))
 	/* check if a flag is set for auto-keyframing (as userprefs only!) */
 #define IS_AUTOKEY_FLAG(flag)	(U.autokey_flag & AUTOKEY_FLAG_##flag)
 
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 6dff4ee6ca4..8952305d6ab 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -110,7 +110,6 @@ void		undo_push_mesh(struct bContext *C, char *name);
 struct EditFace	*EM_get_actFace(struct EditMesh *em, int sloppy);
 void             EM_set_actFace(struct EditMesh *em, struct EditFace *efa);
 float            EM_face_area(struct EditFace *efa);
-void             EM_add_data_layer(struct EditMesh *em, struct CustomData *data, int type);
 
 void		EM_select_edge(struct EditEdge *eed, int sel);
 void		EM_select_face(struct EditFace *efa, int sel);
@@ -134,6 +133,9 @@ struct UvVertMap *EM_make_uv_vert_map(struct EditMesh *em, int selected, int do_
 struct UvMapVert *EM_get_uv_map_vert(struct UvVertMap *vmap, unsigned int v);
 void              EM_free_uv_vert_map(struct UvVertMap *vmap);
 
+void		EM_add_data_layer(struct EditMesh *em, struct CustomData *data, int type);
+void		EM_free_data_layer(struct EditMesh *em, struct CustomData *data, int type);
+
 /* editmesh_mods.c */
 extern unsigned int em_vertoffs, em_solidoffs, em_wireoffs;
 
@@ -147,6 +149,9 @@ int			EM_init_backbuf_circle(struct ViewContext *vc, short xs, short ys, short r
 void		EM_hide_mesh(struct EditMesh *em, int swap);
 void		EM_reveal_mesh(struct EditMesh *em);
 
+void		EM_select_by_material(struct EditMesh *em, int index);
+void		EM_deselect_by_material(struct EditMesh *em, int index); 
+
 /* editface.c */
 struct MTFace	*EM_get_active_mtface(struct EditMesh *em, struct EditFace **act_efa, struct MCol **mcol, int sloppy);
 
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index bfa819632c9..e4e4b1d0486 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -63,6 +63,7 @@ struct Base *ED_object_add_duplicate(struct Scene *scene, struct Base *base, int
 #define EM_FREEDATA		1
 #define EM_FREEUNDO		2
 #define EM_WAITCURSOR	4
+#define EM_DO_UNDO		8
 void ED_object_exit_editmode(struct bContext *C, int flag);
 void ED_object_enter_editmode(struct bContext *C, int flag);
 
diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h
index 0e5d7302837..43cb5053f48 100644
--- a/source/blender/editors/include/ED_particle.h
+++ b/source/blender/editors/include/ED_particle.h
@@ -1,5 +1,5 @@
 /* 
- * $Id: ED_editparticle.h $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesdna/DNA_radio_types.h b/source/blender/editors/include/ED_pointcache.h
similarity index 55%
rename from source/blender/makesdna/DNA_radio_types.h
rename to source/blender/editors/include/ED_pointcache.h
index 4219bf59b93..dc50e274fa9 100644
--- a/source/blender/makesdna/DNA_radio_types.h
+++ b/source/blender/editors/include/ED_pointcache.h
@@ -1,9 +1,5 @@
-/**
- * radio_types.h    dec 2000 Nzc
- *
- * All type defs for the Blender core.
- *
- * $Id$ 
+/* 
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -21,7 +17,7 @@
  * 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.
+ * The Original Code is Copyright (C) 2007 by Janne Karhu.
  * All rights reserved.
  *
  * The Original Code is: all of this file.
@@ -29,34 +25,14 @@
  * Contributor(s): none yet.
  *
  * ***** END GPL LICENSE BLOCK *****
- * 
  */
 
-#ifndef DNA_RADIO_TYPES_H
-#define DNA_RADIO_TYPES_H
+#ifndef ED_PHYSICS_H
+#define ED_PHYSICS_H
 
-typedef struct Radio {
-	short hemires, maxiter;
-	short drawtype, flag;			/* bit 0 and 1: show limits */
-	short subshootp, subshoote, nodelim, maxsublamp;
-	short pama, pami, elma, elmi;	/* patch and elem limits */
-	int maxnode;
-	float convergence;
-	float radfac, gamma;		/* for display */
-	
-} Radio;
+/* operators */
+void ED_operatortypes_pointcache(void);
+//void ED_keymap_pointcache(struct wmWindowManager *wm);
 
-
-/* **************** RADIOSITY ********************* */
-
-/* draw type */
-#define RAD_WIREFRAME	0
-#define RAD_SOLID		1
-#define RAD_GOURAUD		2
-
-/* flag */
-#define RAD_SHOWLIMITS	1
-#define RAD_SHOWZ		2
-
-#endif
+#endif /* ED_PHYSICS_H */
 
diff --git a/source/blender/editors/include/ED_previewrender.h b/source/blender/editors/include/ED_previewrender.h
index c74cb0f9958..10067510e53 100644
--- a/source/blender/editors/include/ED_previewrender.h
+++ b/source/blender/editors/include/ED_previewrender.h
@@ -29,17 +29,14 @@
 struct View3D;
 struct SpaceButs;
 struct RenderInfo;
+struct Scene;
 struct Image;
-struct ScrArea;
-struct uiBlock;
 struct Render;
 struct bContext;
 struct ID;
 
 #define PREVIEW_RENDERSIZE 140
 
-typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha);
-
 /* stores rendered preview  - is also used for icons */
 typedef struct RenderInfo {
 	int pr_rectx;
@@ -74,6 +71,7 @@ void ED_preview_init_dbase(void);
 void ED_preview_free_dbase(void);
 
 void ED_preview_shader_job(const struct bContext *C, void *owner, struct ID *id, int sizex, int sizey);
+void ED_preview_iconrender(struct Scene *scene, struct ID *id, int *rect, int sizex, int sizey);
 
 void ED_preview_draw(const struct bContext *C, void *idp, rcti *rect);
 
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 38e52a8f59c..b576299c1d0 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -132,6 +132,8 @@ int lasso_inside_edge(short mcords[][2], short moves, int x0, int y0, int x1, in
 
 /* modes */
 void ED_view3d_exit_paint_modes(struct bContext *C);
+/* get 3d region from context, also if mouse is in header or toolbar */
+struct RegionView3D *ED_view3d_context_rv3d(struct bContext *C);
 
 #endif /* ED_VIEW3D_H */
 
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index a38dfd93c30..602e94838b7 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -74,8 +74,8 @@ DEF_ICON(ICON_CHECKBOX_DEHLT)
 DEF_ICON(ICON_CHECKBOX_HLT)
 DEF_ICON(ICON_UNLOCKED)
 DEF_ICON(ICON_LOCKED)
-DEF_ICON(ICON_PINNED)
 DEF_ICON(ICON_UNPINNED)
+DEF_ICON(ICON_PINNED)
 DEF_ICON(ICON_BLANK015)
 DEF_ICON(ICON_RIGHTARROW)
 DEF_ICON(ICON_DOWNARROW_HLT)
@@ -658,12 +658,12 @@ DEF_ICON(ICON_SNAP_VERTEX)
 DEF_ICON(ICON_SNAP_EDGE)
 DEF_ICON(ICON_SNAP_FACE)
 DEF_ICON(ICON_SNAP_VOLUME)
+DEF_ICON(ICON_UVS_FACE)
 DEF_ICON(ICON_STICKY_UVS_LOC)
 DEF_ICON(ICON_STICKY_UVS_DISABLE)
 DEF_ICON(ICON_STICKY_UVS_VERT)
 DEF_ICON(ICON_CLIPUV_DEHLT)
 DEF_ICON(ICON_CLIPUV_HLT)
-DEF_ICON(ICON_BLANK219)
 DEF_ICON(ICON_SNAP_PEEL_OBJECT)
 DEF_ICON(ICON_BLANK221)
 DEF_ICON(ICON_GRID)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index c53087464c0..cc8b936b04f 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1,5 +1,5 @@
 /**
- * $Id: UI_interface.h 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -53,6 +53,8 @@ struct uiStyle;
 struct uiFontStyle;
 struct ColorBand;
 struct CurveMapping;
+struct Image;
+struct ImageUser;
 
 typedef struct uiBut uiBut;
 typedef struct uiBlock uiBlock;
@@ -415,7 +417,7 @@ void uiBlockPickerButtons(struct uiBlock *block, float *col, float *hsv, float *
 void uiBlockColorbandButtons(struct uiBlock *block, struct ColorBand *coba, struct rctf *butr, int event);
 
 uiBut *uiDefAutoButR(uiBlock *block, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, char *name, int icon, int x1, int y1, int x2, int y2);
-void uiDefAutoButsRNA(const struct bContext *C, uiLayout *layout, struct PointerRNA *ptr);
+void uiDefAutoButsRNA(const struct bContext *C, uiLayout *layout, struct PointerRNA *ptr, int columns);
 
 /* Links
  *
@@ -452,9 +454,9 @@ typedef void (*uiButSearchFunc)(const struct bContext *C, void *arg, char *str,
 typedef void (*uiBlockHandleFunc)(struct bContext *C, void *arg, int event);
 		
 		/* use inside searchfunc to add items */
-int		uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin);
+int		uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int iconid);
 		/* bfunc gets search item *poin as arg2, or if NULL the old string */
-void	uiButSetSearchFunc	(uiBut *but,		uiButSearchFunc sfunc, void *arg1, uiButHandleFunc bfunc);
+void	uiButSetSearchFunc	(uiBut *but,		uiButSearchFunc sfunc, void *arg1, uiButHandleFunc bfunc, void *active);
 		/* height in pixels, it's using hardcoded values still */
 int		uiSearchBoxhHeight(void);
 
@@ -607,13 +609,17 @@ uiBlock *uiLayoutFreeBlock(uiLayout *layout);
 /* templates */
 void uiTemplateHeader(uiLayout *layout, struct bContext *C);
 void uiTemplateID(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname,
-	char *newop, char *openop, char *unlinkop);
+	char *newop, char *unlinkop);
 uiLayout *uiTemplateModifier(uiLayout *layout, struct PointerRNA *ptr);
 uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr);
 void uiTemplatePreview(uiLayout *layout, struct ID *id);
 void uiTemplateColorRamp(uiLayout *layout, struct ColorBand *coba, int expand);
 void uiTemplateCurveMapping(uiLayout *layout, struct CurveMapping *cumap, int type);
 void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, char *propname);
+void uiTemplateImageLayers(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser);
+ListBase uiTemplateList(uiLayout *layout, struct PointerRNA *ptr, char *propname, struct PointerRNA *activeptr, char *activeprop, int rows, int columns, int compact);
+void uiTemplateRunningJobs(uiLayout *layout, struct bContext *C);
+void uiTemplateOperatorSearch(uiLayout *layout);
 
 /* items */
 void uiItemO(uiLayout *layout, char *name, int icon, char *opname);
@@ -630,6 +636,7 @@ void uiItemR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, cha
 void uiItemFullR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, int value, int expand, int slider, int toggle);
 void uiItemEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, int value);
 void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, char *propname);
+void uiItemPointerR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, struct PointerRNA *searchptr, char *searchpropname);
 
 void uiItemL(uiLayout *layout, char *name, int icon); /* label */
 void uiItemM(uiLayout *layout, struct bContext *C, char *name, int icon, char *menuname); /* menu */
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 7168e593a8a..1ae3634c73b 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -1,5 +1,5 @@
 /**
- * $Id: UI_resources.h 13057 2007-12-30 12:08:28Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/interface/Makefile b/source/blender/editors/interface/Makefile
index dfc8187de49..a3d0692f1e1 100644
--- a/source/blender/editors/interface/Makefile
+++ b/source/blender/editors/interface/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 5ffc6440dc4..00ec875bd86 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1,5 +1,5 @@
 /**
- * $Id: interface.c 16882 2008-10-02 12:29:45Z ton $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -80,7 +80,6 @@
  */
 
 static void ui_free_but(const bContext *C, uiBut *but);
-static void ui_rna_ID_autocomplete(bContext *C, char *str, void *arg_but);
 
 /* ************* translation ************** */
 
@@ -671,7 +670,8 @@ void uiDrawBlock(const bContext *C, uiBlock *block)
 	/* widgets */
 	for(but= block->buttons.first; but; but= but->next) {
 		ui_but_to_pixelrect(&rect, ar, block, but);
-		ui_draw_but(C, ar, &style, but, &rect);
+		if(!(but->flag & UI_HIDDEN))
+			ui_draw_but(C, ar, &style, but, &rect);
 	}
 	
 	/* restore matrix */
@@ -1281,17 +1281,13 @@ void ui_get_but_string(uiBut *but, char *str, int maxlen)
 		else if(type == PROP_POINTER) {
 			/* RNA pointer */
 			PointerRNA ptr= RNA_property_pointer_get(&but->rnapoin, but->rnaprop);
-			PropertyRNA *nameprop;
-
-			if(ptr.data && (nameprop = RNA_struct_name_property(ptr.type)))
-				buf= RNA_property_string_get_alloc(&ptr, nameprop, str, maxlen);
-			else
-				BLI_strncpy(str, "", maxlen);
+			buf= RNA_struct_name_get_alloc(&ptr, str, maxlen);
 		}
-		else
-			BLI_strncpy(str, "", maxlen);
 
-		if(buf && buf != str) {
+		if(!buf) {
+			BLI_strncpy(str, "", maxlen);
+		}
+		else if(buf && buf != str) {
 			/* string was too long, we have to truncate */
 			BLI_strncpy(str, buf, maxlen);
 			MEM_freeN(buf);
@@ -1337,72 +1333,6 @@ void ui_get_but_string(uiBut *but, char *str, int maxlen)
 	}
 }
 
-static void ui_rna_ID_collection(bContext *C, uiBut *but, PointerRNA *ptr, PropertyRNA **prop)
-{
-	CollectionPropertyIterator iter;
-	PropertyRNA *iterprop, *iprop;
-	StructRNA *srna;
-
-	/* look for collection property in Main */
-	RNA_pointer_create(NULL, &RNA_Main, CTX_data_main(C), ptr);
-
-	iterprop= RNA_struct_iterator_property(ptr->type);
-	RNA_property_collection_begin(ptr, iterprop, &iter);
-	*prop= NULL;
-
-	for(; iter.valid; RNA_property_collection_next(&iter)) {
-		iprop= iter.ptr.data;
-
-		/* if it's a collection and has same pointer type, we've got it */
-		if(RNA_property_type(iprop) == PROP_COLLECTION) {
-			srna= RNA_property_pointer_type(ptr, iprop);
-
-			if(RNA_property_pointer_type(ptr, but->rnaprop) == srna) {
-				*prop= iprop;
-				break;
-			}
-		}
-	}
-
-	RNA_property_collection_end(&iter);
-}
-
-/* autocomplete callback for RNA pointers */
-static void ui_rna_ID_autocomplete(bContext *C, char *str, void *arg_but)
-{
-	uiBut *but= arg_but;
-	AutoComplete *autocpl;
-	CollectionPropertyIterator iter;
-	PointerRNA ptr;
-	PropertyRNA *prop, *nameprop;
-	char *name;
-	
-	if(str[0]==0) return;
-
-	/* get the collection */
-	ui_rna_ID_collection(C, but, &ptr, &prop);
-	if(prop==NULL) return;
-
-	autocpl= autocomplete_begin(str, ui_get_but_string_max_length(but));
-	RNA_property_collection_begin(&ptr, prop, &iter);
-
-	/* loop over items in collection */
-	for(; iter.valid; RNA_property_collection_next(&iter)) {
-		if(iter.ptr.data && (nameprop = RNA_struct_name_property(iter.ptr.type))) {
-			name= RNA_property_string_get_alloc(&iter.ptr, nameprop, NULL, 0);
-
-			if(name) {
-				/* test item name */
-				autocomplete_do_name(autocpl, name);
-				MEM_freeN(name);
-			}
-		}
-	}
-
-	RNA_property_collection_end(&iter);
-	autocomplete_end(autocpl, str);
-}
-
 int ui_set_but_string(bContext *C, uiBut *but, const char *str)
 {
 	if(but->rnaprop && ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) {
@@ -1421,21 +1351,21 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str)
 				PointerRNA ptr, rptr;
 				PropertyRNA *prop;
 
-				/* XXX only ID pointers at the moment, needs to support
-				 * custom collection too for bones, vertex groups, .. */
-				ui_rna_ID_collection(C, but, &ptr, &prop);
-
 				if(str == NULL || str[0] == '\0') {
-					memset(&rptr, 0, sizeof(rptr));
-					RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr);
+					RNA_property_pointer_set(&but->rnapoin, but->rnaprop, PointerRNA_NULL);
 					return 1;
 				}
-				else if(prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr)) {
-					RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr);
+				else {
+					ptr= but->rnasearchpoin;
+					prop= but->rnasearchprop;
+					
+					if(prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr))
+						RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr);
+
 					return 1;
 				}
-				else
-					return 0;
+
+				return 0;
 			}
 		}
 	}
@@ -2147,13 +2077,10 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, char *str, short
 		rgb_to_hsv(rgb[0], rgb[1], rgb[2], but->hsv, but->hsv+1, but->hsv+2);
 	}
 
-	if((block->flag & UI_BLOCK_LOOP) || ELEM6(but->type, MENU, TEX, LABEL, IDPOIN, BLOCK, BUTM)) {
-		but->flag |= UI_TEXT_LEFT;
-	}
-	
-	if(but->type==BUT_TOGDUAL) {
+	if((block->flag & UI_BLOCK_LOOP) || ELEM7(but->type, MENU, TEX, LABEL, IDPOIN, BLOCK, BUTM, SEARCH_MENU))
+		but->flag |= (UI_TEXT_LEFT|UI_ICON_LEFT);
+	else if(but->type==BUT_TOGDUAL)
 		but->flag |= UI_ICON_LEFT;
-	}
 
 	but->flag |= (block->flag & UI_BUT_ALIGN);
 
@@ -2257,7 +2184,7 @@ uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, char *str, short x1,
 				RNA_property_int_range(ptr, prop, &hardmin, &hardmax);
 				RNA_property_int_ui_range(ptr, prop, &softmin, &softmax, &step);
 
-				if(min == max) {
+				if(type != ROW && min == max) {
 					min= hardmin;
 					max= hardmax;
 				}
@@ -2272,7 +2199,7 @@ uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, char *str, short x1,
 				RNA_property_float_range(ptr, prop, &hardmin, &hardmax);
 				RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
 
-				if(min == max) {
+				if(type != ROW && min == max) {
 					min= hardmin;
 					max= hardmax;
 				}
@@ -2303,10 +2230,6 @@ uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, char *str, short x1,
 			but->rnaindex= index;
 		else
 			but->rnaindex= 0;
-
-		if(type == IDPOIN)
-			uiButSetCompleteFunc(but, ui_rna_ID_autocomplete, but);
-
 	}
 
 	if(icon) {
@@ -2422,7 +2345,11 @@ void autocomplete_do_name(AutoComplete *autocpl, const char *name)
 		else {
 			/* remove from truncate what is not in bone->name */
 			for(a=0; amaxlen-1; a++) {
-				if(truncate[a]!=name[a])
+				if(name[a] == 0) {
+					truncate[a]= 0;
+					break;
+				}
+				else if(truncate[a]!=name[a])
 					truncate[a]= 0;
 			}
 		}
@@ -2753,7 +2680,7 @@ void uiBlockFlipOrder(uiBlock *block)
 	uiBut *but, *next;
 	float centy, miny=10000, maxy= -10000;
 
-	if(!(U.uiflag & USER_DIRECTIONALORDER))
+	if(U.uiflag & USER_MENUFIXEDORDER)
 		return;
 	
 	for(but= block->buttons.first; but; but= but->next) {
@@ -2992,15 +2919,15 @@ uiBut *uiDefSearchBut(uiBlock *block, void *arg, int retval, int icon, int maxle
 }
 
 /* arg is user value, searchfunc and handlefunc both get it as arg */
-void uiButSetSearchFunc(uiBut *but, uiButSearchFunc sfunc, void *arg, uiButHandleFunc bfunc)
+/* if active set, button opens with this item visible and selected */
+void uiButSetSearchFunc(uiBut *but, uiButSearchFunc sfunc, void *arg, uiButHandleFunc bfunc, void *active)
 {
 	but->search_func= sfunc;
 	but->search_arg= arg;
 	
-	uiButSetFunc(but, bfunc, arg, NULL);
+	uiButSetFunc(but, bfunc, arg, active);
 }
 
-
 /* Program Init/Exit */
 
 void UI_init(void)
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 6d6d4ab9299..8400fee0c55 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -1,5 +1,5 @@
 /**
- * $Id: interface_draw.c 15733 2008-07-24 09:23:13Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index fb5afbf5e36..7ad422ef3b5 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -112,6 +112,9 @@ typedef struct uiHandleButtonData {
 	/* tooltip */
 	ARegion *tooltip;
 	wmTimer *tooltiptimer;
+	
+	/* auto open */
+	int used_mouse;
 	wmTimer *autoopentimer;
 
 	/* text selection/editing */
@@ -284,16 +287,6 @@ static void ui_apply_but_funcs_after(bContext *C)
 		if(after.context)
 			CTX_store_set(C, after.context);
 
-		if(after.func)
-			after.func(C, after.func_arg1, after.func_arg2);
-		if(after.funcN)
-			after.funcN(C, after.func_argN, after.func_arg2);
-		
-		if(after.handle_func)
-			after.handle_func(C, after.handle_func_arg, after.retval);
-		if(after.butm_func)
-			after.butm_func(C, after.butm_func_arg, after.a2);
-
 		if(after.optype)
 			WM_operator_name_call(C, after.optype->idname, after.opcontext, after.opptr);
 		if(after.opptr) {
@@ -308,6 +301,16 @@ static void ui_apply_but_funcs_after(bContext *C)
 			CTX_store_set(C, NULL);
 			CTX_store_free(after.context);
 		}
+
+		if(after.func)
+			after.func(C, after.func_arg1, after.func_arg2);
+		if(after.funcN)
+			after.funcN(C, after.func_argN, after.func_arg2);
+		
+		if(after.handle_func)
+			after.handle_func(C, after.handle_func_arg, after.retval);
+		if(after.butm_func)
+			after.butm_func(C, after.butm_func_arg, after.a2);
 	}
 }
 
@@ -404,7 +407,15 @@ static void ui_apply_but_TOG(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
 
 static void ui_apply_but_ROW(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data)
 {
+	uiBut *bt;
+	
 	ui_set_but_val(but, but->hardmax);
+	
+	/* states of other row buttons */
+	for(bt= block->buttons.first; bt; bt= bt->next)
+		if(bt!=but && bt->poin==but->poin && bt->type==ROW)
+			ui_check_but(bt);
+	
 	ui_apply_but_func(C, but);
 
 	data->retval= but->retval;
@@ -738,11 +749,8 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
 			ui_apply_but_ROW(C, block, but, data);
 			break;
 		case SCROLL:
-			break;
 		case NUM:
 		case NUMABS:
-			ui_apply_but_NUM(C, but, data);
-			break;
 		case SLI:
 		case NUMSLI:
 			ui_apply_but_NUM(C, but, data);
@@ -1218,8 +1226,14 @@ static int ui_textedit_autocomplete(bContext *C, uiBut *but, uiHandleButtonData
 	int changed= 1;
 
 	str= data->str;
-	but->autocomplete_func(C, str, but->autofunc_arg);
+
+	if(data->searchbox)
+		ui_searchbox_autocomplete(C, data->searchbox, but, data->str);
+	else
+		but->autocomplete_func(C, str, but->autofunc_arg);
+
 	but->pos= strlen(str);
+	but->selsta= but->selend= but->pos;
 
 	return changed;
 }
@@ -1346,14 +1360,14 @@ static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
 		return;
 
 	for(but= actbut->next; but; but= but->next) {
-		if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) {
+		if(ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) {
 			data->postbut= but;
 			data->posttype= BUTTON_ACTIVATE_TEXT_EDITING;
 			return;
 		}
 	}
 	for(but= block->buttons.first; but!=actbut; but= but->next) {
-		if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) {
+		if(ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) {
 			data->postbut= but;
 			data->posttype= BUTTON_ACTIVATE_TEXT_EDITING;
 			return;
@@ -1370,14 +1384,14 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
 		return;
 
 	for(but= actbut->prev; but; but= but->prev) {
-		if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) {
+		if(ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) {
 			data->postbut= but;
 			data->posttype= BUTTON_ACTIVATE_TEXT_EDITING;
 			return;
 		}
 	}
 	for(but= block->buttons.last; but!=actbut; but= but->prev) {
-		if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) {
+		if(ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) {
 			data->postbut= but;
 			data->posttype= BUTTON_ACTIVATE_TEXT_EDITING;
 			return;
@@ -1433,7 +1447,6 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
 				}
 			}
 			else if(inbox) {
-				printf("release inside \n");
 				button_activate_state(C, but, BUTTON_STATE_EXIT);
 				retval= WM_UI_HANDLER_BREAK;
 			}
@@ -1502,7 +1515,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
 				
 			case TABKEY:
 				/* there is a key conflict here, we can't tab with autocomplete */
-				if(but->autocomplete_func) {
+				if(but->autocomplete_func || data->searchbox) {
 					changed= ui_textedit_autocomplete(C, but, data);
 					retval= WM_UI_HANDLER_BREAK;
 				}
@@ -2053,6 +2066,11 @@ static int ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, int shift, i
 
 	if(but->type==NUMSLI) deler= ((but->x2-but->x1) - 5.0*but->aspect);
 	else if(but->type==HSVSLI) deler= ((but->x2-but->x1)/2 - 5.0*but->aspect);
+	else if(but->type==SCROLL) {
+		int horizontal= (but->x2 - but->x1 > but->y2 - but->y1);
+		float size= (horizontal)? (but->x2-but->x1): -(but->y2-but->y1);
+		deler= size*(but->softmax - but->softmin)/(but->softmax - but->softmin + but->a1);
+	}
 	else deler= (but->x2-but->x1- 5.0*but->aspect);
 
 	f= (float)(mx-data->dragstartx)/deler + data->dragfstart;
@@ -2223,6 +2241,54 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
 	return retval;
 }
 
+static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
+{
+	int mx, my, click= 0;
+	int retval= WM_UI_HANDLER_CONTINUE;
+	int horizontal= (but->x2 - but->x1 > but->y2 - but->y1);
+	
+	mx= event->x;
+	my= event->y;
+	ui_window_to_block(data->region, block, &mx, &my);
+
+	if(data->state == BUTTON_STATE_HIGHLIGHT) {
+		if(event->val==KM_PRESS) {
+			if(event->type == LEFTMOUSE) {
+				if(horizontal) {
+					data->dragstartx= mx;
+					data->draglastx= mx;
+				}
+				else {
+					data->dragstartx= my;
+					data->draglastx= my;
+				}
+				button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+				retval= WM_UI_HANDLER_BREAK;
+			}
+			else if(ELEM(event->type, PADENTER, RETKEY) && event->val==KM_PRESS)
+				click= 1;
+		}
+	}
+	else if(data->state == BUTTON_STATE_NUM_EDITING) {
+		if(event->type == ESCKEY) {
+			data->cancel= 1;
+			data->escapecancel= 1;
+			button_activate_state(C, but, BUTTON_STATE_EXIT);
+		}
+		else if(event->type == LEFTMOUSE && event->val!=KM_PRESS) {
+			button_activate_state(C, but, BUTTON_STATE_EXIT);
+		}
+		else if(event->type == MOUSEMOVE) {
+			if(ui_numedit_but_SLI(but, data, 0, 0, (horizontal)? mx: my))
+				ui_numedit_apply(C, block, but, data);
+		}
+
+		retval= WM_UI_HANDLER_BREAK;
+	}
+	
+	return retval;
+}
+
 static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
 {
 	
@@ -3065,13 +3131,9 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
 	case OPTIONN:
 		retval= ui_do_but_TOG(C, but, data, event);
 		break;
-#if 0
 	case SCROLL:
-		/* DrawBut(b, 1); */
-		/* do_scrollbut(b); */
-		/* DrawBut(b,0); */
+		retval= ui_do_but_SCROLL(C, block, but, data, event);
 		break;
-#endif
 	case NUM:
 	case NUMABS:
 		retval= ui_do_but_NUM(C, block, but, data, event);
@@ -3232,7 +3294,8 @@ static uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
 		for(but=block->buttons.first; but; but= but->next) {
 			if(ELEM3(but->type, LABEL, ROUNDBOX, SEPR))
 				continue;
-
+			if(but->flag & UI_HIDDEN)
+				continue;
 			if(ui_but_contains_pt(but, mx, my))
 				/* give precedence to already activated buttons */
 				if(!butover || (!butover->active && but->active))
@@ -3284,7 +3347,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
 
 		/* automatic open pulldown block timer */
 		if(ELEM3(but->type, BLOCK, PULLDOWN, ICONTEXTROW)) {
-			if(!data->autoopentimer) {
+			if(data->used_mouse && !data->autoopentimer) {
 				int time;
 
 				if(but->block->auto_open==2) time= 1;    // test for toolbox
@@ -3387,6 +3450,9 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
 		if(but->block->auto_open_last+BUTTON_AUTO_OPEN_THRESH < PIL_check_seconds_timer())
 			but->block->auto_open= 0;
 
+	if(type == BUTTON_ACTIVATE_OVER) {
+		data->used_mouse= 1;
+	}
 	button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
 	
 	if(type == BUTTON_ACTIVATE_OPEN) {
@@ -3705,12 +3771,19 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut *
 		button_activate_exit(C, data, but, 1);
 	}
 	else if(menu->menuretval == UI_RETURN_OUT) {
-		if(ui_mouse_inside_button(data->region, but, event->x, event->y)) {
+		if(event->type==MOUSEMOVE && ui_mouse_inside_button(data->region, but, event->x, event->y)) {
 			button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
 		}
 		else {
-			data->cancel= 1;
-			button_activate_exit(C, data, but, 1);
+			but= ui_but_find_activated(data->region);
+			if(but) {
+				but->active->used_mouse= 0;
+				button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
+			}
+			else {
+				data->cancel= 1;
+				button_activate_exit(C, data, but, 1);
+			}
 		}
 	}
 }
@@ -4049,7 +4122,7 @@ static int ui_handle_menu_return_submenu(bContext *C, wmEvent *event, uiPopupBlo
 	uiBlock *block;
 	uiHandleButtonData *data;
 	uiPopupBlockHandle *submenu;
-	int mx, my;
+	int mx, my, update;
 
 	ar= menu->region;
 	block= ar->uiblocks.first;
@@ -4067,14 +4140,16 @@ static int ui_handle_menu_return_submenu(bContext *C, wmEvent *event, uiPopupBlo
 				menu->butretval= data->retval;
 			}
 		}
-		else if(submenu->menuretval == UI_RETURN_UPDATE)
+
+		update= (submenu->menuretval == UI_RETURN_UPDATE);
+		if(update)
 			menu->menuretval = UI_RETURN_UPDATE;
 
 		/* now let activated button in this menu exit, which
 		 * will actually close the submenu too */
 		ui_handle_button_return_submenu(C, event, but);
 
-		if(submenu->menuretval == UI_RETURN_UPDATE)
+		if(update)
 			submenu->menuretval = 0;
 	}
 
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index df069069a33..315b8693905 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -41,28 +41,30 @@
 #include "BLI_blenlib.h"
 #include "BLI_storage_types.h"
 
+#include "DNA_material_types.h"
 #include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
 #include "DNA_userdef_types.h"
 
-
-#include "BKE_utildefines.h"
 #include "BKE_image.h"
 #include "BKE_icons.h"
+#include "BKE_utildefines.h"
 
 #include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
 
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
+
+#include "ED_datafiles.h"
+#include "ED_previewrender.h"
+
 #include "UI_interface.h"
 #include "UI_interface_icons.h"
-
-// XXX #include "BIF_previewrender.h"
-// XXX #include "BIF_screen.h"
-
 #include "UI_resources.h" /* elubie: should be removed once the enum for the ICONS is in BIF_preview_icons.h */
+
 #include "interface_intern.h"
-#include "ED_datafiles.h"
+
 
 #define ICON_IMAGE_W		600
 #define ICON_IMAGE_H		640
@@ -650,7 +652,6 @@ void UI_icons_init(int first_dyn_id)
 	init_internal_icons();
 }
 
-#if 0
 static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned int *rect)
 {
 	struct ImBuf *ima;
@@ -727,21 +728,28 @@ static void icon_create_mipmap(struct PreviewImage* prv_img, int miplevel)
 }
 
 /* create single icon from jpg, png etc. */
-static void icon_from_image(Image *img, int miplevel)
+static void icon_from_image(Scene *scene, Image *img, int miplevel)
 {
+	ImBuf *ibuf= NULL;
+	ImageUser iuser;
+	PreviewImage *pi;
 	unsigned int pr_size;
 	short image_loaded = 0;
-	struct ImBuf* ibuf=NULL;
-	PreviewImage* pi;
 
 	/* img->ok is zero when Image cannot load */
 	if (img==NULL || img->ok==0)
 		return;
 
+	/* setup dummy image user */
+	memset(&iuser, 0, sizeof(ImageUser));
+	iuser.ok= iuser.framenr= 1;
+	iuser.scene= scene;
+	
 	/* elubie: this needs to be changed: here image is always loaded if not
 	   already there. Very expensive for large images. Need to find a way to 
 	   only get existing ibuf */
-	ibuf = BKE_image_get_ibuf(img, NULL);
+	
+	ibuf = BKE_image_get_ibuf(img, &iuser);
 	if(ibuf==NULL || ibuf->rect==NULL) {
 		return;
 	}
@@ -771,18 +779,14 @@ static void set_alpha(char* cp, int sizex, int sizey, char alpha)
 		}
 	}
 }
-#endif
 
 /* only called when icon has changed */
 /* only call with valid pointer from UI_icon_draw */
-static void icon_set_image(ID *id, DrawInfo *di, PreviewImage* prv_img, int miplevel)
+static void icon_set_image(Scene *scene, ID *id, PreviewImage* prv_img, int miplevel)
 {
-#if 0 // XXX - preview renders have to be redesigned - possibly low level op (elubie)
 	RenderInfo ri;	
 	unsigned int pr_size = 0;
 	
-	if (!di) return;				
-	
 	if (!prv_img) {
 		printf("No preview image for this ID: %s\n", id->name);
 		return;
@@ -791,20 +795,19 @@ static void icon_set_image(ID *id, DrawInfo *di, PreviewImage* prv_img, int mipl
 	/* no drawing (see last parameter doDraw, just calculate preview image 
 		- hopefully small enough to be fast */
 	if (GS(id->name) == ID_IM)
-		icon_from_image((struct Image*)id, miplevel);
+		icon_from_image(scene, (struct Image*)id, miplevel);
 	else {	
 		/* create the preview rect */
 		icon_create_mipmap(prv_img, miplevel);
 
 		ri.curtile= 0;
 		ri.tottile= 0;
-		ri.rect = NULL;
 		ri.pr_rectx = prv_img->w[miplevel];
 		ri.pr_recty = prv_img->h[miplevel];
-
 		pr_size = ri.pr_rectx*ri.pr_recty*sizeof(unsigned int);
+		ri.rect = MEM_callocN(pr_size, "pr icon rect");
 
-		BIF_previewrender(id, &ri, NULL, PR_ICON_RENDER);
+		ED_preview_iconrender(scene, id, ri.rect, ri.pr_rectx, ri.pr_recty);
 
 		/* world is rendered with alpha=0, so it wasn't displayed 
 		   this could be render option for sky to, for later */
@@ -818,15 +821,11 @@ static void icon_set_image(ID *id, DrawInfo *di, PreviewImage* prv_img, int mipl
 			}
 		}
 
-		if (ri.rect) {
-			memcpy(prv_img->rect[miplevel], ri.rect, pr_size);
+		memcpy(prv_img->rect[miplevel], ri.rect, pr_size);
 
-			/* and clean up */
-			MEM_freeN(ri.rect);
-			ri.rect = 0;
-		}
+		/* and clean up */
+		MEM_freeN(ri.rect);
 	}
-#endif
 }
 
 static void icon_draw_rect(float x, float y, int w, int h, float aspect, int rw, int rh, unsigned int *rect)
@@ -912,14 +911,7 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, int mipl
 		PreviewImage* pi = BKE_previewimg_get((ID*)icon->obj); 
 
 		if (pi) {			
-			if (!nocreate && (pi->changed[miplevel] ||!pi->rect[miplevel])) /* changed only ever set by dynamic icons */
-			{
-				// XXX waitcursor(1);
-				/* create the preview rect if necessary */				
-				icon_set_image((ID*)icon->obj, icon->drawinfo, pi, miplevel);
-				pi->changed[miplevel] = 0;
-				// XXX waitcursor(0);
-			}
+			/* no create icon on this level in code */
 			
 			if (!pi->rect[miplevel]) return; /* something has gone wrong! */
 			
@@ -928,6 +920,43 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, int mipl
 	}
 }
 
+void ui_id_icon_render(Scene *scene, ID *id)
+{
+	PreviewImage *pi = BKE_previewimg_get(id); 
+		
+	if (pi) {			
+		if ((pi->changed[0] ||!pi->rect[0])) /* changed only ever set by dynamic icons */
+		{
+			/* create the preview rect if necessary */				
+			icon_set_image(scene, id, pi, 0);
+			pi->changed[0] = 0;
+		}
+	}
+}
+
+int ui_id_icon_get(Scene *scene, ID *id)
+{
+	int iconid= 0;
+	
+	/* icon */
+	switch(GS(id->name))
+	{
+		case ID_MA: /* fall through */
+		case ID_TE: /* fall through */
+		case ID_IM: /* fall through */
+		case ID_WO: /* fall through */
+		case ID_LA: /* fall through */
+			iconid= BKE_icon_getid(id);
+			/* checks if not exists, or changed */
+			ui_id_icon_render(scene, id);
+			break;
+		default:
+			break;
+	}
+
+	return iconid;
+}
+
 static void icon_draw_mipmap(float x, float y, int icon_id, float aspect, int miplevel, int nocreate)
 {
 	int draw_size = preview_size(miplevel);
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 3aed2a7c299..1b16155c7e6 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -1,5 +1,5 @@
 /**
- * $Id: interface.h 14444 2008-04-16 22:40:48Z hos $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -44,12 +44,17 @@ struct uiStyle;
 struct uiWidgetColors;
 struct uiLayout;
 struct bContextStore;
+struct Scene;
+struct ID;
 
 /* ****************** general defines ************** */
 
 /* visual types for drawing */
 /* for time being separated from functional types */
 typedef enum {
+	/* default */
+	UI_WTYPE_REGULAR,
+
 	/* standard set */
 	UI_WTYPE_LABEL,
 	UI_WTYPE_TOGGLE,
@@ -78,7 +83,8 @@ typedef enum {
 	UI_WTYPE_SWATCH,
 	UI_WTYPE_RGB_PICKER,
 	UI_WTYPE_NORMAL,
-	UI_WTYPE_BOX
+	UI_WTYPE_BOX,
+	UI_WTYPE_SCROLL
 	
 } uiWidgetTypeEnum;
 
@@ -98,7 +104,7 @@ typedef enum {
 #define UI_ACTIVE		4
 #define UI_HAS_ICON		8
 #define UI_TEXTINPUT	16
-
+#define UI_HIDDEN		32
 /* warn: rest of uiBut->flag in UI_interface.h */
 
 /* internal panel drawing defines */
@@ -205,6 +211,9 @@ struct uiBut {
 	struct PropertyRNA *rnaprop;
 	int rnaindex;
 
+	struct PointerRNA rnasearchpoin;
+	struct PropertyRNA *rnasearchprop;
+
 	/* Operator data */
 	struct wmOperatorType *optype;
 	int opcontext;
@@ -365,6 +374,7 @@ void ui_tooltip_free(struct bContext *C, struct ARegion *ar);
 ARegion *ui_searchbox_create(struct bContext *C, struct ARegion *butregion, uiBut *but);
 int ui_searchbox_inside(struct ARegion *ar, int x, int y);
 void ui_searchbox_update(struct bContext *C, struct ARegion *ar, uiBut *but, int reset);
+void ui_searchbox_autocomplete(struct bContext *C, struct ARegion *ar, uiBut *but, char *str);
 void ui_searchbox_event(struct bContext *C, struct ARegion *ar, uiBut *but, struct wmEvent *event);
 void ui_searchbox_apply(uiBut *but, struct ARegion *ar);
 void ui_searchbox_free(struct bContext *C, struct ARegion *ar);
@@ -416,11 +426,15 @@ extern void ui_draw_but(const struct bContext *C, ARegion *ar, struct uiStyle *s
 struct ThemeUI;
 void ui_widget_color_init(struct ThemeUI *tui);
 
-void ui_draw_menu_item(struct uiFontStyle *fstyle, rcti *rect, char *name, int state);
+void ui_draw_menu_item(struct uiFontStyle *fstyle, rcti *rect, char *name, int iconid, int state);
 
 /* interface_style.c */
 void uiStyleInit(void);
 
+/* interface_icons.c */
+void ui_id_icon_render(struct Scene *scene, struct ID *id);
+int ui_id_icon_get(struct Scene *scene, struct ID *id);
+
 /* resources.c */
 void init_userdef_do_versions(void);
 void ui_theme_init_userdef(void);
@@ -428,8 +442,9 @@ void ui_resources_init(void);
 void ui_resources_free(void);
 
 /* interface_layout.c */
-void ui_layout_add_but(struct uiLayout *layout, uiBut *but);
+void ui_layout_add_but(uiLayout *layout, uiBut *but);
 int ui_but_can_align(uiBut *but);
+void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop);
 
 /* interface_anim.c */
 void ui_but_anim_flag(uiBut *but, float cfra);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 9101fd743ee..f9816235b88 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -1,5 +1,5 @@
 /**
- * $Id: interface_layout.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -455,9 +455,10 @@ static void ui_item_enum_row(uiLayout *layout, uiBlock *block, PointerRNA *ptr,
 }
 
 /* create label + button for RNA property */
-static void ui_item_with_label(uiLayout *layout, uiBlock *block, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int x, int y, int w, int h)
+static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int x, int y, int w, int h)
 {
 	uiLayout *sub;
+	uiBut *but;
 	PropertySubType subtype;
 
 	sub= uiLayoutRow(layout, 0);
@@ -473,12 +474,13 @@ static void ui_item_with_label(uiLayout *layout, uiBlock *block, char *name, int
 	if(subtype == PROP_FILEPATH || subtype == PROP_DIRPATH) {
 		uiBlockSetCurLayout(block, uiLayoutRow(sub, 1));
 		uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w-UI_UNIT_X, h);
-		uiDefIconBut(block, BUT, 0, ICON_FILESEL, x, y, UI_UNIT_X, h, NULL, 0.0f, 0.0f, 0.0f, 0.0f, "DUMMY file select button"); /* XXX */
+		but= uiDefIconBut(block, BUT, 0, ICON_FILESEL, x, y, UI_UNIT_X, h, NULL, 0.0f, 0.0f, 0.0f, 0.0f, "DUMMY file select button"); /* XXX */
 	}
 	else
-		uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w, h);
+		but= uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w, h);
 
 	uiBlockSetCurLayout(block, layout);
+	return but;
 }
 
 /********************* Button Items *************************/
@@ -601,7 +603,7 @@ void uiItemsEnumO(uiLayout *layout, char *opname, char *propname)
 		RNA_property_enum_items(&ptr, prop, &item, &totitem);
 
 		for(i=0; iroot->type == UI_LAYOUT_MENU) {
@@ -778,8 +784,10 @@ void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, Proper
 	else if(type == PROP_ENUM && expand)
 		ui_item_enum_row(layout, block, ptr, prop, name, 0, 0, w, h);
 	/* property with separate label */
-	else if(type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER)
-		ui_item_with_label(layout, block, name, icon, ptr, prop, index, 0, 0, w, h);
+	else if(type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER) {
+		but= ui_item_with_label(layout, block, name, icon, ptr, prop, index, 0, 0, w, h);
+		ui_but_add_search(but, ptr, prop, NULL, NULL);
+	}
 	/* single button */
 	else {
 		but= uiDefAutoButR(block, ptr, prop, index, (char*)name, icon, 0, 0, w, h);
@@ -850,6 +858,142 @@ void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, char *propname)
 	}
 }
 
+/* Pointer RNA button with search */
+
+static void rna_search_cb(const struct bContext *C, void *arg_but, char *str, uiSearchItems *items)
+{
+	Scene *scene= CTX_data_scene(C);
+	uiBut *but= arg_but;
+	char *name;
+	int i, iconid;
+
+	i = 0;
+	RNA_PROP_BEGIN(&but->rnasearchpoin, itemptr, but->rnasearchprop) {
+		iconid= 0;
+		if(RNA_struct_is_ID(itemptr.type))
+			iconid= ui_id_icon_get(scene, itemptr.data);
+
+		name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
+
+		if(name) {
+			if(BLI_strcasestr(name, str)) {
+				if(!uiSearchItemAdd(items, name, SET_INT_IN_POINTER(i), iconid)) {
+					MEM_freeN(name);
+					break;
+				}
+			}
+
+			MEM_freeN(name);
+		}
+
+		i++;
+	}
+	RNA_PROP_END;
+}
+
+static void search_id_collection(StructRNA *ptype, PointerRNA *ptr, PropertyRNA **prop)
+{
+	StructRNA *srna;
+
+	/* look for collection property in Main */
+	RNA_main_pointer_create(G.main, ptr);
+
+	*prop= NULL;
+
+	RNA_STRUCT_BEGIN(ptr, iprop) {
+		/* if it's a collection and has same pointer type, we've got it */
+		if(RNA_property_type(iprop) == PROP_COLLECTION) {
+			srna= RNA_property_pointer_type(ptr, iprop);
+
+			if(ptype == srna) {
+				*prop= iprop;
+				break;
+			}
+		}
+	}
+	RNA_STRUCT_END;
+}
+
+void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop)
+{
+	StructRNA *ptype;
+	PointerRNA sptr;
+
+	/* for ID's we do automatic lookup */
+	if(!searchprop) {
+		if(RNA_property_type(prop) == PROP_POINTER) {
+			ptype= RNA_property_pointer_type(ptr, prop);
+			search_id_collection(ptype, &sptr, &searchprop);
+			searchptr= &sptr;
+		}
+	}
+
+	/* turn button into search button */
+	if(searchprop) {
+		but->type= SEARCH_MENU;
+		but->hardmax= MAX2(but->hardmax, 256);
+		but->rnasearchpoin= *searchptr;
+		but->rnasearchprop= searchprop;
+		but->flag |= UI_ICON_LEFT|UI_TEXT_LEFT;
+
+		uiButSetSearchFunc(but, rna_search_cb, but, NULL, NULL);
+	}
+}
+
+void uiItemPointerR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, struct PointerRNA *searchptr, char *searchpropname)
+{
+	PropertyRNA *prop, *searchprop;
+	PropertyType type;
+	uiBut *but;
+	uiBlock *block;
+	StructRNA *icontype;
+	int w, h;
+	
+	/* validate arguments */
+	if(!ptr->data || !searchptr->data)
+		return;
+
+	prop= RNA_struct_find_property(ptr, propname);
+
+	if(!prop) {
+		printf("uiItemPointerR: property not found: %s\n", propname);
+		return;
+	}
+	
+	type= RNA_property_type(prop);
+	if(!ELEM(type, PROP_POINTER, PROP_STRING)) {
+		printf("uiItemPointerR: property %s must be a pointer or string.\n", propname);
+		return;
+	}
+
+	searchprop= RNA_struct_find_property(searchptr, searchpropname);
+
+	if(!searchprop || RNA_property_type(searchprop) != PROP_COLLECTION) {
+		printf("uiItemPointerR: search collection property not found: %s\n", searchpropname);
+		return;
+	}
+
+	/* get icon & name */
+	if(!icon) {
+		if(type == PROP_POINTER)
+			icontype= RNA_property_pointer_type(ptr, prop);
+		else
+			icontype= RNA_property_pointer_type(searchptr, searchprop);
+
+		icon= RNA_struct_ui_icon(icontype);
+	}
+	if(!name)
+		name= (char*)RNA_property_ui_name(prop);
+
+	/* create button */
+	block= uiLayoutGetBlock(layout);
+
+	ui_item_rna_size(layout, name, icon, prop, 0, &w, &h);
+	but= ui_item_with_label(layout, block, name, icon, ptr, prop, 0, 0, 0, w, h);
+
+	ui_but_add_search(but, ptr, prop, searchptr, searchprop);
+}
+
 /* menu item */
 static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
 {
@@ -1267,7 +1411,6 @@ static void ui_litem_layout_box(uiLayout *litem)
 	h= litem->h;
 
 	litem->x += style->boxspace;
-	litem->y -= style->boxspace;
 
 	if(w != 0) litem->w -= 2*style->boxspace;
 	if(h != 0) litem->h -= 2*style->boxspace;
@@ -1348,6 +1491,7 @@ static void ui_litem_estimate_column_flow(uiLayout *litem)
 		}
 	}
 
+	litem->w= x;
 	litem->h= litem->y - miny;
 }
 
@@ -1453,9 +1597,9 @@ static void ui_litem_layout_free(uiLayout *litem)
 	totw -= minx;
 	toth -= miny;
 
-	if(litem->w && totw > litem->w)
+	if(litem->w && totw > 0)
 		scalex= (float)litem->w/(float)totw;
-	if(litem->h && toth > litem->h)
+	if(litem->h && toth > 0)
 		scaley= (float)litem->h/(float)toth;
 	
 	x= litem->x;
@@ -1466,15 +1610,15 @@ static void ui_litem_layout_free(uiLayout *litem)
 		ui_item_size(item, &itemw, &itemh);
 
 		if(scalex != 1.0f) {
-			newx= itemx*scalex;
-			itemw= (itemx + itemw)*scalex - newx;
-			itemx= newx;
+			newx= (itemx - minx)*scalex;
+			itemw= (itemx - minx + itemw)*scalex - newx;
+			itemx= minx + newx;
 		}
 
 		if(scaley != 1.0f) {
-			newy= itemy*scaley;
-			itemh= (itemy + itemh)*scaley - newy;
-			itemy= newy;
+			newy= (itemy - miny)*scaley;
+			itemh= (itemy - miny + itemh)*scaley - newy;
+			itemy= miny + newy;
 		}
 
 		ui_item_position(item, x+itemx-minx, y+itemy-miny, itemw, itemh);
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 72076175ad5..a20884a61a3 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -104,7 +104,9 @@ static int panel_aligned(ScrArea *sa, ARegion *ar)
 		SpaceButs *sbuts= sa->spacedata.first;
 		return sbuts->align;
 	}
-	else if(ar->regiontype==RGN_TYPE_UI)
+	else if(sa->spacetype==SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS)
+		return BUT_VERTICAL;
+	else if(ELEM(ar->regiontype, RGN_TYPE_UI, RGN_TYPE_TOOLS))
 		return BUT_VERTICAL;
 	
 	return 0;
@@ -126,6 +128,8 @@ static int panels_re_align(ScrArea *sa, ARegion *ar, Panel **r_pa)
 	}
 	else if(ar->regiontype==RGN_TYPE_UI)
 		return 1;
+	else if(sa->spacetype==SPACE_FILE && ar->regiontype == RGN_TYPE_CHANNELS)
+		return 1;
 
 	/* in case panel is added or disappears */
 	for(pa=ar->panels.first; pa; pa=pa->next) {
@@ -1288,6 +1292,7 @@ int ui_handler_panel_region(bContext *C, wmEvent *event)
 
 /**************** window level modal panel interaction **************/
 
+/* note, this is modal handler and should not swallow events for animation */
 static int ui_handler_panel(bContext *C, wmEvent *event, void *userdata)
 {
 	Panel *panel= userdata;
@@ -1303,8 +1308,6 @@ static int ui_handler_panel(bContext *C, wmEvent *event, void *userdata)
 			panel_activate_state(C, panel, PANEL_STATE_ANIMATION);
 		else
 			panel_activate_state(C, panel, PANEL_STATE_EXIT);
-
-		return WM_UI_HANDLER_BREAK;
 	}
 	else if(event->type == MOUSEMOVE) {
 		if(data->state == PANEL_STATE_WAIT_UNTAB)
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 32bcae77e6b..27fb0731d67 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -40,6 +40,7 @@
 #include "BLI_dynstr.h"
 
 #include "BKE_context.h"
+#include "BKE_icons.h"
 #include "BKE_report.h"
 #include "BKE_screen.h"
 #include "BKE_texture.h"
@@ -181,7 +182,7 @@ MenuData *decompose_menu_string(char *str)
 				*s= '\0';
 				s++;
 			}
-		} else if (c=='|' || c=='\0') {
+		} else if (c=='|' || c == '\n' || c=='\0') {
 			if (nitem) {
 				*s= '\0';
 
@@ -433,7 +434,10 @@ struct uiSearchItems {
 	
 	char **names;
 	void **pointers;
-	
+	int *icons;
+
+	AutoComplete *autocpl;
+	void *active;
 };
 
 typedef struct uiSearchboxData {
@@ -448,8 +452,21 @@ typedef struct uiSearchboxData {
 
 /* exported for use by search callbacks */
 /* returns zero if nothing to add */
-int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin)
+int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int iconid)
 {
+	/* hijack for autocomplete */
+	if(items->autocpl) {
+		autocomplete_do_name(items->autocpl, name);
+		return 1;
+	}
+	
+	/* hijack for finding active item */
+	if(items->active) {
+		if(poin==items->active)
+			items->offset_i= items->totitem;
+		items->totitem++;
+		return 1;
+	}
 	
 	if(items->totitem>=items->maxitem) {
 		items->more= 1;
@@ -464,6 +481,7 @@ int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin)
 	
 	BLI_strncpy(items->names[items->totitem], name, items->maxstrlen);
 	items->pointers[items->totitem]= poin;
+	items->icons[items->totitem]= iconid;
 	
 	items->totitem++;
 	
@@ -588,20 +606,52 @@ void ui_searchbox_update(bContext *C, ARegion *ar, uiBut *but, int reset)
 	/* reset vars */
 	data->items.totitem= 0;
 	data->items.more= 0;
-	if(reset==0)
+	if(reset==0) {
 		data->items.offset_i= data->items.offset;
+	}
 	else {
 		data->items.offset_i= data->items.offset= 0;
 		data->active= 0;
+		
+		/* handle active */
+		if(but->search_func && but->func_arg2) {
+			data->items.active= but->func_arg2;
+			but->search_func(C, but->search_arg, but->editstr, &data->items);
+			data->items.active= NULL;
+			
+			/* found active item, calculate real offset by centering it */
+			if(data->items.totitem) {
+				/* first case, begin of list */
+				if(data->items.offset_i < data->items.maxitem) {
+					data->active= data->items.offset_i+1;
+					data->items.offset_i= 0;
+				}
+				else {
+					/* second case, end of list */
+					if(data->items.totitem - data->items.offset_i <= data->items.maxitem) {
+						data->active= 1 + data->items.offset_i - data->items.totitem + data->items.maxitem;
+						data->items.offset_i= data->items.totitem - data->items.maxitem;
+					}
+					else {
+						/* center active item */
+						data->items.offset_i -= data->items.maxitem/2;
+						data->active= 1 + data->items.maxitem/2;
+					}
+				}
+			}
+			data->items.offset= data->items.offset_i;
+			data->items.totitem= 0;
+		}
 	}
 	
 	/* callback */
 	if(but->search_func)
 		but->search_func(C, but->search_arg, but->editstr, &data->items);
 	
-	if(reset) {
+	/* handle case where editstr is equal to one of items */
+	if(reset && data->active==0) {
 		int a;
-		/* handle case where editstr is equal to one of items */
+		
 		for(a=0; aitems.totitem; a++) {
 			char *cpoin= strchr(data->items.names[a], '|');
 			
@@ -620,6 +670,18 @@ void ui_searchbox_update(bContext *C, ARegion *ar, uiBut *but, int reset)
 	ED_region_tag_redraw(ar);
 }
 
+void ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str)
+{
+	uiSearchboxData *data= ar->regiondata;
+
+	data->items.autocpl= autocomplete_begin(str, ui_get_but_string_max_length(but));
+
+	but->search_func(C, but->search_arg, but->editstr, &data->items);
+
+	autocomplete_end(data->items.autocpl, str);
+	data->items.autocpl= NULL;
+}
+
 static void ui_searchbox_region_draw(const bContext *C, ARegion *ar)
 {
 	uiSearchboxData *data= ar->regiondata;
@@ -639,18 +701,21 @@ static void ui_searchbox_region_draw(const bContext *C, ARegion *ar)
 		for(a=0; aitems.totitem; a++) {
 			ui_searchbox_butrect(&rect, data, a);
 			
-			ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], (a+1)==data->active?UI_ACTIVE:0);
+			/* widget itself */
+			ui_draw_menu_item(&data->fstyle, &rect, data->items.names[a], data->items.icons[a], (a+1)==data->active?UI_ACTIVE:0);
 			
 		}
 		/* indicate more */
 		if(data->items.more) {
+			ui_searchbox_butrect(&rect, data, data->items.maxitem-1);
 			glEnable(GL_BLEND);
-			UI_icon_draw((data->bbox.xmax-data->bbox.xmin)/2, 8, ICON_TRIA_DOWN);
+			UI_icon_draw((rect.xmax-rect.xmin)/2, rect.ymin-9, ICON_TRIA_DOWN);
 			glDisable(GL_BLEND);
 		}
 		if(data->items.offset) {
+			ui_searchbox_butrect(&rect, data, 0);
 			glEnable(GL_BLEND);
-			UI_icon_draw((data->bbox.xmax-data->bbox.xmin)/2, data->bbox.ymax-13, ICON_TRIA_UP);
+			UI_icon_draw((rect.xmax-rect.xmin)/2, rect.ymax-7, ICON_TRIA_UP);
 			glDisable(GL_BLEND);
 		}
 	}
@@ -666,6 +731,7 @@ static void ui_searchbox_region_free(ARegion *ar)
 		MEM_freeN(data->items.names[a]);
 	MEM_freeN(data->items.names);
 	MEM_freeN(data->items.pointers);
+	MEM_freeN(data->items.icons);
 	
 	MEM_freeN(data);
 	ar->regiondata= NULL;
@@ -679,7 +745,7 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
 	uiSearchboxData *data;
 	float aspect= but->block->aspect;
 	float x1f, x2f, y1f, y2f;
-	int x1, x2, y1, y2, winx, winy;
+	int x1, x2, y1, y2, winx, winy, ofsx, ofsy;
 	
 	/* create area region */
 	ar= ui_add_temporary_region(CTX_wm_screen(C));
@@ -732,6 +798,14 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
 		x2f= but->x2 + 5;	/* symmetrical */
 		y2f= but->y1;
 		y1f= y2f - uiSearchBoxhHeight();
+
+		ofsx= (but->block->panel)? but->block->panel->ofsx: 0;
+		ofsy= (but->block->panel)? but->block->panel->ofsy: 0;
+
+		x1f += ofsx;
+		x2f += ofsx;
+		y1f += ofsy;
+		y2f += ofsy;
 	
 		/* minimal width */
 		if(x2f - x1f < 150) x2f= x1f+150; // XXX arbitrary
@@ -794,6 +868,7 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
 	data->items.totitem= 0;
 	data->items.names= MEM_callocN(SEARCH_ITEMS*sizeof(void *), "search names");
 	data->items.pointers= MEM_callocN(SEARCH_ITEMS*sizeof(void *), "search pointers");
+	data->items.icons= MEM_callocN(SEARCH_ITEMS*sizeof(int), "search icons");
 	for(x1=0; x1items.names[x1]= MEM_callocN(but->hardmax+1, "search pointers");
 	
@@ -1720,24 +1795,118 @@ static void do_picker_small_cb(bContext *C, void *bt1, void *hsv1)
 		popup->menuretval= UI_RETURN_UPDATE;
 }
 
+/* picker sizes S hsize, F full size, D spacer, B button/pallette height  */
+#define SPICK1	150.0
+#define DPICK1	6.0
 
-/* only the color, a circle, slider */
-void uiBlockPickerSmall(uiBlock *block, float *col, float *hsv, float *old, char *hexcol, char mode, short retval)
+/* only the color, a HS circle and V slider */
+static void uiBlockPickerSmall(uiBlock *block, float *col, float *hsv, float *old, char *hexcol, char mode, short retval)
 {
 	uiBut *bt;
 	
 	VECCOPY(old, col);	// old color stored there, for palette_cb to work
 	
 	/* HS circle */
-	bt= uiDefButF(block, HSVCIRCLE, retval, "",	0, 0,SPICK,SPICK, col, 0.0, 0.0, 0, 0, "");
+	bt= uiDefButF(block, HSVCIRCLE, retval, "",	0, 0,SPICK1,SPICK1, col, 0.0, 0.0, 0, 0, "");
 	uiButSetFunc(bt, do_picker_small_cb, bt, hsv);
 
 	/* value */
-	bt= uiDefButF(block, HSVCUBE, retval, "",	SPICK+DPICK,0,14,SPICK, col, 0.0, 0.0, 4, 0, "");
+	bt= uiDefButF(block, HSVCUBE, retval, "",	SPICK1+DPICK1,0,14,SPICK1, col, 0.0, 0.0, 4, 0, "");
 	uiButSetFunc(bt, do_picker_small_cb, bt, hsv);
-
 }
 
+
+static void picker_new_hide_reveal(uiBlock *block, short colormode)
+{
+	uiBut *bt;
+	
+	/* tag buttons */
+	for(bt= block->buttons.first; bt; bt= bt->next) {
+		
+		if(bt->type==NUMSLI || bt->type==TEX) {
+			if( bt->str[1]=='e') {
+				if(colormode==2) bt->flag &= ~UI_HIDDEN;
+				else bt->flag |= UI_HIDDEN;
+			}
+			else if( ELEM3(bt->str[0], 'R', 'G', 'B')) {
+				if(colormode==0) bt->flag &= ~UI_HIDDEN;
+				else bt->flag |= UI_HIDDEN;
+			}
+			else if( ELEM3(bt->str[0], 'H', 'S', 'V')) {
+				if(colormode==1) bt->flag &= ~UI_HIDDEN;
+				else bt->flag |= UI_HIDDEN;
+			}
+		}
+	}
+}
+
+static void do_picker_new_mode_cb(bContext *C, void *bt1, void *colv)
+{
+	uiBut *bt= bt1;
+	short colormode= ui_get_but_val(bt);
+
+	picker_new_hide_reveal(bt->block, colormode);
+}
+
+
+/* a HS circle, V slider, rgb/hsv/hex sliders */
+static void uiBlockPickerNew(uiBlock *block, float *col, float *hsv, float *old, char *hexcol, char mode, short retval)
+{
+	static short colormode= 0;	/* temp? 0=rgb, 1=hsv, 2=hex */
+	uiBut *bt;
+	int width;
+	
+	VECCOPY(old, col);	// old color stored there, for palette_cb to work
+	
+	/* HS circle */
+	bt= uiDefButF(block, HSVCIRCLE, retval, "",	0, 0,SPICK1,SPICK1, col, 0.0, 0.0, 0, 0, "");
+	uiButSetFunc(bt, do_picker_small_cb, bt, hsv);
+	
+	/* value */
+	bt= uiDefButF(block, HSVCUBE, retval, "",	SPICK1+DPICK1,0,14,SPICK1, col, 0.0, 0.0, 4, 0, "");
+	uiButSetFunc(bt, do_picker_small_cb, bt, hsv);
+	
+	/* mode */
+	width= (SPICK1+DPICK1+14)/3;
+	uiBlockBeginAlign(block);
+	bt= uiDefButS(block, ROW, retval, "RGB",	0, -30, width, 19, &colormode, 0.0, 0.0, 0, 0, "");
+	uiButSetFunc(bt, do_picker_new_mode_cb, bt, col);
+	bt= uiDefButS(block, ROW, retval, "HSV",	width, -30, width, 19, &colormode, 0.0, 1.0, 0, 0, "");
+	uiButSetFunc(bt, do_picker_new_mode_cb, bt, hsv);
+	bt= uiDefButS(block, ROW, retval, "Hex",	2*width, -30, width, 19, &colormode, 0.0, 2.0, 0, 0, "");
+	uiButSetFunc(bt, do_picker_new_mode_cb, bt, hexcol);
+	uiBlockEndAlign(block);
+	
+	/* sliders or hex */
+	width= (SPICK1+DPICK1+14);
+	rgb_to_hsv(col[0], col[1], col[2], hsv, hsv+1, hsv+2);
+	sprintf(hexcol, "%02X%02X%02X", (unsigned int)(col[0]*255.0), (unsigned int)(col[1]*255.0), (unsigned int)(col[2]*255.0));	
+
+	uiBlockBeginAlign(block);
+	bt= uiDefButF(block, NUMSLI, 0, "R ",	0, -60, width, 19, col, 0.0, 1.0, 10, 3, "");
+	uiButSetFunc(bt, do_palette1_cb, bt, hsv);
+	bt= uiDefButF(block, NUMSLI, 0, "G ",	0, -80, width, 19, col+1, 0.0, 1.0, 10, 3, "");
+	uiButSetFunc(bt, do_palette1_cb, bt, hsv);
+	bt= uiDefButF(block, NUMSLI, 0, "B ",	0, -100, width, 19, col+2, 0.0, 1.0, 10, 3, "");
+	uiButSetFunc(bt, do_palette1_cb, bt, hsv);
+	uiBlockEndAlign(block);
+
+	uiBlockBeginAlign(block);
+	bt= uiDefButF(block, NUMSLI, 0, "H ",	0, -60, width, 19, hsv, 0.0, 1.0, 10, 3, "");
+	uiButSetFunc(bt, do_palette2_cb, bt, col);
+	bt= uiDefButF(block, NUMSLI, 0, "S ",	0, -80, width, 19, hsv+1, 0.0, 1.0, 10, 3, "");
+	uiButSetFunc(bt, do_palette2_cb, bt, col);
+	bt= uiDefButF(block, NUMSLI, 0, "V ",	0, -100, width, 19, hsv+2, 0.0, 1.0, 10, 3, "");
+	uiButSetFunc(bt, do_palette2_cb, bt, col);
+	uiBlockEndAlign(block);
+
+	bt= uiDefBut(block, TEX, 0, "Hex: ", 0, -80, width, 19, hexcol, 0, 8, 0, 0, "Hex triplet for color (#RRGGBB)");
+	uiButSetFunc(bt, do_palette_hex_cb, bt, hexcol);
+
+	picker_new_hide_reveal(block, colormode);
+}
+
+
 static int ui_picker_small_wheel(const bContext *C, uiBlock *block, wmEvent *event)
 {
 	float add= 0.0f;
@@ -1790,13 +1959,22 @@ uiBlock *ui_block_func_COL(bContext *C, uiPopupBlockHandle *handle, void *arg_bu
 		block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_KEEP_OPEN;
 		uiBoundsBlock(block, 3);
 	}
-	else {
+	else if(win->eventstate->alt) {
 		uiBlockPickerSmall(block, handle->retvec, hsvcol, oldcol, hexcol, 'p', 0);
 		block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1|UI_BLOCK_OUT_1;
 		uiBoundsBlock(block, 10);
 		
 		block->block_event_func= ui_picker_small_wheel;
-	}		
+	}
+	else {
+		uiBlockPickerNew(block, handle->retvec, hsvcol, oldcol, hexcol, 'p', 0);
+		block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_KEEP_OPEN;
+		uiBoundsBlock(block, 10);
+		
+		block->block_event_func= ui_picker_small_wheel;
+	}
+	
+	
 	/* and lets go */
 	block->direction= UI_TOP;
 	
@@ -2464,7 +2642,6 @@ static uiPopupBlockHandle *ui_pup_menu(bContext *C, int maxrow, uiMenuHandleFunc
 	return menu;
 }
 
-
 static void operator_name_cb(bContext *C, void *arg, int retval)
 {
 	const char *opname= arg;
@@ -2585,6 +2762,8 @@ void uiPupMenuReports(bContext *C, ReportList *reports)
 			BLI_dynstr_appendf(ds, "Error %%i%d%%t|%s", ICON_ERROR, report->message);
 		else if(report->type >= RPT_WARNING)
 			BLI_dynstr_appendf(ds, "Warning %%i%d%%t|%s", ICON_ERROR, report->message);
+		else if(report->type >= RPT_INFO)
+			BLI_dynstr_appendf(ds, "Info %%t|%s", report->message);
 	}
 
 	str= BLI_dynstr_get_cstring(ds);
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index 831a8a5bf6c..e8fba38f793 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -92,6 +92,7 @@ static uiStyle *ui_style_new(ListBase *styles, const char *name)
 	style->paneltitle.uifont_id= UIFONT_DEFAULT;
 	style->paneltitle.points= 13;
 	style->paneltitle.kerning= 0.0;
+	style->paneltitle.overlap= 0;
 	style->paneltitle.shadow= 5;
 	style->paneltitle.shadx= 2;
 	style->paneltitle.shady= -2;
@@ -101,6 +102,7 @@ static uiStyle *ui_style_new(ListBase *styles, const char *name)
 	style->grouplabel.uifont_id= UIFONT_DEFAULT;
 	style->grouplabel.points= 12;
 	style->grouplabel.kerning= 0.0;
+	style->grouplabel.overlap= 0;
 	style->grouplabel.shadow= 3;
 	style->grouplabel.shadx= 1;
 	style->grouplabel.shady= -1;
@@ -109,6 +111,7 @@ static uiStyle *ui_style_new(ListBase *styles, const char *name)
 	style->widgetlabel.uifont_id= UIFONT_DEFAULT;
 	style->widgetlabel.points= 11;
 	style->widgetlabel.kerning= 0.0;
+	style->widgetlabel.overlap= 0;
 	style->widgetlabel.shadow= 3;
 	style->widgetlabel.shadx= 1;
 	style->widgetlabel.shady= -1;
@@ -145,22 +148,6 @@ static uiFont *uifont_to_blfont(int id)
 
 /* *************** draw ************************ */
 
-static void ui_font_shadow_draw(uiFontStyle *fs, int x, int y, char *str)
-{
-	float color[4];
-	
-	glGetFloatv(GL_CURRENT_COLOR, color);
-	
-	glColor4f(fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha);
-	
-	BLF_blur(fs->shadow);
-	BLF_position(x+fs->shadx, y+fs->shady, 0.0f);
-	BLF_draw(str);
-	BLF_blur(0);
-	
-	glColor4fv(color);
-}
-
 void uiStyleFontDraw(uiFontStyle *fs, rcti *rect, char *str)
 {
 	float height;
@@ -179,14 +166,23 @@ void uiStyleFontDraw(uiFontStyle *fs, rcti *rect, char *str)
 	/* clip is very strict, so we give it some space */
 	BLF_clipping(rect->xmin-1, rect->ymin-4, rect->xmax+1, rect->ymax+4);
 	BLF_enable(BLF_CLIPPING);
-	
-	if(fs->shadow) 
-		ui_font_shadow_draw(fs, rect->xmin+xofs, rect->ymin+yofs, str);
-	
 	BLF_position(rect->xmin+xofs, rect->ymin+yofs, 0.0f);
-	BLF_draw(str);
 
+	if (fs->shadow) {
+		BLF_enable(BLF_SHADOW);
+		BLF_shadow(fs->shadow, fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha);
+		BLF_shadow_offset(fs->shadx, fs->shady);
+	}
+
+	if (fs->overlap)
+		BLF_enable(BLF_OVERLAP_CHAR);
+
+	BLF_draw(str);
 	BLF_disable(BLF_CLIPPING);
+	if (fs->shadow)
+		BLF_disable(BLF_SHADOW);
+	if (fs->overlap)
+		BLF_disable(BLF_OVERLAP_CHAR);
 }
 
 /* ************** helpers ************************ */
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 15c0619e4e1..8f1d57b28ed 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -1,5 +1,5 @@
 /**
- * $Id: interface_templates.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -27,9 +27,14 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
 #include "BLI_string.h"
 
 #include "BKE_context.h"
+#include "BKE_icons.h"
+#include "BKE_global.h"
 #include "BKE_library.h"
 #include "BKE_utildefines.h"
 
@@ -43,6 +48,7 @@
 
 #include "UI_interface.h"
 #include "UI_resources.h"
+#include "interface_intern.h"
 
 void ui_template_fix_linking()
 {
@@ -58,22 +64,93 @@ void uiTemplateHeader(uiLayout *layout, bContext *C)
 	ED_area_header_standardbuttons(C, block, 0);
 }
 
-/******************* Header ID Template ************************/
+/********************** Search Callbacks *************************/
 
 typedef struct TemplateID {
 	PointerRNA ptr;
 	PropertyRNA *prop;
 
-	int flag;
-	short browse;
-
-	char newop[256];
-	char openop[256];
-	char unlinkop[256];
-	
-	short idtype;
+	ListBase *idlb;
 } TemplateID;
 
+/* Search browse menu, assign  */
+static void id_search_call_cb(struct bContext *C, void *arg_template, void *item)
+{
+	TemplateID *template= (TemplateID*)arg_template;
+
+	/* ID */
+	if(item) {
+		PointerRNA idptr;
+
+		RNA_id_pointer_create(item, &idptr);
+		RNA_property_pointer_set(&template->ptr, template->prop, idptr);
+		RNA_property_update(C, &template->ptr, template->prop);
+	}
+}
+
+/* ID Search browse menu, do the search */
+static void id_search_cb(const struct bContext *C, void *arg_template, char *str, uiSearchItems *items)
+{
+	TemplateID *template= (TemplateID*)arg_template;
+	Scene *scene= CTX_data_scene(C);
+	ListBase *lb= template->idlb;
+	ID *id;
+	int iconid;
+
+	/* ID listbase */
+	for(id= lb->first; id; id= id->next) {
+		iconid= ui_id_icon_get(scene, id);
+
+		if(BLI_strcasestr(id->name+2, str))
+			if(!uiSearchItemAdd(items, id->name+2, id, iconid))
+				break;
+	}
+}
+
+/* ID Search browse menu, open */
+static uiBlock *search_menu(bContext *C, ARegion *ar, void *arg_litem)
+{
+	static char search[256];
+	static TemplateID template;
+	PointerRNA idptr;
+	wmEvent event;
+	wmWindow *win= CTX_wm_window(C);
+	uiBlock *block;
+	uiBut *but;
+	
+	/* clear initial search string, then all items show */
+	search[0]= 0;
+	/* arg_litem is malloced, can be freed by parent button */
+	template= *((TemplateID*)arg_litem);
+	
+	/* get active id for showing first item */
+	idptr= RNA_property_pointer_get(&template.ptr, template.prop);
+
+	block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
+	uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
+	
+	/* fake button, it holds space for search items */
+	uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
+	
+	but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, "");
+	uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
+	
+	uiBoundsBlock(block, 6);
+	uiBlockSetDirection(block, UI_DOWN);	
+	uiEndBlock(C, block);
+	
+	event= *(win->eventstate);	/* XXX huh huh? make api call */
+	event.type= EVT_BUT_OPEN;
+	event.val= KM_PRESS;
+	event.customdata= but;
+	event.customdatafree= FALSE;
+	wm_event_add(win, &event);
+	
+	return block;
+}
+
+/************************ ID Template ***************************/
+
 static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
 {
 	TemplateID *template= (TemplateID*)arg_litem;
@@ -81,14 +158,18 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
 	ID *id= idptr.data;
 	int event= GET_INT_FROM_POINTER(arg_event);
 	
-	if(event == UI_ID_BROWSE && template->browse == 32767)
-		event= UI_ID_ADD_NEW;
-	else if(event == UI_ID_BROWSE && template->browse == 32766)
-		event= UI_ID_OPEN;
-
 	switch(event) {
 		case UI_ID_BROWSE:
-			printf("warning, id browse shouldnt come here\n");
+		case UI_ID_PIN:
+			printf("warning, id event %d shouldnt come here\n", event);
+			break;
+		case UI_ID_OPEN:
+		case UI_ID_ADD_NEW:
+			if(template->idlb->last) {
+				RNA_id_pointer_create(template->idlb->last, &idptr);
+				RNA_property_pointer_set(&template->ptr, template->prop, idptr);
+				RNA_property_update(C, &template->ptr, template->prop);
+			}
 			break;
 		case UI_ID_DELETE:
 			memset(&idptr, 0, sizeof(idptr));
@@ -102,14 +183,6 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
 			}
 			else return;
 			break;
-		case UI_ID_PIN:
-			break;
-		case UI_ID_ADD_NEW:
-			WM_operator_name_call(C, template->newop, WM_OP_INVOKE_REGION_WIN, NULL);
-			break;
-		case UI_ID_OPEN:
-			WM_operator_name_call(C, template->openop, WM_OP_INVOKE_REGION_WIN, NULL);
-			break;
 #if 0
 		case UI_ID_ALONE:
 			if(!id || id->us < 1)
@@ -125,114 +198,24 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
 	}
 }
 
-/* ID Search browse menu, assign  */
-static void id_search_call_cb(struct bContext *C, void *arg_litem, void *item)
-{
-	if(item) {
-		TemplateID *template= (TemplateID*)arg_litem;
-		PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop);
-
-		RNA_id_pointer_create(item, &idptr);
-		RNA_property_pointer_set(&template->ptr, template->prop, idptr);
-		RNA_property_update(C, &template->ptr, template->prop);
-	}	
-}
-
-/* ID Search browse menu, do the search */
-static void id_search_cb(const struct bContext *C, void *arg_litem, char *str, uiSearchItems *items)
-{
-	TemplateID *template= (TemplateID*)arg_litem;
-	ListBase *lb= wich_libbase(CTX_data_main(C), template->idtype);
-	ID *id;
-	
-	for(id= lb->first; id; id= id->next) {
-		
-		if(BLI_strcasestr(id->name+2, str)) {
-			if(0==uiSearchItemAdd(items, id->name+2, id))
-				break;
-		}
-	}
-}
-
-/* ID Search browse menu, open */
-static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
-{
-	static char search[256];
-	static TemplateID template;
-	wmEvent event;
-	wmWindow *win= CTX_wm_window(C);
-	uiBlock *block;
-	uiBut *but;
-	
-	/* clear initial search string, then all items show */
-	search[0]= 0;
-	/* arg_litem is malloced, can be freed by parent button */
-	template= *((TemplateID*)arg_litem);
-	
-	block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
-	uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
-	
-	/* fake button, it holds space for search items */
-	uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
-	
-	but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, "");
-	uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb);
-	
-	uiBoundsBlock(block, 6);
-	uiBlockSetDirection(block, UI_DOWN);	
-	uiEndBlock(C, block);
-	
-	event= *(win->eventstate);	/* XXX huh huh? make api call */
-	event.type= EVT_BUT_OPEN;
-	event.val= KM_PRESS;
-	event.customdata= but;
-	event.customdatafree= FALSE;
-	wm_event_add(win, &event);
-	
-	return block;
-}
-
-/* ****************** */
-
-
-static void template_header_ID(bContext *C, uiBlock *block, TemplateID *template, StructRNA *type)
+static void template_ID(bContext *C, uiBlock *block, TemplateID *template, StructRNA *type, int flag, char *newop, char *unlinkop)
 {
 	uiBut *but;
 	PointerRNA idptr;
 	ListBase *lb;
 
 	idptr= RNA_property_pointer_get(&template->ptr, template->prop);
-	lb= wich_libbase(CTX_data_main(C), template->idtype);
+	lb= template->idlb;
+
+	uiBlockBeginAlign(block);
 
 	if(idptr.type)
 		type= idptr.type;
 	if(type)
 		uiDefIconBut(block, LABEL, 0, RNA_struct_ui_icon(type), 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
 
-	uiBlockBeginAlign(block);
-	if(template->flag & UI_ID_BROWSE) {
-		/*
-		char *extrastr, *str;
-		
-		if((template->flag & UI_ID_ADD_NEW) && (template->flag & UI_ID_OPEN))
-			extrastr= "OPEN NEW %x 32766 |ADD NEW %x 32767";
-		else if(template->flag & UI_ID_ADD_NEW)
-			extrastr= "ADD NEW %x 32767";
-		else if(template->flag & UI_ID_OPEN)
-			extrastr= "OPEN NEW %x 32766";
-		else
-			extrastr= NULL;
-
-		duptemplate= MEM_dupallocN(template);
-		IDnames_to_pupstring(&str, NULL, extrastr, lb, idptr.data, &duptemplate->browse);
-
-		but= uiDefButS(block, MENU, 0, str, 0, 0, UI_UNIT_X, UI_UNIT_Y, &duptemplate->browse, 0, 0, 0, 0, "Browse existing choices, or add new");
-		uiButSetNFunc(but, template_id_cb, duptemplate, SET_INT_IN_POINTER(UI_ID_BROWSE));
-	
-		MEM_freeN(str);
-		*/
-		uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X, UI_UNIT_Y, "Browse ID data");
-	}
+	if(flag & UI_ID_BROWSE)
+		uiDefBlockButN(block, search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X, UI_UNIT_Y, "Browse ID data");
 
 	/* text button with name */
 	if(idptr.data) {
@@ -244,11 +227,12 @@ static void template_header_ID(bContext *C, uiBlock *block, TemplateID *template
 		uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
 	}
 	
-	if(template->flag & UI_ID_ADD_NEW) {
+	if(flag & UI_ID_ADD_NEW) {
 		int w= idptr.data?UI_UNIT_X:UI_UNIT_X*6;
 		
-		if(template->newop[0]) {
-			but= uiDefIconTextButO(block, BUT, template->newop, WM_OP_EXEC_REGION_WIN, ICON_ZOOMIN, "Add New", 0, 0, w, UI_UNIT_Y, NULL);
+		if(newop) {
+			but= uiDefIconTextButO(block, BUT, newop, WM_OP_EXEC_REGION_WIN, ICON_ZOOMIN, "Add New", 0, 0, w, UI_UNIT_Y, NULL);
+			uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
 		}
 		else {
 			but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, "Add New", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
@@ -257,9 +241,9 @@ static void template_header_ID(bContext *C, uiBlock *block, TemplateID *template
 	}
 	
 	/* delete button */
-	if(idptr.data && (template->flag & UI_ID_DELETE)) {
-		if(template->unlinkop[0]) {
-			but= uiDefIconButO(block, BUT, template->unlinkop, WM_OP_EXEC_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+	if(idptr.data && (flag & UI_ID_DELETE)) {
+		if(unlinkop) {
+			but= uiDefIconButO(block, BUT, unlinkop, WM_OP_EXEC_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
 		}
 		else {
 			but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
@@ -270,12 +254,13 @@ static void template_header_ID(bContext *C, uiBlock *block, TemplateID *template
 	uiBlockEndAlign(block);
 }
 
-void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop)
+void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *unlinkop)
 {
 	TemplateID *template;
 	uiBlock *block;
 	PropertyRNA *prop;
 	StructRNA *type;
+	int flag;
 
 	if(!ptr->data)
 		return;
@@ -290,26 +275,19 @@ void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname
 	template= MEM_callocN(sizeof(TemplateID), "TemplateID");
 	template->ptr= *ptr;
 	template->prop= prop;
-	template->flag= UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE;
 
-	if(newop) {
-		template->flag |= UI_ID_ADD_NEW;
-		BLI_strncpy(template->newop, newop, sizeof(template->newop));
-	}
-	if(openop) {
-		template->flag |= UI_ID_OPEN;
-		BLI_strncpy(template->openop, openop, sizeof(template->openop));
-	}
-	if(unlinkop)
-		BLI_strncpy(template->unlinkop, unlinkop, sizeof(template->unlinkop));
+	flag= UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE;
+
+	if(newop)
+		flag |= UI_ID_ADD_NEW;
 
 	type= RNA_property_pointer_type(ptr, prop);
-	template->idtype = RNA_type_to_ID_code(type);
+	template->idlb= wich_libbase(CTX_data_main(C), RNA_type_to_ID_code(type));
 
-	if(template->idtype) {
+	if(template->idlb) {
 		uiLayoutRow(layout, 1);
 		block= uiLayoutGetBlock(layout);
-		template_header_ID(C, block, template, type);
+		template_ID(C, block, template, type, flag, newop, unlinkop);
 	}
 
 	MEM_freeN(template);
@@ -362,6 +340,15 @@ static void modifiers_del(bContext *C, void *ob_v, void *md_v)
 	BKE_reports_clear(&reports);
 }
 
+static void modifiers_activate(bContext *C, void *ob_v, void *md_v)
+{
+	Scene *scene= CTX_data_scene(C);
+	Object *ob= ob_v;
+
+	WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
+	DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+}
+
 static void modifiers_moveUp(bContext *C, void *ob_v, void *md_v)
 {
 	Scene *scene= CTX_data_scene(C);
@@ -555,7 +542,10 @@ static uiLayout *draw_modifier(uiLayout *layout, Object *ob, ModifierData *md, i
 		uiBlockSetEmboss(block, UI_EMBOSSN);
 		uiDefIconButBitI(block, ICONTOG, eModifierMode_Expanded, 0, ICON_TRIA_RIGHT, 0, 0, UI_UNIT_X, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, "Collapse/Expand Modifier");
 	}
-
+	
+	/* modifier-type icon */
+	uiDefIconBut(block, BUT, 0, RNA_struct_ui_icon(ptr.type), 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Current Modifier Type");
+	
 	uiBlockSetEmboss(block, UI_EMBOSS);
 	
 	if (isVirtual) {
@@ -566,14 +556,16 @@ static uiLayout *draw_modifier(uiLayout *layout, Object *ob, ModifierData *md, i
 		uiButSetFunc(but, modifiers_convertToReal, ob, md);
 	} else {
 		uiBlockBeginAlign(block);
-		uiDefBut(block, TEX, 0, "", 0, 0, buttonWidth-60, UI_UNIT_Y, md->name, 0.0, sizeof(md->name)-1, 0.0, 0.0, "Modifier name"); 
+		uiDefBut(block, TEX, 0, "", 0, 0, buttonWidth-40, UI_UNIT_Y, md->name, 0.0, sizeof(md->name)-1, 0.0, 0.0, "Modifier name"); 
 
 		/* Softbody not allowed in this situation, enforce! */
 		if (((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) && (md->type!=eModifierType_Surface)) {
 			uiDefIconButBitI(block, TOG, eModifierMode_Render, 0, ICON_SCENE, 0, 0, 19, UI_UNIT_Y,&md->mode, 0, 0, 1, 0, "Enable modifier during rendering");
 			but= uiDefIconButBitI(block, TOG, eModifierMode_Realtime, 0, ICON_VIEW3D, 0, 0, 19, UI_UNIT_Y,&md->mode, 0, 0, 1, 0, "Enable modifier during interactive display");
+			uiButSetFunc(but, modifiers_activate, ob, md);
 			if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
-				uiDefIconButBitI(block, TOG, eModifierMode_Editmode, 0, ICON_EDITMODE_HLT, 0, 0, 19, UI_UNIT_Y,&md->mode, 0, 0, 1, 0, "Enable modifier during Editmode (only if enabled for display)");
+				but= uiDefIconButBitI(block, TOG, eModifierMode_Editmode, 0, ICON_EDITMODE_HLT, 0, 0, 19, UI_UNIT_Y,&md->mode, 0, 0, 1, 0, "Enable modifier during Editmode (only if enabled for display)");
+				uiButSetFunc(but, modifiers_activate, ob, md);
 			}
 		}
 		uiBlockEndAlign(block);
@@ -1490,3 +1482,264 @@ void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, char *propname)
 		}
 	}
 }
+
+
+/************************* List Template **************************/
+
+ListBase uiTemplateList(uiLayout *layout, PointerRNA *ptr, char *propname, PointerRNA *activeptr, char *activepropname, int rows, int columns, int compact)
+{
+	CollectionPointerLink *link;
+	PropertyRNA *prop= NULL, *activeprop;
+	PropertyType type, activetype;
+	uiLayout *box, *row, *col;
+	uiBlock *block;
+	uiBut *but;
+	Panel *pa;
+	ListBase lb;
+	char *name, str[32];
+	int i= 0, activei= 0, len, items, found, min, max;
+
+	lb.first= lb.last= NULL;
+	
+	/* validate arguments */
+	block= uiLayoutGetBlock(layout);
+	pa= block->panel;
+
+	if(!pa) {
+		printf("uiTemplateList: only works inside a panel.\n");
+		return lb;
+	}
+
+	if(!activeptr->data)
+		return lb;
+	
+	if(ptr->data) {
+		prop= RNA_struct_find_property(ptr, propname);
+		if(!prop) {
+			printf("uiTemplateList: property not found: %s\n", propname);
+			return lb;
+		}
+	}
+
+	activeprop= RNA_struct_find_property(activeptr, activepropname);
+	if(!activeprop) {
+		printf("uiTemplateList: property not found: %s\n", activepropname);
+		return lb;
+	}
+
+	if(prop) {
+		type= RNA_property_type(prop);
+		if(type != PROP_COLLECTION) {
+			printf("uiTemplateList: expected collection property.\n");
+			return lb;
+		}
+	}
+
+	activetype= RNA_property_type(activeprop);
+	if(activetype != PROP_INT) {
+		printf("uiTemplateList: expected integer property.\n");
+		return lb;
+	}
+
+	/* get active data */
+	activei= RNA_property_int_get(activeptr, activeprop);
+
+	if(compact) {
+		/* compact layout */
+		found= 0;
+
+		row= uiLayoutRow(layout, 1);
+
+		if(ptr->data && prop) {
+			/* create list items */
+			RNA_PROP_BEGIN(ptr, itemptr, prop) {
+				found= (activei == i);
+
+				if(found) {
+					/* create button */
+					name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
+					if(name) {
+						uiItemL(row, name, RNA_struct_ui_icon(itemptr.type));
+						MEM_freeN(name);
+					}
+
+					/* add to list to return */
+					link= MEM_callocN(sizeof(CollectionPointerLink), "uiTemplateList return");
+					link->ptr= itemptr;
+					BLI_addtail(&lb, link);
+				}
+
+				i++;
+			}
+			RNA_PROP_END;
+		}
+
+		/* if not found, add in dummy button */
+		if(i == 0)
+			uiItemL(row, "", 0);
+
+		/* next/prev button */
+		sprintf(str, "%d :", i);
+		but= uiDefIconTextButR(block, NUM, 0, 0, str, 0,0,UI_UNIT_X*5,UI_UNIT_Y, activeptr, activepropname, 0, 0, 0, 0, 0, "");
+		if(i == 0)
+			uiButSetFlag(but, UI_BUT_DISABLED);
+	}
+	else {
+		/* default rows/columns */
+		if(rows == 0)
+			rows= 5;
+		if(columns == 0)
+			columns= 1;
+
+		/* layout */
+		box= uiLayoutBox(layout);
+		row= uiLayoutRow(box, 0);
+		col = uiLayoutColumn(row, 1);
+
+		uiBlockSetEmboss(block, UI_EMBOSSN);
+
+		/* init numbers */
+		RNA_property_int_range(activeptr, activeprop, &min, &max);
+
+		len= max - min + 1;
+		items= rows*columns;
+
+		pa->list_scroll= MIN2(pa->list_scroll, len-items);
+		pa->list_scroll= MAX2(pa->list_scroll, 0);
+
+		if(ptr->data && prop) {
+			/* create list items */
+			RNA_PROP_BEGIN(ptr, itemptr, prop) {
+				if(i >= pa->list_scroll && ilist_scroll+items) {
+					name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
+
+					if(name) {
+						/* create button */
+						but= uiDefIconTextButR(block, ROW, 0, RNA_struct_ui_icon(itemptr.type), name, 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, "");
+						uiButSetFlag(but, UI_ICON_LEFT|UI_TEXT_LEFT);
+
+						MEM_freeN(name);
+					}
+
+					/* add to list to return */
+					link= MEM_callocN(sizeof(CollectionPointerLink), "uiTemplateList return");
+					link->ptr= itemptr;
+					BLI_addtail(&lb, link);
+				}
+
+				i++;
+			}
+			RNA_PROP_END;
+		}
+
+		/* add dummy buttons to fill space */
+		while(i < pa->list_scroll+items) {
+			if(i >= pa->list_scroll)
+				uiItemL(col, "", 0);
+			i++;
+		}
+
+		uiBlockSetEmboss(block, UI_EMBOSS);
+
+		/* add scrollbar */
+		if(len > items) {
+			col= uiLayoutColumn(row, 0);
+			uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*0.75,UI_UNIT_Y*items, &pa->list_scroll, 0, len-items, items, 0, "");
+		}
+	}
+
+	/* return items in list */
+	return lb;
+}
+
+/************************* Operator Search Template **************************/
+
+static void operator_call_cb(struct bContext *C, void *arg1, void *arg2)
+{
+	wmOperatorType *ot= arg2;
+	
+	if(ot)
+		WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, NULL);
+}
+
+static void operator_search_cb(const struct bContext *C, void *arg, char *str, uiSearchItems *items)
+{
+	wmOperatorType *ot = WM_operatortype_first();
+	
+	for(; ot; ot= ot->next) {
+		
+		if(BLI_strcasestr(ot->name, str)) {
+			if(ot->poll==NULL || ot->poll((bContext *)C)) {
+				char name[256];
+				int len= strlen(ot->name);
+				
+				/* display name for menu, can hold hotkey */
+				BLI_strncpy(name, ot->name, 256);
+				
+				/* check for hotkey */
+				if(len < 256-6) {
+					if(WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, &name[len+1], 256-len-1))
+						name[len]= '|';
+				}
+				
+				if(0==uiSearchItemAdd(items, name, ot, 0))
+					break;
+			}
+		}
+	}
+}
+
+void uiTemplateOperatorSearch(uiLayout *layout)
+{
+	uiBlock *block;
+	uiBut *but;
+	static char search[256]= "";
+		
+	block= uiLayoutGetBlock(layout);
+	uiBlockSetCurLayout(block, layout);
+
+	but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X*6, UI_UNIT_Y, "");
+	uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL);
+}
+
+/************************* Running Jobs Template **************************/
+
+#define B_STOPRENDER	1
+#define B_STOPCAST		2
+#define B_STOPANIM		3
+
+static void do_running_jobs(bContext *C, void *arg, int event)
+{
+	switch(event) {
+		case B_STOPRENDER:
+			G.afbreek= 1;
+			break;
+		case B_STOPCAST:
+			WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C));
+			break;
+		case B_STOPANIM:
+			ED_screen_animation_timer(C, 0, 0);
+			break;
+	}
+}
+
+void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
+{
+	bScreen *screen= CTX_wm_screen(C);
+	Scene *scene= CTX_data_scene(C);
+	wmWindowManager *wm= CTX_wm_manager(C);
+	uiBlock *block;
+
+	block= uiLayoutGetBlock(layout);
+	uiBlockSetCurLayout(block, layout);
+
+	uiBlockSetHandleFunc(block, do_running_jobs, NULL);
+
+	if(WM_jobs_test(wm, scene))
+		uiDefIconTextBut(block, BUT, B_STOPRENDER, ICON_REC, "Render", 0,0,75,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop rendering");
+	if(WM_jobs_test(wm, screen))
+		uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_REC, "Capture", 0,0,85,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop screencast");
+	if(screen->animtimer)
+		uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_REC, "Anim Player", 0,0,85,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop animation playback");
+}
+
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index a75a3402774..eb79848d7d2 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -43,6 +43,7 @@
 #include "BKE_colortools.h"
 #include "BKE_context.h"
 #include "BKE_idprop.h"
+#include "BKE_icons.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
 #include "BKE_texture.h"
@@ -110,7 +111,12 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
 			but= uiDefButR(block, MENU, 0, NULL, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
 			break;
 		case PROP_STRING:
-			but= uiDefButR(block, TEX, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
+			if(icon && name && strcmp(name, "") == 0)
+				but= uiDefIconButR(block, TEX, 0, icon, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
+			else if(icon)
+				but= uiDefIconTextButR(block, TEX, 0, icon, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
+			else
+				but= uiDefButR(block, TEX, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
 			break;
 		case PROP_POINTER: {
 			PointerRNA pptr;
@@ -120,6 +126,8 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
 			if(!pptr.type)
 				pptr.type= RNA_property_pointer_type(ptr, prop);
 			icon= RNA_struct_ui_icon(pptr.type);
+			if(icon == ICON_DOT)
+				icon= 0;
 
 			but= uiDefIconTextButR(block, IDPOIN, 0, icon, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
 			break;
@@ -139,69 +147,39 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
 	return but;
 }
 
-void uiDefAutoButsRNA(const bContext *C, uiLayout *layout, PointerRNA *ptr)
+void uiDefAutoButsRNA(const bContext *C, uiLayout *layout, PointerRNA *ptr, int columns)
 {
-	CollectionPropertyIterator iter;
-	PropertyRNA *iterprop, *prop;
-	uiLayout *split;
+	uiLayout *split, *col;
 	char *name;
 
 	uiItemL(layout, (char*)RNA_struct_ui_name(ptr->type), 0);
 
-	iterprop= RNA_struct_iterator_property(ptr->type);
-	RNA_property_collection_begin(ptr, iterprop, &iter);
-
-	for(; iter.valid; RNA_property_collection_next(&iter)) {
-		prop= iter.ptr.data;
-
+	RNA_STRUCT_BEGIN(ptr, prop) {
 		if(strcmp(RNA_property_identifier(prop), "rna_type") == 0)
 			continue;
 
-		split = uiLayoutSplit(layout, 0.5f);
-
 		name= (char*)RNA_property_ui_name(prop);
 
-		uiItemL(uiLayoutColumn(split, 0), name, 0);
-		uiItemFullR(uiLayoutColumn(split, 0), "", 0, ptr, prop, -1, 0, 0, 0, 0);
-	}
+		if(columns == 1) {
+			col= uiLayoutColumn(layout, 1);
+			uiItemL(col, name, 0);
+		}
+		else if(columns == 2) {
+			split = uiLayoutSplit(layout, 0.5f);
 
-	RNA_property_collection_end(&iter);
-}
+			uiItemL(uiLayoutColumn(split, 0), name, 0);
+			col= uiLayoutColumn(split, 0);
+		}
 
-/* temp call, single collumn, test for toolbar only */
-void uiDefAutoButsRNA_single(const bContext *C, uiLayout *layout, PointerRNA *ptr)
-{
-	CollectionPropertyIterator iter;
-	PropertyRNA *iterprop, *prop;
-	uiLayout *col;
-	char *name;
-	
-	uiItemL(layout, (char*)RNA_struct_ui_name(ptr->type), 0);
-	
-	iterprop= RNA_struct_iterator_property(ptr->type);
-	RNA_property_collection_begin(ptr, iterprop, &iter);
-	
-	for(; iter.valid; RNA_property_collection_next(&iter)) {
-		prop= iter.ptr.data;
-		
-		if(strcmp(RNA_property_identifier(prop), "rna_type") == 0)
-			continue;
-		
-		name= (char*)RNA_property_ui_name(prop);
-		col= uiLayoutColumn(layout, 1);
-		uiItemL(col, name, 0);
-		
 		/* temp hack to show normal button for spin/screw */
 		if(strcmp(name, "Axis")==0) {
-			uiDefButR(uiLayoutGetBlock(layout), BUT_NORMAL, 0, name, 0, 0, 100, 100, ptr, "axis", -1, 0, 0, -1, -1, NULL);
+			uiDefButR(uiLayoutGetBlock(col), BUT_NORMAL, 0, name, 0, 0, 100, 100, ptr, "axis", -1, 0, 0, -1, -1, NULL);
 		}
 		else uiItemFullR(col, "", 0, ptr, prop, -1, 0, 0, 0, 0);
 	}
-	
-	RNA_property_collection_end(&iter);
+	RNA_STRUCT_END;
 }
 
-
 /***************************** ID Utilities *******************************/
 /* note, C code version, will be replaced with version in interface_templates.c */
 
@@ -304,9 +282,25 @@ static void id_search_cb(const struct bContext *C, void *arg_params, char *str,
 	ID *id;
 	
 	for(id= params->lb->first; id; id= id->next) {
+		int iconid= 0;
+		
+		
+		/* icon */
+		switch(GS(id->name))
+		{
+			case ID_MA: /* fall through */
+			case ID_TE: /* fall through */
+			case ID_IM: /* fall through */
+			case ID_WO: /* fall through */
+			case ID_LA: /* fall through */
+				iconid= BKE_icon_getid(id);
+				break;
+			default:
+				break;
+		}
 		
 		if(BLI_strcasestr(id->name+2, str)) {
-			if(0==uiSearchItemAdd(items, id->name+2, id))
+			if(0==uiSearchItemAdd(items, id->name+2, id, iconid))
 				break;
 		}
 	}
@@ -333,7 +327,7 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_params)
 	uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
 	
 	but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, "");
-	uiButSetSearchFunc(but, id_search_cb, ¶ms, id_search_call_cb);
+	uiButSetSearchFunc(but, id_search_cb, ¶ms, id_search_call_cb, NULL);
 	
 	uiBoundsBlock(block, 6);
 	uiBlockSetDirection(block, UI_DOWN);	
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 14df9026078..ed2d00cb00d 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -102,6 +102,7 @@ typedef struct uiWidgetBase {
 	float inner_uv[64][2];
 	
 	short inner, outline, emboss; /* set on/off */
+	short shadedir;
 	
 	uiWidgetTrias tria1;
 	uiWidgetTrias tria2;
@@ -199,6 +200,7 @@ static void widget_init(uiWidgetBase *wtb)
 	wtb->inner= 1;
 	wtb->outline= 1;
 	wtb->emboss= 1;
+	wtb->shadedir= 1;
 }
 
 /* helper call, makes shadow rect, with 'sun' above menu, so only shadow to left/right/bottom */
@@ -583,7 +585,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
 			glShadeModel(GL_SMOOTH);
 			glBegin(GL_POLYGON);
 			for(a=0; atotvert; a++) {
-				round_box_shade_col4(col1, col2, wtb->inner_uv[a][1]);
+				round_box_shade_col4(col1, col2, wtb->inner_uv[a][wtb->shadedir]);
 				glVertex2fv(wtb->inner_v[a]);
 			}
 			glEnd();
@@ -1026,7 +1028,7 @@ static struct uiWidgetColors wcol_menu_back= {
 	{0, 0, 0, 255},
 	{25, 25, 25, 230},
 	{45, 45, 45, 230},
-	{255, 255, 255, 255},
+	{100, 100, 100, 255},
 	
 	{255, 255, 255, 255},
 	{255, 255, 255, 255},
@@ -1088,6 +1090,32 @@ static struct uiWidgetColors wcol_box= {
 	0, 0
 };
 
+static struct uiWidgetColors wcol_toggle= {
+	{25, 25, 25, 255},
+	{153, 153, 153, 255},
+	{100, 100, 100, 255},
+	{25, 25, 25, 255},
+	
+	{0, 0, 0, 255},
+	{255, 255, 255, 255},
+	
+	0,
+	0, 0
+};
+
+static struct uiWidgetColors wcol_scroll= {
+	{25, 25, 25, 255},
+	{180, 180, 180, 255},
+	{153, 153, 153, 255},
+	{90, 90, 90, 255},
+	
+	{0, 0, 0, 255},
+	{255, 255, 255, 255},
+	
+	1,
+	0, -20
+};
+
 /* free wcol struct to play with */
 static struct uiWidgetColors wcol_tmp= {
 	{0, 0, 0, 255},
@@ -1109,9 +1137,10 @@ void ui_widget_color_init(ThemeUI *tui)
 
 	tui->wcol_regular= wcol_regular;
 	tui->wcol_tool= wcol_tool;
-	tui->wcol_radio= wcol_radio;
 	tui->wcol_text= wcol_text;
+	tui->wcol_radio= wcol_radio;
 	tui->wcol_option= wcol_option;
+	tui->wcol_toggle= wcol_toggle;
 	tui->wcol_num= wcol_num;
 	tui->wcol_numslider= wcol_numslider;
 	tui->wcol_menu= wcol_menu;
@@ -1119,6 +1148,7 @@ void ui_widget_color_init(ThemeUI *tui)
 	tui->wcol_menu_back= wcol_menu_back;
 	tui->wcol_menu_item= wcol_menu_item;
 	tui->wcol_box= wcol_box;
+	tui->wcol_scroll= wcol_scroll;
 }
 
 /* ************ button callbacks, state ***************** */
@@ -1602,6 +1632,75 @@ void ui_draw_link_bezier(rcti *rect)
 	}
 }
 
+static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
+{
+	uiWidgetBase wtb;
+	rcti rect1;
+	double value;
+	char inner[3];
+	float fac, size, rad;
+	int horizontal;
+
+	/* determine horizontal/vertical */
+	horizontal= (rect->xmax - rect->xmin > rect->ymax - rect->ymin);
+
+	if(horizontal)
+		rad= 0.5f*(rect->ymax - rect->ymin);
+	else
+		rad= 0.5f*(rect->xmax - rect->xmin);
+
+	widget_init(&wtb);
+	wtb.shadedir= (horizontal)? 1: 0;
+
+	/* draw back part, colors swapped and shading inverted */
+	VECCOPY(inner, wcol->inner);
+	VECCOPY(wcol->inner, wcol->item);
+	if(horizontal)
+		SWAP(short, wcol->shadetop, wcol->shadedown);
+	if(state & UI_SELECT)
+		SWAP(short, wcol->shadetop, wcol->shadedown);
+	
+	round_box_edges(&wtb, roundboxalign, rect, rad); /* XXX vertical gradient is wrong */
+	widgetbase_draw(&wtb, wcol);
+
+	VECCOPY(wcol->inner, inner);
+	if(horizontal)
+		SWAP(short, wcol->shadetop, wcol->shadedown);
+	if(state & UI_SELECT)
+		SWAP(short, wcol->shadetop, wcol->shadedown);
+	
+	/* front part */
+	value= ui_get_but_val(but);
+
+	size= (but->softmax + but->a1 - but->softmin);
+	size= MAX2(size, 2);
+	
+	/* position */
+	rect1= *rect;
+
+	if(horizontal) {
+		fac= (rect->xmax - rect->xmin)/(size);
+		rect1.xmin= rect1.xmin + ceil(fac*(value - but->softmin));
+		rect1.xmax= rect1.xmin + ceil(fac*(but->a1 - but->softmin));
+	}
+	else {
+		fac= (rect->ymax - rect->ymin)/(size);
+		rect1.ymax= rect1.ymax - ceil(fac*(value - but->softmin));
+		rect1.ymin= rect1.ymax - ceil(fac*(but->a1 - but->softmin));
+	}
+
+	/* draw */
+	wtb.emboss= 0; /* only emboss once */
+
+	if(!horizontal)
+		SWAP(short, wcol->shadetop, wcol->shadedown);
+
+	round_box_edges(&wtb, roundboxalign, &rect1, rad); /* XXX vertical gradient is wrong */
+	widgetbase_draw(&wtb, wcol);
+
+	if(!horizontal)
+		SWAP(short, wcol->shadetop, wcol->shadedown);
+}
 
 static void widget_link(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign)
 {
@@ -1896,12 +1995,16 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
 	wt.text= widget_draw_text_icon;
 	
 	switch(type) {
+		case UI_WTYPE_REGULAR:
+			break;
+
 		case UI_WTYPE_LABEL:
 			wt.draw= NULL;
 			wt.state= widget_state_label;
 			break;
 			
 		case UI_WTYPE_TOGGLE:
+			wt.wcol_theme= &btheme->tui.wcol_toggle;
 			break;
 			
 		case UI_WTYPE_OPTION:
@@ -1914,7 +2017,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
 			wt.wcol_theme= &btheme->tui.wcol_radio;
 			wt.draw= widget_radiobut;
 			break;
-			
+
 		case UI_WTYPE_NUMBER:
 			wt.wcol_theme= &btheme->tui.wcol_num;
 			wt.draw= widget_numbut;
@@ -1995,6 +2098,11 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
 			
 		case UI_WTYPE_NORMAL:
 			break;
+
+		case UI_WTYPE_SCROLL:
+			wt.wcol_theme= &btheme->tui.wcol_scroll;
+			wt.custom= widget_scroll;
+			break;
 	}
 	
 	return &wt;
@@ -2089,6 +2197,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
 			case BUT:
 				wt= widget_type(UI_WTYPE_EXEC);
 				break;
+
 			case NUM:
 				wt= widget_type(UI_WTYPE_NUMBER);
 				break;
@@ -2184,9 +2293,13 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
 			case BUT_CURVE:
 				ui_draw_but_CURVE(ar, but, &tui->wcol_regular, rect);
 				break;
-				
+
+			case SCROLL:
+				wt= widget_type(UI_WTYPE_SCROLL);
+				break;
+
 			default:
-				wt= widget_type(UI_WTYPE_TOGGLE);
+				wt= widget_type(UI_WTYPE_REGULAR);
 		}
 	}
 	
@@ -2195,6 +2308,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
 		int roundboxalign, state;
 		
 		roundboxalign= widget_roundbox_set(but, rect);
+
 		state= but->flag;
 		if(but->editstr) state |= UI_TEXTINPUT;
 		
@@ -2242,7 +2356,7 @@ void ui_draw_search_back(uiStyle *style, uiBlock *block, rcti *rect)
 
 /* helper call to draw a menu item without button */
 /* state: UI_ACTIVE or 0 */
-void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, char *name, int state)
+void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, char *name, int iconid, int state)
 {
 	uiWidgetType *wt= widget_type(UI_WTYPE_MENU_ITEM);
 	rcti _rect= *rect;
@@ -2256,6 +2370,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, char *name, int state)
 	
 	/* text location offset */
 	rect->xmin+=5;
+	if(iconid) rect->xmin+= ICON_HEIGHT;
 
 	/* cut string in 2 parts? */
 	cpoin= strchr(name, '|');
@@ -2278,5 +2393,12 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, char *name, int state)
 	/* restore rect, was messed with */
 	*rect= _rect;
 
+	if(iconid) {
+		int xs= rect->xmin+4;
+		int ys= 1 + (rect->ymin+rect->ymax- ICON_HEIGHT)/2;
+		glEnable(GL_BLEND);
+		UI_icon_draw_aspect_blended(xs, ys, iconid, 1.2f, 0); /* XXX scale weak get from fstyle? */
+		glDisable(GL_BLEND);
+	}
 }
 
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 0a65718b708..f83dee23417 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -1,5 +1,5 @@
 /**
- * $Id: resources.c 12755 2007-12-02 05:50:38Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 189898cc907..aa5aa65d300 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -1,5 +1,5 @@
 /**
- * $Id: view2d.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -316,6 +316,12 @@ void UI_view2d_curRect_validate(View2D *v2d)
 	if (v2d->keepzoom & V2D_LOCKZOOM_Y)
 		height= winy;
 		
+	/* values used to divide, so make it safe */
+	if(width<1) width= 1;
+	if(height<1) height= 1;
+	if(winx<1) winx= 1;
+	if(winy<1) winy= 1;
+	
 	/* keepzoom (V2D_KEEPZOOM set), indicates that zoom level on each axis must not exceed limits 
 	 * NOTE: in general, it is not expected that the lock-zoom will be used in conjunction with this
 	 */
diff --git a/source/blender/editors/mesh/Makefile b/source/blender/editors/mesh/Makefile
index 650771519cd..8ae40e1b957 100644
--- a/source/blender/editors/mesh/Makefile
+++ b/source/blender/editors/mesh/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/mesh/editmesh.c b/source/blender/editors/mesh/editmesh.c
index dd003d103d5..7f5201f4704 100644
--- a/source/blender/editors/mesh/editmesh.c
+++ b/source/blender/editors/mesh/editmesh.c
@@ -841,7 +841,7 @@ void make_editMesh(Scene *scene, Object *ob)
 	
 	em= me->edit_mesh;
 	
-	em->selectmode= scene->selectmode; // warning needs to be synced
+	em->selectmode= scene->toolsettings->selectmode; // warning needs to be synced
 	em->act_face = NULL;
 	em->totvert= tot= me->totvert;
 	em->totedge= me->totedge;
@@ -1556,7 +1556,7 @@ static int mesh_separate_material(Scene *scene, Base *editbase)
 		/* clear selection, we're going to use that to select material group */
 		EM_clear_flag_all(em, SELECT);
 		/* select the material */
-		editmesh_select_by_material(em, curr_mat);
+		EM_select_by_material(em, curr_mat);
 		/* and now separate */
 		if(0==mesh_separate_selected(scene, editbase)) {
 			BKE_mesh_end_editmesh(me, em);
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index 57fb2c19c75..12138ee13d2 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -1276,7 +1276,7 @@ static float new_primitive_matrix(bContext *C, float primmat[][4])
 	Object *obedit= CTX_data_edit_object(C);
 	Scene *scene = CTX_data_scene(C);
 	View3D *v3d =CTX_wm_view3d(C);
-	RegionView3D *rv3d= CTX_wm_region_view3d(C);
+	RegionView3D *rv3d= ED_view3d_context_rv3d(C);
 	float *curs, mat[3][3], vmat[3][3], cmat[3][3], imat[3][3];
 	
 	Mat4One(primmat);
@@ -1295,9 +1295,9 @@ static float new_primitive_matrix(bContext *C, float primmat[][4])
 	/* center */
 	curs= give_cursor(scene, v3d);
 	VECCOPY(primmat[3], curs);
+	VECSUB(primmat[3], primmat[3], obedit->obmat[3]);
 	Mat3Inv(imat, mat);
 	Mat3MulVecfl(imat, primmat[3]);
-	VECSUB(primmat[3], primmat[3], obedit->obmat[3]);
 	
 	if(v3d) return v3d->grid;
 	return 1.0f;
diff --git a/source/blender/editors/mesh/editmesh_mods.c b/source/blender/editors/mesh/editmesh_mods.c
index a1f8b3251c8..70a0c6b82da 100644
--- a/source/blender/editors/mesh/editmesh_mods.c
+++ b/source/blender/editors/mesh/editmesh_mods.c
@@ -3242,7 +3242,7 @@ static int toggle_select_all_exec(bContext *C, wmOperator *op)
 void MESH_OT_select_all_toggle(wmOperatorType *ot)
 {
 	/* identifiers */
-	ot->name= "Select or Deselect All";
+	ot->name= "Select/Deselect All";
 	ot->idname= "MESH_OT_select_all_toggle";
 	
 	/* api callbacks */
@@ -3484,7 +3484,7 @@ void MESH_OT_select_random(wmOperatorType *ot)
 	RNA_def_float_percentage(ot->srna, "percent", 0.5f, 0.0f, 1.0f, "Percent", "Percentage of vertices to select randomly.", 0.0001f, 1.0f);
 }
 
-void editmesh_select_by_material(EditMesh *em, int index) 
+void EM_select_by_material(EditMesh *em, int index) 
 {
 	EditFace *efa;
 	
@@ -3497,7 +3497,7 @@ void editmesh_select_by_material(EditMesh *em, int index)
 	EM_selectmode_flush(em);
 }
 
-void editmesh_deselect_by_material(EditMesh *em, int index) 
+void EM_deselect_by_material(EditMesh *em, int index) 
 {
 	EditFace *efa;
 	
@@ -3531,7 +3531,7 @@ static void mesh_selection_type(Scene *scene, EditMesh *em, int val)
 		
 		/* note, em stores selectmode to be able to pass it on everywhere without scene,
 		   this is only until all select modes and toolsettings are settled more */
-		scene->selectmode= em->selectmode;
+		scene->toolsettings->selectmode= em->selectmode;
 //		if (EM_texFaceCheck())
 	}
 }
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index b26fded4fb6..dc9c8c6b6d2 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -787,7 +787,7 @@ static int extrude_repeat_mesh(bContext *C, wmOperator *op)
 	Object *obedit= CTX_data_edit_object(C);
 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
 
-	RegionView3D *rv3d = CTX_wm_region_view3d(C);		
+	RegionView3D *rv3d = ED_view3d_context_rv3d(C);		
 		
 	int steps = RNA_int_get(op->ptr,"steps");
 	
@@ -949,7 +949,7 @@ static int spin_mesh_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
 	Scene *scene = CTX_data_scene(C);
 	View3D *v3d = CTX_wm_view3d(C);
-	RegionView3D *rv3d= CTX_wm_region_view3d(C);
+	RegionView3D *rv3d= ED_view3d_context_rv3d(C);
 	
 	RNA_float_set_array(op->ptr, "center", give_cursor(scene, v3d));
 	RNA_float_set_array(op->ptr, "axis", rv3d->viewinv[2]);
@@ -1056,7 +1056,7 @@ static int screw_mesh_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
 	Scene *scene = CTX_data_scene(C);
 	View3D *v3d = CTX_wm_view3d(C);
-	RegionView3D *rv3d= CTX_wm_region_view3d(C);
+	RegionView3D *rv3d= ED_view3d_context_rv3d(C);
 	
 	RNA_float_set_array(op->ptr, "center", give_cursor(scene, v3d));
 	RNA_float_set_array(op->ptr, "axis", rv3d->viewinv[1]);
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 83a4211dda1..22e3b4060a4 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -234,5 +234,14 @@ void MESH_OT_colors_mirror(struct wmOperatorType *ot);
 void MESH_OT_delete(struct wmOperatorType *ot);
 void MESH_OT_rip(struct wmOperatorType *ot);
 
+/* ******************* mesh_layers.c */
+
+void MESH_OT_uv_texture_add(struct wmOperatorType *ot);
+void MESH_OT_uv_texture_remove(struct wmOperatorType *ot);
+void MESH_OT_vertex_color_add(struct wmOperatorType *ot);
+void MESH_OT_vertex_color_remove(struct wmOperatorType *ot);
+void MESH_OT_sticky_add(struct wmOperatorType *ot);
+void MESH_OT_sticky_remove(struct wmOperatorType *ot);
+
 #endif // MESH_INTERN_H
 
diff --git a/source/blender/editors/mesh/mesh_layers.c b/source/blender/editors/mesh/mesh_layers.c
new file mode 100644
index 00000000000..99d50d1a9b0
--- /dev/null
+++ b/source/blender/editors/mesh/mesh_layers.c
@@ -0,0 +1,424 @@
+/**
+ * $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) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ * 
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include 
+#include 
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_customdata_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+
+#include "BLI_editVert.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_mesh.h"
+#include "ED_view3d.h"
+
+#include "mesh_intern.h"
+
+static void delete_customdata_layer(Mesh *me, CustomDataLayer *layer)
+{
+	CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
+	void *actlayerdata, *rndlayerdata, *clonelayerdata, *masklayerdata, *layerdata=layer->data;
+	int type= layer->type;
+	int index= CustomData_get_layer_index(data, type);
+	int i, actindex, rndindex, cloneindex, maskindex;
+	
+	/* ok, deleting a non-active layer needs to preserve the active layer indices.
+	  to do this, we store a pointer to the .data member of both layer and the active layer,
+	  (to detect if we're deleting the active layer or not), then use the active
+	  layer data pointer to find where the active layer has ended up.
+	  
+	  this is necassary because the deletion functions only support deleting the active
+	  layer. */
+	actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data;
+	rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data;
+	clonelayerdata = data->layers[CustomData_get_clone_layer_index(data, type)].data;
+	masklayerdata = data->layers[CustomData_get_mask_layer_index(data, type)].data;
+	CustomData_set_layer_active(data, type, layer - &data->layers[index]);
+
+	if(me->edit_mesh) {
+		EM_free_data_layer(me->edit_mesh, data, type);
+	}
+	else {
+		CustomData_free_layer_active(data, type, me->totface);
+		mesh_update_customdata_pointers(me);
+	}
+
+	if(!CustomData_has_layer(data, type))
+		if(type == CD_MCOL && (G.f & G_VERTEXPAINT))
+			G.f &= ~G_VERTEXPAINT; /* get out of vertexpaint mode */
+
+	/* reconstruct active layer */
+	if (actlayerdata != layerdata) {
+		/* find index */
+		actindex = CustomData_get_layer_index(data, type);
+		for (i=actindex; itotlayer; i++) {
+			if (data->layers[i].data == actlayerdata) {
+				actindex = i - actindex;
+				break;
+			}
+		}
+		
+		/* set index */
+		CustomData_set_layer_active(data, type, actindex);
+	}
+	
+	if (rndlayerdata != layerdata) {
+		/* find index */
+		rndindex = CustomData_get_layer_index(data, type);
+		for (i=rndindex; itotlayer; i++) {
+			if (data->layers[i].data == rndlayerdata) {
+				rndindex = i - rndindex;
+				break;
+			}
+		}
+		
+		/* set index */
+		CustomData_set_layer_render(data, type, rndindex);
+	}
+	
+	if (clonelayerdata != layerdata) {
+		/* find index */
+		cloneindex = CustomData_get_layer_index(data, type);
+		for (i=cloneindex; itotlayer; i++) {
+			if (data->layers[i].data == clonelayerdata) {
+				cloneindex = i - cloneindex;
+				break;
+			}
+		}
+		
+		/* set index */
+		CustomData_set_layer_clone(data, type, cloneindex);
+	}
+	
+	if (masklayerdata != layerdata) {
+		/* find index */
+		maskindex = CustomData_get_layer_index(data, type);
+		for (i=maskindex; itotlayer; i++) {
+			if (data->layers[i].data == masklayerdata) {
+				maskindex = i - maskindex;
+				break;
+			}
+		}
+		
+		/* set index */
+		CustomData_set_layer_mask(data, type, maskindex);
+	}
+}
+
+/*********************** UV texture operators ************************/
+
+static int uv_texture_add_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene= CTX_data_scene(C);
+	Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+	Mesh *me;
+	EditMesh *em;
+	int layernum;
+
+	if(!ob || ob->type!=OB_MESH)
+		return OPERATOR_CANCELLED;
+	
+	me= (Mesh*)ob->data;
+
+	if(scene->obedit == ob) {
+		em= me->edit_mesh;
+
+		layernum= CustomData_number_of_layers(&em->fdata, CD_MTFACE);
+		if(layernum >= MAX_MTFACE)
+			return OPERATOR_CANCELLED;
+
+		EM_add_data_layer(em, &em->fdata, CD_MTFACE);
+		CustomData_set_layer_active(&em->fdata, CD_MTFACE, layernum);
+	}
+	else if(ob) {
+		layernum= CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+		if(layernum >= MAX_MTFACE)
+			return OPERATOR_CANCELLED;
+
+		if(me->mtface)
+			CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface);
+		else
+			CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface);
+
+		CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum);
+		mesh_update_customdata_pointers(me);
+	}
+
+	DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
+
+	return OPERATOR_FINISHED;
+}
+
+void MESH_OT_uv_texture_add(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Add UV Texture";
+	ot->idname= "MESH_OT_uv_texture_add";
+	
+	/* api callbacks */
+	ot->exec= uv_texture_add_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int uv_texture_remove_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene= CTX_data_scene(C);
+	Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+	Mesh *me;
+	CustomDataLayer *cdl;
+	int index;
+
+	if(!ob || ob->type!=OB_MESH)
+		return OPERATOR_CANCELLED;
+	
+	me= (Mesh*)ob->data;
+ 	index= CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
+	cdl= (index == -1)? NULL: &me->fdata.layers[index];
+
+	if(!cdl)
+		return OPERATOR_CANCELLED;
+
+	delete_customdata_layer(me, cdl);
+
+	DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
+
+	return OPERATOR_FINISHED;
+}
+
+void MESH_OT_uv_texture_remove(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Remove UV Texture";
+	ot->idname= "MESH_OT_uv_texture_remove";
+	
+	/* api callbacks */
+	ot->exec= uv_texture_remove_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/*********************** vertex color operators ************************/
+
+static int vertex_color_add_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene= CTX_data_scene(C);
+	Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+	Mesh *me;
+	EditMesh *em;
+	MCol *mcol;
+	int layernum;
+
+	if(!ob || ob->type!=OB_MESH)
+		return OPERATOR_CANCELLED;
+	
+	me= (Mesh*)ob->data;
+
+	if(scene->obedit == ob) {
+		em= me->edit_mesh;
+
+		layernum= CustomData_number_of_layers(&em->fdata, CD_MCOL);
+		if(layernum >= MAX_MCOL)
+			return OPERATOR_CANCELLED;
+
+		EM_add_data_layer(em, &em->fdata, CD_MCOL);
+		CustomData_set_layer_active(&em->fdata, CD_MCOL, layernum);
+	}
+	else {
+		layernum= CustomData_number_of_layers(&me->fdata, CD_MCOL);
+		if(layernum >= MAX_MCOL)
+			return OPERATOR_CANCELLED;
+
+		mcol= me->mcol;
+
+		if(me->mcol)
+			CustomData_add_layer(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface);
+		else
+			CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface);
+
+		CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
+		mesh_update_customdata_pointers(me);
+
+		if(!mcol)
+			shadeMeshMCol(scene, ob, me);
+	}
+
+	DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
+
+	return OPERATOR_FINISHED;
+}
+
+void MESH_OT_vertex_color_add(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Add Vertex Color";
+	ot->idname= "MESH_OT_vertex_color_add";
+	
+	/* api callbacks */
+	ot->exec= vertex_color_add_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int vertex_color_remove_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene= CTX_data_scene(C);
+	Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+	Mesh *me;
+	CustomDataLayer *cdl;
+	int index;
+
+	if(!ob || ob->type!=OB_MESH)
+		return OPERATOR_CANCELLED;
+	
+	me= (Mesh*)ob->data;
+ 	index= CustomData_get_active_layer_index(&me->fdata, CD_MCOL);
+	cdl= (index == -1)? NULL: &me->fdata.layers[index];
+
+	if(!cdl)
+		return OPERATOR_CANCELLED;
+
+	delete_customdata_layer(me, cdl);
+
+	DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
+
+	return OPERATOR_FINISHED;
+}
+
+void MESH_OT_vertex_color_remove(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Remove Vertex Color";
+	ot->idname= "MESH_OT_vertex_color_remove";
+	
+	/* api callbacks */
+	ot->exec= vertex_color_remove_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/*********************** sticky operators ************************/
+
+static int sticky_add_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene= CTX_data_scene(C);
+	Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+	Mesh *me;
+
+	if(!ob || ob->type!=OB_MESH)
+		return OPERATOR_CANCELLED;
+	
+	me= (Mesh*)ob->data;
+
+	if(me->msticky)
+		return OPERATOR_CANCELLED;
+
+	// XXX RE_make_sticky();
+
+	DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
+
+	return OPERATOR_FINISHED;
+}
+
+void MESH_OT_sticky_add(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Add Sticky";
+	ot->idname= "MESH_OT_sticky_add";
+	
+	/* api callbacks */
+	ot->exec= sticky_add_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int sticky_remove_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene= CTX_data_scene(C);
+	Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+	Mesh *me;
+
+	if(!ob || ob->type!=OB_MESH)
+		return OPERATOR_CANCELLED;
+	
+	me= (Mesh*)ob->data;
+
+	if(!me->msticky)
+		return OPERATOR_CANCELLED;
+
+	CustomData_free_layer_active(&me->vdata, CD_MSTICKY, me->totvert);
+	me->msticky= NULL;
+
+	DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
+
+	return OPERATOR_FINISHED;
+}
+
+void MESH_OT_sticky_remove(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Remove Sticky";
+	ot->idname= "MESH_OT_sticky_remove";
+	
+	/* api callbacks */
+	ot->exec= sticky_remove_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 5a86180a60f..2a9357ed0f0 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -183,6 +183,12 @@ void ED_operatortypes_mesh(void)
 	WM_operatortype_append(MESH_OT_knife_cut);
 	WM_operatortype_append(MESH_OT_rip);
 	
+	WM_operatortype_append(MESH_OT_uv_texture_add);
+	WM_operatortype_append(MESH_OT_uv_texture_remove);
+	WM_operatortype_append(MESH_OT_vertex_color_add);
+	WM_operatortype_append(MESH_OT_vertex_color_remove);
+	WM_operatortype_append(MESH_OT_sticky_add);
+	WM_operatortype_append(MESH_OT_sticky_remove);
 }
 
 /* note mesh keymap also for other space? */
diff --git a/source/blender/editors/object/Makefile b/source/blender/editors/object/Makefile
index c0312023bfd..70ada46c80f 100644
--- a/source/blender/editors/object/Makefile
+++ b/source/blender/editors/object/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/object/editkey.c b/source/blender/editors/object/editkey.c
index 913046c5ab8..1c31c7c7653 100644
--- a/source/blender/editors/object/editkey.c
+++ b/source/blender/editors/object/editkey.c
@@ -55,6 +55,7 @@
 
 #include "BKE_action.h"
 #include "BKE_anim.h"
+#include "BKE_context.h"
 #include "BKE_curve.h"
 #include "BKE_depsgraph.h"
 #include "BKE_global.h"
@@ -70,11 +71,15 @@
 
 #include "ED_object.h"
 
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
 #include "object_intern.h"
 
 /* XXX */
 static void BIF_undo_push() {}
-static void error() {}
 /* XXX */
 
 #if 0 // XXX old animation system
@@ -394,25 +399,6 @@ void insert_curvekey(Scene *scene, Curve *cu, short rel)
 
 /* ******************** */
 
-void insert_shapekey(Scene *scene, Object *ob)
-{
-	if(get_mesh(ob) && get_mesh(ob)->mr) {
-		error("Cannot create shape keys on a multires mesh.");
-	}
-	else {
-		Key *key;
-	
-		if(ob->type==OB_MESH) insert_meshkey(scene, ob->data, 1);
-		else if ELEM(ob->type, OB_CURVE, OB_SURF) insert_curvekey(scene, ob->data, 1);
-		else if(ob->type==OB_LATTICE) insert_lattkey(scene, ob->data, 1);
-	
-		key= ob_get_key(ob);
-		ob->shapenr= BLI_countlist(&key->block);
-	
-		BIF_undo_push("Add Shapekey");
-	}
-}
-
 void delete_key(Scene *scene, Object *ob)
 {
 	KeyBlock *kb, *rkb;
@@ -473,6 +459,123 @@ void delete_key(Scene *scene, Object *ob)
 	BIF_undo_push("Delete Shapekey");
 }
 
+/********************** shape key operators *********************/
+
+static int shape_key_add_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene= CTX_data_scene(C);
+	Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+	Key *key;
+
+	if(!ob)
+		return OPERATOR_CANCELLED;
+
+	if(ob->type==OB_MESH) insert_meshkey(scene, ob->data, 1);
+	else if ELEM(ob->type, OB_CURVE, OB_SURF) insert_curvekey(scene, ob->data, 1);
+	else if(ob->type==OB_LATTICE) insert_lattkey(scene, ob->data, 1);
+
+	key= ob_get_key(ob);
+	ob->shapenr= BLI_countlist(&key->block);
+
+	WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+	
+	return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_shape_key_add(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Add Shape Key";
+	ot->idname= "OBJECT_OT_shape_key_add";
+	
+	/* api callbacks */
+	ot->exec= shape_key_add_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int shape_key_remove_exec(bContext *C, wmOperator *op)
+{
+	Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+	Scene *scene= CTX_data_scene(C);
+	Main *bmain= CTX_data_main(C);
+	KeyBlock *kb, *rkb;
+	Key *key;
+	//IpoCurve *icu;
+
+	if(!ob)
+		return OPERATOR_CANCELLED;
+	
+	key= ob_get_key(ob);
+	if(key==NULL)
+		return OPERATOR_CANCELLED;
+	
+	kb= BLI_findlink(&key->block, ob->shapenr-1);
+
+	if(kb) {
+		for(rkb= key->block.first; rkb; rkb= rkb->next)
+			if(rkb->relative == ob->shapenr-1)
+				rkb->relative= 0;
+
+		BLI_remlink(&key->block, kb);
+		key->totkey--;
+		if(key->refkey== kb)
+			key->refkey= key->block.first;
+			
+		if(kb->data) MEM_freeN(kb->data);
+		MEM_freeN(kb);
+		
+		for(kb= key->block.first; kb; kb= kb->next)
+			if(kb->adrcode>=ob->shapenr)
+				kb->adrcode--;
+		
+#if 0 // XXX old animation system
+		if(key->ipo) {
+			
+			for(icu= key->ipo->curve.first; icu; icu= icu->next) {
+				if(icu->adrcode==ob->shapenr-1) {
+					BLI_remlink(&key->ipo->curve, icu);
+					free_ipo_curve(icu);
+					break;
+				}
+			}
+			for(icu= key->ipo->curve.first; icu; icu= icu->next) 
+				if(icu->adrcode>=ob->shapenr)
+					icu->adrcode--;
+		}
+#endif // XXX old animation system		
+		
+		if(ob->shapenr>1) ob->shapenr--;
+	}
+	
+	if(key->totkey==0) {
+		if(GS(key->from->name)==ID_ME) ((Mesh *)key->from)->key= NULL;
+		else if(GS(key->from->name)==ID_CU) ((Curve *)key->from)->key= NULL;
+		else if(GS(key->from->name)==ID_LT) ((Lattice *)key->from)->key= NULL;
+
+		free_libblock_us(&(bmain->key), key);
+	}
+	
+	DAG_object_flush_update(scene, OBACT, OB_RECALC_DATA);
+	WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+	
+	return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_shape_key_remove(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Remove Shape Key";
+	ot->idname= "OBJECT_OT_shape_key_remove";
+	
+	/* api callbacks */
+	ot->exec= shape_key_remove_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
 void move_keys(Object *ob)
 {
 #if 0
@@ -560,3 +663,4 @@ void move_keys(Object *ob)
 	BIF_undo_push("Move Shapekey(s)");
 #endif
 }
+
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 74a1fc12631..c436ccdb328 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -340,7 +340,7 @@ static int object_add_mesh_exec(bContext *C, wmOperator *op)
 	
 	if(obedit==NULL || obedit->type!=OB_MESH) {
 		object_add_type(C, OB_MESH);
-		ED_object_enter_editmode(C, 0);
+		ED_object_enter_editmode(C, EM_DO_UNDO);
 		newob = 1;
 	}
 	else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
@@ -388,7 +388,7 @@ static int object_add_mesh_exec(bContext *C, wmOperator *op)
 void OBJECT_OT_mesh_add(wmOperatorType *ot)
 {
 	/* identifiers */
-	ot->name= "Mesh";
+	ot->name= "Add Mesh";
 	ot->description = "Add a mesh object to the scene.";
 	ot->idname= "OBJECT_OT_mesh_add";
 	
@@ -398,8 +398,8 @@ void OBJECT_OT_mesh_add(wmOperatorType *ot)
 	
 	ot->poll= ED_operator_scene_editable;
 	
-	/* flags */
-	ot->flag= 0;
+	/* flags: no register or undo, this operator calls operators */
+	ot->flag= 0; //OPTYPE_REGISTER|OPTYPE_UNDO;
 	
 	RNA_def_enum(ot->srna, "type", prop_mesh_types, 0, "Primitive", "");
 }
@@ -462,7 +462,7 @@ static int object_add_curve_invoke(bContext *C, wmOperator *op, wmEvent *event)
 void OBJECT_OT_curve_add(wmOperatorType *ot)
 {
 	/* identifiers */
-	ot->name= "Curve";
+	ot->name= "Add Curve";
 	ot->description = "Add a curve object to the scene.";
 	ot->idname= "OBJECT_OT_curve_add";
 	
@@ -520,7 +520,7 @@ static int object_add_surface_exec(bContext *C, wmOperator *op)
 void OBJECT_OT_surface_add(wmOperatorType *ot)
 {
 	/* identifiers */
-	ot->name= "Surface";
+	ot->name= "Add Surface";
 	ot->description = "Add a surface object to the scene.";
 	ot->idname= "OBJECT_OT_surface_add";
 	
@@ -557,7 +557,7 @@ static int object_add_text_exec(bContext *C, wmOperator *op)
 void OBJECT_OT_text_add(wmOperatorType *ot)
 {
 	/* identifiers */
-	ot->name= "Text";
+	ot->name= "Add Text";
 	ot->description = "Add a text object to the scene";
 	ot->idname= "OBJECT_OT_text_add";
 	
@@ -602,7 +602,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op)
 void OBJECT_OT_armature_add(wmOperatorType *ot)
 {	
 	/* identifiers */
-	ot->name= "Armature";
+	ot->name= "Add Armature";
 	ot->description = "Add an armature object to the scene.";
 	ot->idname= "OBJECT_OT_armature_add";
 	
@@ -1395,7 +1395,8 @@ static int parent_clear_exec(bContext *C, wmOperator *op)
 	
 	DAG_scene_sort(CTX_data_scene(C));
 	ED_anim_dag_flush_update(C);
-	
+	WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+
 	return OPERATOR_FINISHED;
 }
 
@@ -2600,7 +2601,8 @@ static int parent_set_exec(bContext *C, wmOperator *op)
 	CTX_DATA_END;
 	
 	DAG_scene_sort(CTX_data_scene(C));
-	ED_anim_dag_flush_update(C);	
+	ED_anim_dag_flush_update(C);
+	WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
 	
 	return OPERATOR_FINISHED;
 }
@@ -2648,7 +2650,7 @@ void OBJECT_OT_parent_set(wmOperatorType *ot)
 	ot->poll= ED_operator_object_active;
 	
 	/* flags */
-	ot->flag= 0;
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 	
 	RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
 }
@@ -3349,6 +3351,7 @@ void ED_object_enter_editmode(bContext *C, int flag)
 		WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, scene);
 	}
 	
+	if(flag & EM_DO_UNDO) ED_undo_push(C, "Enter Editmode");
 	if(flag & EM_WAITCURSOR) waitcursor(0);
 }
 
@@ -3661,7 +3664,7 @@ void special_editmenu(Scene *scene, View3D *v3d)
 			if(!psys)
 				return;
 
-			if(scene->selectmode & SCE_SELECT_POINT)
+			if(pset->selectmode & SCE_SELECT_POINT)
 				nr= pupmenu("Specials%t|Rekey%x1|Subdivide%x2|Select First%x3|Select Last%x4|Remove Doubles%x5");
 			else
 				nr= pupmenu("Specials%t|Rekey%x1|Remove Doubles%x5");
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 1eb867e19a0..a52acdd4e1e 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -92,5 +92,19 @@ void OBJECT_OT_modifier_mdef_bind(struct wmOperatorType *ot);
 /* editconstraint.c */
 void OBJECT_OT_constraint_add(struct wmOperatorType *ot);
 
+/* object_vgroup.c */
+void OBJECT_OT_vertex_group_add(struct wmOperatorType *ot);
+void OBJECT_OT_vertex_group_remove(struct wmOperatorType *ot);
+void OBJECT_OT_vertex_group_assign(struct wmOperatorType *ot);
+void OBJECT_OT_vertex_group_remove_from(struct wmOperatorType *ot);
+void OBJECT_OT_vertex_group_select(struct wmOperatorType *ot);
+void OBJECT_OT_vertex_group_deselect(struct wmOperatorType *ot);
+void OBJECT_OT_vertex_group_copy_to_linked(struct wmOperatorType *ot);
+void OBJECT_OT_vertex_group_copy(struct wmOperatorType *ot);
+
+/* editkey.c */
+void OBJECT_OT_shape_key_add(struct wmOperatorType *ot);
+void OBJECT_OT_shape_key_remove(struct wmOperatorType *ot);
+
 #endif /* ED_OBJECT_INTERN_H */
 
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index ee506220b67..4bcfcc4d5ab 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -1,5 +1,5 @@
 /**
- * $Id: object_modifier.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index cfee6a55152..6fa78a53840 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -104,6 +104,18 @@ void ED_operatortypes_object(void)
 	WM_operatortype_append(OBJECT_OT_modifier_mdef_bind);
 
 	WM_operatortype_append(OBJECT_OT_constraint_add);
+
+	WM_operatortype_append(OBJECT_OT_vertex_group_add);
+	WM_operatortype_append(OBJECT_OT_vertex_group_remove);
+	WM_operatortype_append(OBJECT_OT_vertex_group_assign);
+	WM_operatortype_append(OBJECT_OT_vertex_group_remove_from);
+	WM_operatortype_append(OBJECT_OT_vertex_group_select);
+	WM_operatortype_append(OBJECT_OT_vertex_group_deselect);
+	WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_linked);
+	WM_operatortype_append(OBJECT_OT_vertex_group_copy);
+
+	WM_operatortype_append(OBJECT_OT_shape_key_add);
+	WM_operatortype_append(OBJECT_OT_shape_key_remove);
 }
 
 void ED_keymap_object(wmWindowManager *wm)
diff --git a/source/blender/editors/mesh/editdeform.c b/source/blender/editors/object/object_vgroup.c
similarity index 80%
rename from source/blender/editors/mesh/editdeform.c
rename to source/blender/editors/object/object_vgroup.c
index 3ccd4d56ece..fb71fc09108 100644
--- a/source/blender/editors/mesh/editdeform.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -48,19 +48,26 @@
 #include "BLI_blenlib.h"
 #include "BLI_editVert.h"
 
+#include "BKE_context.h"
 #include "BKE_customdata.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_depsgraph.h"
 #include "BKE_deform.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
 #include "BKE_displist.h"
 #include "BKE_global.h"
 #include "BKE_lattice.h"
 #include "BKE_mesh.h"
 #include "BKE_utildefines.h"
 
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
 #include "ED_mesh.h"
 #include "ED_view3d.h"
-#include "mesh_intern.h"
+
+#include "object_intern.h"
 
 /* XXX */
 static void BIF_undo_push() {}
@@ -719,18 +726,13 @@ void add_vert_to_defgroup (Object *ob, bDeformGroup *dg, int vertnum,
 }
 
 /* Only available in editmode */
-void assign_verts_defgroup (Object *obedit, float weight)
+void assign_verts_defgroup (Object *ob, float weight)
 {
-	Object *ob;
 	EditVert *eve;
 	bDeformGroup *dg, *eg;
 	MDeformWeight *newdw;
 	MDeformVert *dvert;
 	int	i, done;
-	
-// XXX	if(multires_level1_test()) return;
-
-	ob= obedit;
 
 	if (!ob)
 		return;
@@ -883,18 +885,13 @@ float get_vert_defgroup (Object *ob, bDeformGroup *dg, int vertnum)
 
 /* Only available in editmode */
 /* removes from active defgroup, if allverts==0 only selected vertices */
-void remove_verts_defgroup (Object *obedit, int allverts)
+void remove_verts_defgroup (Object *ob, int allverts)
 {
-	Object *ob;
 	EditVert *eve;
 	MDeformVert *dvert;
 	MDeformWeight *newdw;
 	bDeformGroup *dg, *eg;
 	int	i;
-	
-// XXX	if(multires_level1_test()) return;
-
-	ob= obedit;
 
 	if (!ob)
 		return;
@@ -966,14 +963,10 @@ void remove_verts_defgroup (Object *obedit, int allverts)
 
 /* Only available in editmode */
 /* removes from all defgroup, if allverts==0 only selected vertices */
-void remove_verts_defgroups(Object *obedit, int allverts)
+void remove_verts_defgroups(Object *ob, int allverts)
 {
-	Object *ob;
 	int actdef, defCount;
-	
-//  XXX	if (multires_level1_test()) return;
 
-	ob= obedit;
 	if (ob == NULL) return;
 	
 	actdef= ob->actdef;
@@ -1107,4 +1100,245 @@ void vgroup_operation_with_menu(Object *ob)
 	}
 }
 
+/********************** vertex group operators *********************/
+
+static int vertex_group_add_exec(bContext *C, wmOperator *op)
+{
+	Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+	Scene *scene= CTX_data_scene(C);
+
+	if(!ob)
+		return OPERATOR_CANCELLED;
+
+	add_defgroup(ob);
+	DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
+	
+	return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_vertex_group_add(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Add Vertex Group";
+	ot->idname= "OBJECT_OT_vertex_group_add";
+	
+	/* api callbacks */
+	ot->exec= vertex_group_add_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int vertex_group_remove_exec(bContext *C, wmOperator *op)
+{
+	Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+	Scene *scene= CTX_data_scene(C);
+
+	if(!ob)
+		return OPERATOR_CANCELLED;
+
+	if(scene->obedit == ob) {
+		del_defgroup(ob);
+		WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
+	}
+	else {
+		del_defgroup_in_object_mode(ob);
+		DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+		WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
+	}
+	
+	return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_vertex_group_remove(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Remove Vertex Group";
+	ot->idname= "OBJECT_OT_vertex_group_remove";
+	
+	/* api callbacks */
+	ot->exec= vertex_group_remove_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int vertex_group_assign_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene= CTX_data_scene(C);
+	ToolSettings *ts= CTX_data_tool_settings(C);
+	Object *ob= CTX_data_edit_object(C);
+
+	if(!ob)
+		return OPERATOR_CANCELLED;
+
+	assign_verts_defgroup(ob, ts->vgroup_weight);
+	DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
+	
+	return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_vertex_group_assign(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Assign Vertex Group";
+	ot->idname= "OBJECT_OT_vertex_group_assign";
+	
+	/* api callbacks */
+	ot->exec= vertex_group_assign_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int vertex_group_remove_from_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene= CTX_data_scene(C);
+	Object *ob= CTX_data_edit_object(C);
+
+	if(!ob)
+		return OPERATOR_CANCELLED;
+
+	remove_verts_defgroup(ob, 0);
+	DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
+	
+	return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Remove from Vertex Group";
+	ot->idname= "OBJECT_OT_vertex_group_remove_from";
+	
+	/* api callbacks */
+	ot->exec= vertex_group_remove_from_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int vertex_group_select_exec(bContext *C, wmOperator *op)
+{
+	Object *ob= CTX_data_edit_object(C);
+
+	if(!ob)
+		return OPERATOR_CANCELLED;
+
+	sel_verts_defgroup(ob, 1); /* runs countall() */
+	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
+
+	return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_vertex_group_select(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Select Vertex Group";
+	ot->idname= "OBJECT_OT_vertex_group_select";
+	
+	/* api callbacks */
+	ot->exec= vertex_group_select_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int vertex_group_deselect_exec(bContext *C, wmOperator *op)
+{
+	Object *ob= CTX_data_edit_object(C);
+
+	if(!ob)
+		return OPERATOR_CANCELLED;
+
+	sel_verts_defgroup(ob, 0); /* runs countall() */
+	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
+
+	return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_vertex_group_deselect(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Deselect Vertex Group";
+	ot->idname= "OBJECT_OT_vertex_group_deselect";
+	
+	/* api callbacks */
+	ot->exec= vertex_group_deselect_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int vertex_group_copy_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene= CTX_data_scene(C);
+	Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+
+	if(!ob)
+		return OPERATOR_CANCELLED;
+
+	duplicate_defgroup(ob);
+	DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
+	
+	return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_vertex_group_copy(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Copy Vertex Group";
+	ot->idname= "OBJECT_OT_vertex_group_copy";
+	
+	/* api callbacks */
+	ot->exec= vertex_group_copy_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene= CTX_data_scene(C);
+	Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+    Base *base;
+	int retval= OPERATOR_CANCELLED;
+
+	if(!ob)
+		return retval;
+
+    for(base=scene->base.first; base; base= base->next) {
+        if(base->object->type==ob->type) {
+            if(base->object!=ob && base->object->data==ob->data) {
+                BLI_freelistN(&base->object->defbase);
+                BLI_duplicatelist(&base->object->defbase, &ob->defbase);
+                base->object->actdef= ob->actdef;
+
+                DAG_object_flush_update(scene, base->object, OB_RECALC_DATA);
+				WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, base->object);
+
+				retval = OPERATOR_FINISHED;
+            }
+        }
+    }
+	
+	return retval;
+}
+
+void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Copy Vertex Group to Linked";
+	ot->idname= "OBJECT_OT_vertex_group_copy_to_linked";
+	
+	/* api callbacks */
+	ot->exec= vertex_group_copy_to_linked_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
 
diff --git a/source/blender/editors/physics/Makefile b/source/blender/editors/physics/Makefile
index a71ea9e2083..63968fdd537 100644
--- a/source/blender/editors/physics/Makefile
+++ b/source/blender/editors/physics/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/physics/ed_pointcache.c b/source/blender/editors/physics/ed_pointcache.c
new file mode 100644
index 00000000000..893c59a521d
--- /dev/null
+++ b/source/blender/editors/physics/ed_pointcache.c
@@ -0,0 +1,382 @@
+/*
+ * $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) 2007 by Janne Karhu.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_object_force.h"
+#include "DNA_modifier_types.h"
+
+#include "BKE_context.h"
+#include "BKE_particle.h"
+#include "BKE_report.h"
+#include "BKE_scene.h"
+#include "BKE_utildefines.h" 
+#include "BKE_pointcache.h"
+#include "BKE_global.h"
+#include "BKE_modifier.h"
+
+#include "BLI_blenlib.h"
+
+#include "ED_screen.h"
+#include "ED_pointcache.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "physics_intern.h"
+
+static int cache_break_test(void *cbd) {
+	return G.afbreek==1;
+}
+/**************************** general **********************************/
+static int ptcache_bake_all_poll(bContext *C)
+{
+	Scene *scene= CTX_data_scene(C);
+
+	if(!scene)
+		return 0;
+	
+	return 1;
+}
+
+static int ptcache_bake_all_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene= CTX_data_scene(C);
+	PTCacheBaker baker;
+
+
+	baker.scene = scene;
+	baker.pid = NULL;
+	baker.bake = RNA_boolean_get(op->ptr, "bake");
+	baker.render = 0;
+	baker.quick_step = 1;
+	baker.break_test = cache_break_test;
+	baker.break_data = NULL;
+	baker.progressbar = (void (*)(void *, int))WM_timecursor;
+	baker.progresscontext = CTX_wm_window(C);
+
+	BKE_ptcache_make_cache(&baker);
+
+	WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+
+	return OPERATOR_FINISHED;
+}
+static int ptcache_free_bake_all_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene= CTX_data_scene(C);
+	Base *base;
+	PTCacheID *pid;
+	ListBase pidlist;
+
+	for(base=scene->base.first; base; base= base->next) {
+		BKE_ptcache_ids_from_object(&pidlist, base->object);
+
+		for(pid=pidlist.first; pid; pid=pid->next) {
+			pid->cache->flag &= ~PTCACHE_BAKED;
+		}
+		
+		BLI_freelistN(&pidlist);
+	}
+
+	WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+
+	return OPERATOR_FINISHED;
+}
+
+void PTCACHE_OT_bake_all(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Bake All Physics";
+	ot->idname= "PTCACHE_OT_bake_all";
+	
+	/* api callbacks */
+	ot->exec= ptcache_bake_all_exec;
+	ot->poll= ptcache_bake_all_poll;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+	RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
+}
+void PTCACHE_OT_free_bake_all(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Free All Physics Bakes";
+	ot->idname= "PTCACHE_OT_free_bake_all";
+	
+	/* api callbacks */
+	ot->exec= ptcache_free_bake_all_exec;
+	ot->poll= ptcache_bake_all_poll;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/**************************** cloth **********************************/
+static int ptcache_bake_cloth_poll(bContext *C)
+{
+	Scene *scene= CTX_data_scene(C);
+	Object *ob= CTX_data_active_object(C);
+	ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+
+	if(!scene || !ob || ob->id.lib || !clmd)
+		return 0;
+	
+	return 1;
+}
+
+static int ptcache_bake_cloth_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene= CTX_data_scene(C);
+	Object *ob= CTX_data_active_object(C);
+	ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+	PTCacheID pid;
+	PTCacheBaker baker;
+
+	BKE_ptcache_id_from_cloth(&pid, ob, clmd);
+
+	baker.scene = scene;
+	baker.pid = &pid;
+	baker.bake = RNA_boolean_get(op->ptr, "bake");
+	baker.render = 0;
+	baker.quick_step = 1;
+	baker.break_test = cache_break_test;
+	baker.break_data = NULL;
+	baker.progressbar = WM_timecursor;
+	baker.progresscontext = CTX_wm_window(C);
+
+	BKE_ptcache_make_cache(&baker);
+
+	WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+
+	return OPERATOR_FINISHED;
+}
+static int ptcache_free_bake_cloth_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene= CTX_data_scene(C);
+	Object *ob= CTX_data_active_object(C);
+	ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+	PTCacheID pid;
+
+	BKE_ptcache_id_from_cloth(&pid, ob, clmd);
+	pid.cache->flag &= ~PTCACHE_BAKED;
+
+	WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+
+	return OPERATOR_FINISHED;
+}
+void PTCACHE_OT_cache_cloth(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Bake Cloth";
+	ot->idname= "PTCACHE_OT_cache_cloth";
+	
+	/* api callbacks */
+	ot->exec= ptcache_bake_cloth_exec;
+	ot->poll= ptcache_bake_cloth_poll;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+	RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
+}
+void PTCACHE_OT_free_bake_cloth(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Free Cloth Bake";
+	ot->idname= "PTCACHE_OT_free_bake_cloth";
+	
+	/* api callbacks */
+	ot->exec= ptcache_free_bake_cloth_exec;
+	ot->poll= ptcache_bake_cloth_poll;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+static int ptcache_bake_from_cloth_cache_exec(bContext *C, wmOperator *op)
+{
+	Object *ob= CTX_data_active_object(C);
+	ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+	PTCacheID pid;
+
+	BKE_ptcache_id_from_cloth(&pid, ob, clmd);
+	pid.cache->flag |= PTCACHE_BAKED;
+
+	return OPERATOR_FINISHED;
+}
+void PTCACHE_OT_bake_from_cloth_cache(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Bake From Cache";
+	ot->idname= "PTCACHE_OT_bake_from_cloth_cache";
+	
+	/* api callbacks */
+	ot->exec= ptcache_bake_from_cloth_cache_exec;
+	ot->poll= ptcache_bake_cloth_poll;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/**************************** particles **********************************/
+static int ptcache_bake_particle_system_poll(bContext *C)
+{
+	Scene *scene= CTX_data_scene(C);
+	Object *ob= CTX_data_active_object(C);
+
+	if(!scene || !ob || ob->id.lib)
+		return 0;
+	
+	return (ob->particlesystem.first != NULL);
+}
+
+static int ptcache_bake_particle_system_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene= CTX_data_scene(C);
+	Object *ob= CTX_data_active_object(C);
+	ParticleSystem *psys =psys_get_current(ob);
+	PTCacheID pid;
+	PTCacheBaker baker;
+
+	BKE_ptcache_id_from_particles(&pid, ob, psys);
+
+	baker.scene = scene;
+	baker.pid = &pid;
+	baker.bake = RNA_boolean_get(op->ptr, "bake");
+	baker.render = 0;
+	baker.quick_step = 1;
+	baker.break_test = cache_break_test;
+	baker.break_data = NULL;
+	baker.progressbar = (void (*)(void *, int))WM_timecursor;
+	baker.progresscontext = CTX_wm_window(C);
+
+	BKE_ptcache_make_cache(&baker);
+
+	WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+
+	return OPERATOR_FINISHED;
+}
+static int ptcache_free_bake_particle_system_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene= CTX_data_scene(C);
+	Object *ob= CTX_data_active_object(C);
+	ParticleSystem *psys= psys_get_current(ob);
+	PTCacheID pid;
+
+	BKE_ptcache_id_from_particles(&pid, ob, psys);
+	psys->pointcache->flag &= ~PTCACHE_BAKED;
+
+	WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+
+	return OPERATOR_FINISHED;
+}
+void PTCACHE_OT_cache_particle_system(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Bake Particles";
+	ot->idname= "PTCACHE_OT_cache_particle_system";
+	
+	/* api callbacks */
+	ot->exec= ptcache_bake_particle_system_exec;
+	ot->poll= ptcache_bake_particle_system_poll;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+	RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
+}
+void PTCACHE_OT_free_bake_particle_system(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Free Particles Bake";
+	ot->idname= "PTCACHE_OT_free_bake_particle_system";
+	
+	/* api callbacks */
+	ot->exec= ptcache_free_bake_particle_system_exec;
+	ot->poll= ptcache_bake_particle_system_poll;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+static int ptcache_bake_from_particles_cache_exec(bContext *C, wmOperator *op)
+{
+	Object *ob= CTX_data_active_object(C);
+	ParticleSystem *psys= psys_get_current(ob);
+	PTCacheID pid;
+
+	BKE_ptcache_id_from_particles(&pid, ob, psys);
+	psys->pointcache->flag |= PTCACHE_BAKED;
+
+	return OPERATOR_FINISHED;
+}
+void PTCACHE_OT_bake_from_particles_cache(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Bake From Cache";
+	ot->idname= "PTCACHE_OT_bake_from_particles_cache";
+	
+	/* api callbacks */
+	ot->exec= ptcache_bake_from_particles_cache_exec;
+	ot->poll= ptcache_bake_particle_system_poll;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/**************************** registration **********************************/
+
+void ED_operatortypes_pointcache(void)
+{
+	WM_operatortype_append(PTCACHE_OT_bake_all);
+	WM_operatortype_append(PTCACHE_OT_free_bake_all);
+	WM_operatortype_append(PTCACHE_OT_cache_particle_system);
+	WM_operatortype_append(PTCACHE_OT_free_bake_particle_system);
+	WM_operatortype_append(PTCACHE_OT_bake_from_particles_cache);
+	WM_operatortype_append(PTCACHE_OT_cache_cloth);
+	WM_operatortype_append(PTCACHE_OT_free_bake_cloth);
+	WM_operatortype_append(PTCACHE_OT_bake_from_cloth_cache);
+}
+
+//void ED_keymap_pointcache(wmWindowManager *wm)
+//{
+//	ListBase *keymap= WM_keymap_listbase(wm, "Pointcache", 0, 0);
+//	
+//	WM_keymap_add_item(keymap, "PHYSICS_OT_bake_all", AKEY, KM_PRESS, 0, 0);
+//	WM_keymap_add_item(keymap, "PHYSICS_OT_free_all", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
+//	WM_keymap_add_item(keymap, "PHYSICS_OT_bake_particle_system", PADMINUS, KM_PRESS, KM_CTRL, 0);
+//	WM_keymap_add_item(keymap, "PHYSICS_OT_free_particle_system", LKEY, KM_PRESS, 0, 0);
+//}
+
diff --git a/source/blender/editors/physics/editparticle.c b/source/blender/editors/physics/editparticle.c
index b6625cb387c..1b6b5b43522 100644
--- a/source/blender/editors/physics/editparticle.c
+++ b/source/blender/editors/physics/editparticle.c
@@ -1,5 +1,5 @@
 /*
- * $Id: editparticle.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -225,7 +225,7 @@ void PE_hide_keys_time(Scene *scene, ParticleSystem *psys, float cfra)
 	ParticleEditSettings *pset=PE_settings(scene);
 	int i, k, totpart= psys->totpart;
 
-	if(pset->draw_timed && scene->selectmode==SCE_SELECT_POINT) {
+	if(pset->draw_timed && pset->selectmode==SCE_SELECT_POINT) {
 		LOOP_PARTICLES(i, pa) {
 			LOOP_KEYS(k, key) {
 				if(fabs(cfra-*key->time) < pset->draw_timed)
@@ -425,11 +425,12 @@ static void for_mouse_hit_keys(PEData *data, ForKeyFunc func, int nearest)
 	ParticleEdit *edit= psys->edit;
 	ParticleData *pa;
 	ParticleEditKey *key;
+	ParticleEditSettings *pset= PE_settings(data->scene);
 	int i, k, totpart, nearest_pa, nearest_key;
 	float dist= data->rad;
 
 	/* in path select mode we have no keys */
-	if(data->scene->selectmode==SCE_SELECT_PATH)
+	if(pset->selectmode==SCE_SELECT_PATH)
 		return;
 
 	totpart= psys->totpart;
@@ -439,7 +440,7 @@ static void for_mouse_hit_keys(PEData *data, ForKeyFunc func, int nearest)
 	LOOP_PARTICLES(i, pa) {
 		if(pa->flag & PARS_HIDE) continue;
 
-		if(data->scene->selectmode == SCE_SELECT_END) {
+		if(pset->selectmode == SCE_SELECT_END) {
 			/* only do end keys */
 			key= edit->keys[i] + pa->totkey-1;
 
@@ -481,18 +482,19 @@ static void foreach_mouse_hit_particle(PEData *data, ForParticleFunc func, int s
 	ParticleSystem *psys= data->psys;
 	ParticleData *pa;
 	ParticleEditKey *key;
+	ParticleEditSettings *pset= PE_settings(data->scene);
 	int i, k, totpart;
 
 	totpart= psys->totpart;
 
 	/* all is selected in path mode */
-	if(data->scene->selectmode==SCE_SELECT_PATH)
+	if(pset->selectmode==SCE_SELECT_PATH)
 		selected=0;
 
 	LOOP_PARTICLES(i, pa) {
 		if(pa->flag & PARS_HIDE) continue;
 
-		if(data->scene->selectmode==SCE_SELECT_END) {
+		if(pset->selectmode==SCE_SELECT_END) {
 			/* only do end keys */
 			key= psys->edit->keys[i] + pa->totkey-1;
 
@@ -522,6 +524,7 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
 	ParticleData *pa;
 	ParticleEditKey *key;
 	ParticleSystemModifierData *psmd=0;
+	ParticleEditSettings *pset= PE_settings(data->scene);
 	int i, k, totpart;
 	float mat[4][4], imat[4][4];
 
@@ -529,7 +532,7 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
 	totpart= psys->totpart;
 
 	/* all is selected in path mode */
-	if(data->scene->selectmode==SCE_SELECT_PATH)
+	if(pset->selectmode==SCE_SELECT_PATH)
 		selected= 0;
 
 	Mat4One(imat);
@@ -541,7 +544,7 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
 		psys_mat_hair_to_global(data->ob, psmd->dm, psys->part->from, pa, mat);
 		Mat4Invert(imat,mat);
 
-		if(data->scene->selectmode==SCE_SELECT_END) {
+		if(pset->selectmode==SCE_SELECT_END) {
 			/* only do end keys */
 			key= psys->edit->keys[i] + pa->totkey-1;
 
@@ -610,6 +613,7 @@ static int count_selected_keys(Scene *scene, ParticleSystem *psys)
 {
 	ParticleData *pa;
 	ParticleEditKey *key;
+	ParticleEditSettings *pset= PE_settings(scene);
 	int i, k, totpart, sel= 0;
 
 	totpart= psys->totpart;
@@ -619,12 +623,12 @@ static int count_selected_keys(Scene *scene, ParticleSystem *psys)
 
 		key= psys->edit->keys[i];
 
-		if(scene->selectmode==SCE_SELECT_POINT) {
+		if(pset->selectmode==SCE_SELECT_POINT) {
 			for(k=0; ktotkey; k++,key++)
 				if(key->flag & PEK_SELECT)
 					sel++;
 		}
-		else if(scene->selectmode==SCE_SELECT_END) {
+		else if(pset->selectmode==SCE_SELECT_END) {
 			key += pa->totkey-1;
 
 			if(key->flag & PEK_SELECT)
@@ -1454,6 +1458,7 @@ int PE_lasso_select(bContext *C, short mcords[][2], short moves, short select)
 	ParticleEdit *edit;
 	ParticleData *pa;
 	ParticleEditKey *key;
+	ParticleEditSettings *pset= PE_settings(scene);
 	float co[3], mat[4][4];
 	short vertco[2];
 	int i, k, totpart;
@@ -1470,7 +1475,7 @@ int PE_lasso_select(bContext *C, short mcords[][2], short moves, short select)
 
 		psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
 
-		if(scene->selectmode==SCE_SELECT_POINT) {
+		if(pset->selectmode==SCE_SELECT_POINT) {
 			LOOP_KEYS(k, key) {
 				VECCOPY(co, key->co);
 				Mat4MulVecfl(mat, co);
@@ -1487,7 +1492,7 @@ int PE_lasso_select(bContext *C, short mcords[][2], short moves, short select)
 				}
 			}
 		}
-		else if(scene->selectmode==SCE_SELECT_END) {
+		else if(pset->selectmode==SCE_SELECT_END) {
 			key= edit->keys[i] + pa->totkey - 1;
 
 			VECCOPY(co, key->co);
@@ -2349,7 +2354,7 @@ enum { DEL_PARTICLE, DEL_KEY };
 static EnumPropertyItem delete_type_items[]= {
 	{DEL_PARTICLE, "PARTICLE", 0, "Particle", ""},
 	{DEL_KEY, "KEY", 0, "Key", ""},
-	{0, NULL, NULL}};
+	{0, NULL, 0, NULL, NULL}};
 
 static void set_delete_particle(PEData *data, int pa_index)
 {
@@ -3842,6 +3847,7 @@ void PE_change_act_psys(Scene *scene, Object *ob, ParticleSystem *psys)
 static int specials_menu_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
 	Scene *scene= CTX_data_scene(C);
+	ParticleEditSettings *pset=PE_settings(scene);
 	uiPopupMenu *pup;
 	uiLayout *layout;
 
@@ -3849,7 +3855,7 @@ static int specials_menu_invoke(bContext *C, wmOperator *op, wmEvent *event)
 	layout= uiPupMenuLayout(pup);
 
 	uiItemO(layout, NULL, 0, "PARTICLE_OT_rekey");
-	if(scene->selectmode & SCE_SELECT_POINT) {
+	if(pset->selectmode & SCE_SELECT_POINT) {
 		uiItemO(layout, NULL, 0, "PARTICLE_OT_subdivide");
 		uiItemO(layout, NULL, 0, "PARTICLE_OT_select_first");
 		uiItemO(layout, NULL, 0, "PARTICLE_OT_select_last");
diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h
index cbc94b3a058..e03649575cb 100644
--- a/source/blender/editors/physics/physics_intern.h
+++ b/source/blender/editors/physics/physics_intern.h
@@ -1,5 +1,5 @@
 /*
- * $Id: physics_intern.h 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/preview/Makefile b/source/blender/editors/preview/Makefile
index c44da6753f3..48e1dc64673 100644
--- a/source/blender/editors/preview/Makefile
+++ b/source/blender/editors/preview/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/preview/previewrender.c b/source/blender/editors/preview/previewrender.c
index 1ce20fcb0af..1efa5108b96 100644
--- a/source/blender/editors/preview/previewrender.c
+++ b/source/blender/editors/preview/previewrender.c
@@ -114,46 +114,12 @@ typedef struct ShaderPreview {
 	ID *id;
 	
 	int sizex, sizey;
+	int *pr_rect;
 	int pr_method;
 	
 } ShaderPreview;
 
 
-static void set_previewrect(ScrArea *sa, RenderInfo *ri)
-{
-	ARegion *ar= NULL; // XXX
-	rctf viewplane;
-	
-	BLI_init_rctf(&viewplane, PR_XMIN, PR_XMAX, PR_YMIN, PR_YMAX);
-
-//	ui_graphics_to_window_rct(ar->win, &viewplane, &ri->disprect);
-	
-	/* correction for gla draw */
-	BLI_translate_rcti(&ri->disprect, -ar->winrct.xmin, -ar->winrct.ymin);
-	
-	glMatrixMode(GL_PROJECTION);
-	glPushMatrix();
-	glMatrixMode(GL_MODELVIEW);
-	glPushMatrix();
-	
-	glaDefine2DArea(&ar->winrct);
-
-	ri->pr_rectx= (ri->disprect.xmax-ri->disprect.xmin);
-	ri->pr_recty= (ri->disprect.ymax-ri->disprect.ymin);
-}
-
-static void end_previewrect(ARegion *ar)
-{
-	glMatrixMode(GL_PROJECTION);
-	glPopMatrix();
-	glMatrixMode(GL_MODELVIEW);
-	glPopMatrix();
-	
-	// restore viewport / scissor which was set by glaDefine2DArea
-	glViewport(ar->winrct.xmin, ar->winrct.ymin, ar->winx, ar->winy);
-	glScissor(ar->winrct.xmin, ar->winrct.ymin, ar->winx, ar->winy);
-
-}
 
 /* unused now */
 void draw_tex_crop(Tex *tex)
@@ -438,196 +404,6 @@ static Scene *preview_prepare_scene(Scene *scene, int id_type, ShaderPreview *sp
 	return NULL;
 }
 
-void previewrender_progress(void *handle, RenderResult *rr, volatile rcti *renrect)
-{
-	SpaceButs *sbuts= NULL; // XXX
-	RenderLayer *rl;
-	RenderInfo *ri= sbuts->ri;
-	float ofsx, ofsy;
-	
-	if(renrect) return;
-	
-	rl= rr->layers.first;
-	
-	ofsx= ri->disprect.xmin + rr->tilerect.xmin;
-	ofsy= ri->disprect.ymin + rr->tilerect.ymin;
-	
-	glDrawBuffer(GL_FRONT);
-	glaDrawPixelsSafe_to32(ofsx, ofsy, rr->rectx, rr->recty, rr->rectx, rl->rectf);
-	bglFlush();
-	glDrawBuffer(GL_BACK);
-}
-
-
-/* called by interface_icons.c, or by BIF_previewrender_buts or by nodes... */
-void BIF_previewrender(Scene *scene, struct ID *id, struct RenderInfo *ri, struct ScrArea *area, int pr_method)
-{
-	SpaceButs *sbuts= NULL; // XXX
-	Render *re;
-	RenderStats *rstats;
-	Scene *sce;
-	int oldx= ri->pr_rectx, oldy= ri->pr_recty;
-	char name [32];
-	
-	if(ri->tottile && ri->curtile>=ri->tottile) return;
-	
-	/* check for return with a new event */
-	if(pr_method!=PR_ICON_RENDER && qtest()) {
-//		if(area)
-//			addafterqueue(area->win, RENDERPREVIEW, 1);
-		return;
-	}
-	
-	/* get the stuff from the builtin preview dbase */
-//	sce= preview_prepare_scene(scene, ri, GS(id->name), id, pr_method);
-	if(sce==NULL) return;
-	
-	/* set drawing conditions OK */
-	if(area) {
-		sbuts= area->spacedata.first;	/* needed for flag */
-		
-		set_previewrect(area, ri); // uses UImat
-		
-		/* because preview render size can differs */
-		if(ri->rect && (oldx!=ri->pr_rectx || oldy!=ri->pr_recty)) {
-			MEM_freeN(ri->rect);
-			ri->rect= NULL;
-			ri->curtile= 0;
-		}
-	}
-	
-// XXX	sprintf(name, "ButsPreview %d", area?area->win:0);
-	re= RE_GetRender(name);
-	
-	/* full refreshed render from first tile */
-	if(re==NULL || ri->curtile==0) {
-		
-		re= RE_NewRender(name);
-		
-		/* handle cases */
-		if(pr_method==PR_DRAW_RENDER) {
-//			RE_display_draw_cb(re, previewrender_progress);
-//			RE_test_break_cb(re, qtest);
-			sce->r.scemode |= R_NODE_PREVIEW;
-			if(sbuts->flag & SB_PRV_OSA)
-				sce->r.mode |= R_OSA;
-			sce->r.scemode &= ~R_NO_IMAGE_LOAD;
-		}
-		else if(pr_method==PR_DO_RENDER) {
-//			RE_test_break_cb(re, qtest);
-			sce->r.scemode |= R_NODE_PREVIEW;
-			sce->r.scemode &= ~R_NO_IMAGE_LOAD;
-		}
-		else {	/* PR_ICON_RENDER */
-			sce->r.scemode &= ~R_NODE_PREVIEW;
-			sce->r.scemode |= R_NO_IMAGE_LOAD;
-		}
-		
-		/* allocates render result */
-		RE_InitState(re, NULL, &sce->r, ri->pr_rectx, ri->pr_recty, NULL);
-		
-		/* enforce preview image clear */
-		if(GS(id->name)==ID_MA) {
-			Material *ma= (Material *)id;
-			ntreeClearPreview(ma->nodetree);
-		}
-	}
-	/* entire cycle for render engine */
-	RE_SetCamera(re, sce->camera);
-	RE_Database_FromScene(re, sce, 1);
-	RE_TileProcessor(re, ri->curtile, 0);	// actual render engine
-	RE_Database_Free(re);
-	
-	/* handle results */
-	if(pr_method==PR_ICON_RENDER) {
-		if(ri->rect==NULL)
-			ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
-		RE_ResultGet32(re, ri->rect);
-	}
-	else {
-		rstats= RE_GetStats(re);
-		
-		if(rstats->partsdone!=ri->curtile) {
-			if(ri->rect==NULL)
-				ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
-			RE_ResultGet32(re, ri->rect);
-		}
-		
-		if(rstats->totpart==rstats->partsdone && rstats->partsdone) {
-			// allqueues
-		}
-		else {
-//			if(pr_method==PR_DRAW_RENDER && qtest())
-//				addafterqueue(area->win, RENDERPREVIEW, 1);
-		}
-		
-		ri->curtile= rstats->partsdone;
-		ri->tottile= rstats->totpart;
-	}
-
-	/* unassign the pointers, reset vars */
-//	preview_prepare_scene(scene, ri, GS(id->name), NULL, 0);
-	
-}
-
-
-/* afterqueue call */
-void BIF_previewrender_buts(Scene *scene, SpaceButs *sbuts)
-{
-//	ScrArea *sa= NULL; // XXX
-	ARegion *ar= NULL; // XXX
-	uiBlock *block;
-	struct ID* id = 0;
-//	struct ID* idfrom = 0;
-	struct ID* idshow = 0;
-	Object *ob;
-	
-	if (!sbuts->ri) return;
-	
-	
-//	block= uiFindOpenPanelBlockName(&sa->uiblocks, "Preview");
-	if(block==NULL) return;
-	
-	ob= ((scene->basact)? (scene->basact)->object: 0);
-	
-	/* we cant trust this global lockpoin.. for example with headerless window */
-//	buttons_active_id(&id, &idfrom);
-	sbuts->lockpoin= id;
-	
-	if(sbuts->mainb==CONTEXT_SHADING) {
-		int tab= TAB_SHADING_MAT; // XXX sbuts->tab[CONTEXT_SHADING];
-		
-		if(tab==TAB_SHADING_MAT) 
-			idshow = sbuts->lockpoin;
-		else if(tab==TAB_SHADING_TEX) 
-			idshow = sbuts->lockpoin;
-		else if(tab==TAB_SHADING_LAMP) {
-			if(ob && ob->type==OB_LAMP) idshow= ob->data;
-		}
-		else if(tab==TAB_SHADING_WORLD)
-			idshow = sbuts->lockpoin;
-	}
-	else if(sbuts->mainb==CONTEXT_OBJECT) {
-		if(ob && ob->type==OB_LAMP) idshow = ob->data;
-	}
-	
-	if (idshow) {
-		BKE_icon_changed(BKE_icon_getid(idshow));
-//		uiPanelPush(block);
-//		BIF_previewrender(scene, idshow, sbuts->ri, sbuts->area, PR_DRAW_RENDER);
-//		uiPanelPop(block);
-		end_previewrect(ar);
-	}
-	else {
-		/* no active block to draw. But we do draw black if possible */
-		if(sbuts->ri->rect) {
-			memset(sbuts->ri->rect, 0, sizeof(int)*sbuts->ri->pr_rectx*sbuts->ri->pr_recty);
-			sbuts->ri->tottile= 10000;
-//			addqueue(sa->win, REDRAW, 1);
-		}
-		return;
-	}
-}
 
 /* new UI convention: draw is in pixel space already. */
 /* uses ROUNDBOX button in block to get the rect */
@@ -1006,7 +782,7 @@ static void shader_preview_updatejob(void *spv)
 	
 }
 
-/* runs inside thread */
+/* runs inside thread for material, in foreground for icons */
 static void shader_preview_startjob(void *customdata, short *stop, short *do_update)
 {
 	ShaderPreview *sp= customdata;
@@ -1064,9 +840,8 @@ static void shader_preview_startjob(void *customdata, short *stop, short *do_upd
 
 	/* handle results */
 	if(sp->pr_method==PR_ICON_RENDER) {
-		//if(ri->rect==NULL)
-		//	ri->rect= MEM_mallocN(sizeof(int)*ri->pr_rectx*ri->pr_recty, "BIF_previewrender");
-		//RE_ResultGet32(re, ri->rect);
+		if(sp->pr_rect)
+			RE_ResultGet32(re, sp->pr_rect);
 	}
 	else {
 		/* validate owner */
@@ -1113,6 +888,29 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, int sizex, in
 	WM_jobs_callbacks(steve, shader_preview_startjob, NULL, shader_preview_updatejob);
 	
 	WM_jobs_start(CTX_wm_manager(C), steve);
+	
+	/* signal to rerender icon in menus */
+	BKE_icon_changed(BKE_icon_getid(id));
+}
+
+/* rect should be allocated, sizex/sizy pixels, 32 bits */
+void ED_preview_iconrender(Scene *scene, ID *id, int *rect, int sizex, int sizey)
+{
+	ShaderPreview *sp= MEM_callocN(sizeof(ShaderPreview), "ShaderPreview");
+	short stop=0, do_update=0;
+	
+	/* customdata for preview thread */
+	sp->scene= scene;
+	sp->sizex= sizex;
+	sp->sizey= sizey;
+	sp->pr_method= PR_ICON_RENDER;
+	sp->pr_rect= rect;
+	sp->id = id;
+
+	shader_preview_startjob(sp, &stop, &do_update);
+	
+	MEM_freeN(sp);
 }
 
 
+
diff --git a/source/blender/editors/screen/Makefile b/source/blender/editors/screen/Makefile
index cf6e692c304..923a020afcf 100644
--- a/source/blender/editors/screen/Makefile
+++ b/source/blender/editors/screen/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 07d8fb370e6..535e99ccfef 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -259,14 +259,16 @@ static void region_scissor_winrct(ARegion *ar, rcti *winrct)
 	while(ar->prev) {
 		ar= ar->prev;
 		
-		if(ar->flag & RGN_FLAG_HIDDEN);
-		else if(ar->alignment==RGN_OVERLAP_LEFT) {
-			winrct->xmin= ar->winrct.xmax + 1;
+		if(BLI_isect_rcti(winrct, &ar->winrct, NULL)) {
+			if(ar->flag & RGN_FLAG_HIDDEN);
+			else if(ar->alignment==RGN_OVERLAP_LEFT) {
+				winrct->xmin= ar->winrct.xmax + 1;
+			}
+			else if(ar->alignment==RGN_OVERLAP_RIGHT) {
+				winrct->xmax= ar->winrct.xmin - 1;
+			}
+			else break;
 		}
-		else if(ar->alignment==RGN_OVERLAP_RIGHT) {
-			winrct->xmax= ar->winrct.xmin - 1;
-		}
-		else break;
 	}
 }
 
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index a81a52fd544..a23487effa1 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -1,5 +1,5 @@
 /**
- * $Id: glutil.c 11920 2007-09-02 17:25:03Z elubie $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 2aa6758850e..dcfdfbf8285 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -59,6 +59,7 @@
 #include "ED_util.h"
 #include "ED_screen.h"
 #include "ED_mesh.h"
+#include "ED_object.h"
 #include "ED_screen_types.h"
 
 #include "RE_pipeline.h"
@@ -2509,7 +2510,9 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
 	/* flush multires changes (for sculpt) */
 	multires_force_update(CTX_data_active_object(C));
 	
-	// get editmode results
+	/* get editmode results */
+	ED_object_exit_editmode(C, 0);	/* 0 = does not exit editmode */
+	
 	// store spare
 	// get view3d layer, local layer, make this nice api call to render
 	// store spare
diff --git a/source/blender/editors/sculpt_paint/Makefile b/source/blender/editors/sculpt_paint/Makefile
index 9353116a4bc..012a39b8d25 100644
--- a/source/blender/editors/sculpt_paint/Makefile
+++ b/source/blender/editors/sculpt_paint/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index fa33e214737..a2b883eabfc 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -1,5 +1,5 @@
 /*
- * $Id: sculptmode.c 18309 2009-01-04 07:47:11Z nicholasbishop $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -148,6 +148,7 @@ typedef struct StrokeCache {
 	float *layer_disps; /* Displacements for each vertex */
  	float (*mesh_store)[3]; /* Copy of the mesh vertices' locations */
 	short (*orig_norms)[3]; /* Copy of the mesh vertices' normals */
+	float (*face_norms)[3]; /* Copy of the mesh faces' normals */
 	float rotation; /* Texture rotation (radians) for anchored and rake modes */
 	int pixel_radius, previous_pixel_radius;
 	ListBase grab_active_verts[8]; /* The same list of verts is used throught grab stroke */
@@ -155,7 +156,6 @@ typedef struct StrokeCache {
 	float old_grab_location[3];
 	int symmetry; /* Symmetry index between 0 and 7 */
 	float view_normal[3], view_normal_symmetry[3];
-	int last_dot[2]; /* Last location of stroke application */
 	int last_rake[2]; /* Last location of updating rake rotation */
 } StrokeCache;
 
@@ -240,7 +240,6 @@ static float brush_strength(Sculpt *sd, StrokeCache *cache)
 	float dir= sd->brush->flag & BRUSH_DIR_IN ? -1 : 1;
 	float pressure= 1;
 	float flip= cache->flip ? -1:1;
-	float anchored = sd->brush->flag & BRUSH_ANCHORED ? 25 : 1;
 
 	if(sd->brush->flag & BRUSH_ALPHA_PRESSURE)
 		pressure *= cache->pressure;
@@ -250,6 +249,7 @@ static float brush_strength(Sculpt *sd, StrokeCache *cache)
 	case SCULPT_TOOL_INFLATE:
 	case SCULPT_TOOL_CLAY:
 	case SCULPT_TOOL_FLATTEN:
+	case SCULPT_TOOL_LAYER:
 		return alpha * dir * pressure * flip; /*XXX: not sure why? was multiplied by G.vd->grid */;
 	case SCULPT_TOOL_SMOOTH:
 		return alpha * 4 * pressure;
@@ -257,46 +257,27 @@ static float brush_strength(Sculpt *sd, StrokeCache *cache)
 		return alpha / 2 * dir * pressure * flip;
 	case SCULPT_TOOL_GRAB:
 		return 1;
-	case SCULPT_TOOL_LAYER:
-		return sd->brush->alpha / 50.0f * dir * pressure * flip * anchored; /*XXX: not sure why? multiplied by G.vd->grid */;
 	default:
 		return 0;
 	}
 }
 
-/* For clipping against a mirror modifier */
-static void sculpt_clip(StrokeCache *cache, float *co, const float val[3])
+/* Handles clipping against a mirror modifier and SCULPT_LOCK axis flags */
+static void sculpt_clip(Sculpt *sd, float *co, const float val[3])
 {
 	int i;
+
 	for(i=0; i<3; ++i) {
-		if((cache->flag & (CLIP_X << i)) && (fabs(co[i]) <= cache->clip_tolerance[i]))
+		if(sd->flags & (SCULPT_LOCK_X << i))
+			continue;
+
+		if((sd->session->cache->flag & (CLIP_X << i)) && (fabs(co[i]) <= sd->session->cache->clip_tolerance[i]))
 			co[i]= 0.0f;
 		else
 			co[i]= val[i];
 	}		
 }
 
-static void sculpt_axislock(Sculpt *sd, float *co)
-{
-	if(sd->flags == (SCULPT_LOCK_X|SCULPT_LOCK_Y|SCULPT_LOCK_Z))
-		return;
-
-	if(sd->session->cache->vc.v3d->twmode == V3D_MANIP_LOCAL) {
-		float mat[3][3], imat[3][3];
-		Mat3CpyMat4(mat, sd->session->cache->vc.obact->obmat);
-		Mat3Inv(imat, mat);
-		Mat3MulVecfl(mat, co);
-		if (sd->flags & SCULPT_LOCK_X) co[0] = 0.0;
-		if (sd->flags & SCULPT_LOCK_Y) co[1] = 0.0;
-		if (sd->flags & SCULPT_LOCK_Z) co[2] = 0.0;		
-		Mat3MulVecfl(imat, co);
-	} else {
-		if (sd->flags & SCULPT_LOCK_X) co[0] = 0.0;
-		if (sd->flags & SCULPT_LOCK_Y) co[1] = 0.0;
-		if (sd->flags & SCULPT_LOCK_Z) co[2] = 0.0;		
-	}
-}
-
 static void add_norm_if(float view_vec[3], float out[3], float out_flip[3], const short no[3])
 {
 	float fno[3] = {no[0], no[1], no[2]};
@@ -353,8 +334,6 @@ static void do_draw_brush(Sculpt *sd, SculptSession *ss, const ListBase* active_
 
 	calc_area_normal(sd, area_normal, active_verts);
 	
-	sculpt_axislock(sd, area_normal);
-	
 	while(node){
 		float *co= ss->mvert[node->Index].co;
 
@@ -362,7 +341,7 @@ static void do_draw_brush(Sculpt *sd, SculptSession *ss, const ListBase* active_
 		                     co[1]+area_normal[1]*ss->cache->radius*node->Fade*ss->cache->scale[1],
 		                     co[2]+area_normal[2]*ss->cache->radius*node->Fade*ss->cache->scale[2]};
 		                     
-		sculpt_clip(ss->cache, co, val);
+		sculpt_clip(sd, co, val);
 		
 		node= node->next;
 	}
@@ -412,37 +391,37 @@ static void neighbor_average(SculptSession *ss, float avg[3], const int vert)
 		VecCopyf(avg, ss->mvert[vert].co);
 }
 
-static void do_smooth_brush(SculptSession *ss, const ListBase* active_verts)
+static void do_smooth_brush(Sculpt *s, const ListBase* active_verts)
 {
 	ActiveData *node= active_verts->first;
 	int i;
 	
 	for(i = 0; i < 2; ++i) {
 		while(node){
-			float *co= ss->mvert[node->Index].co;
+			float *co= s->session->mvert[node->Index].co;
 			float avg[3], val[3];
 			
-			neighbor_average(ss, avg, node->Index);
+			neighbor_average(s->session, avg, node->Index);
 			val[0] = co[0]+(avg[0]-co[0])*node->Fade;
 			val[1] = co[1]+(avg[1]-co[1])*node->Fade;
 			val[2] = co[2]+(avg[2]-co[2])*node->Fade;
 			
-			sculpt_clip(ss->cache, co, val);
+			sculpt_clip(s, co, val);
 			node= node->next;
 		}
 	}
 }
 
-static void do_pinch_brush(SculptSession *ss, const ListBase* active_verts)
+static void do_pinch_brush(Sculpt *s, const ListBase* active_verts)
 {
  	ActiveData *node= active_verts->first;
 
 	while(node) {
-		float *co= ss->mvert[node->Index].co;
-		const float val[3]= {co[0]+(ss->cache->location[0]-co[0])*node->Fade,
-		                     co[1]+(ss->cache->location[1]-co[1])*node->Fade,
-		                     co[2]+(ss->cache->location[2]-co[2])*node->Fade};
-		sculpt_clip(ss->cache, co, val);
+		float *co= s->session->mvert[node->Index].co;
+		const float val[3]= {co[0]+(s->session->cache->location[0]-co[0])*node->Fade,
+		                     co[1]+(s->session->cache->location[1]-co[1])*node->Fade,
+		                     co[2]+(s->session->cache->location[2]-co[2])*node->Fade};
+		sculpt_clip(s, co, val);
 		node= node->next;
 	}
 }
@@ -454,7 +433,6 @@ static void do_grab_brush(Sculpt *sd, SculptSession *ss)
 	float grab_delta[3];
 	
 	VecCopyf(grab_delta, ss->cache->grab_delta_symmetry);
-	sculpt_axislock(sd, grab_delta);
 	
 	while(node) {
 		float *co= ss->mvert[node->Index].co;
@@ -462,7 +440,7 @@ static void do_grab_brush(Sculpt *sd, SculptSession *ss)
 		VecCopyf(add, grab_delta);
 		VecMulf(add, node->Fade);
 		VecAddf(add, add, co);
-		sculpt_clip(ss->cache, co, add);
+		sculpt_clip(sd, co, add);
 
 		node= node->next;
 	}
@@ -473,42 +451,38 @@ static void do_layer_brush(Sculpt *sd, SculptSession *ss, const ListBase *active
 {
 	float area_normal[3];
 	ActiveData *node= active_verts->first;
-	float lim= brush_strength(sd, ss->cache);
+	float lim= ss->cache->radius / 4;
 
-	if(sd->brush->flag & BRUSH_DIR_IN)
+	if(ss->cache->flip)
 		lim = -lim;
 
 	calc_area_normal(sd, area_normal, active_verts);
 
 	while(node){
 		float *disp= &ss->cache->layer_disps[node->Index];
+		float *co= ss->mvert[node->Index].co;
+		float val[3];
 		
-		if((lim > 0 && *disp < lim) ||
-		   (lim < 0 && *disp > lim)) {
-		  	float *co= ss->mvert[node->Index].co;
-			float val[3];
-		  	
-			*disp+= node->Fade;
+		*disp+= node->Fade;
+		
+		/* Don't let the displacement go past the limit */
+		if((lim < 0 && *disp < lim) || (lim > 0 && *disp > lim))
+			*disp = lim;
+		
+		val[0] = ss->cache->mesh_store[node->Index][0]+area_normal[0] * *disp*ss->cache->scale[0];
+		val[1] = ss->cache->mesh_store[node->Index][1]+area_normal[1] * *disp*ss->cache->scale[1];
+		val[2] = ss->cache->mesh_store[node->Index][2]+area_normal[2] * *disp*ss->cache->scale[2];
 
-			if(lim < 0 && *disp < lim)
-				*disp = lim;
-			else if(lim > 0 && *disp > lim)
-					*disp = lim;
-
-			val[0] = ss->cache->mesh_store[node->Index][0]+area_normal[0] * *disp*ss->cache->scale[0];
-			val[1] = ss->cache->mesh_store[node->Index][1]+area_normal[1] * *disp*ss->cache->scale[1];
-			val[2] = ss->cache->mesh_store[node->Index][2]+area_normal[2] * *disp*ss->cache->scale[2];
-			//VecMulf(val, ss->cache->radius);
-			sculpt_clip(ss->cache, co, val);
-		}
+		sculpt_clip(sd, co, val);
 
 		node= node->next;
 	}
 }
 
-static void do_inflate_brush(SculptSession *ss, const ListBase *active_verts)
+static void do_inflate_brush(Sculpt *s, const ListBase *active_verts)
 {
 	ActiveData *node= active_verts->first;
+	SculptSession *ss = s->session;
 	float add[3];
 	
 	while(node) {
@@ -524,7 +498,7 @@ static void do_inflate_brush(SculptSession *ss, const ListBase *active_verts)
 		add[2]*= ss->cache->scale[2];
 		VecAddf(add, add, co);
 		
-		sculpt_clip(ss->cache, co, add);
+		sculpt_clip(s, co, add);
 
 		node= node->next;
 	}
@@ -587,7 +561,7 @@ static void do_flatten_clay_brush(Sculpt *sd, SculptSession *ss, const ListBase
 			VecAddf(val, val, tmp);
 		}
 
-		sculpt_clip(ss->cache, co, val);
+		sculpt_clip(sd, co, val);
 		
 		node= node->next;
 	}
@@ -763,37 +737,6 @@ static void sculpt_add_damaged_rect(SculptSession *ss)
 	}
 }
 
-/* Clears the depth buffer in each modified area. */
-#if 0
-static void sculpt_clear_damaged_areas(SculptSession *ss)
-{
-	RectNode *rn= NULL;
-
-	for(rn = ss->damaged_rects.first; rn; rn = rn->next) {
-		rcti clp = rn->r;
-		rcti *win = NULL; /*XXX: &curarea->winrct; */
-		
-		clp.xmin += win->xmin;
-		clp.xmax += win->xmin;
-		clp.ymin += win->ymin;
-		clp.ymax += win->ymin;
-		
-		if(clp.xmin < win->xmax && clp.xmax > win->xmin &&
-		   clp.ymin < win->ymax && clp.ymax > win->ymin) {
-			if(clp.xmin < win->xmin) clp.xmin = win->xmin;
-			if(clp.ymin < win->ymin) clp.ymin = win->ymin;
-			if(clp.xmax > win->xmax) clp.xmax = win->xmax;
-			if(clp.ymax > win->ymax) clp.ymax = win->ymax;
-
-			glScissor(clp.xmin + 1, clp.ymin + 1,
-				  clp.xmax - clp.xmin - 2,
-				  clp.ymax - clp.ymin - 2);
-		}
-		
-		glClear(GL_DEPTH_BUFFER_BIT);
-	}
-}
-#endif
 static void do_brush_action(Sculpt *sd, StrokeCache *cache)
 {
 	SculptSession *ss = sd->session;
@@ -845,13 +788,13 @@ static void do_brush_action(Sculpt *sd, StrokeCache *cache)
 			do_draw_brush(sd, ss, &active_verts);
 			break;
 		case SCULPT_TOOL_SMOOTH:
-			do_smooth_brush(ss, &active_verts);
+			do_smooth_brush(sd, &active_verts);
 			break;
 		case SCULPT_TOOL_PINCH:
-			do_pinch_brush(ss, &active_verts);
+			do_pinch_brush(sd, &active_verts);
 			break;
 		case SCULPT_TOOL_INFLATE:
-			do_inflate_brush(ss, &active_verts);
+			do_inflate_brush(sd, &active_verts);
 			break;
 		case SCULPT_TOOL_GRAB:
 			do_grab_brush(sd, ss);
@@ -905,15 +848,6 @@ static void do_symmetrical_brush_actions(Sculpt *sd, StrokeCache *cache)
 	const char symm = sd->flags & 7;
 	int i;
 
-	/* Brush spacing: only apply dot if next dot is far enough away */
-	if((sd->brush->flag & BRUSH_SPACE) && !(sd->brush->flag & BRUSH_ANCHORED) && !cache->first_time) {
-		int dx = cache->last_dot[0] - cache->mouse[0];
-		int dy = cache->last_dot[1] - cache->mouse[1];
-		if(sqrt(dx*dx+dy*dy) < sd->brush->spacing)
-			return;
-	}
-	memcpy(cache->last_dot, cache->mouse, sizeof(int) * 2);
-
 	VecCopyf(cache->location, cache->true_location);
 	VecCopyf(cache->grab_delta_symmetry, cache->grab_delta);
 	cache->symmetry = 0;
@@ -1012,25 +946,6 @@ static void sculpt_update_tex(Sculpt *sd)
 	}
 }
 
-void sculptmode_selectbrush_menu(void)
-{
-	/* XXX: I guess menus belong elsewhere too?
-
-	Sculpt *sd= sculpt_data();
-	int val;
-	
-	pupmenu_set_active(sd->brush_type);
-	
-	val= pupmenu("Select Brush%t|Draw|Smooth|Pinch|Inflate|Grab|Layer|Flatten");
-
-	if(val>0) {
-		sd->brush_type= val;
-
-		allqueue(REDRAWVIEW3D, 1);
-		allqueue(REDRAWBUTSEDIT, 1);
-	}*/
-}
-
 static void sculptmode_update_all_projverts(SculptSession *ss)
 {
 	unsigned i;
@@ -1109,89 +1024,11 @@ static void sculpt_update_mesh_elements(bContext *C)
 	}
 }
 
-/* XXX: lots of drawing code (partial redraw), has to go elsewhere */
-#if 0
-void sculptmode_draw_wires(SculptSession *ss, int only_damaged)
+static int sculpt_mode_poll(bContext *C)
 {
-	Mesh *me = get_mesh(OBACT);
-	int i;
-
-	bglPolygonOffset(1.0);
-	glDepthMask(0);
-	BIF_ThemeColor((OBACT==OBACT)?TH_ACTIVE:TH_SELECT);
-
-	for(i=0; itotedge; i++) {
-		MEdge *med= &me->medge[i];
-
-		if((!only_damaged || (ss->projverts[med->v1].inside || ss->projverts[med->v2].inside)) &&
-		   (med->flag & ME_EDGEDRAW)) {
-			glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, &med->v1);
-		}
-	}
-
-	glDepthMask(1);
-	bglPolygonOffset(0.0);
+	return G.f & G_SCULPTMODE;
 }
 
-void sculptmode_draw_mesh(int only_damaged) 
-{
-	int i, j, dt, drawCurrentMat = 1, matnr= -1;
-	SculptSession *ss = sculpt_session();
-
-	sculpt_update_mesh_elements(ss, OBACT);
-
-	persp(PERSP_VIEW);
-	mymultmatrix(OBACT->obmat);
-	glEnable(GL_DEPTH_TEST);
-	glEnable(GL_LIGHTING);
-	/* XXX: GPU_set_object_materials(G.scene, OBACT, 0, NULL); */
-	glEnable(GL_CULL_FACE);
-
-	glShadeModel(GL_SMOOTH);
-
-	glVertexPointer(3, GL_FLOAT, sizeof(MVert), &cache->mvert[0].co);
-	glNormalPointer(GL_SHORT, sizeof(MVert), &cache->mvert[0].no);
-
-	dt= MIN2(G.vd->drawtype, OBACT->dt);
-	if(dt==OB_WIRE)
-		glColorMask(0,0,0,0);
-
-	for(i=0; itotface; ++i) {
-		MFace *f= &ss->mface[i];
-		char inside= 0;
-		int new_matnr= f->mat_nr + 1;
-		
-		if(new_matnr != matnr)
-			drawCurrentMat= GPU_enable_material(matnr = new_matnr, NULL);
-		
-		/* If only_damaged!=0, only draw faces that are partially
-		   inside the area(s) modified by the brush */
-		if(only_damaged) {
-			for(j=0; j<(f->v4?4:3); ++j) {
-				if(ss->projverts[*((&f->v1)+j)].inside) {
-					inside= 1;
-					break;
-				}
-			}
-		}
-		else
-			inside= 1;
-			
-		if(inside && drawCurrentMat)
-			glDrawElements(f->v4?GL_QUADS:GL_TRIANGLES, f->v4?4:3, GL_UNSIGNED_INT, &f->v1);
-	}
-
-	glDisable(GL_CULL_FACE);
-	glDisable(GL_LIGHTING);
-	glColorMask(1,1,1,1);
-
-	if(dt==OB_WIRE || (OBACT->dtx & OB_DRAWWIRE))
-		sculptmode_draw_wires(ss, only_damaged);
-
-	glDisable(GL_DEPTH_TEST);
-}
-#endif
-
 static int sculpt_poll(bContext *C)
 {
 	return G.f & G_SCULPTMODE && CTX_wm_area(C)->spacetype == SPACE_VIEW3D &&
@@ -1203,16 +1040,21 @@ static void draw_paint_cursor(bContext *C, int x, int y, void *customdata)
 {
 	Sculpt *sd= CTX_data_tool_settings(C)->sculpt;
 	
-	glTranslatef((float)x, (float)y, 0.0f);
-	
 	glColor4ub(255, 100, 100, 128);
 	glEnable( GL_LINE_SMOOTH );
 	glEnable(GL_BLEND);
+
+	glTranslatef((float)x, (float)y, 0.0f);
 	glutil_draw_lined_arc(0.0, M_PI*2.0, sd->brush->size, 40);
+	glTranslatef((float)-x, (float)-y, 0.0f);
+
+	if(sd->session && sd->session->cache && sd->brush && (sd->brush->flag & BRUSH_SMOOTH_STROKE)) {
+		ARegion *ar = CTX_wm_region(C);
+		sdrawline(x, y, sd->session->cache->mouse[0] - ar->winrct.xmin, sd->session->cache->mouse[1] - ar->winrct.ymin);
+	}
+
 	glDisable(GL_BLEND);
 	glDisable( GL_LINE_SMOOTH );
-	
-	glTranslatef((float)-x, (float)-y, 0.0f);
 }
 
 static void toggle_paint_cursor(bContext *C)
@@ -1269,7 +1111,7 @@ static void SCULPT_OT_brush_curve_preset(wmOperatorType *ot)
 	ot->idname= "SCULPT_OT_brush_curve_preset";
 
 	ot->exec= sculpt_brush_curve_preset_exec;
-	ot->poll= sculpt_poll;
+	ot->poll= sculpt_mode_poll;
 
 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 
@@ -1334,6 +1176,8 @@ static void sculpt_cache_free(StrokeCache *cache)
 		MEM_freeN(cache->mesh_store);
 	if(cache->orig_norms)
 		MEM_freeN(cache->orig_norms);
+	if(cache->face_norms)
+		MEM_freeN(cache->face_norms);
 	if(cache->mats)
 		MEM_freeN(cache->mats);
 	MEM_freeN(cache);
@@ -1353,6 +1197,9 @@ static void sculpt_update_cache_invariants(Sculpt *sd, bContext *C, wmOperator *
 	RNA_int_get_array(op->ptr, "initial_mouse", cache->initial_mouse);
 	cache->depth = RNA_float_get(op->ptr, "depth");
 
+	cache->mouse[0] = cache->initial_mouse[0];
+	cache->mouse[1] = cache->initial_mouse[1];
+
 	/* Truly temporary data that isn't stored in properties */
 
 	view3d_set_viewcontext(C, &cache->vc);
@@ -1362,9 +1209,11 @@ static void sculpt_update_cache_invariants(Sculpt *sd, bContext *C, wmOperator *
 
 	sculpt_update_mesh_elements(C);
 
+	if(sd->brush->sculpt_tool == SCULPT_TOOL_LAYER)
+		cache->layer_disps = MEM_callocN(sizeof(float) * sd->session->totvert, "layer brush displacements");
+
 	/* Make copies of the mesh vertex locations and normals for some tools */
 	if(sd->brush->sculpt_tool == SCULPT_TOOL_LAYER || (sd->brush->flag & BRUSH_ANCHORED)) {
-		cache->layer_disps = MEM_callocN(sizeof(float) * sd->session->totvert, "layer brush displacements");
 		cache->mesh_store= MEM_mallocN(sizeof(float) * 3 * sd->session->totvert, "sculpt mesh vertices copy");
 		for(i = 0; i < sd->session->totvert; ++i)
 			VecCopyf(cache->mesh_store[i], sd->session->mvert[i].co);
@@ -1376,6 +1225,13 @@ static void sculpt_update_cache_invariants(Sculpt *sd, bContext *C, wmOperator *
 				cache->orig_norms[i][1] = sd->session->mvert[i].no[1];
 				cache->orig_norms[i][2] = sd->session->mvert[i].no[2];
 			}
+
+			if(sd->session->face_normals) {
+				float *fn = sd->session->face_normals;
+				cache->face_norms= MEM_mallocN(sizeof(float) * 3 * sd->session->totface, "Sculpt face norms");
+				for(i = 0; i < sd->session->totface; ++i, fn += 3)
+					VecCopyf(cache->face_norms[i], fn);
+			}
 		}
 	}
 
@@ -1485,9 +1341,6 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *even
 	Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
 
 	view3d_operator_needs_opengl(C);
-	sculpt_brush_stroke_init_properties(C, op, event, sd->session);
-
-	sculptmode_update_all_projverts(sd->session);
 
 	/* TODO: Shouldn't really have to do this at the start of every
 	   stroke, but sculpt would need some sort of notification when
@@ -1502,17 +1355,27 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *even
 
 static void sculpt_restore_mesh(Sculpt *sd)
 {
-	StrokeCache *cache = sd->session->cache;
+	SculptSession *ss = sd->session;
+	StrokeCache *cache = ss->cache;
 	int i;
 	
 	/* Restore the mesh before continuing with anchored stroke */
 	if((sd->brush->flag & BRUSH_ANCHORED) && cache->mesh_store) {
-		for(i = 0; i < sd->session->totvert; ++i) {
-			VecCopyf(sd->session->mvert[i].co, cache->mesh_store[i]);
-			sd->session->mvert[i].no[0] = cache->orig_norms[i][0];
-			sd->session->mvert[i].no[1] = cache->orig_norms[i][1];
-			sd->session->mvert[i].no[2] = cache->orig_norms[i][2];
+		for(i = 0; i < ss->totvert; ++i) {
+			VecCopyf(ss->mvert[i].co, cache->mesh_store[i]);
+			ss->mvert[i].no[0] = cache->orig_norms[i][0];
+			ss->mvert[i].no[1] = cache->orig_norms[i][1];
+			ss->mvert[i].no[2] = cache->orig_norms[i][2];
 		}
+
+		if(ss->face_normals) {
+			float *fn = ss->face_normals;
+			for(i = 0; i < ss->totface; ++i, fn += 3)
+				VecCopyf(fn, cache->face_norms[i]);
+		}
+
+		if(sd->brush->sculpt_tool == SCULPT_TOOL_LAYER)
+			memset(cache->layer_disps, 0, sizeof(float) * ss->totvert);
 	}
 }
 
@@ -1542,38 +1405,141 @@ static void sculpt_flush_update(bContext *C)
 	ED_region_tag_redraw(ar);
 }
 
-static int sculpt_brush_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
+/* Returns zero if no sculpt changes should be made, non-zero otherwise */
+static int sculpt_smooth_stroke(Sculpt *s, int output[2], wmEvent *event)
+{
+	output[0] = event->x;
+	output[1] = event->y;
+
+	if(s->brush->flag & BRUSH_SMOOTH_STROKE && s->brush->sculpt_tool != SCULPT_TOOL_GRAB) {
+		StrokeCache *cache = s->session->cache;
+		float u = .9, v = 1.0 - u;
+		int dx = cache->mouse[0] - event->x, dy = cache->mouse[1] - event->y;
+		int radius = 50;
+
+		/* If the mouse is moving within the radius of the last move,
+		   don't update the mouse position. This allows sharp turns. */
+		if(dx*dx + dy*dy < radius*radius)
+			return 0;
+
+		output[0] = event->x * v + cache->mouse[0] * u;
+		output[1] = event->y * v + cache->mouse[1] * u;
+	}
+
+	return 1;
+}
+
+/* Returns zero if the stroke dots should not be spaced, non-zero otherwise */
+int sculpt_space_stroke_enabled(Sculpt *s)
+{
+	Brush *br = s->brush;
+	return (br->flag & BRUSH_SPACE) && !(br->flag & BRUSH_ANCHORED) && (br->sculpt_tool != SCULPT_TOOL_GRAB);
+}
+
+/* Put the location of the next sculpt stroke dot into the stroke RNA and apply it to the mesh */
+static void sculpt_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *event, int mouse[2])
 {
-	PointerRNA itemptr;
 	Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+	StrokeCache *cache = sd->session->cache;
+	PointerRNA itemptr;
+	float cur_depth;
 	float center[3];
-	int mouse[2] = {event->x, event->y};
-
-	sculpt_update_mesh_elements(C);
-
-	unproject(sd->session->cache->mats, center, event->x, event->y,
-		  read_cached_depth(&sd->session->cache->vc, event->x, event->y));
 
+	cur_depth = read_cached_depth(&cache->vc, mouse[0], mouse[1]);
+	unproject(sd->session->cache->mats, center, mouse[0], mouse[1], cur_depth);
+				
 	/* Add to stroke */
 	RNA_collection_add(op->ptr, "stroke", &itemptr);
 	RNA_float_set_array(&itemptr, "location", center);
 	RNA_int_set_array(&itemptr, "mouse", mouse);
 	RNA_boolean_set(&itemptr, "flip", event->shift);
 	sculpt_update_cache_variants(sd, &itemptr);
-
+				
 	sculpt_restore_mesh(sd);
-	do_symmetrical_brush_actions(CTX_data_tool_settings(C)->sculpt, sd->session->cache);
-
-	sculpt_flush_update(C);
+	do_symmetrical_brush_actions(sd, cache);
+				
 	sculpt_post_stroke_free(sd->session);
+}
+
+/* For brushes with stroke spacing enabled, moves mouse in steps
+   towards the final mouse location. */
+static int sculpt_space_stroke(bContext *C, wmOperator *op, wmEvent *event, Sculpt *s, const int final_mouse[2])
+{
+	StrokeCache *cache = s->session->cache;
+	int cnt = 0;
+
+	if(sculpt_space_stroke_enabled(s)) {
+		float vec[2] = {final_mouse[0] - cache->mouse[0], final_mouse[1] - cache->mouse[1]};
+		int mouse[2] = {cache->mouse[0], cache->mouse[1]};
+		float length, scale;
+		int steps = 0, i;
+
+		/* Normalize the vector between the last stroke dot and the goal */
+		length = sqrt(vec[0]*vec[0] + vec[1]*vec[1]);
+
+		if(length > FLT_EPSILON) {
+			scale = s->brush->spacing / length;
+			vec[0] *= scale;
+			vec[1] *= scale;
+
+			steps = (int)(length / s->brush->spacing);
+			for(i = 0; i < steps; ++i, ++cnt) {
+				mouse[0] += vec[0];
+				mouse[1] += vec[1];
+				sculpt_brush_stroke_add_step(C, op, event, mouse);
+			}
+		}
+	}
+
+	return cnt;
+}
+
+static int sculpt_brush_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+	Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+	ARegion *ar = CTX_wm_region(C);
+	float cur_depth;
+
+	sculpt_update_mesh_elements(C);
+
+	if(!sd->session->cache) {
+		ViewContext vc;
+		view3d_set_viewcontext(C, &vc);
+		cur_depth = read_cached_depth(&vc, event->x, event->y);
+
+		/* Don't start the stroke until a valid depth is found */
+		if(cur_depth < 1.0 - FLT_EPSILON) {
+			sculpt_brush_stroke_init_properties(C, op, event, sd->session);
+			sculptmode_update_all_projverts(sd->session);
+		}
+
+		ED_region_tag_redraw(ar);
+	}
+
+	if(sd->session->cache) {
+		int mouse[2];
+
+		if(sculpt_smooth_stroke(sd, mouse, event)) {
+			if(sculpt_space_stroke_enabled(sd)) {
+				if(!sculpt_space_stroke(C, op, event, sd, mouse))
+					ED_region_tag_redraw(ar);
+			}
+			else
+				sculpt_brush_stroke_add_step(C, op, event, mouse);
+			sculpt_flush_update(C);
+		}
+		else
+			ED_region_tag_redraw(ar);
+	}
 
 	/* Finished */
 	if(event->type == LEFTMOUSE && event->val == 0) {
-		request_depth_update(sd->session->cache->vc.rv3d);
-
-		sculpt_cache_free(sd->session->cache);
-
-		sculpt_undo_push(C, sd);
+		if(sd->session->cache) {
+			request_depth_update(sd->session->cache->vc.rv3d);
+			sculpt_cache_free(sd->session->cache);
+			sd->session->cache = NULL;
+			sculpt_undo_push(C, sd);
+		}
 
 		return OPERATOR_FINISHED;
 	}
@@ -1717,454 +1683,3 @@ void ED_operatortypes_sculpt()
 	WM_operatortype_append(SCULPT_OT_sculptmode_toggle);
 	WM_operatortype_append(SCULPT_OT_brush_curve_preset);
 }
-
-void sculpt(Sculpt *sd)
-{
-#if 0
-	SculptSession *ss= sd->session;
-	Object *ob= NULL; /*XXX */
-	Mesh *me;
-	MultiresModifierData *mmd = NULL;
-	/* lastSigMouse is for the rake, to store the last place the mouse movement was significant */
-	short mouse[2], mvalo[2], lastSigMouse[2],firsttime=1, mousebut;
-	short modifier_calculations= 0;
-	BrushAction *a = MEM_callocN(sizeof(BrushAction), "brush action");
-	short spacing= 32000;
-	int scissor_box[4];
-	float offsetRot;
-	int smooth_stroke = 0, i;
-	int anchored, rake = 0 /* XXX: rake = ? */;
-
-	/* XXX: checking that sculpting is allowed
-	if(!(G.f & G_SCULPTMODE) || G.obedit || !ob || ob->id.lib || !get_mesh(ob) || (get_mesh(ob)->totface == 0))
-		return;
-	if(!(ob->lay & G.vd->lay))
-		error("Active object is not in this layer");
-	if(ob_get_keyblock(ob)) {
-		if(!(ob->shapeflag & OB_SHAPE_LOCK)) {
-			error("Cannot sculpt on unlocked shape key");
-			return;
-		}
-	}*/
-	
-	anchored = sd->brush->flag & BRUSH_ANCHORED;
-	smooth_stroke = (sd->flags & SCULPT_INPUT_SMOOTH) && (sd->brush->sculpt_tool != SCULPT_TOOL_GRAB) && !anchored;
-
-	if(smooth_stroke)
-		sculpt_stroke_new(256);
-
-	ss->damaged_rects.first = ss->damaged_rects.last = NULL;
-	ss->damaged_verts.first = ss->damaged_verts.last = NULL;
-	ss->vertexcosnos = NULL;
-
-	mmd = sculpt_multires_active(ob);
-
-	/* Check that vertex users are up-to-date */
-	if(ob != active_ob || !ss->vertex_users || ss->vertex_users_size != cache->totvert) {
-		sculpt_vertexusers_free(ss);
-		calc_vertex_users(ss);
-		if(ss->projverts)
-			MEM_freeN(ss->projverts);
-		ss->projverts = NULL;
-		active_ob= ob;
-	}
-		
-	glEnableClientState(GL_VERTEX_ARRAY);
-	glEnableClientState(GL_NORMAL_ARRAY);
-
-	/*XXX:
-	persp(PERSP_VIEW);
-	getmouseco_areawin(mvalo);*/
-
-	/* Init texture
-	   FIXME: Shouldn't be doing this every time! */
-	if(sd->tex_mode!=SCULPTREPT_3D)
-		sculptmode_update_tex(sd);
-
-	/*XXX: getmouseco_areawin(mouse); */
-	mvalo[0]= mouse[0];
-	mvalo[1]= mouse[1];
-	lastSigMouse[0]=mouse[0];
-	lastSigMouse[1]=mouse[1];
-	mousebut = 0; /* XXX: L_MOUSE; */
-
-	/* If modifier_calculations is true, then extra time must be spent
-	   updating the mesh. This takes a *lot* longer, so it's worth
-	   skipping if the modifier stack is empty. */
-	modifier_calculations= sculpt_modifiers_active(ob);
-
-	if(modifier_calculations)
-		ss->vertexcosnos= mesh_get_mapped_verts_nors(NULL, ob); /* XXX: scene = ? */
-	sculptmode_update_all_projverts(ss);
-
-	/* Capture original copy */
-	if(sd->flags & SCULPT_DRAW_FAST)
-		glAccum(GL_LOAD, 1);
-
-	/* Get original scissor box */
-	glGetIntegerv(GL_SCISSOR_BOX, scissor_box);
-	
-	/* For raking, get the original angle*/
-	offsetRot=sculpt_tex_angle(sd);
-
-	me = get_mesh(ob);
-
-	while (/*XXX:get_mbut() & mousebut*/0) {
-		/* XXX: getmouseco_areawin(mouse); */
-		/* If rake, and the mouse has moved over 10 pixels (euclidean) (prevents jitter) then get the new angle */
-		if (rake && (pow(lastSigMouse[0]-mouse[0],2)+pow(lastSigMouse[1]-mouse[1],2))>100){
-			/*Nasty looking, but just orig + new angle really*/
-			set_tex_angle(sd, offsetRot+180.+to_deg(atan2((float)(mouse[1]-lastSigMouse[1]),(float)(mouse[0]-lastSigMouse[0]))));
-			lastSigMouse[0]=mouse[0];
-			lastSigMouse[1]=mouse[1];
-		}
-		
-		if(firsttime || mouse[0]!=mvalo[0] || mouse[1]!=mvalo[1] ||
-		   sd->brush->flag & BRUSH_AIRBRUSH) {
-			a->firsttime = firsttime;
-			firsttime= 0;
-
-			if(smooth_stroke)
-				sculpt_stroke_add_point(ss->stroke, mouse[0], mouse[1]);
-
-			spacing+= sqrt(pow(mvalo[0]-mouse[0],2)+pow(mvalo[1]-mouse[1],2));
-
-			if(modifier_calculations && !ss->vertexcosnos)
-				ss->vertexcosnos= mesh_get_mapped_verts_nors(NULL, ob); /*XXX scene = ? */
-
-			if(sd->brush->sculpt_tool != SCULPT_TOOL_GRAB) {
-				if(anchored) {
- 					/* Restore the mesh before continuing with anchored stroke */
- 					/*if(a->mesh_store) {
- 						for(i = 0; i < cache->totvert; ++i) {
- 							VecCopyf(cache->mvert[i].co, &a->mesh_store[i].x);
-							cache->mvert[i].no[0] = a->orig_norms[i][0];
-							cache->mvert[i].no[1] = a->orig_norms[i][1];
-							cache->mvert[i].no[2] = a->orig_norms[i][2];
-						}
-						}*/
-					
-  					//do_symmetrical_brush_actions(sd, a, mouse, NULL);
-  				}
-				else {
-					if(smooth_stroke) {
-						sculpt_stroke_apply(sd, ss->stroke);
-					}
-					else if(sd->spacing==0 || spacing>sd->spacing) {
-						//do_symmetrical_brush_actions(sd, a, mouse, NULL);
-						spacing= 0;
-					}
-				}
-			}
-			else {
-				//do_symmetrical_brush_actions(sd, a, mouse, mvalo);
-				//unproject(ss, sd->pivot, mouse[0], mouse[1], a->depth);
-			}
-
-			if((!ss->multires && modifier_calculations) || ob_get_keyblock(ob)) {
-				/* XXX: DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); */ }
-
-			if(modifier_calculations || sd->brush->sculpt_tool == SCULPT_TOOL_GRAB || !(sd->flags & SCULPT_DRAW_FAST)) {
-				calc_damaged_verts(ss, a);
-				/*XXX: scrarea_do_windraw(curarea);
-				screen_swapbuffers(); */
-			} else { /* Optimized drawing */
-				calc_damaged_verts(ss, a);
-
-				/* Draw the stored image to the screen */
-				glAccum(GL_RETURN, 1);
-
-				sculpt_clear_damaged_areas(ss);
-				
-				/* Draw all the polygons that are inside the modified area(s) */
-				glScissor(scissor_box[0], scissor_box[1], scissor_box[2], scissor_box[3]);
-				/* XXX: sculptmode_draw_mesh(1); */
-				glAccum(GL_LOAD, 1);
-
-				projverts_clear_inside(ss);
-
-				/* XXX: persp(PERSP_WIN); */
-				glDisable(GL_DEPTH_TEST);
-				
-				/* Draw cursor */
-				if(sd->flags & SCULPT_TOOL_DRAW)
-					fdrawXORcirc((float)mouse[0],(float)mouse[1],sd->brush->size);
-				/* XXX: if(smooth_stroke)
-				   sculpt_stroke_draw();
-				
-				myswapbuffers(); */
-			}
-
-			BLI_freelistN(&ss->damaged_rects);
-			ss->damaged_rects.first = ss->damaged_rects.last = NULL;
-	
-			mvalo[0]= mouse[0];
-			mvalo[1]= mouse[1];
-
-			if(ss->vertexcosnos) {
-				MEM_freeN(ss->vertexcosnos);
-				ss->vertexcosnos= NULL;
-			}
-
-		}
-		else { /*XXX:BIF_wait_for_statechange();*/ }
-	}
-
-	/* Set the rotation of the brush back to what it was before any rake */
-	set_tex_angle(sd, offsetRot);
-	
-	if(smooth_stroke) {
-		sculpt_stroke_apply_all(sd, ss->stroke);
-		calc_damaged_verts(ss, a);
-		BLI_freelistN(&ss->damaged_rects);
-	}
-
-	//if(a->layer_disps) MEM_freeN(a->layer_disps);
-	//if(a->mesh_store) MEM_freeN(a->mesh_store);
-	//if(a->orig_norms) MEM_freeN(a->orig_norms);
-	for(i=0; i<8; ++i)
-		BLI_freelistN(&a->grab_active_verts[i]);
-	MEM_freeN(a);
-	sculpt_stroke_free(ss->stroke);
-	ss->stroke = NULL;
-
-	if(mmd) {
-		if(mmd->undo_verts && mmd->undo_verts != cache->mvert)
-			MEM_freeN(mmd->undo_verts);
-		
-		mmd->undo_verts = cache->mvert;
-		mmd->undo_verts_tot = cache->totvert;
-	}
-
-	//sculpt_undo_push(sd);
-
-	/* XXX: if(G.vd->depths) G.vd->depths->damaged= 1;
-	   allqueue(REDRAWVIEW3D, 0); */
-#endif
-}
-
-/* Partial Mesh Visibility */
-
-/* XXX: Partial vis. always was a mess, have to figure something out */
-#if 0
-/* mode: 0=hide outside selection, 1=hide inside selection */
-static void sculptmode_do_pmv(Object *ob, rcti *hb_2d, int mode)
-{
-	Mesh *me= get_mesh(ob);
-	float hidebox[6][3];
-	vec3f plane_normals[4];
-	float plane_ds[4];
-	unsigned i, j;
-	unsigned ndx_show, ndx_hide;
-	MVert *nve;
-	unsigned face_cnt_show= 0, face_ndx_show= 0;
-	unsigned edge_cnt_show= 0, edge_ndx_show= 0;
-	unsigned *old_map= NULL;
-	const unsigned SHOW= 0, HIDE=1;
-
-	/* Convert hide box from 2D to 3D */
-	unproject(hidebox[0], hb_2d->xmin, hb_2d->ymax, 1);
-	unproject(hidebox[1], hb_2d->xmax, hb_2d->ymax, 1);
-	unproject(hidebox[2], hb_2d->xmax, hb_2d->ymin, 1);
-	unproject(hidebox[3], hb_2d->xmin, hb_2d->ymin, 1);
-	unproject(hidebox[4], hb_2d->xmin, hb_2d->ymax, 0);
-	unproject(hidebox[5], hb_2d->xmax, hb_2d->ymin, 0);
-	
-	/* Calculate normals for each side of hide box */
-	CalcNormFloat(hidebox[0], hidebox[1], hidebox[4], &plane_normals[0].x);
-	CalcNormFloat(hidebox[1], hidebox[2], hidebox[5], &plane_normals[1].x);
-	CalcNormFloat(hidebox[2], hidebox[3], hidebox[5], &plane_normals[2].x);
-	CalcNormFloat(hidebox[3], hidebox[0], hidebox[4], &plane_normals[3].x);
-	
-	/* Calculate D for each side of hide box */
-	for(i= 0; i<4; ++i)
-		plane_ds[i]= hidebox[i][0]*plane_normals[i].x + hidebox[i][1]*plane_normals[i].y +
-			hidebox[i][2]*plane_normals[i].z;
-	
-	/* Add partial visibility to mesh */
-	if(!me->pv) {
-		me->pv= MEM_callocN(sizeof(PartialVisibility),"PartialVisibility");
-	} else {
-		old_map= MEM_callocN(sizeof(unsigned)*me->pv->totvert,"PMV oldmap");
-		for(i=0; ipv->totvert; ++i) {
-			old_map[i]= me->pv->vert_map[i]totvert?0:1;
-		}
-		mesh_pmv_revert(ob, me);
-	}
-	
-	/* Kill sculpt data */
-	active_ob= NULL;
-	
-	/* Initalize map with which verts are to be hidden */
-	me->pv->vert_map= MEM_mallocN(sizeof(unsigned)*me->totvert, "PMV vertmap");
-	me->pv->totvert= me->totvert;
-	me->totvert= 0;
-	for(i=0; ipv->totvert; ++i) {
-		me->pv->vert_map[i]= mode ? HIDE:SHOW;
-		for(j=0; j<4; ++j) {
-			if(me->mvert[i].co[0] * plane_normals[j].x +
-			   me->mvert[i].co[1] * plane_normals[j].y +
-			   me->mvert[i].co[2] * plane_normals[j].z < plane_ds[j] ) {
-				me->pv->vert_map[i]= mode ? SHOW:HIDE; /* Vert is outside the hide box */
-				break;
-			}
-		}
-		if(old_map && old_map[i]) me->pv->vert_map[i]= 1;
-		if(!me->pv->vert_map[i]) ++me->totvert;
-
-	}
-	if(old_map) MEM_freeN(old_map);
-
-	/* Find out how many faces to show */
-	for(i=0; itotface; ++i) {
-		if(!me->pv->vert_map[me->mface[i].v1] &&
-		   !me->pv->vert_map[me->mface[i].v2] &&
-		   !me->pv->vert_map[me->mface[i].v3]) {
-			if(me->mface[i].v4) {
-				if(!me->pv->vert_map[me->mface[i].v4])
-					++face_cnt_show;
-			}
-			else ++face_cnt_show;
-		}
-	}
-	/* Find out how many edges to show */
-	for(i=0; itotedge; ++i) {
-		if(!me->pv->vert_map[me->medge[i].v1] &&
-		   !me->pv->vert_map[me->medge[i].v2])
-			++edge_cnt_show;
-	}
-
-	/* Create new vert array and reset each vert's map with map[old]=new index */
-	nve= MEM_mallocN(sizeof(MVert)*me->pv->totvert, "PMV verts");
-	ndx_show= 0; ndx_hide= me->totvert;
-	for(i=0; ipv->totvert; ++i) {
-		if(me->pv->vert_map[i]) {
-			me->pv->vert_map[i]= ndx_hide;
-			nve[me->pv->vert_map[i]]= me->mvert[i];
-			++ndx_hide;
-		} else {
-			me->pv->vert_map[i]= ndx_show;
-			nve[me->pv->vert_map[i]]= me->mvert[i];
-			++ndx_show;
-		}
-	}
-	CustomData_free_layer_active(&me->vdata, CD_MVERT, me->pv->totvert);
-	me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, nve, me->totvert);
-
-	/* Create new face array */
-	me->pv->old_faces= me->mface;
-	me->pv->totface= me->totface;
-	me->mface= MEM_mallocN(sizeof(MFace)*face_cnt_show, "PMV faces");
-	for(i=0; itotface; ++i) {
-		MFace *pr_f= &me->pv->old_faces[i];
-		char show= 0;
-
-		if(me->pv->vert_map[pr_f->v1] < me->totvert &&
-		   me->pv->vert_map[pr_f->v2] < me->totvert &&
-		   me->pv->vert_map[pr_f->v3] < me->totvert) {
-			if(pr_f->v4) {
-				if(me->pv->vert_map[pr_f->v4] < me->totvert)
-					show= 1;
-			}
-			else show= 1;
-		}
-
-		if(show) {
-			MFace *cr_f= &me->mface[face_ndx_show];
-			*cr_f= *pr_f;
-			cr_f->v1= me->pv->vert_map[pr_f->v1];
-			cr_f->v2= me->pv->vert_map[pr_f->v2];
-			cr_f->v3= me->pv->vert_map[pr_f->v3];
-			cr_f->v4= pr_f->v4 ? me->pv->vert_map[pr_f->v4] : 0;
-			test_index_face(cr_f,NULL,0,pr_f->v4?4:3);
-			++face_ndx_show;
-		}
-	}
-	me->totface= face_cnt_show;
-	CustomData_set_layer(&me->fdata, CD_MFACE, me->mface);
-
-	/* Create new edge array */
-	me->pv->old_edges= me->medge;
-	me->pv->totedge= me->totedge;
-	me->medge= MEM_mallocN(sizeof(MEdge)*edge_cnt_show, "PMV edges");
-	me->pv->edge_map= MEM_mallocN(sizeof(int)*me->pv->totedge,"PMV edgemap");
-	for(i=0; itotedge; ++i) {
-		if(me->pv->vert_map[me->pv->old_edges[i].v1] < me->totvert &&
-		   me->pv->vert_map[me->pv->old_edges[i].v2] < me->totvert) {
-			MEdge *cr_e= &me->medge[edge_ndx_show];
-			me->pv->edge_map[i]= edge_ndx_show;
-			*cr_e= me->pv->old_edges[i];
-			cr_e->v1= me->pv->vert_map[me->pv->old_edges[i].v1];
-			cr_e->v2= me->pv->vert_map[me->pv->old_edges[i].v2];
-			++edge_ndx_show;
-		}
-		else me->pv->edge_map[i]= -1;
-	}
-	me->totedge= edge_cnt_show;
-	CustomData_set_layer(&me->edata, CD_MEDGE, me->medge);
-
-	/* XXX: DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA); */
-}
-
-static rcti sculptmode_pmv_box()
-{
-	/*XXX:	short down[2], mouse[2];
-	rcti ret;
-
-	getmouseco_areawin(down);
-
-	while((get_mbut()&L_MOUSE) || (get_mbut()&R_MOUSE)) {
-		getmouseco_areawin(mouse);
-
-		scrarea_do_windraw(curarea);
-
-		persp(PERSP_WIN);
-		glLineWidth(2);
-		setlinestyle(2);
-		sdrawXORline(down[0],down[1],mouse[0],down[1]);
-		sdrawXORline(mouse[0],down[1],mouse[0],mouse[1]);
-		sdrawXORline(mouse[0],mouse[1],down[0],mouse[1]);
-		sdrawXORline(down[0],mouse[1],down[0],down[1]);
-		setlinestyle(0);
-		glLineWidth(1);
-		persp(PERSP_VIEW);
-
-		screen_swapbuffers();
-		backdrawview3d(0);
-	}
-
-	ret.xmin= down[0]mouse[0]?down[0]:mouse[0];
-	ret.ymax= down[1]>mouse[1]?down[1]:mouse[1];
-	return ret;*/
-}
-
-void sculptmode_pmv(int mode)
-{
-	Object *ob= NULL; /*XXX: OBACT; */
-	rcti hb_2d;
-	
-	if(ob_get_key(ob)) {
-		error("Cannot hide mesh with shape keys enabled");
-		return;
-	}
-	
-	hb_2d= sculptmode_pmv_box(); /* Get 2D hide box */
-	
-	sculptmode_correct_state();
-
-	waitcursor(1);
-
-	if(hb_2d.xmax-hb_2d.xmin > 3 && hb_2d.ymax-hb_2d.ymin > 3) {
-		init_sculptmatrices();
-
-		sculptmode_do_pmv(ob,&hb_2d,mode);
-	}
-	else mesh_pmv_off(ob, get_mesh(ob));
-
-	/*XXX: scrarea_do_windraw(curarea); */
-
-	waitcursor(0);
-}
-#endif
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 112da5b4f0f..febca301939 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -1,5 +1,5 @@
 /*
- * $Id: BDR_sculptmode.h 13396 2008-01-25 04:17:38Z nicholasbishop $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/sculpt_paint/sculpt_stroke.c b/source/blender/editors/sculpt_paint/sculpt_stroke.c
index 1c23ec2a546..554ff580358 100644
--- a/source/blender/editors/sculpt_paint/sculpt_stroke.c
+++ b/source/blender/editors/sculpt_paint/sculpt_stroke.c
@@ -1,5 +1,5 @@
 /*
- * $Id: sculpt_stroke.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_action/Makefile b/source/blender/editors/space_action/Makefile
index 840f31b8a40..e856587acca 100644
--- a/source/blender/editors/space_action/Makefile
+++ b/source/blender/editors/space_action/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 6eae581aa40..2c9f91e0941 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -1,5 +1,5 @@
 /**
- * $Id: drawaction.c 17746 2008-12-08 11:19:44Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index a0f1adbd97e..5d262cb03c5 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -1,5 +1,5 @@
 /**
- * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index b82e44f3aa3..06f35f5cf05 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -1,5 +1,5 @@
 /**
- * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_api/Makefile b/source/blender/editors/space_api/Makefile
index 46f926afbc9..474fbe89053 100644
--- a/source/blender/editors/space_api/Makefile
+++ b/source/blender/editors/space_api/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index 4f9c1f4b7a7..510103895f4 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -50,6 +50,7 @@
 #include "ED_screen.h"
 #include "ED_space_api.h"
 #include "ED_uvedit.h"
+#include "ED_pointcache.h"
 
 /* only call once on startup, storage is global in BKE kernel listbase */
 void ED_spacetypes_init(void)
@@ -89,6 +90,7 @@ void ED_spacetypes_init(void)
 	ED_operatortypes_curve();
 	ED_operatortypes_armature();
 	ED_marker_operatortypes();
+	ED_operatortypes_pointcache();
 	
 	ui_view2d_operatortypes();
 	
diff --git a/source/blender/editors/space_buttons/Makefile b/source/blender/editors/space_buttons/Makefile
index b96d1cc5495..a4894ede06b 100644
--- a/source/blender/editors/space_buttons/Makefile
+++ b/source/blender/editors/space_buttons/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/space_buttons/SConscript b/source/blender/editors/space_buttons/SConscript
index 541da52f7f9..a0a7dad4077 100644
--- a/source/blender/editors/space_buttons/SConscript
+++ b/source/blender/editors/space_buttons/SConscript
@@ -12,7 +12,4 @@ defs = []
 if env['WITH_BF_GAMEENGINE']:
 	defs.append('GAMEBLENDER=1')
 
-	if env['WITH_BF_SOLID']:
-		defs.append('USE_SUMO_SOLID')
-
 env.BlenderLib ( 'bf_editors_space_buttons', sources, Split(incs), defs, libtype=['core'], priority=[120] )
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index d97b4acdb96..01794d1bba8 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -552,7 +552,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
 		if(ptr) {
 			Object *ob= ptr->data;
 
-			if(ob && ob->type && (ob->typetype && (ob->typetotcol)
 				CTX_data_pointer_set(result, &ob->id, &RNA_MaterialSlot, ob->mat+ob->actcol-1);
 		}
 
@@ -668,7 +668,6 @@ void buttons_context_draw(const bContext *C, uiLayout *layout)
 	uiBlock *block;
 	uiBut *but;
 	PointerRNA *ptr;
-	PropertyRNA *nameprop;
 	char namebuf[128], *name;
 	int a, icon;
 
@@ -688,7 +687,7 @@ void buttons_context_draw(const bContext *C, uiLayout *layout)
 
 		if(ptr->data) {
 			icon= RNA_struct_ui_icon(ptr->type);
-			nameprop= RNA_struct_name_property(ptr->type);
+			name= RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf));
 
 #if 0
 			if(sbuts->mainb != BCONTEXT_SCENE && ptr->type == &RNA_Scene) {
@@ -696,9 +695,7 @@ void buttons_context_draw(const bContext *C, uiLayout *layout)
 			}
 			else
 #endif
-			if(nameprop) {
-				name= RNA_property_string_get_alloc(ptr, nameprop, namebuf, sizeof(namebuf));
-
+			if(name) {
 				uiItemL(row, name, icon);
 
 				if(name != namebuf)
diff --git a/source/blender/editors/space_buttons/buttons_header.c b/source/blender/editors/space_buttons/buttons_header.c
index 98fd198d84b..7c622f172a2 100644
--- a/source/blender/editors/space_buttons/buttons_header.c
+++ b/source/blender/editors/space_buttons/buttons_header.c
@@ -1,5 +1,5 @@
 /**
- * $Id: buttons_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -173,10 +173,10 @@ void buttons_header_buttons(const bContext *C, ARegion *ar)
 		uiDefIconButS(block, ROW, B_CONTEXT_SWITCH,	ICON_OBJECT_DATA,	xco+=XIC, yco, XIC, YIC, &(sbuts->mainb), 0.0, (float)BCONTEXT_OBJECT, 0, 0, "Object");
 	if(sbuts->pathflag & (1<mainb), 0.0, (float)BCONTEXT_CONSTRAINT, 0, 0, "Constraint");
-	if(sbuts->pathflag & (1<mainb), 0.0, (float)BCONTEXT_MODIFIER, 0, 0, "Modifier");
 	if(sbuts->pathflag & (1<dataicon,	xco+=XIC, yco, XIC, YIC, &(sbuts->mainb), 0.0, (float)BCONTEXT_DATA, 0, 0, "Object Data");
+	if(sbuts->pathflag & (1<mainb), 0.0, (float)BCONTEXT_MODIFIER, 0, 0, "Modifier");
 	if(sbuts->pathflag & (1<mainb), 0.0, (float)BCONTEXT_BONE, 0, 0, "Bone");
 	if(sbuts->pathflag & (1<name= "Add Material Slot";
+	ot->idname= "OBJECT_OT_material_slot_add";
+	
+	/* api callbacks */
+	ot->exec= material_slot_add_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int material_slot_remove_exec(bContext *C, wmOperator *op)
+{
+	Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+
+	if(!ob)
+		return OPERATOR_CANCELLED;
+
+	object_remove_material_slot(ob);
+	WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+	
+	return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_material_slot_remove(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Remove Material Slot";
+	ot->idname= "OBJECT_OT_material_slot_remove";
+	
+	/* api callbacks */
+	ot->exec= material_slot_remove_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int material_slot_assign_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene= CTX_data_scene(C);
+	Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+
+	if(!ob)
+		return OPERATOR_CANCELLED;
+
+	if(ob && ob->actcol>0) {
+		if(ob->type == OB_MESH) {
+			EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
+			EditFace *efa;
+
+			if(em) {
+				for(efa= em->faces.first; efa; efa=efa->next)
+					if(efa->f & SELECT)
+						efa->mat_nr= ob->actcol-1;
+			}
+		}
+		else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
+			ListBase *editnurb= ((Curve*)ob->data)->editnurb;
+			Nurb *nu;
+
+			if(editnurb) {
+				for(nu= editnurb->first; nu; nu= nu->next)
+					if(isNurbsel(nu))
+						nu->mat_nr= nu->charidx= ob->actcol-1;
+			}
+		}
+		else if(ob->type == OB_FONT) {
+			EditFont *ef= ((Curve*)ob->data)->editfont;
+    		int i, selstart, selend;
+
+			if(ef && BKE_font_getselection(ob, &selstart, &selend)) {
+				for(i=selstart; i<=selend; i++)
+					ef->textbufinfo[i].mat_nr = ob->actcol-1;
+			}
+		}
+	}
+
+    DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+    WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
+	
+	return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_material_slot_assign(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Assign Material Slot";
+	ot->idname= "OBJECT_OT_material_slot_assign";
+	
+	/* api callbacks */
+	ot->exec= material_slot_assign_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int material_slot_de_select(bContext *C, int select)
+{
+	Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+
+	if(!ob)
+		return OPERATOR_CANCELLED;
+
+	if(ob->type == OB_MESH) {
+		EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
+
+		if(em) {
+			if(select)
+				EM_select_by_material(em, ob->actcol-1);
+			else
+				EM_deselect_by_material(em, ob->actcol-1);
+		}
+	}
+	else if ELEM(ob->type, OB_CURVE, OB_SURF) {
+		ListBase *editnurb= ((Curve*)ob->data)->editnurb;
+		Nurb *nu;
+		BPoint *bp;
+		BezTriple *bezt;
+		int a;
+
+		for(nu= editnurb->first; nu; nu=nu->next) {
+			if(nu->mat_nr==ob->actcol-1) {
+				if(nu->bezt) {
+					a= nu->pntsu;
+					bezt= nu->bezt;
+					while(a--) {
+						if(bezt->hide==0) {
+							if(select) {
+								bezt->f1 |= SELECT;
+								bezt->f2 |= SELECT;
+								bezt->f3 |= SELECT;
+							}
+							else {
+								bezt->f1 &= ~SELECT;
+								bezt->f2 &= ~SELECT;
+								bezt->f3 &= ~SELECT;
+							}
+						}
+						bezt++;
+					}
+				}
+				else if(nu->bp) {
+					a= nu->pntsu*nu->pntsv;
+					bp= nu->bp;
+					while(a--) {
+						if(bp->hide==0) {
+							if(select) bp->f1 |= SELECT;
+							else bp->f1 &= ~SELECT;
+						}
+						bp++;
+					}
+				}
+			}
+		}
+	}
+
+    WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
+
+	return OPERATOR_FINISHED;
+}
+
+static int material_slot_select_exec(bContext *C, wmOperator *op)
+{
+	return material_slot_de_select(C, 1);
+}
+
+void OBJECT_OT_material_slot_select(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Select Material Slot";
+	ot->idname= "OBJECT_OT_material_slot_select";
+	
+	/* api callbacks */
+	ot->exec= material_slot_select_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int material_slot_deselect_exec(bContext *C, wmOperator *op)
+{
+	return material_slot_de_select(C, 0);
+}
+
+void OBJECT_OT_material_slot_deselect(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Deselect Material Slot";
+	ot->idname= "OBJECT_OT_material_slot_deselect";
+	
+	/* api callbacks */
+	ot->exec= material_slot_deselect_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
 /********************** new material operator *********************/
 
 static int new_material_exec(bContext *C, wmOperator *op)
 {
-	PointerRNA ptr;
-	Material *ma;
+	Material *ma= CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
 	Object *ob;
+	PointerRNA ptr;
 	int index;
 
 	/* add or copy material */
-	ptr= CTX_data_pointer_get(C, "material");
-	ma= (RNA_struct_is_a(ptr.type, &RNA_Material))? ptr.data: NULL;
-
 	if(ma)
 		ma= copy_material(ma);
 	else
@@ -70,9 +291,9 @@ static int new_material_exec(bContext *C, wmOperator *op)
 	ma->id.us--; /* compensating for us++ in assign_material */
 
 	/* attempt to assign to material slot */
-	ptr= CTX_data_pointer_get(C, "material_slot");
+	ptr= CTX_data_pointer_get_type(C, "material_slot", &RNA_MaterialSlot);
 
-	if(RNA_struct_is_a(ptr.type, &RNA_MaterialSlot)) {
+	if(ptr.data) {
 		ob= ptr.id.data;
 		index= (Material**)ptr.data - ob->mat;
 
@@ -80,6 +301,8 @@ static int new_material_exec(bContext *C, wmOperator *op)
 
 		WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
 	}
+
+	WM_event_add_notifier(C, NC_MATERIAL|NA_ADDED, ma);
 	
 	return OPERATOR_FINISHED;
 }
@@ -101,15 +324,12 @@ void MATERIAL_OT_new(wmOperatorType *ot)
 
 static int new_texture_exec(bContext *C, wmOperator *op)
 {
-	PointerRNA ptr;
+	Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
 	ID *id;
-	Tex *tex;
 	MTex *mtex;
+	PointerRNA ptr;
 
 	/* add or copy texture */
-	ptr= CTX_data_pointer_get(C, "texture");
-	tex= (RNA_struct_is_a(ptr.type, &RNA_Texture))? ptr.data: NULL;
-
 	if(tex)
 		tex= copy_texture(tex);
 	else
@@ -118,9 +338,9 @@ static int new_texture_exec(bContext *C, wmOperator *op)
 	id_us_min(&tex->id);
 
 	/* attempt to assign to texture slot */
-	ptr= CTX_data_pointer_get(C, "texture_slot");
+	ptr= CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot);
 
-	if(RNA_struct_is_a(ptr.type, &RNA_TextureSlot)) {
+	if(ptr.data) {
 		id= ptr.id.data;
 		mtex= ptr.data;
 
@@ -133,6 +353,8 @@ static int new_texture_exec(bContext *C, wmOperator *op)
 
 		/* XXX nodes, notifier .. */
 	}
+
+	WM_event_add_notifier(C, NC_TEXTURE|NA_ADDED, tex);
 	
 	return OPERATOR_FINISHED;
 }
@@ -154,27 +376,21 @@ void TEXTURE_OT_new(wmOperatorType *ot)
 
 static int new_world_exec(bContext *C, wmOperator *op)
 {
-	PointerRNA ptr;
-	Scene *scene;
-	World *wo;
+	Scene *scene= CTX_data_scene(C);
+	World *wo= CTX_data_pointer_get_type(C, "world", &RNA_World).data;
 
 	/* add or copy world */
-	ptr= CTX_data_pointer_get(C, "world");
-	wo= (RNA_struct_is_a(ptr.type, &RNA_World))? ptr.data: NULL;
-
 	if(wo)
 		wo= copy_world(wo);
 	else
 		wo= add_world("World");
 
 	/* assign to scene */
-	scene= CTX_data_scene(C);
-
 	if(scene->world)
 		id_us_min(&scene->world->id);
 	scene->world= wo;
 
-	// XXX notifier
+	WM_event_add_notifier(C, NC_WORLD|NA_ADDED, wo);
 	
 	return OPERATOR_FINISHED;
 }
@@ -192,3 +408,109 @@ void WORLD_OT_new(wmOperatorType *ot)
 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
+
+
+/********************** particle system slot operators *********************/
+
+static int particle_system_add_exec(bContext *C, wmOperator *op)
+{
+	Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+	Scene *scene = CTX_data_scene(C);
+
+	if(!scene || !ob)
+		return OPERATOR_CANCELLED;
+
+	object_add_particle_system(scene, ob);
+	WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+	
+	return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_particle_system_add(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Add Particle System Slot";
+	ot->idname= "OBJECT_OT_particle_system_add";
+	
+	/* api callbacks */
+	ot->exec= particle_system_add_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int particle_system_remove_exec(bContext *C, wmOperator *op)
+{
+	Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+	Scene *scene = CTX_data_scene(C);
+
+	if(!scene || !ob)
+		return OPERATOR_CANCELLED;
+
+	object_remove_particle_system(scene, ob);
+	WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+	
+	return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_particle_system_remove(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Remove Particle System Slot";
+	ot->idname= "OBJECT_OT_particle_system_remove";
+	
+	/* api callbacks */
+	ot->exec= particle_system_remove_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/********************** new particle settings operator *********************/
+
+static int new_particle_settings_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene = CTX_data_scene(C);
+	ParticleSettings *part= CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings).data;
+	Object *ob;
+	PointerRNA ptr;
+
+	/* add or copy particle setting */
+	if(part)
+		part= psys_copy_settings(part);
+	else
+		part= psys_new_settings("PSys", NULL);
+
+	/* attempt to assign to material slot */
+	ptr= CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+
+	if(ptr.data) {
+		ParticleSystem *psys = (ParticleSystem*)ptr.data;
+		ob= ptr.id.data;
+
+		if(psys->part)
+			psys->part->id.us--;
+
+		psys->part = part;
+
+		DAG_scene_sort(scene);
+		DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+
+		WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+	}
+	
+	return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_new(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "New Particle Settings";
+	ot->idname= "PARTICLE_OT_new";
+	
+	/* api callbacks */
+	ot->exec= new_particle_settings_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index 38ce88019ed..b89a13ce218 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -210,9 +210,20 @@ static void buttons_main_area_draw(const bContext *C, ARegion *ar)
 
 void buttons_operatortypes(void)
 {
+	WM_operatortype_append(OBJECT_OT_material_slot_add);
+	WM_operatortype_append(OBJECT_OT_material_slot_remove);
+	WM_operatortype_append(OBJECT_OT_material_slot_assign);
+	WM_operatortype_append(OBJECT_OT_material_slot_select);
+	WM_operatortype_append(OBJECT_OT_material_slot_deselect);
+
 	WM_operatortype_append(MATERIAL_OT_new);
 	WM_operatortype_append(TEXTURE_OT_new);
 	WM_operatortype_append(WORLD_OT_new);
+
+	WM_operatortype_append(OBJECT_OT_particle_system_add);
+	WM_operatortype_append(OBJECT_OT_particle_system_remove);
+
+	WM_operatortype_append(PARTICLE_OT_new);
 }
 
 void buttons_keymap(struct wmWindowManager *wm)
@@ -220,14 +231,23 @@ void buttons_keymap(struct wmWindowManager *wm)
 	
 }
 
+//#define PY_HEADER
 /* add handlers, stuff you only do once or on area/region changes */
 static void buttons_header_area_init(wmWindowManager *wm, ARegion *ar)
 {
+#ifdef PY_HEADER
+	ED_region_header_init(ar);
+#else
 	UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+#endif
 }
 
 static void buttons_header_area_draw(const bContext *C, ARegion *ar)
 {
+#ifdef PY_HEADER
+	ED_region_header(C, ar);
+#else
+
 	float col[3];
 	
 	/* clear */
@@ -243,7 +263,8 @@ static void buttons_header_area_draw(const bContext *C, ARegion *ar)
 	UI_view2d_view_ortho(C, &ar->v2d);
 	
 	buttons_header_buttons(C, ar);
-	
+#endif	
+
 	/* restore view matrix? */
 	UI_view2d_view_restore(C);
 }
@@ -310,6 +331,7 @@ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn)
 		case NC_SCENE:
 			switch(wmn->data) {
 				case ND_FRAME:
+				case ND_MODE:
 					ED_area_tag_redraw(sa);
 					break;
 					
@@ -327,6 +349,11 @@ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn)
 				case ND_GEOM_SELECT:
 					ED_area_tag_redraw(sa);
 					break;
+				case ND_SHADING:
+				case ND_SHADING_DRAW:
+					/* currently works by redraws... if preview is set, it (re)starts job */
+					sbuts->preview= 1;
+					break;
 			}
 			break;
 		case NC_MATERIAL:
@@ -337,7 +364,6 @@ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn)
 				case ND_SHADING_DRAW:
 					/* currently works by redraws... if preview is set, it (re)starts job */
 					sbuts->preview= 1;
-					printf("shader notifier \n");
 					break;
 			}					
 			break;
diff --git a/source/blender/editors/space_file/Makefile b/source/blender/editors/space_file/Makefile
index 8f48217473c..2f4180448e5 100644
--- a/source/blender/editors/space_file/Makefile
+++ b/source/blender/editors/space_file/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 6ed8f87d987..02ee8f508c1 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -550,81 +550,4 @@ void file_draw_list(const bContext *C, ARegion *ar)
 	}
 }
 
-static void file_draw_fsmenu_category(const bContext *C, ARegion *ar, FSMenuCategory category, const char* category_name, short *starty)
-{
-	struct FSMenu* fsmenu = fsmenu_get();
-	char bookmark[FILE_MAX];
-	int nentries = fsmenu_get_nentries(fsmenu, category);
-	
-	short sx, sy, xpos, ypos;
-	int bmwidth = ar->v2d.cur.xmax - ar->v2d.cur.xmin - 2*TILE_BORDER_X - ICON_DEFAULT_WIDTH - 4;
-	int fontsize = file_font_pointsize();
-	int cat_icon;
-	int i;
 
-	sx = ar->v2d.cur.xmin + TILE_BORDER_X;
-	sy = *starty;
-
-	UI_ThemeColor(TH_TEXT_HI);
-	file_draw_string(sx, sy, category_name, bmwidth, fontsize, FILE_SHORTEN_END);
-	
-	sy -= fontsize*2.0f;
-
-	switch(category) {
-		case FS_CATEGORY_SYSTEM:
-			cat_icon = ICON_DISK_DRIVE; break;
-		case FS_CATEGORY_BOOKMARKS:
-			cat_icon = ICON_BOOKMARKS; break;
-		case FS_CATEGORY_RECENT:
-			cat_icon = ICON_FILE_FOLDER; break;
-	}
-
-	for (i=0; i< nentries && (sy > ar->v2d.cur.ymin) ;++i) {
-		char *fname = fsmenu_get_entry(fsmenu, category, i);
-
-		if (fname) {
-			int sl;
-			BLI_strncpy(bookmark, fname, FILE_MAX);
-		
-			sl = strlen(bookmark)-1;
-			if (sl > 1) {
-			while (bookmark[sl] == '\\' || bookmark[sl] == '/') {
-				bookmark[sl] = '\0';
-				sl--;
-			}
-			}
-			
-			if (fsmenu_is_selected(fsmenu, category, i) ) {
-				UI_ThemeColor(TH_HILITE);
-				uiRoundBox(sx, sy - fontsize*2.0f, ar->v2d.cur.xmax - TILE_BORDER_X, sy, 4.0f);
-				UI_ThemeColor(TH_TEXT);
-			} else {
-				UI_ThemeColor(TH_TEXT_HI);
-			}
-
-			xpos = sx;
-			ypos = sy - (TILE_BORDER_Y * 0.5);
-			
-			file_draw_icon(xpos, ypos, cat_icon, ICON_DEFAULT_WIDTH, ICON_DEFAULT_WIDTH);
-			xpos += ICON_DEFAULT_WIDTH + 4;
-			file_draw_string(xpos, ypos, bookmark, bmwidth, fontsize, FILE_SHORTEN_FRONT);
-			sy -= fontsize*2.0;
-			fsmenu_set_pos(fsmenu, category, i, xpos, ypos);
-		}
-	}
-
-	*starty = sy;
-}
-
-void file_draw_fsmenu(const bContext *C, ARegion *ar)
-{
-	int linestep = file_font_pointsize()*2.0f;
-	short sy= ar->v2d.cur.ymax-2*TILE_BORDER_Y;
-
-	file_draw_fsmenu_category(C, ar, FS_CATEGORY_SYSTEM, "SYSTEM", &sy);
-	sy -= linestep;
-	file_draw_fsmenu_category(C, ar, FS_CATEGORY_BOOKMARKS, "BOOKMARKS", &sy);
-	sy -= linestep;
-	file_draw_fsmenu_category(C, ar, FS_CATEGORY_RECENT, "RECENT", &sy);
-	
-}
diff --git a/source/blender/editors/space_file/file_header.c b/source/blender/editors/space_file/file_header.c
index 34374268d5c..4799003d6c7 100644
--- a/source/blender/editors/space_file/file_header.c
+++ b/source/blender/editors/space_file/file_header.c
@@ -1,5 +1,5 @@
 /**
- * $Id: file_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h
index 642189ad3fd..668e14c95e6 100644
--- a/source/blender/editors/space_file/file_intern.h
+++ b/source/blender/editors/space_file/file_intern.h
@@ -30,6 +30,9 @@
 
 /* internal exports only */
 
+struct ARegion;
+struct ARegionType;
+struct SpaceFile;
 
 /* file_header.c */
 void file_header_buttons(const bContext *C, ARegion *ar);
@@ -45,7 +48,6 @@ void file_draw_buttons(const bContext *C, ARegion *ar);
 void file_calc_previews(const bContext *C, ARegion *ar);
 void file_draw_previews(const bContext *C, ARegion *ar);
 void file_draw_list(const bContext *C, ARegion *ar);
-void file_draw_fsmenu(const bContext *C, ARegion *ar);
 
 /* file_ops.h */
 struct wmOperatorType;
@@ -56,6 +58,9 @@ void FILE_OT_select(struct wmOperatorType *ot);
 void FILE_OT_select_all_toggle(struct wmOperatorType *ot);
 void FILE_OT_select_border(struct wmOperatorType *ot);
 void FILE_OT_select_bookmark(struct wmOperatorType *ot);
+void FILE_OT_add_bookmark(struct wmOperatorType *ot);
+void FILE_OT_delete_bookmark(struct wmOperatorType *ot);
+void FILE_OT_hidedot(struct wmOperatorType *ot);
 void FILE_OT_loadimages(struct wmOperatorType *ot);
 void FILE_OT_exec(struct wmOperatorType *ot);
 void FILE_OT_cancel(struct wmOperatorType *ot);
@@ -66,11 +71,14 @@ void FILE_OT_bookmark_toggle(struct wmOperatorType *ot);
 int file_exec(bContext *C, struct wmOperator *unused);
 int file_cancel_exec(bContext *C, struct wmOperator *unused);
 int file_parent_exec(bContext *C, struct wmOperator *unused);
-int file_hilight_set(SpaceFile *sfile, ARegion *ar, int mx, int my);
+int file_hilight_set(struct SpaceFile *sfile, struct ARegion *ar, int mx, int my);
 
 /* filesel.c */
 float file_string_width(const char* str);
 float file_font_pointsize();
 
+/* file_panels.c */
+void file_panels_register(struct ARegionType *art);
+
 #endif /* ED_FILE_INTERN_H */
 
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index 0c6cadc05c1..aaa1793efbb 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -42,6 +42,8 @@
 #include "ED_screen.h"
 #include "ED_fileselect.h"
 
+#include "MEM_guardedalloc.h"
+
 #include "RNA_access.h"
 #include "RNA_define.h"
 
@@ -135,22 +137,15 @@ static void file_select(SpaceFile* sfile, ARegion* ar, const rcti* rect, short v
 		params->active_file = last_file;
 
 		if(file && S_ISDIR(file->type)) {
-			/* the path is too long and we are not going up! */
-			if (strcmp(file->relname, ".") &&
-				strcmp(file->relname, "..") &&
-				strlen(params->dir) + strlen(file->relname) >= FILE_MAX ) 
+			/* the path is too long! */
+			if (strlen(params->dir) + strlen(file->relname) >= FILE_MAX ) 
 			{
 				// XXX error("Path too long, cannot enter this directory");
 			} else {
-				if (strcmp(file->relname, "..")==0) {
-					/* avoids /../../ */
-					BLI_parent_dir(params->dir);
-				} else {
-					strcat(params->dir, file->relname);
-					strcat(params->dir,"/");
-					params->file[0] = '\0';
-					BLI_cleanup_dir(G.sce, params->dir);
-				}
+				strcat(params->dir, file->relname);
+				strcat(params->dir,"/");
+				params->file[0] = '\0';
+				BLI_cleanup_dir(G.sce, params->dir);
 				filelist_setdir(sfile->files, params->dir);
 				filelist_free(sfile->files);
 				params->active_file = -1;
@@ -190,7 +185,7 @@ static int file_border_select_exec(bContext *C, wmOperator *op)
 	rect.xmax= RNA_int_get(op->ptr, "xmax");
 	rect.ymax= RNA_int_get(op->ptr, "ymax");
 
-	BLI_isect_rctf(&(ar->v2d.mask), &rect, &rect);
+	BLI_isect_rcti(&(ar->v2d.mask), &rect, &rect);
 	
 	file_select(sfile, ar, &rect, val );
 	WM_event_add_notifier(C, NC_WINDOW, NULL);
@@ -234,7 +229,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
 		/* single select, deselect all selected first */
 		file_deselect_all(sfile);
 		file_select(sfile, ar, &rect, val );
-		WM_event_add_notifier(C, NC_WINDOW, NULL);
+		WM_event_add_notifier(C, NC_FILE|ND_PARAMS, NULL);
 	}
 	return OPERATOR_FINISHED;
 }
@@ -299,75 +294,25 @@ void FILE_OT_select_all_toggle(wmOperatorType *ot)
 
 /* ---------- BOOKMARKS ----------- */
 
-static int file_select_bookmark_category(SpaceFile* sfile, ARegion* ar, short x, short y, FSMenuCategory category)
-{
-	struct FSMenu* fsmenu = fsmenu_get();
-	int nentries = fsmenu_get_nentries(fsmenu, category);
-	int linestep = file_font_pointsize()*2.0f;
-	short xs, ys;
-	int i;
-	int selected = -1;
-
-	for (i=0; i < nentries; ++i) {
-		fsmenu_get_pos(fsmenu, category, i, &xs, &ys);
-		if ( (y<=ys) && (y>ys-linestep) ) {
-			fsmenu_select_entry(fsmenu, category, i);
-			selected = i;
-			break;
-		}
-	}
-	return selected;
-}
-
-static void file_select_bookmark(SpaceFile* sfile, ARegion* ar, short x, short y)
-{
-	float fx, fy;
-	int selected;
-	FSMenuCategory category = FS_CATEGORY_SYSTEM;
-
-	if (BLI_in_rcti(&ar->v2d.mask, x, y)) {
-		char *entry;
-
-		UI_view2d_region_to_view(&ar->v2d, x, y, &fx, &fy);
-		selected = file_select_bookmark_category(sfile, ar, fx, fy, FS_CATEGORY_SYSTEM);
-		if (selected<0) {
-			category = FS_CATEGORY_BOOKMARKS;
-			selected = file_select_bookmark_category(sfile, ar, fx, fy, category);
-		}
-		if (selected<0) {
-			category = FS_CATEGORY_RECENT;
-			selected = file_select_bookmark_category(sfile, ar, fx, fy, category);
-		}
-		
-		if (selected>=0) {
-			entry= fsmenu_get_entry(fsmenu_get(), category, selected);			
-			/* which string */
-			if (entry) {
-				FileSelectParams* params = sfile->params;
-				BLI_strncpy(params->dir, entry, sizeof(params->dir));
-				BLI_cleanup_dir(G.sce, params->dir);
-				filelist_free(sfile->files);	
-				filelist_setdir(sfile->files, params->dir);
-				params->file[0] = '\0';			
-				params->active_file = -1;
-			}
-		}
-	}
-}
-
 static int bookmark_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
-	ScrArea *sa= CTX_wm_area(C);
-	ARegion *ar= CTX_wm_region(C);	
 	SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
 
-	short x, y;
+	if(RNA_struct_find_property(op->ptr, "dir")) {
+		char entry[256];
+		FileSelectParams* params = sfile->params;
 
-	x = event->x - ar->winrct.xmin;
-	y = event->y - ar->winrct.ymin;
+		RNA_string_get(op->ptr, "dir", entry);
+		BLI_strncpy(params->dir, entry, sizeof(params->dir));
+		BLI_cleanup_dir(G.sce, params->dir);
+		filelist_free(sfile->files);	
+		filelist_setdir(sfile->files, params->dir);
+		params->file[0] = '\0';			
+		params->active_file = -1;
 
-	file_select_bookmark(sfile, ar, x, y);
-	ED_area_tag_redraw(sa);
+		WM_event_add_notifier(C, NC_FILE|ND_PARAMS, NULL);
+	}
+	
 	return OPERATOR_FINISHED;
 }
 
@@ -380,8 +325,75 @@ void FILE_OT_select_bookmark(wmOperatorType *ot)
 	/* api callbacks */
 	ot->invoke= bookmark_select_invoke;
 	ot->poll= ED_operator_file_active;
+
+	RNA_def_string(ot->srna, "dir", "", 256, "Dir", "");
 }
 
+static int bookmark_add_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+	ScrArea *sa= CTX_wm_area(C);
+	SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+	struct FSMenu* fsmenu = fsmenu_get();
+	struct FileSelectParams* params= ED_fileselect_get_params(sfile);
+
+	if (params->dir[0] != '\0') {
+		char name[FILE_MAX];
+	
+		fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir, 0, 1);
+		BLI_make_file_string("/", name, BLI_gethome(), ".Bfs");
+		fsmenu_write_file(fsmenu, name);
+	}
+
+	ED_area_tag_redraw(sa);
+	return OPERATOR_FINISHED;
+}
+
+void FILE_OT_add_bookmark(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Add Bookmark";
+	ot->idname= "FILE_OT_add_bookmark";
+	
+	/* api callbacks */
+	ot->invoke= bookmark_add_invoke;
+	ot->poll= ED_operator_file_active;
+}
+
+static int bookmark_delete_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+	ScrArea *sa= CTX_wm_area(C);
+	SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+	struct FSMenu* fsmenu = fsmenu_get();
+	int nentries = fsmenu_get_nentries(fsmenu, FS_CATEGORY_BOOKMARKS);
+	if(RNA_struct_find_property(op->ptr, "index")) {
+		int index = RNA_int_get(op->ptr, "index");
+		if ( (index >-1) && (index < nentries)) {
+			char name[FILE_MAX];
+			
+			fsmenu_remove_entry(fsmenu, FS_CATEGORY_BOOKMARKS, index);
+			BLI_make_file_string("/", name, BLI_gethome(), ".Bfs");
+			fsmenu_write_file(fsmenu, name);
+			ED_area_tag_redraw(sa);
+		}
+	}
+
+	return OPERATOR_FINISHED;
+}
+
+void FILE_OT_delete_bookmark(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Delete Bookmark";
+	ot->idname= "FILE_OT_delete_bookmark";
+	
+	/* api callbacks */
+	ot->invoke= bookmark_delete_invoke;
+	ot->poll= ED_operator_file_active;
+
+	RNA_def_int(ot->srna, "index", -1, -1, 20000, "Index", "", -1, 20000);
+}
+
+
 static int loadimages_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
 	ScrArea *sa= CTX_wm_area(C);
@@ -548,7 +560,7 @@ int file_parent_exec(bContext *C, wmOperator *unused)
 		filelist_free(sfile->files);
 		sfile->params->active_file = -1;
 	}		
-	ED_area_tag_redraw(CTX_wm_area(C));
+	WM_event_add_notifier(C, NC_FILE|ND_FILELIST, NULL);
 
 	return OPERATOR_FINISHED;
 
@@ -575,8 +587,8 @@ int file_refresh_exec(bContext *C, wmOperator *unused)
 		filelist_setdir(sfile->files, sfile->params->dir);
 		filelist_free(sfile->files);
 		sfile->params->active_file = -1;
-	}		
-	ED_area_tag_redraw(CTX_wm_area(C));
+	}
+	WM_event_add_notifier(C, NC_FILE|ND_FILELIST, NULL);
 
 	return OPERATOR_FINISHED;
 
@@ -594,14 +606,58 @@ void FILE_OT_refresh(struct wmOperatorType *ot)
 	ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
 }
 
+int file_hidedot_exec(bContext *C, wmOperator *unused)
+{
+	SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+	
+	if(sfile->params) {
+		sfile->params->flag ^= FILE_HIDE_DOT;
+		filelist_free(sfile->files);
+		sfile->params->active_file = -1;
+		WM_event_add_notifier(C, NC_FILE|ND_FILELIST, NULL);
+	}
+	
+	return OPERATOR_FINISHED;
+
+}
+
+
+void FILE_OT_hidedot(struct wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Toggle Hide Dot Files";
+	ot->idname= "FILE_OT_hidedot";
+	
+	/* api callbacks */
+	ot->exec= file_hidedot_exec;
+	ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
+}
+
 struct ARegion *file_buttons_region(struct ScrArea *sa)
 {
-	ARegion *ar;
+	ARegion *ar, *arnew;
 	
 	for(ar= sa->regionbase.first; ar; ar= ar->next)
 		if(ar->regiontype==RGN_TYPE_CHANNELS)
 			return ar;
-	return NULL;
+
+	/* add subdiv level; after header */
+	for(ar= sa->regionbase.first; ar; ar= ar->next)
+		if(ar->regiontype==RGN_TYPE_HEADER)
+			break;
+	
+	/* is error! */
+	if(ar==NULL) return NULL;
+	
+	arnew= MEM_callocN(sizeof(ARegion), "buttons for file panels");
+	
+	BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+	arnew->regiontype= RGN_TYPE_CHANNELS;
+	arnew->alignment= RGN_ALIGN_LEFT;
+	
+	arnew->flag = RGN_FLAG_HIDDEN;
+	
+	return arnew;
 }
 
 int file_bookmark_toggle_exec(bContext *C, wmOperator *unused)
diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c
new file mode 100644
index 00000000000..29c759d43c0
--- /dev/null
+++ b/source/blender/editors/space_file/file_panels.c
@@ -0,0 +1,165 @@
+/**
+ * $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) 2009 Blender Foundation.
+ * All rights reserved.
+ *
+ * 
+ * Contributor(s): Blender Foundation, Andrea Weikert
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "file_intern.h"
+#include "fsmenu.h"
+
+#include 
+
+static void do_file_panel_events(bContext *C, void *arg, int event)
+{
+
+}
+
+static void file_panel_category(const bContext *C, Panel *pa, FSMenuCategory category, int icon, int allow_delete)
+{
+	uiBlock *block;
+	uiStyle *style= U.uistyles.first;
+	int i;
+	int fontsize = file_font_pointsize();
+	struct FSMenu* fsmenu = fsmenu_get();
+	int nentries = fsmenu_get_nentries(fsmenu, category);
+
+	uiLayoutSetAlignment(pa->layout, UI_LAYOUT_ALIGN_LEFT);
+	block= uiLayoutFreeBlock(pa->layout);
+	uiBlockSetHandleFunc(block, do_file_panel_events, NULL);
+	uiBlockSetEmboss(block, UI_EMBOSSP);
+	uiBlockBeginAlign(block);
+	for (i=0; i< nentries;++i) {
+		char dir[FILE_MAX];
+		char temp[FILE_MAX];
+		uiLayout* layout = uiLayoutRow(pa->layout, UI_LAYOUT_ALIGN_LEFT);
+		char *entry = fsmenu_get_entry(fsmenu, category, i);
+
+		/* create nice bookmark name, shows last directory in the full path currently */
+		BLI_strncpy(temp, entry, FILE_MAX);
+		BLI_add_slash(temp);
+		BLI_getlastdir(temp, dir, FILE_MAX);
+		BLI_del_slash(dir);
+
+		/* operator shows the short bookmark name, should eventually have tooltip */
+		uiItemStringO(layout, dir, icon, "FILE_OT_select_bookmark", "dir", entry);
+		if (allow_delete && fsmenu_can_save(fsmenu, category, i) )
+			uiItemIntO(layout, "", ICON_X, "FILE_OT_delete_bookmark", "index", i);
+	}
+	uiBlockEndAlign(block);
+}
+
+static void file_panel_system(const bContext *C, Panel *pa)
+{
+	file_panel_category(C, pa, FS_CATEGORY_SYSTEM, ICON_DISK_DRIVE, 0);
+}
+
+static void file_panel_bookmarks(const bContext *C, Panel *pa)
+{
+	file_panel_category(C, pa, FS_CATEGORY_BOOKMARKS, ICON_BOOKMARKS, 1);
+}
+
+
+static void file_panel_recent(const bContext *C, Panel *pa)
+{
+	file_panel_category(C, pa, FS_CATEGORY_RECENT, ICON_FILE_FOLDER, 0);
+}
+
+
+static void file_panel_operator(const bContext *C, Panel *pa)
+{
+	SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+	struct wmOperator *op = sfile ? sfile->op : NULL;
+	uiBlock *block;
+	int sy;
+
+	block= uiLayoutFreeBlock(pa->layout);
+	uiBlockSetHandleFunc(block, do_file_panel_events, NULL);
+
+	sy= 0;
+	if (op) {
+		uiBlockBeginAlign(block);
+		RNA_STRUCT_BEGIN(op->ptr, prop) {
+			if(strcmp(RNA_property_identifier(prop), "rna_type") == 0)
+				continue;
+			if(strcmp(RNA_property_identifier(prop), "filename") == 0)
+				continue;
+
+			uiItemFullR(pa->layout, NULL, 0, op->ptr, prop, -1, 0, 0, 0, 0);
+		}
+		RNA_STRUCT_END;
+		uiBlockEndAlign(block);
+	}
+	uiBlockLayoutResolve(C, block, NULL, &sy);
+	uiEndBlock(C, block);
+	uiDrawBlock(C, block);
+}
+
+
+void file_panels_register(ARegionType *art)
+{
+	PanelType *pt;
+
+	pt= MEM_callocN(sizeof(PanelType), "spacetype file system directories");
+	strcpy(pt->idname, "FILE_PT_system");
+	strcpy(pt->label, "System");
+	pt->draw= file_panel_system;
+	BLI_addtail(&art->paneltypes, pt);
+
+	pt= MEM_callocN(sizeof(PanelType), "spacetype file bookmarks");
+	strcpy(pt->idname, "FILE_PT_bookmarks");
+	strcpy(pt->label, "Bookmarks");
+	pt->draw= file_panel_bookmarks;
+	BLI_addtail(&art->paneltypes, pt);
+
+	pt= MEM_callocN(sizeof(PanelType), "spacetype file recent directories");
+	strcpy(pt->idname, "FILE_PT_recent");
+	strcpy(pt->label, "Recent");
+	pt->draw= file_panel_recent;
+	BLI_addtail(&art->paneltypes, pt);
+
+	pt= MEM_callocN(sizeof(PanelType), "spacetype file operator properties");
+	strcpy(pt->idname, "FILE_PT_operator");
+	strcpy(pt->label, "Operator");
+	pt->draw= file_panel_operator;
+	BLI_addtail(&art->paneltypes, pt);
+}
\ No newline at end of file
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 766dec7c064..573aed72728 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -823,16 +823,16 @@ void filelist_sort(struct FileList* filelist, short sort)
 	int num;/*  , act= 0; */
 
 	switch(sort) {
-	case FILE_SORTALPHA:
+	case FILE_SORT_ALPHA:
 		qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_name);	
 		break;
-	case FILE_SORTDATE:
+	case FILE_SORT_TIME:
 		qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_date);	
 		break;
-	case FILE_SORTSIZE:
+	case FILE_SORT_SIZE:
 		qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_size);	
 		break;
-	case FILE_SORTEXTENS:
+	case FILE_SORT_EXTENSION:
 		qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_extension);	
 	}
 
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
index f10c89926d6..e929e028849 100644
--- a/source/blender/editors/space_file/filelist.h
+++ b/source/blender/editors/space_file/filelist.h
@@ -49,7 +49,6 @@ void				filelist_free_icons();
 struct FileList *	filelist_copy(struct FileList* filelist);
 int					filelist_find(struct FileList* filelist, char *file);
 void				filelist_free(struct FileList* filelist);
-void				filelist_freelib(struct FileList* filelist);
 void				filelist_sort(struct FileList* filelist, short sort);
 int					filelist_numfiles(struct FileList* filelist);
 const char *		filelist_dir(struct FileList* filelist);
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index d57fc7f90bc..ea42ad80fe6 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -84,7 +84,7 @@
 FileSelectParams* ED_fileselect_get_params(struct SpaceFile *sfile)
 {
 	if (!sfile->params) {
-		ED_fileselect_set_params(sfile, "", "/", 0, FILE_SHORTDISPLAY, 0, FILE_SORTALPHA);
+		ED_fileselect_set_params(sfile, "", "/", 0, FILE_SHORTDISPLAY, 0, FILE_SORT_ALPHA);
 	}
 	return sfile->params;
 }
@@ -159,7 +159,7 @@ float file_string_width(const char* str)
 {
 	uiStyle *style= U.uistyles.first;
 	uiStyleFontSet(&style->widget);
-	return BLF_width(str);
+	return BLF_width((char *)str);
 }
 
 float file_font_pointsize()
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index 59e8dcf82e6..a87ad4c4fd8 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -65,7 +65,6 @@ struct _FSMenuEntry {
 
 	char *path;
 	short save;
-	short xs, ys;
 };
 
 typedef struct FSMenu
@@ -74,9 +73,6 @@ typedef struct FSMenu
 	FSMenuEntry *fsmenu_bookmarks;
 	FSMenuEntry *fsmenu_recent;
 
-	FSMenuCategory selected_category;
-	int selected_entry;
-
 } FSMenu;
 
 static FSMenu *g_fsmenu = NULL;
@@ -89,17 +85,6 @@ struct FSMenu* fsmenu_get(void)
 	return g_fsmenu;
 }
 
-void fsmenu_select_entry(struct FSMenu* fsmenu, FSMenuCategory category, int index)
-{
-	fsmenu->selected_category = category;
-	fsmenu->selected_entry = index;
-}
-
-int	fsmenu_is_selected(struct FSMenu* fsmenu, FSMenuCategory category, int index)
-{
-	return (category==fsmenu->selected_category) && (index==fsmenu->selected_entry);
-}
-
 static FSMenuEntry *fsmenu_get_category(struct FSMenu* fsmenu, FSMenuCategory category)
 {
 	FSMenuEntry *fsms = NULL;
@@ -154,36 +139,16 @@ char *fsmenu_get_entry(struct FSMenu* fsmenu, FSMenuCategory category, int idx)
 	return fsme?fsme->path:NULL;
 }
 
-void fsmenu_set_pos(struct FSMenu* fsmenu, FSMenuCategory category, int idx, short xs, short ys)
+short fsmenu_can_save (struct FSMenu* fsmenu, FSMenuCategory category, int idx)
 {
 	FSMenuEntry *fsme;
 
 	for (fsme= fsmenu_get_category(fsmenu, category); fsme && idx; fsme= fsme->next)
 		idx--;
 
-	if (fsme) {
-		fsme->xs = xs;
-		fsme->ys = ys;
-	}
+	return fsme?fsme->save:0;
 }
 
-int	fsmenu_get_pos (struct FSMenu* fsmenu, FSMenuCategory category, int idx, short* xs, short* ys)
-{
-	FSMenuEntry *fsme;
-
-	for (fsme= fsmenu_get_category(fsmenu, category); fsme && idx; fsme= fsme->next)
-		idx--;
-
-	if (fsme) {
-		*xs = fsme->xs;
-		*ys = fsme->ys;
-		return 1;
-	}
-
-	return 0;
-}
-
-
 void fsmenu_insert_entry(struct FSMenu* fsmenu, FSMenuCategory category, char *path, int sorted, short save)
 {
 	FSMenuEntry *prev;
diff --git a/source/blender/editors/space_file/fsmenu.h b/source/blender/editors/space_file/fsmenu.h
index c51c45b7dc4..2cab622d523 100644
--- a/source/blender/editors/space_file/fsmenu.h
+++ b/source/blender/editors/space_file/fsmenu.h
@@ -52,22 +52,15 @@ int		fsmenu_get_nentries		(struct FSMenu* fsmenu, FSMenuCategory category);
 	 */
 char*	fsmenu_get_entry		(struct FSMenu* fsmenu, FSMenuCategory category, int index);
 
-void	fsmenu_select_entry		(struct FSMenu* fsmenu, FSMenuCategory category, int index);
-
-int		fsmenu_is_selected		(struct FSMenu* fsmenu, FSMenuCategory category, int index);
-
-	/** Sets the position of the  fsmenu entry at @a index */
-void	fsmenu_set_pos			(struct FSMenu* fsmenu, FSMenuCategory category, int index, short xs, short ys);
-
-	/** Returns the position of the  fsmenu entry at @a index. return value is 1 if successful, 0 otherwise */
-int		fsmenu_get_pos			(struct FSMenu* fsmenu, FSMenuCategory category, int index, short* xs, short* ys);
-
 	/** Inserts a new fsmenu entry with the given @a path.
 	 * Duplicate entries are not added.
 	 * @param sorted Should entry be inserted in sorted order?
 	 */
 void	fsmenu_insert_entry		(struct FSMenu* fsmenu, FSMenuCategory category, char *path, int sorted, short save);
 
+	/** Return whether the entry was created by the user and can be saved and deleted */
+short   fsmenu_can_save			(struct FSMenu* fsmenu, FSMenuCategory category, int index);
+
 	/** Removes the fsmenu entry at the given @a index. */
 void	fsmenu_remove_entry		(struct FSMenu* fsmenu, FSMenuCategory category, int index);
 
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 37d8f2bffa4..156c7d6f9be 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -163,6 +163,46 @@ static SpaceLink *file_duplicate(SpaceLink *sl)
 	return (SpaceLink *)sfilen;
 }
 
+static void file_refresh(const bContext *C, ScrArea *sa)
+{
+	SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+	FileSelectParams *params = ED_fileselect_get_params(sfile);
+
+	if (!sfile->files) {
+		sfile->files = filelist_new();
+		filelist_setdir(sfile->files, params->dir);
+		params->active_file = -1; // added this so it opens nicer (ton)
+	}
+	filelist_hidedot(sfile->files, params->flag & FILE_HIDE_DOT);
+	if (filelist_empty(sfile->files))
+	{
+		filelist_readdir(sfile->files);
+	}
+	filelist_setfilter(sfile->files, params->flag & FILE_FILTER ? params->filter : 0);	
+	if(params->sort!=FILE_SORT_NONE) filelist_sort(sfile->files, params->sort);		
+}
+
+static void file_listener(ScrArea *sa, wmNotifier *wmn)
+{
+	SpaceFile* sfile = (SpaceFile*)sa->spacedata.first;
+
+	/* context changes */
+	switch(wmn->category) {
+		case NC_FILE:
+			switch (wmn->data) {
+				case ND_FILELIST:
+					if (sfile->files) filelist_free(sfile->files);
+					ED_area_tag_refresh(sa);
+					ED_area_tag_redraw(sa);
+					break;
+				case ND_PARAMS:
+					ED_area_tag_refresh(sa);
+					ED_area_tag_redraw(sa);
+					break;
+			}
+			break;
+	}
+}
 
 /* add handlers, stuff you only do once or on area/region changes */
 static void file_main_area_init(wmWindowManager *wm, ARegion *ar)
@@ -188,31 +228,9 @@ static void file_main_area_draw(const bContext *C, ARegion *ar)
 	View2D *v2d= &ar->v2d;
 	View2DScrollers *scrollers;
 	float col[3];
-	
-	if (!sfile->files) {
-		sfile->files = filelist_new();
-		filelist_setdir(sfile->files, params->dir);
-		params->active_file = -1; // added this so it opens nicer (ton)
-	}
 
 	layout = ED_fileselect_get_layout(sfile, ar);
 
-	if (filelist_empty(sfile->files))
-	{
-		unsigned int filter = 0;
-		filelist_hidedot(sfile->files, params->flag & FILE_HIDE_DOT);
-		if (params->flag & FILE_FILTER) {
-			filter = params->filter ;
-		} else {
-			filter = 0;
-		}
-
-		filelist_setfilter(sfile->files, filter);
-		filelist_readdir(sfile->files);
-		
-		if(params->sort!=FILE_SORTALPHA) filelist_sort(sfile->files, params->sort);		
-	}
-
 	/* clear and setup matrix */
 	UI_GetThemeColor3fv(TH_BACK, col);
 	glClearColor(col[0], col[1], col[2], 0.0);
@@ -274,20 +292,25 @@ void file_operatortypes(void)
 	WM_operatortype_append(FILE_OT_parent);
 	WM_operatortype_append(FILE_OT_refresh);
 	WM_operatortype_append(FILE_OT_bookmark_toggle);
+	WM_operatortype_append(FILE_OT_add_bookmark);
+	WM_operatortype_append(FILE_OT_delete_bookmark);
+	WM_operatortype_append(FILE_OT_hidedot);
 }
 
 /* NOTE: do not add .blend file reading on this level */
 void file_keymap(struct wmWindowManager *wm)
 {
 	ListBase *keymap= WM_keymap_listbase(wm, "File", SPACE_FILE, 0);
+	WM_keymap_add_item(keymap, "FILE_OT_bookmark_toggle", NKEY, KM_PRESS, 0, 0);
 	WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_PRESS, 0, 0);
 	WM_keymap_add_item(keymap, "FILE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
 	WM_keymap_add_item(keymap, "FILE_OT_select_border", BKEY, KM_PRESS, 0, 0);
 	WM_keymap_add_item(keymap, "FILE_OT_highlight", MOUSEMOVE, KM_ANY, 0, 0);
 	WM_keymap_add_item(keymap, "FILE_OT_parent", PKEY, KM_PRESS, 0, 0);
-	
+	WM_keymap_add_item(keymap, "FILE_OT_add_bookmark", BKEY, KM_PRESS, KM_CTRL, 0);
+	WM_keymap_add_item(keymap, "FILE_OT_hidedot", HKEY, KM_PRESS, 0, 0);
 	WM_keymap_add_item(keymap, "FILE_OT_loadimages", TIMER1, KM_ANY, KM_ANY, 0);
-
+	
 	keymap= WM_keymap_listbase(wm, "FileBookmark", SPACE_FILE, 0);
 	WM_keymap_add_item(keymap, "FILE_OT_select_bookmark", LEFTMOUSE, KM_PRESS, 0, 0);
 }
@@ -295,56 +318,31 @@ void file_keymap(struct wmWindowManager *wm)
 
 static void file_channel_area_init(wmWindowManager *wm, ARegion *ar)
 {
-	ListBase *keymap;
-
-	UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
-
-	/* own keymap */
-	keymap= WM_keymap_listbase(wm, "FileBookmark", SPACE_FILE, 0);
-	WM_event_add_keymap_handler_bb(&ar->handlers, keymap, NULL, NULL);
+	ED_region_panels_init(wm, ar);
 }
 
 static void file_channel_area_draw(const bContext *C, ARegion *ar)
 {
-	View2D *v2d= &ar->v2d;
-	float col[3];
+	ED_region_panels(C, ar, 1, NULL);
+}
 
-	UI_GetThemeColor3fv(TH_PANEL, col);
-	glClearColor(col[0], col[1], col[2], 0.0);
-	glClear(GL_COLOR_BUFFER_BIT);
-
-	/* data... */
-	UI_view2d_view_ortho(C, v2d);
-
-	file_draw_fsmenu(C, ar);
+static void file_channel_area_listener(ARegion *ar, wmNotifier *wmn)
+{
+	/* context changes */
+	switch(wmn->category) {
+		
+	}
 }
 
 /* add handlers, stuff you only do once or on area/region changes */
 static void file_header_area_init(wmWindowManager *wm, ARegion *ar)
 {
-	UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+	ED_region_header_init(ar);
 }
 
 static void file_header_area_draw(const bContext *C, ARegion *ar)
 {
-	float col[3];
-	
-	/* clear */
-	if(ED_screen_area_active(C))
-		UI_GetThemeColor3fv(TH_HEADER, col);
-	else
-		UI_GetThemeColor3fv(TH_HEADERDESEL, col);
-	
-	glClearColor(col[0], col[1], col[2], 0.0);
-	glClear(GL_COLOR_BUFFER_BIT);
-	
-	/* set view2d view matrix for scrolling (without scrollers) */
-	UI_view2d_view_ortho(C, &ar->v2d);
-	
-	file_header_buttons(C, ar);
-	
-	/* restore view matrix? */
-	UI_view2d_view_restore(C);
+	ED_region_header(C, ar);
 }
 
 /* add handlers, stuff you only do once or on area/region changes */
@@ -386,6 +384,8 @@ void ED_spacetype_file(void)
 	st->free= file_free;
 	st->init= file_init;
 	st->duplicate= file_duplicate;
+	st->refresh= file_refresh;
+	st->listener= file_listener;
 	st->operatortypes= file_operatortypes;
 	st->keymap= file_keymap;
 	
@@ -405,6 +405,7 @@ void ED_spacetype_file(void)
 	art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
 	art->init= file_header_area_init;
 	art->draw= file_header_area_draw;
+	// art->listener= file_header_area_listener;
 	BLI_addhead(&st->regiontypes, art);
 	
 	/* regions: ui */
@@ -421,10 +422,13 @@ void ED_spacetype_file(void)
 	art->regionid = RGN_TYPE_CHANNELS;
 	art->minsizex= 240;
 	art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+	art->listener= file_channel_area_listener;
 	art->init= file_channel_area_init;
 	art->draw= file_channel_area_draw;
 	BLI_addhead(&st->regiontypes, art);
-	
+	file_panels_register(art);
+
+
 	BKE_spacetype_register(st);
 
 }
diff --git a/source/blender/editors/space_graph/Makefile b/source/blender/editors/space_graph/Makefile
index 340495ecc79..e04a354fb1d 100644
--- a/source/blender/editors/space_graph/Makefile
+++ b/source/blender/editors/space_graph/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index acf712d0147..ddf4105fdf4 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -1,5 +1,5 @@
 /**
- * $Id: drawipo.c 17512 2008-11-20 05:55:42Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 49397ed0edd..b624d02a633 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -1,5 +1,5 @@
 /**
- * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 9aaef9fca8a..7746f49d135 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -1,5 +1,5 @@
 /**
- * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_image/Makefile b/source/blender/editors/space_image/Makefile
index 44d841a0606..e7e9a9b5665 100644
--- a/source/blender/editors/space_image/Makefile
+++ b/source/blender/editors/space_image/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index b5df0257e71..edf9bcbd896 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -383,6 +383,7 @@ static void image_editcursor_buts(const bContext *C, View2D *v2d, uiBlock *block
 	}
 }
 
+#if 0
 static void image_panel_view_properties(const bContext *C, Panel *pa)
 {
 	SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
@@ -439,6 +440,7 @@ static void image_panel_view_properties(const bContext *C, Panel *pa)
 	}
 	image_editcursor_buts(C, &ar->v2d, block);
 }
+#endif
 
 void brush_buttons(const bContext *C, uiBlock *block, short fromsima,
 				   int evt_nop, int evt_change,
@@ -1023,42 +1025,53 @@ static void image_load_fs_cb(bContext *C, void *ima_pp_v, void *iuser_v)
 static void image_multi_cb(bContext *C, void *rr_v, void *iuser_v) 
 {
 	BKE_image_multilayer_index(rr_v, iuser_v); 
+	WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
 }
 static void image_multi_inclay_cb(bContext *C, void *rr_v, void *iuser_v) 
 {
 	RenderResult *rr= rr_v;
 	ImageUser *iuser= iuser_v;
 	int tot= BLI_countlist(&rr->layers) + (rr->rectf?1:0);  /* fake compo result layer */
-	if(iuser->layerlayerlayer++;
-	BKE_image_multilayer_index(rr, iuser); 
+		BKE_image_multilayer_index(rr, iuser); 
+		WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
+	}
 }
 static void image_multi_declay_cb(bContext *C, void *rr_v, void *iuser_v) 
 {
 	ImageUser *iuser= iuser_v;
-	if(iuser->layer>0)
+
+	if(iuser->layer>0) {
 		iuser->layer--;
-	BKE_image_multilayer_index(rr_v, iuser); 
+		BKE_image_multilayer_index(rr_v, iuser); 
+		WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
+	}
 }
 static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v) 
 {
 	RenderResult *rr= rr_v;
 	ImageUser *iuser= iuser_v;
 	RenderLayer *rl= BLI_findlink(&rr->layers, iuser->layer);
+
 	if(rl) {
 		int tot= BLI_countlist(&rl->passes) + (rl->rectf?1:0);	/* builtin render result has no combined pass in list */
 		if(iuser->passpass++;
 			BKE_image_multilayer_index(rr, iuser); 
+			WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
 		}
 	}
 }
 static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v) 
 {
 	ImageUser *iuser= iuser_v;
+
 	if(iuser->pass>0) {
 		iuser->pass--;
 		BKE_image_multilayer_index(rr_v, iuser); 
+		WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
 	}
 }
 
@@ -1075,7 +1088,7 @@ static void image_pack_cb(bContext *C, void *ima_v, void *iuser_v)
 				}
 				
 				if ((G.fileflags & G_AUTOPACK) == 0) {
-					unpackImage(ima, PF_ASK);
+					unpackImage(NULL, ima, PF_ASK); /* XXX report errors */
 					ED_undo_push(C, "Unpack image");
 				}
 			} 
@@ -1084,7 +1097,7 @@ static void image_pack_cb(bContext *C, void *ima_v, void *iuser_v)
 				if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) {
 					// XXX error("Can't pack painted image. Save image or use Repack as PNG.");
 				} else {
-					ima->packedfile = newPackedFile(ima->name);
+					ima->packedfile = newPackedFile(NULL, ima->name); /* XXX report errors */
 					ED_undo_push(C, "Pack image");
 				}
 			}
@@ -1353,6 +1366,23 @@ void ED_image_uiblock_panel(const bContext *C, uiBlock *block, Image **ima_pp, I
 	 uiBlockEndAlign(block);
 }	
 
+void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
+{
+	uiBlock *block= uiLayoutFreeBlock(layout);
+	Scene *scene= CTX_data_scene(C);
+	RenderResult *rr;
+
+	/* render layers and passes */
+	if(ima && iuser) {
+		rr= BKE_image_get_renderresult(scene, ima);
+
+		if(rr) {
+			uiBlockBeginAlign(block);
+			uiblock_layer_pass_buttons(block, rr, iuser, 0, 0, 0, 160);
+			uiBlockEndAlign(block);
+		}
+	}
+}
 
 static void image_panel_properties(const bContext *C, Panel *pa)
 {
@@ -1377,12 +1407,6 @@ void image_buttons_register(ARegionType *art)
 	pt->draw= image_panel_properties;
 	BLI_addtail(&art->paneltypes, pt);
 
-	pt= MEM_callocN(sizeof(PanelType), "spacetype image view properties");
-	strcpy(pt->idname, "IMAGE_PT_view_properties");
-	strcpy(pt->label, "View Properties");
-	pt->draw= image_panel_view_properties;
-	BLI_addtail(&art->paneltypes, pt);
-
 	pt= MEM_callocN(sizeof(PanelType), "spacetype image panel paint");
 	strcpy(pt->idname, "IMAGE_PT_paint");
 	strcpy(pt->label, "Paint");
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 122e298baaa..e61931f2fad 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -311,12 +311,14 @@ static void sima_draw_alpha_pixelsf(float x1, float y1, int rectx, int recty, fl
 //	glColorMask(1, 1, 1, 1);
 }
 
+#ifdef WITH_LCMS
 static void sima_draw_colorcorrected_pixels(float x1, float y1, ImBuf *ibuf)
 {
 	colorcorrection_do_ibuf(ibuf, "MONOSCNR.ICM"); /* path is hardcoded here, find some place better */
 	
 	glaDrawPixelsSafe(x1, y1, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->crect);
 }
+#endif
 
 static void sima_draw_zbuf_pixels(float x1, float y1, int rectx, int recty, int *recti)
 {
@@ -450,7 +452,7 @@ static unsigned int *get_part_from_ibuf(ImBuf *ibuf, short startx, short starty,
 	return rectmain;
 }
 
-static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Image *ima, ImBuf *ibuf, float zoomx, float zoomy)
+static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Image *ima, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy)
 {
 	unsigned int *rect;
 	int dx, dy, sx, sy, x, y;
@@ -477,7 +479,7 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Image *ima, I
 	/* draw repeated */
 	for(sy=0; sy+dy<=ibuf->y; sy+= dy) {
 		for(sx=0; sx+dx<=ibuf->x; sx+= dx) {
-			UI_view2d_view_to_region(&ar->v2d, (float)sx/(float)ibuf->x, (float)sy/(float)ibuf->y, &x, &y);
+			UI_view2d_to_region_no_clip(&ar->v2d, fx + (float)sx/(float)ibuf->x, fy + (float)sy/(float)ibuf->y, &x, &y);
 
 			glaDrawPixelsSafe(x, y, dx, dy, dx, GL_RGBA, GL_UNSIGNED_BYTE, rect);
 		}
@@ -488,16 +490,19 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Image *ima, I
 	MEM_freeN(rect);
 }
 
-static void draw_image_buffer_repeated(SpaceImage *sima, ARegion *ar, Scene *scene, ImBuf *ibuf, float zoomx, float zoomy)
+static void draw_image_buffer_repeated(SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float zoomx, float zoomy)
 {
 	float x, y;
 	double time_current;
 	
 	time_current = PIL_check_seconds_timer();
 
-	for(x=ar->v2d.cur.xmin; xv2d.cur.xmax; x += zoomx) { 
-		for(y=ar->v2d.cur.ymin; yv2d.cur.ymax; y += zoomy) { 
-			draw_image_buffer(sima, ar, scene, ibuf, x, y, zoomx, zoomy);
+	for(x=floor(ar->v2d.cur.xmin); xv2d.cur.xmax; x += 1.0f) { 
+		for(y=floor(ar->v2d.cur.ymin); yv2d.cur.ymax; y += 1.0f) { 
+			if(ima && (ima->tpageflag & IMA_TILES))
+				draw_image_buffer_tiled(sima, ar, ima, ibuf, x, y, zoomx, zoomy);
+			else
+				draw_image_buffer(sima, ar, scene, ibuf, x, y, zoomx, zoomy);
 
 			/* only draw until running out of time */
 			if((PIL_check_seconds_timer() - time_current) > 0.25)
@@ -667,9 +672,9 @@ void draw_image_main(SpaceImage *sima, ARegion *ar, Scene *scene)
 	if(ibuf==NULL)
 		draw_image_grid(ar, zoomx, zoomy);
 	else if(sima->flag & SI_DRAW_TILE)
-		draw_image_buffer_repeated(sima, ar, scene, ibuf, zoomx, zoomy);
+		draw_image_buffer_repeated(sima, ar, scene, ima, ibuf, zoomx, zoomy);
 	else if(ima && (ima->tpageflag & IMA_TILES))
-		draw_image_buffer_tiled(sima, ar, ima, ibuf, zoomx, zoomy);
+		draw_image_buffer_tiled(sima, ar, ima, ibuf, 0.0f, 0.0, zoomx, zoomy);
 	else
 		draw_image_buffer(sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy);
 
@@ -699,12 +704,5 @@ void draw_image_main(SpaceImage *sima, ARegion *ar, Scene *scene)
 		}
 	}
 #endif
-
-#if 0
-	/* it is important to end a view in a transform compatible with buttons */
-	bwin_scalematrix(sa->win, sima->blockscale, sima->blockscale, sima->blockscale);
-	if(!(G.rendering && show_render))
-		image_blockhandlers(sa);
-#endif
 }
 
diff --git a/source/blender/editors/space_image/image_header.c b/source/blender/editors/space_image/image_header.c
index adf4772efde..9550c4c3a29 100644
--- a/source/blender/editors/space_image/image_header.c
+++ b/source/blender/editors/space_image/image_header.c
@@ -802,11 +802,11 @@ void image_header_buttons(const bContext *C, ARegion *ar)
 			uiBlockBeginAlign(block);
 			
 			uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_REDR, ICON_VERTEXSEL,
-				xco,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode");
+				xco,yco,XIC,YIC, &scene->toolsettings->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode");
 			uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_REDR, ICON_EDGESEL,
-				xco+=XIC,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Edge select mode");
+				xco+=XIC,yco,XIC,YIC, &scene->toolsettings->selectmode, 1.0, 0.0, 0, 0, "Edge select mode");
 			uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_REDR, ICON_FACESEL,
-				xco+=XIC,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Face select mode");
+				xco+=XIC,yco,XIC,YIC, &scene->toolsettings->selectmode, 1.0, 0.0, 0, 0, "Face select mode");
 
 			uiBlockEndAlign(block);
 		}
@@ -837,14 +837,14 @@ void image_header_buttons(const bContext *C, ARegion *ar)
 		/* snap options, identical to options in 3d view header */
 		uiBlockBeginAlign(block);
 
-		if (scene->snap_flag & SCE_SNAP) {
-			uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEO,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Use Snap or Grid (Shift Tab).");
+		if (scene->toolsettings->snap_flag & SCE_SNAP) {
+			uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEO,xco,yco,XIC,YIC, &scene->toolsettings->snap_flag, 0, 0, 0, 0, "Use Snap or Grid (Shift Tab).");
 			xco+= XIC;
-			uiDefButS(block, MENU, B_NOP, "Mode%t|Closest%x0|Center%x1|Median%x2",xco,yco,70,YIC, &scene->snap_target, 0, 0, 0, 0, "Snap Target Mode.");
+			uiDefButS(block, MENU, B_NOP, "Mode%t|Closest%x0|Center%x1|Median%x2",xco,yco,70,YIC, &scene->toolsettings->snap_target, 0, 0, 0, 0, "Snap Target Mode.");
 			xco+= 70;
 		}
 		else {
-			uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEAR,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab).");	
+			uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEAR,xco,yco,XIC,YIC, &scene->toolsettings->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab).");	
 			xco+= XIC;
 		}
 
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 537996601b8..24781cc115e 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -577,34 +577,30 @@ void IMAGE_OT_view_zoom_ratio(wmOperatorType *ot)
 
 /**************** load/replace/save callbacks ******************/
 
-static char *filesel_imagetype_string(Image *ima)
-{
-	char *strp, *str= MEM_callocN(15*32, "menu for filesel");
-	
-	strp= str;
-	str += sprintf(str, "Save Image as: %%t|");
-	str += sprintf(str, "Targa %%x%d|", R_TARGA);
-	str += sprintf(str, "Targa Raw %%x%d|", R_RAWTGA);
-	str += sprintf(str, "PNG %%x%d|", R_PNG);
-	str += sprintf(str, "BMP %%x%d|", R_BMP);
-	str += sprintf(str, "Jpeg %%x%d|", R_JPEG90);
+/* XXX make dynamic */
+static const EnumPropertyItem image_file_type_items[] = {
+		{R_TARGA, "TARGA", 0, "Targa", ""},
+		{R_RAWTGA, "TARGA RAW", 0, "Targa Raw", ""},
+		{R_PNG, "PNG", 0, "PNG", ""},
+		{R_BMP, "BMP", 0, "BMP", ""},
+		{R_JPEG90, "JPEG", 0, "Jpeg", ""},
 #ifdef WITH_OPENJPEG
-	str += sprintf(str, "Jpeg 2000 %%x%d|", R_JP2);
+		{R_JP2, "JPEG_2000", 0, "Jpeg 2000", ""},
 #endif
-	str += sprintf(str, "Iris %%x%d|", R_IRIS);
-	if(G.have_libtiff)
-		str += sprintf(str, "Tiff %%x%d|", R_TIFF);
-	str += sprintf(str, "Radiance HDR %%x%d|", R_RADHDR);
-	str += sprintf(str, "Cineon %%x%d|", R_CINEON);
-	str += sprintf(str, "DPX %%x%d|", R_DPX);
+		{R_IRIS, "IRIS", 0, "Iris", ""},
+	//if(G.have_libtiff)
+		{R_TIFF, "TIFF", 0, "Tiff", ""},
+		{R_RADHDR, "RADIANCE_HDR", 0, "Radiance HDR", ""},
+		{R_CINEON, "CINEON", 0, "Cineon", ""},
+		{R_DPX, "DPX", 0, "DPX", ""},
 #ifdef WITH_OPENEXR
-	str += sprintf(str, "OpenEXR %%x%d|", R_OPENEXR);
+		{R_OPENEXR, "OPENEXR", 0, "OpenEXR", ""},
 	/* saving sequences of multilayer won't work, they copy buffers  */
-	if(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER);
-	else str += sprintf(str, "MultiLayer %%x%d|", R_MULTILAYER);
+	/*if(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER);
+	else*/
+		{R_MULTILAYER, "MULTILAYER", 0, "MultiLayer", ""},
 #endif	
-	return strp;
-}
+		{0, NULL, 0, NULL, NULL}};
 
 static void image_filesel(bContext *C, wmOperator *op, const char *path)
 {
@@ -799,7 +795,9 @@ static int save_as_exec(bContext *C, wmOperator *op)
 	if(!ima)
 		return OPERATOR_CANCELLED;
 
+	sima->imtypenr= RNA_enum_get(op->ptr, "file_type");
 	RNA_string_get(op->ptr, "filename", str);
+
 	save_image_doit(C, sima, scene, op, str);
 
 	return OPERATOR_FINISHED;
@@ -820,10 +818,6 @@ static int save_as_invoke(bContext *C, wmOperator *op, wmEvent *event)
 
 	/* always opens fileselect */
 	if(ibuf) {
-		char *strp;
-		
-		strp= filesel_imagetype_string(ima); // XXX unused still
-		
 		/* cant save multilayer sequence, ima->rr isn't valid for a specific frame */
 		if(ima->rr && !(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER))
 			sima->imtypenr= R_MULTILAYER;
@@ -831,14 +825,14 @@ static int save_as_invoke(bContext *C, wmOperator *op, wmEvent *event)
 			sima->imtypenr= scene->r.imtype;
 		else
 			sima->imtypenr= BKE_ftype_to_imtype(ibuf->ftype);
+
+		RNA_enum_set(op->ptr, "file_type", sima->imtypenr);
 		
 		if(ibuf->name[0]==0)
 			BLI_strncpy(ibuf->name, G.ima, FILE_MAX);
 		
 		// XXX note: we can give default menu enums to operator for this 
 		image_filesel(C, op, ibuf->name);
-
-		MEM_freeN(strp);
 		
 		return OPERATOR_RUNNING_MODAL;
 	}
@@ -862,6 +856,7 @@ void IMAGE_OT_save_as(wmOperatorType *ot)
 
 	/* properties */
 	RNA_def_string_file_path(ot->srna, "filename", "", FILE_MAX, "Filename", "File path to save image to.");
+	RNA_def_enum(ot->srna, "file_type", image_file_type_items, R_PNG, "File Type", "File type to save image as.");
 }
 
 /******************** save image operator ********************/
@@ -1119,7 +1114,7 @@ static int pack_exec(bContext *C, wmOperator *op)
 	if(as_png)
 		BKE_image_memorypack(ima);
 	else
-		ima->packedfile= newPackedFile(ima->name);
+		ima->packedfile= newPackedFile(op->reports, ima->name);
 
 	return OPERATOR_FINISHED;
 }
@@ -1167,13 +1162,76 @@ void IMAGE_OT_pack(wmOperatorType *ot)
 
 /********************* unpack operator *********************/
 
+/* XXX move this to some place where it can be reused */
+
+const EnumPropertyItem unpack_method_items[] = {
+	{PF_USE_LOCAL, "USE_LOCAL", 0, "Use Local File", ""},
+	{PF_WRITE_LOCAL, "WRITE_LOCAL", 0, "Write Local File (overwrite existing)", ""},
+	{PF_USE_ORIGINAL, "USE_ORIGINAL", 0, "Use Original File", ""},
+	{PF_WRITE_ORIGINAL, "WRITE_ORIGINAL", 0, "Write Original File (overwrite existing)", ""},
+	{0, NULL, 0, NULL, NULL}};
+
+void unpack_menu(bContext *C, char *opname, char *abs_name, char *folder, PackedFile *pf)
+{
+	uiPopupMenu *pup;
+	uiLayout *layout;
+	char line[FILE_MAXDIR + FILE_MAXFILE + 100];
+	char local_name[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX];
+	
+	strcpy(local_name, abs_name);
+	BLI_splitdirstring(local_name, fi);
+	sprintf(local_name, "//%s/%s", folder, fi);
+
+	pup= uiPupMenuBegin(C, "Unpack file", 0);
+	layout= uiPupMenuLayout(pup);
+
+	uiItemEnumO(layout, "Remove Pack", 0, opname, "method", PF_REMOVE);
+
+	if(strcmp(abs_name, local_name)) {
+		switch(checkPackedFile(local_name, pf)) {
+			case PF_NOFILE:
+				sprintf(line, "Create %s", local_name);
+				uiItemEnumO(layout, line, 0, opname, "method", PF_WRITE_LOCAL);
+				break;
+			case PF_EQUAL:
+				sprintf(line, "Use %s (identical)", local_name);
+				uiItemEnumO(layout, line, 0, opname, "method", PF_USE_LOCAL);
+				break;
+			case PF_DIFFERS:
+				sprintf(line, "Use %s (differs)", local_name);
+				uiItemEnumO(layout, line, 0, opname, "method", PF_USE_LOCAL);
+				sprintf(line, "Overwrite %s", local_name);
+				uiItemEnumO(layout, line, 0, opname, "method", PF_WRITE_LOCAL);
+				break;
+		}
+	}
+	
+	switch(checkPackedFile(abs_name, pf)) {
+		case PF_NOFILE:
+			sprintf(line, "Create %s", abs_name);
+			uiItemEnumO(layout, line, 0, opname, "method", PF_WRITE_ORIGINAL);
+			break;
+		case PF_EQUAL:
+			sprintf(line, "Use %s (identical)", abs_name);
+			uiItemEnumO(layout, line, 0, opname, "method", PF_USE_ORIGINAL);
+			break;
+		case PF_DIFFERS:
+			sprintf(line, "Use %s (differs)", local_name);
+			uiItemEnumO(layout, line, 0, opname, "method", PF_USE_ORIGINAL);
+			sprintf(line, "Overwrite %s", local_name);
+			uiItemEnumO(layout, line, 0, opname, "method", PF_WRITE_ORIGINAL);
+			break;
+	}
+
+	uiPupMenuEnd(C, pup);
+}
+
 static int unpack_exec(bContext *C, wmOperator *op)
 {
 	Image *ima= CTX_data_edit_image(C);
+	int method= RNA_enum_get(op->ptr, "method");
 
-	if(!ima)
-		return OPERATOR_CANCELLED;
-	if(!ima->packedfile)
+	if(!ima || !ima->packedfile)
 		return OPERATOR_CANCELLED;
 
 	if(ima->source==IMA_SRC_SEQUENCE || ima->source==IMA_SRC_MOVIE) {
@@ -1184,7 +1242,27 @@ static int unpack_exec(bContext *C, wmOperator *op)
 	if(G.fileflags & G_AUTOPACK)
 		BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so image will be packed again on file save.");
 	
-	unpackImage(ima, PF_ASK);
+	unpackImage(op->reports, ima, method);
+
+	return OPERATOR_FINISHED;
+}
+
+static int unpack_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+	Image *ima= CTX_data_edit_image(C);
+
+	if(!ima || !ima->packedfile)
+		return OPERATOR_CANCELLED;
+
+	if(ima->source==IMA_SRC_SEQUENCE || ima->source==IMA_SRC_MOVIE) {
+		BKE_report(op->reports, RPT_ERROR, "Can't unpack movie or image sequence.");
+		return OPERATOR_CANCELLED;
+	}
+
+	if(G.fileflags & G_AUTOPACK)
+		BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so image will be packed again on file save.");
+	
+	unpack_menu(C, "IMAGE_OT_unpack", ima->name, "textures", ima->packedfile);
 
 	return OPERATOR_FINISHED;
 }
@@ -1197,10 +1275,14 @@ void IMAGE_OT_unpack(wmOperatorType *ot)
 	
 	/* api callbacks */
 	ot->exec= unpack_exec;
+	ot->invoke= unpack_invoke;
 	ot->poll= space_image_poll;
 
 	/* flags */
 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+	/* properties */
+	RNA_def_enum(ot->srna, "method", unpack_method_items, PF_USE_LOCAL, "Method", "How to unpack.");
 }
 
 /******************** sample image operator ********************/
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 49f950fe67b..7d6faa00dfc 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -327,12 +327,10 @@ static void image_main_area_set_view2d(SpaceImage *sima, ARegion *ar, Scene *sce
 #endif
 	if(sima->image) {
 		ImBuf *ibuf= ED_space_image_buffer(sima);
-		float xuser_asp, yuser_asp;
 		
-		ED_image_aspect(sima->image, &xuser_asp, &yuser_asp);
 		if(ibuf) {
-			width= ibuf->x*xuser_asp;
-			height= ibuf->y*yuser_asp;
+			width= ibuf->x;
+			height= ibuf->y;
 		}
 		else if(sima->image->type==IMA_TYPE_R_RESULT) {
 			/* not very important, just nice */
@@ -683,7 +681,7 @@ void ED_image_aspect(Image *ima, float *aspx, float *aspy)
 	*aspx= *aspy= 1.0;
 
 	if((ima == NULL) || (ima->type == IMA_TYPE_R_RESULT) || (ima->type == IMA_TYPE_COMPOSITE) ||
-	   (ima->tpageflag & IMA_TILES) || (ima->aspx==0.0 || ima->aspy==0.0))
+	   (ima->aspx==0.0 || ima->aspy==0.0))
 		return;
 
 	/* x is always 1 */
diff --git a/source/blender/editors/space_info/Makefile b/source/blender/editors/space_info/Makefile
index bc04ddc7824..931c2f2097c 100644
--- a/source/blender/editors/space_info/Makefile
+++ b/source/blender/editors/space_info/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/space_info/SConscript b/source/blender/editors/space_info/SConscript
index 05afcae162e..01268115687 100644
--- a/source/blender/editors/space_info/SConscript
+++ b/source/blender/editors/space_info/SConscript
@@ -11,7 +11,4 @@ defs = []
 if env['WITH_BF_GAMEENGINE']:
 	defs.append('GAMEBLENDER=1')
 
-	if env['WITH_BF_SOLID']:
-		defs.append('USE_SUMO_SOLID')
-
 env.BlenderLib ( 'bf_editors_space_info', sources, Split(incs), defs, libtype=['core'], priority=[70] )
diff --git a/source/blender/editors/space_info/info_header.c b/source/blender/editors/space_info/info_header.c
deleted file mode 100644
index ac39c67d8f2..00000000000
--- a/source/blender/editors/space_info/info_header.c
+++ /dev/null
@@ -1,507 +0,0 @@
-/**
- * $Id: info_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
- *
- * ***** 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) 2008 Blender Foundation.
- * All rights reserved.
- *
- * 
- * Contributor(s): Blender Foundation
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include 
-#include 
-
-#include "DNA_packedFile_types.h"
-#include "DNA_space_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_userdef_types.h"
-#include "DNA_windowmanager_types.h"
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_bpath.h"
-
-#include "BKE_context.h"
-#include "BKE_global.h"
-#include "BKE_image.h"
-#include "BKE_main.h"
-#include "BKE_packedFile.h"
-#include "BKE_screen.h"
-
-#include "ED_screen.h"
-#include "ED_types.h"
-#include "ED_util.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
-
-#include "UI_interface.h"
-#include "UI_resources.h"
-#include "UI_view2d.h"
-
-#include "IMB_imbuf_types.h"
-
-#include "info_intern.h"
-
-static int pupmenu() {return 0;}
-static int okee() {return 0;}
-static int error() {return 0;}
-
-/* ************************ header area region *********************** */
-
-#define B_STOPRENDER	1
-#define B_STOPCAST		2
-#define B_STOPANIM		3
-
-static void do_viewmenu(bContext *C, void *arg, int event)
-{
-}
-
-static uiBlock *dummy_viewmenu(bContext *C, ARegion *ar, void *arg_unused)
-{
-	ScrArea *curarea= CTX_wm_area(C);
-	uiBlock *block;
-	short yco= 0, menuwidth=120;
-	
-	block= uiBeginBlock(C, ar, "dummy_viewmenu", UI_EMBOSSP);
-	uiBlockSetButmFunc(block, do_viewmenu, NULL);
-	
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Nothing yet", 0, yco-=20, 
-					 menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
-	
-	if(curarea->headertype==HEADERTOP) {
-		uiBlockSetDirection(block, UI_DOWN);
-	}
-	else {
-		uiBlockSetDirection(block, UI_TOP);
-		uiBlockFlipOrder(block);
-	}
-	
-	uiTextBoundsBlock(block, 50);
-	uiEndBlock(C, block);
-	
-	return block;
-}
-
-static int buttons_do_unpack()
-{
-	int how;
-	char menu[2048];
-	char *line = menu;
-	int ret_value = 1, count = 0;
-	
-	count = countPackedFiles();
-	
-	if(!count) {
-		pupmenu("No packed files. Autopack disabled");
-		return ret_value;
-	}
-	if (count == 1)
-		line += sprintf(line, "Unpack 1 file%%t");
-	else
-		line += sprintf(line, "Unpack %d files%%t", count);
-	
-	line += sprintf(line, "|Use files in current directory (create when necessary)%%x%d", PF_USE_LOCAL);
-	line += sprintf(line, "|Write files to current directory (overwrite existing files)%%x%d", PF_WRITE_LOCAL);
-	line += sprintf(line, "|%%l|Use files in original location (create when necessary)%%x%d", PF_USE_ORIGINAL);
-	line += sprintf(line, "|Write files to original location (overwrite existing files)%%x%d", PF_WRITE_ORIGINAL);
-	line += sprintf(line, "|%%l|Disable AutoPack, keep all packed files %%x%d", PF_KEEP);
-	line += sprintf(line, "|Ask for each file %%x%d", PF_ASK);
-	
-	how = pupmenu(menu);
-	
-	if(how == -1)
-		ret_value = 0;
-	else {
-		if (how != PF_KEEP) unpackAll(how);
-		G.fileflags &= ~G_AUTOPACK;
- 	}
- 	
-	return ret_value;
-}
-
-static void check_packAll()
-{
-	// first check for dirty images
-	Image *ima;
-	
-	for(ima = G.main->image.first; ima; ima= ima->id.next) {
-		if (ima->ibufs.first) { /* XXX FIX */
-			ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
-			
-			if (ibuf && (ibuf->userflags &= IB_BITMAPDIRTY))
-				break;
-		}
-	}
-
-	if (ima == NULL || okee("Some images are painted on. These changes will be lost. Continue ?")) {
-		packAll();
-		G.fileflags |= G_AUTOPACK;
-	}
-}
-
-static void do_info_externalfiles(bContext *C, void *arg, int event)
-{
-	switch (event) {
-		
-		case 1: /* pack data */
-			check_packAll();
-			break;
-		case 3: /* unpack data */
-			if (buttons_do_unpack() != 0) {
-				/* Clear autopack bit only if user selected one of the unpack options */
-				G.fileflags &= ~G_AUTOPACK;
-			}
-			break;
-		case 10: /* make all paths relative */
-			if (G.relbase_valid) {
-				int tot,changed,failed,linked;
-				char str[512];
-				char txtname[24]; /* text block name */
-				txtname[0] = '\0';
-				makeFilesRelative(txtname, &tot, &changed, &failed, &linked);
-				if (failed) sprintf(str, "Make Relative%%t|Total files %i|Changed %i|Failed %i, See Text \"%s\"|Linked %i", tot, changed, failed, txtname, linked);
-				else		sprintf(str, "Make Relative%%t|Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked);
-				pupmenu(str);
-			} else {
-				pupmenu("Can't set relative paths with an unsaved blend file");
-			}
-			break;
-		case 11: /* make all paths absolute */
-		{
-			int tot,changed,failed,linked;
-			char str[512];
-			char txtname[24]; /* text block name */
-			txtname[0] = '\0';
-			makeFilesAbsolute(txtname, &tot, &changed, &failed, &linked);
-			sprintf(str, "Make Absolute%%t|Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked);
-			if (failed) sprintf(str, "Make Absolute%%t|Total files %i|Changed %i|Failed %i, See Text \"%s\"|Linked %i", tot, changed, failed, txtname, linked);
-			else		sprintf(str, "Make Absolute%%t|Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked);
-			
-			pupmenu(str);
-		}
-			break;
-		case 12: /* check images exist */
-		{
-			char txtname[24]; /* text block name */
-			txtname[0] = '\0';
-			
-			/* run the missing file check */
-			checkMissingFiles( txtname );
-			
-			if (txtname[0] == '\0') {
-				okee("No external files missing");
-			} else {
-				char str[128];
-				sprintf(str, "Missing files listed in Text \"%s\"", txtname );
-				error(str);
-			}
-		}
-			break;
-		case 13: /* search for referenced files that are not available  */
-// XXX			if(curarea->spacetype==SPACE_INFO) {
-//				ScrArea *sa;
-//				sa= closest_bigger_area();
-//				areawinset(sa->win);
-//			}
-//			activate_fileselect(FILE_SPECIAL, "Find Missing Files", "", findMissingFiles);
-			break;
-	}
-	
-}
-
-
-uiBlock *info_externalfiles(bContext *C, ARegion *ar, void *arg_unused)
-{
-	uiBlock *block;
-	short yco = 20, menuwidth = 120;
-	
-	block= uiBeginBlock(C, ar, "info_externalfiles", UI_EMBOSSP);
-	uiBlockSetButmFunc(block, do_info_externalfiles, NULL);
-	
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Pack into .blend file",				0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 1, "");
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Unpack into Files...",				0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 3, "");
-	
-	uiDefBut(block, SEPR, 0, "",					0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
-	
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make all Paths Relative",				0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 10, "");
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make all Paths Absolute",				0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 11, "");
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Report Missing Files...",				0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 12, "");
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find Missing Files...",				0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 13, "");
-	
-	uiBlockSetDirection(block, UI_RIGHT);
-	uiTextBoundsBlock(block, 60);
-	return block;
-}
-
-
-
-static void info_filemenu(bContext *C, uiLayout *layout, void *arg_unused)
-{
-	
-	uiLayoutSetOperatorContext(layout, WM_OP_EXEC_AREA);
-	uiItemO(layout, NULL, 0, "WM_OT_read_homefile"); 
-	uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_AREA);
-	uiItemO(layout, NULL, 0, "WM_OT_open_mainfile"); 
-//	uiDefIconTextBlockBut(block, info_openrecentmenu, NULL, ICON_RIGHTARROW_THIN, "Open Recent",0, yco-=20, 120, 19, "");
-//	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Recover Last Session",				0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
-	
-	uiItemS(layout);
-	
-	uiLayoutSetOperatorContext(layout, WM_OP_EXEC_AREA);
-	uiItemO(layout, NULL, 0, "WM_OT_save_mainfile"); 
-	uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_AREA);
-	uiItemO(layout, NULL, 0, "WM_OT_save_as_mainfile"); 
-
-#if 0
-	if(U.flag & USER_FILECOMPRESS) {
-		uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Compress File",	 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 35, "Enable file compression");
-	} else {
-		uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Compress File",	 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 35, "Enable file compression");
-	}
-	
-	uiDefBut(block, SEPR, 0, "",					0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
-	
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Rendered Image...|F3",			0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Screenshot Subwindow|Ctrl F3",			0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 24, "");
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Screenshot All|Ctrl Shift F3",			0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 25, "");
-#if GAMEBLENDER == 1
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Game As Runtime...",			0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 22, "");
-#endif
-	uiDefBut(block, SEPR, 0, "",					0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
-	
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Default Settings|Ctrl U",			0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 31, "");
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Load Factory Settings",				0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 32, "");
-	
-	
-	uiDefBut(block, SEPR, 0, "",					0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
-	
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Append or Link|Shift F1",	0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Append or Link (Image Browser)|Ctrl F1",	0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
-//	uiDefIconTextBlockBut(block, info_file_importmenu, NULL, ICON_RIGHTARROW_THIN, "Import", 0, yco-=20, menuwidth, 19, "");
-//	uiDefIconTextBlockBut(block, info_file_exportmenu, NULL, ICON_RIGHTARROW_THIN, "Export", 0, yco-=20, menuwidth, 19, "");
-	
-	uiDefBut(block, SEPR, 0, "",					0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
-	
-	uiDefIconTextBlockBut(block, info_externalfiles, NULL, ICON_RIGHTARROW_THIN, "External Data",0, yco-=20, 120, 19, "");
-	
-	uiDefBut(block, SEPR, 0, "",					0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
-	
-	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Quit Blender|Ctrl Q",				0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
-	uiBlockSetDirection(block, UI_DOWN);
-	uiTextBoundsBlock(block, 80);
-	
-	uiEndBlock(C, block);
-	return block;
-#endif
-}
-
-
-static void do_info_buttons(bContext *C, void *arg, int event)
-{
-	switch(event) {
-		case B_STOPRENDER:
-			G.afbreek= 1;
-			break;
-		case B_STOPCAST:
-			WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C));
-			break;
-		case B_STOPANIM:
-			ED_screen_animation_timer(C, 0, 0);
-			break;
-	}
-}
-
-static void screen_idpoin_handle(bContext *C, ID *id, int event)
-{
-	switch(event) {
-		case UI_ID_BROWSE:
-			/* exception: can't set screens inside of area/region handers */
-			WM_event_add_notifier(C, NC_SCREEN|ND_SCREENBROWSE, id);
-			break;
-		case UI_ID_DELETE:
-			ED_undo_push(C, "");
-			break;
-		case UI_ID_RENAME:
-			break;
-		case UI_ID_ADD_NEW:
-			/* XXX not implemented */
-			break;
-		case UI_ID_OPEN:
-			/* XXX not implemented */
-			break;
-		case UI_ID_ALONE:
-			/* XXX not implemented */
-			break;
-		case UI_ID_PIN:
-			break;
-	}
-}
-
-static void scene_idpoin_handle(bContext *C, ID *id, int event)
-{
-	switch(event) {
-		case UI_ID_BROWSE:
-			/* exception: can't set screens inside of area/region handers */
-			WM_event_add_notifier(C, NC_SCENE|ND_SCENEBROWSE, id);
-			break;
-		case UI_ID_DELETE:
-			ED_undo_push(C, "");
-			break;
-		case UI_ID_RENAME:
-			break;
-		case UI_ID_ADD_NEW:
-			/* XXX not implemented */
-			break;
-		case UI_ID_OPEN:
-			/* XXX not implemented */
-			break;
-		case UI_ID_ALONE:
-			/* XXX not implemented */
-			break;
-		case UI_ID_PIN:
-			break;
-	}
-}
-
-static void operator_call_cb(struct bContext *C, void *arg1, void *arg2)
-{
-	wmOperatorType *ot= arg2;
-	
-	if(ot)
-		WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, NULL);
-}
-
-static void operator_search_cb(const struct bContext *C, void *arg, char *str, uiSearchItems *items)
-{
-	wmOperatorType *ot = WM_operatortype_first();
-	
-	for(; ot; ot= ot->next) {
-		
-		if(BLI_strcasestr(ot->name, str)) {
-			if(ot->poll==NULL || ot->poll((bContext *)C)) {
-				char name[256];
-				int len= strlen(ot->name);
-				
-				/* display name for menu, can hold hotkey */
-				BLI_strncpy(name, ot->name, 256);
-				
-				/* check for hotkey */
-				if(len < 256-6) {
-					if(WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, &name[len+1], 256-len-1))
-						name[len]= '|';
-				}
-				
-				if(0==uiSearchItemAdd(items, name, ot))
-					break;
-			}
-		}
-	}
-}
-
-void info_header_buttons(const bContext *C, ARegion *ar)
-{
-	wmWindow *win= CTX_wm_window(C);
-	bScreen *screen= CTX_wm_screen(C);
-	ScrArea *sa= CTX_wm_area(C);
-	uiBlock *block;
-	int xco, yco= 3;
-	
-	block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS);
-	uiBlockSetHandleFunc(block, do_info_buttons, NULL);
-	
-	xco= ED_area_header_standardbuttons(C, block, yco);
-	
-	if((sa->flag & HEADER_NO_PULLDOWN)==0) {
-		int xmax;
-		
-		xmax= GetButStringLength("File");
-		uiDefMenuBut(block, info_filemenu, NULL, "File", xco, yco, xmax-3, 20, "");
-		xco+= xmax;
-		
-		xmax= GetButStringLength("Add");
-		uiDefPulldownBut(block, dummy_viewmenu, sa, "Add",	xco, yco, xmax-3, 20, "");
-		xco+= xmax;
-		
-		xmax= GetButStringLength("Timeline");
-		uiDefPulldownBut(block, dummy_viewmenu, sa, "Timeline",	xco, yco, xmax-3, 20, "");
-		xco+= xmax;
-		
-		xmax= GetButStringLength("Game");
-		uiDefPulldownBut(block, dummy_viewmenu, sa, "Game",	xco, yco, xmax-3, 20, "");
-		xco+= xmax;
-		
-		xmax= GetButStringLength("Render");
-		uiDefPulldownBut(block, dummy_viewmenu, sa, "Render",	xco, yco, xmax-3, 20, "");
-		xco+= xmax;
-		
-		xmax= GetButStringLength("Help");
-		uiDefPulldownBut(block, dummy_viewmenu, NULL, "Help",	xco, yco, xmax-3, 20, "");
-		xco+= xmax;
-	}
-	
-	uiBlockSetEmboss(block, UI_EMBOSS);
-	
-	if(screen->full==0) {
-		xco= uiDefIDPoinButs(block, CTX_data_main(C), NULL, (ID*)win->screen, ID_SCR, NULL, xco, yco,
-						 screen_idpoin_handle, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_DELETE);
-		xco += 8;
-		xco= uiDefIDPoinButs(block, CTX_data_main(C), NULL, (ID*)screen->scene, ID_SCE, NULL, xco, yco,
-							 scene_idpoin_handle, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_ADD_NEW|UI_ID_DELETE);
-		xco += 8;
-	}	
-
-	if(WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C))) {
-		uiDefIconTextBut(block, BUT, B_STOPRENDER, ICON_REC, "Render", xco+5,yco,75,19, NULL, 0.0f, 0.0f, 0, 0, "Stop rendering");
-		xco+= 80;
-	}
-	if(WM_jobs_test(CTX_wm_manager(C), CTX_wm_screen(C))) {
-		uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_REC, "Capture", xco+5,yco,85,19, NULL, 0.0f, 0.0f, 0, 0, "Stop screencast");
-		xco+= 90;
-	}
-	if(screen->animtimer) {
-		uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_REC, "Anim Player", xco+5,yco,85,19, NULL, 0.0f, 0.0f, 0, 0, "Stop animation playback");
-		xco+= 90;
-	}
-	
-	{
-		static char search[256]= "";
-		uiBut *but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, xco+5, yco, 120, 19, "");
-		
-		uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb);
-
-		xco+= 125;
-	}
-
-	
-	/* always as last  */
-	UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin);
-	
-	uiEndBlock(C, block);
-	uiDrawBlock(C, block);
-}
-
-
diff --git a/source/blender/editors/space_info/info_intern.h b/source/blender/editors/space_info/info_intern.h
index 213c0688f20..519364b58d9 100644
--- a/source/blender/editors/space_info/info_intern.h
+++ b/source/blender/editors/space_info/info_intern.h
@@ -30,10 +30,17 @@
 
 /* internal exports only */
 
+struct wmOperatorType;
 
 /* info_header.c */
 void info_header_buttons(const bContext *C, ARegion *ar);
 
+void FILE_OT_pack_all(struct wmOperatorType *ot);
+void FILE_OT_unpack_all(struct wmOperatorType *ot);
+void FILE_OT_make_paths_relative(struct wmOperatorType *ot);
+void FILE_OT_make_paths_absolute(struct wmOperatorType *ot);
+void FILE_OT_report_missing_files(struct wmOperatorType *ot);
+void FILE_OT_find_missing_files(struct wmOperatorType *ot);
 
 #endif /* ED_INFO_INTERN_H */
 
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
new file mode 100644
index 00000000000..56f925a2e81
--- /dev/null
+++ b/source/blender/editors/space_info/info_ops.c
@@ -0,0 +1,397 @@
+/**
+ * $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) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * 
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include 
+#include 
+
+#include "DNA_packedFile_types.h"
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_bpath.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_main.h"
+#include "BKE_packedFile.h"
+#include "BKE_report.h"
+#include "BKE_screen.h"
+
+#include "ED_screen.h"
+#include "ED_types.h"
+#include "ED_util.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "IMB_imbuf_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_types.h"
+
+#include "info_intern.h"
+
+/********************* pack all operator *********************/
+
+static int pack_all_exec(bContext *C, wmOperator *op)
+{
+	Main *bmain= CTX_data_main(C);
+
+	packAll(bmain, op->reports);
+	G.fileflags |= G_AUTOPACK;
+
+	return OPERATOR_FINISHED;
+}
+
+static int pack_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+	Main *bmain= CTX_data_main(C);
+	Image *ima;
+	ImBuf *ibuf;
+
+	// first check for dirty images
+	for(ima=bmain->image.first; ima; ima=ima->id.next) {
+		if(ima->ibufs.first) { /* XXX FIX */
+			ibuf= BKE_image_get_ibuf(ima, NULL);
+			
+			if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY))
+				break;
+		}
+	}
+
+	if(ima) {
+		uiPupMenuOkee(C, "FILE_OT_pack_all", "Some images are painted on. These changes will be lost. Continue?");
+		return OPERATOR_CANCELLED;
+	}
+
+	return pack_all_exec(C, op);
+}
+
+void FILE_OT_pack_all(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Pack All";
+	ot->idname= "FILE_OT_pack_all";
+	
+	/* api callbacks */
+	ot->exec= pack_all_exec;
+	ot->invoke= pack_all_invoke;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/********************* unpack all operator *********************/
+
+static const EnumPropertyItem unpack_all_method_items[] = {
+	{PF_USE_LOCAL, "USE_LOCAL", 0, "Use files in current directory (create when necessary)", ""},
+	{PF_WRITE_LOCAL, "WRITE_LOCAL", 0, "Write files to current directory (overwrite existing files)", ""},
+	{PF_USE_ORIGINAL, "USE_ORIGINAL", 0, "Use files in original location (create when necessary)", ""},
+	{PF_WRITE_ORIGINAL, "WRITE_ORIGINAL", 0, "Write files to original location (overwrite existing files)", ""},
+	{PF_KEEP, "KEEP", 0, "Disable AutoPack, keep all packed files", ""},
+	{PF_ASK, "ASK", 0, "Ask for each file", ""},
+	{0, NULL, 0, NULL, NULL}};
+
+static int unpack_all_exec(bContext *C, wmOperator *op)
+{
+	Main *bmain= CTX_data_main(C);
+	int method= RNA_enum_get(op->ptr, "method");
+
+	if(method != PF_KEEP) unpackAll(bmain, op->reports, method); /* XXX PF_ASK can't work here */
+	G.fileflags &= ~G_AUTOPACK;
+
+	return OPERATOR_FINISHED;
+}
+
+static int unpack_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+	Main *bmain= CTX_data_main(C);
+	uiPopupMenu *pup;
+	uiLayout *layout;
+	char title[128];
+	int count = 0;
+	
+	count = countPackedFiles(bmain);
+	
+	if(!count) {
+		BKE_report(op->reports, RPT_WARNING, "No packed files. Autopack disabled.");
+		G.fileflags &= ~G_AUTOPACK;
+		return OPERATOR_CANCELLED;
+	}
+
+	if(count == 1)
+		sprintf(title, "Unpack 1 file");
+	else
+		sprintf(title, "Unpack %d files", count);
+	
+	pup= uiPupMenuBegin(C, title, 0);
+	layout= uiPupMenuLayout(pup);
+
+	uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
+	uiItemsEnumO(layout, "FILE_OT_unpack_all", "method");
+
+	uiPupMenuEnd(C, pup);
+
+	return OPERATOR_CANCELLED;
+}
+
+void FILE_OT_unpack_all(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Unpack All";
+	ot->idname= "FILE_OT_unpack_all";
+	
+	/* api callbacks */
+	ot->exec= unpack_all_exec;
+	ot->invoke= unpack_all_invoke;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+	/* properties */
+	RNA_def_enum(ot->srna, "method", unpack_all_method_items, PF_USE_LOCAL, "Method", "How to unpack.");
+}
+
+/********************* make paths relative operator *********************/
+
+static int make_paths_relative_exec(bContext *C, wmOperator *op)
+{
+	char txtname[24]; /* text block name */
+	int tot, changed, failed, linked;
+
+	if(!G.relbase_valid) {
+		BKE_report(op->reports, RPT_WARNING, "Can't set relative paths with an unsaved blend file.");
+		return OPERATOR_CANCELLED;
+	}
+
+	txtname[0] = '\0';
+	makeFilesRelative(txtname, &tot, &changed, &failed, &linked);
+
+	if(failed)
+		BKE_reportf(op->reports, RPT_ERROR, "Total files %i|Changed %i|Failed %i, See Text \"%s\"|Linked %i", tot, changed, failed, txtname, linked); 
+	else
+		BKE_reportf(op->reports, RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked);
+
+	return OPERATOR_FINISHED;
+}
+
+void FILE_OT_make_paths_relative(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Make All Paths Relative";
+	ot->idname= "FILE_OT_make_paths_relative";
+	
+	/* api callbacks */
+	ot->exec= make_paths_relative_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/********************* make paths absolute operator *********************/
+
+static int make_paths_absolute_exec(bContext *C, wmOperator *op)
+{
+	char txtname[24]; /* text block name */
+	int tot, changed, failed, linked;
+
+	if(!G.relbase_valid) {
+		BKE_report(op->reports, RPT_WARNING, "Can't set absolute paths with an unsaved blend file.");
+		return OPERATOR_CANCELLED;
+	}
+
+	txtname[0] = '\0';
+	makeFilesAbsolute(txtname, &tot, &changed, &failed, &linked);
+
+	if(failed)
+		BKE_reportf(op->reports, RPT_ERROR, "Total files %i|Changed %i|Failed %i, See Text \"%s\"|Linked %i", tot, changed, failed, txtname, linked); 
+	else
+		BKE_reportf(op->reports, RPT_INFO, "Total files %i|Changed %i|Failed %i|Linked %i", tot, changed, failed, linked);
+
+	return OPERATOR_FINISHED;
+}
+
+void FILE_OT_make_paths_absolute(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Make All Paths Absolute";
+	ot->idname= "FILE_OT_make_paths_absolute";
+	
+	/* api callbacks */
+	ot->exec= make_paths_absolute_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/********************* report missing files operator *********************/
+
+static int report_missing_files_exec(bContext *C, wmOperator *op)
+{
+	char txtname[24]; /* text block name */
+
+	txtname[0] = '\0';
+	
+	/* run the missing file check */
+	checkMissingFiles(txtname);
+	
+	if(txtname[0] == '\0')
+		BKE_report(op->reports, RPT_INFO, "No external files missing.");
+	else
+		BKE_reportf(op->reports, RPT_ERROR, "Missing files listed in Text \"%s\"", txtname);
+	
+	return OPERATOR_FINISHED;
+}
+
+void FILE_OT_report_missing_files(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Report Missing Files...";
+	ot->idname= "FILE_OT_report_missing_files";
+	
+	/* api callbacks */
+	ot->exec= report_missing_files_exec;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/********************* find missing files operator *********************/
+
+static int find_missing_files_exec(bContext *C, wmOperator *op)
+{
+	char *filename;
+	
+	filename= RNA_string_get_alloc(op->ptr, "filename", NULL, 0);
+	findMissingFiles(filename);
+	MEM_freeN(filename);
+
+	return OPERATOR_FINISHED;
+}
+
+static int find_missing_files_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+	/* XXX file open button text "Find Missing Files" */
+	WM_event_add_fileselect(C, op); 
+	return OPERATOR_RUNNING_MODAL;
+}
+
+void FILE_OT_find_missing_files(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name= "Find Missing Files...";
+	ot->idname= "FILE_OT_find_missing_files";
+	
+	/* api callbacks */
+	ot->exec= find_missing_files_exec;
+	ot->invoke= find_missing_files_invoke;
+
+	/* flags */
+	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+	/* properties */
+	RNA_def_string_file_path(ot->srna, "filename", "", FILE_MAX, "Filename", "File path of image to open.");
+}
+
+#if 0
+static void info_filemenu(bContext *C, uiLayout *layout, void *arg_unused)
+{
+	
+	uiLayoutSetOperatorContext(layout, WM_OP_EXEC_AREA);
+	uiItemO(layout, NULL, 0, "WM_OT_read_homefile"); 
+	uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_AREA);
+	uiItemO(layout, NULL, 0, "WM_OT_open_mainfile"); 
+//	uiDefIconTextBlockBut(block, info_openrecentmenu, NULL, ICON_RIGHTARROW_THIN, "Open Recent",0, yco-=20, 120, 19, "");
+//	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Recover Last Session",				0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
+	
+	uiItemS(layout);
+	
+	uiLayoutSetOperatorContext(layout, WM_OP_EXEC_AREA);
+	uiItemO(layout, NULL, 0, "WM_OT_save_mainfile"); 
+	uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_AREA);
+	uiItemO(layout, NULL, 0, "WM_OT_save_as_mainfile"); 
+
+#if 0
+	if(U.flag & USER_FILECOMPRESS) {
+		uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Compress File",	 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 35, "Enable file compression");
+	} else {
+		uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Compress File",	 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 35, "Enable file compression");
+	}
+	
+	uiDefBut(block, SEPR, 0, "",					0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+	
+	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Rendered Image...|F3",			0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
+	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Screenshot Subwindow|Ctrl F3",			0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 24, "");
+	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Screenshot All|Ctrl Shift F3",			0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 25, "");
+#if GAMEBLENDER == 1
+	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Game As Runtime...",			0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 22, "");
+#endif
+	uiDefBut(block, SEPR, 0, "",					0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+	
+	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save Default Settings|Ctrl U",			0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 31, "");
+	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Load Factory Settings",				0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 32, "");
+	
+	
+	uiDefBut(block, SEPR, 0, "",					0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+	
+	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Append or Link|Shift F1",	0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Append or Link (Image Browser)|Ctrl F1",	0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
+//	uiDefIconTextBlockBut(block, info_file_importmenu, NULL, ICON_RIGHTARROW_THIN, "Import", 0, yco-=20, menuwidth, 19, "");
+//	uiDefIconTextBlockBut(block, info_file_exportmenu, NULL, ICON_RIGHTARROW_THIN, "Export", 0, yco-=20, menuwidth, 19, "");
+	
+	uiDefBut(block, SEPR, 0, "",					0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+	
+	uiDefIconTextBlockBut(block, info_externalfiles, NULL, ICON_RIGHTARROW_THIN, "External Data",0, yco-=20, 120, 19, "");
+	
+	uiDefBut(block, SEPR, 0, "",					0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+	
+	uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Quit Blender|Ctrl Q",				0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
+	uiBlockSetDirection(block, UI_DOWN);
+	uiTextBoundsBlock(block, 80);
+	
+	uiEndBlock(C, block);
+	return block;
+#endif
+}
+#endif
+
diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c
index d72ecd60da9..7b24e8f4e07 100644
--- a/source/blender/editors/space_info/space_info.c
+++ b/source/blender/editors/space_info/space_info.c
@@ -151,7 +151,12 @@ static void info_main_area_draw(const bContext *C, ARegion *ar)
 
 void info_operatortypes(void)
 {
-	
+	WM_operatortype_append(FILE_OT_pack_all);
+	WM_operatortype_append(FILE_OT_unpack_all);
+	WM_operatortype_append(FILE_OT_make_paths_relative);
+	WM_operatortype_append(FILE_OT_make_paths_absolute);
+	WM_operatortype_append(FILE_OT_report_missing_files);
+	WM_operatortype_append(FILE_OT_find_missing_files);
 }
 
 void info_keymap(struct wmWindowManager *wm)
@@ -162,29 +167,12 @@ void info_keymap(struct wmWindowManager *wm)
 /* add handlers, stuff you only do once or on area/region changes */
 static void info_header_area_init(wmWindowManager *wm, ARegion *ar)
 {
-	UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+	ED_region_header_init(ar);
 }
 
 static void info_header_area_draw(const bContext *C, ARegion *ar)
 {
-	float col[3];
-	
-	/* clear */
-	if(ED_screen_area_active(C))
-		UI_GetThemeColor3fv(TH_HEADER, col);
-	else
-		UI_GetThemeColor3fv(TH_HEADERDESEL, col);
-	
-	glClearColor(col[0], col[1], col[2], 0.0);
-	glClear(GL_COLOR_BUFFER_BIT);
-	
-	/* set view2d view matrix for scrolling (without scrollers) */
-	UI_view2d_view_ortho(C, &ar->v2d);
-	
-	info_header_buttons(C, ar);
-	
-	/* restore view matrix? */
-	UI_view2d_view_restore(C);
+	ED_region_header(C, ar);
 }
 
 static void info_main_area_listener(ARegion *ar, wmNotifier *wmn)
diff --git a/source/blender/editors/space_logic/Makefile b/source/blender/editors/space_logic/Makefile
index e07a5bbf4a9..d5709993368 100644
--- a/source/blender/editors/space_logic/Makefile
+++ b/source/blender/editors/space_logic/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/space_logic/SConscript b/source/blender/editors/space_logic/SConscript
index 46a9858a836..e32fcc1b535 100644
--- a/source/blender/editors/space_logic/SConscript
+++ b/source/blender/editors/space_logic/SConscript
@@ -12,7 +12,4 @@ defs = []
 if env['WITH_BF_GAMEENGINE']:
 	defs.append('GAMEBLENDER=1')
 
-	if env['WITH_BF_SOLID']:
-		defs.append('USE_SUMO_SOLID')
-
 env.BlenderLib ( 'bf_editors_space_game', sources, Split(incs), defs, libtype=['core'], priority=[120] )
diff --git a/source/blender/editors/space_logic/logic_buttons.c b/source/blender/editors/space_logic/logic_buttons.c
index 240ddfc2614..b082d5d6ae2 100644
--- a/source/blender/editors/space_logic/logic_buttons.c
+++ b/source/blender/editors/space_logic/logic_buttons.c
@@ -1,5 +1,5 @@
 /**
- * $Id: image_buttons.c 20913 2009-06-16 01:22:56Z blendix $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_logic/logic_header.c b/source/blender/editors/space_logic/logic_header.c
index 00fc130e771..d0e905728be 100644
--- a/source/blender/editors/space_logic/logic_header.c
+++ b/source/blender/editors/space_logic/logic_header.c
@@ -1,5 +1,5 @@
 /**
- * $Id: logic_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index b9385a54d34..55e21561c34 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -1,5 +1,5 @@
 /**
- * $Id: logic_window.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -3056,12 +3056,12 @@ void logic_buttons(bContext *C, ARegion *ar)
 	/* ******************************* */
 	xco= 500; yco= 170; width= 300;
 
-	uiDefPulldownBut(block, controller_menu, NULL, "Controllers", xco-10, yco+35, 100, 19, "");
+	uiDefBlockBut(block, controller_menu, NULL, "Controllers", xco-10, yco+35, 100, UI_UNIT_Y, "");
 	
 	uiBlockBeginAlign(block);
-	uiDefButBitS(block, TOG, BUTS_CONT_SEL,  B_REDR, "Sel", xco+110, yco+35, (width-100)/3, 19, &slogic->scaflag, 0, 0, 0, 0, "Show all selected Objects");
-	uiDefButBitS(block, TOG, BUTS_CONT_ACT, B_REDR, "Act", xco+110+(width-100)/3, yco+35, (width-100)/3, 19, &slogic->scaflag, 0, 0, 0, 0, "Show active Object");
-	uiDefButBitS(block, TOG, BUTS_CONT_LINK, B_REDR, "Link", xco+110+2*(width-100)/3, yco+35, (width-100)/3, 19, &slogic->scaflag, 0, 0, 0, 0, "Show linked Objects to Sensor/Actuator");
+	uiDefButBitS(block, TOG, BUTS_CONT_SEL,  B_REDR, "Sel", xco+110, yco+35, (width-100)/3, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show all selected Objects");
+	uiDefButBitS(block, TOG, BUTS_CONT_ACT, B_REDR, "Act", xco+110+(width-100)/3, yco+35, (width-100)/3, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show active Object");
+	uiDefButBitS(block, TOG, BUTS_CONT_LINK, B_REDR, "Link", xco+110+2*(width-100)/3, yco+35, (width-100)/3, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show linked Objects to Sensor/Actuator");
 	uiBlockEndAlign(block);
 	
 	ob= CTX_data_active_object(C);
@@ -3077,9 +3077,9 @@ void logic_buttons(bContext *C, ARegion *ar)
 		/* presume it is only objects for now */
 		uiBlockBeginAlign(block);
 //		if(ob->controllers.first) uiSetCurFont(block, UI_HELVB);
-		uiDefButBitS(block, TOG, OB_SHOWCONT, B_REDR, ob->id.name+2,(short)(xco-10), yco, (short)(width-30), 19, &ob->scaflag, 0, 0, 0, 0, "Active Object name");
+		uiDefButBitS(block, TOG, OB_SHOWCONT, B_REDR, ob->id.name+2,(short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Active Object name");
 //		if(ob->controllers.first) uiSetCurFont(block, UI_HELV);
-		uiDefButBitS(block, TOG, OB_ADDCONT, B_ADD_CONT, "Add",(short)(xco+width-40), yco, 50, 19, &ob->scaflag, 0, 0, 0, 0, "Add a new Controller");
+		uiDefButBitS(block, TOG, OB_ADDCONT, B_ADD_CONT, "Add",(short)(xco+width-40), yco, 50, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Add a new Controller");
 		uiBlockEndAlign(block);
 		yco-=20;
 		
@@ -3100,7 +3100,7 @@ void logic_buttons(bContext *C, ARegion *ar)
 		if(ob->scaflag & OB_SHOWCONT) {
 
 			/* first show the state */
-			uiDefBlockBut(block, object_state_mask_menu, ob, "State", (short)(xco-10), (short)(yco-10), 36, 19, "Object state menu: store and retrieve initial state");
+			uiDefBlockBut(block, object_state_mask_menu, ob, "State", (short)(xco-10), (short)(yco-10), 36, UI_UNIT_Y, "Object state menu: store and retrieve initial state");
 
 			if (!ob->state)
 				ob->state = 1;
@@ -3116,9 +3116,9 @@ void logic_buttons(bContext *C, ARegion *ar)
 				}
 			}
 			uiBlockBeginAlign(block);
-			uiDefButBitS(block, TOG, OB_SETSTBIT, B_SET_STATE_BIT, "All",(short)(xco+226), yco-10, 22, 19, &ob->scaflag, 0, 0, 0, 0, "Set all state bits");
-			uiDefButBitS(block, TOG, OB_INITSTBIT, B_INIT_STATE_BIT, "Ini",(short)(xco+248), yco-10, 22, 19, &ob->scaflag, 0, 0, 0, 0, "Set the initial state");
-			uiDefButBitS(block, TOG, OB_DEBUGSTATE, 0, "D",(short)(xco+270), yco-10, 15, 19, &ob->scaflag, 0, 0, 0, 0, "Print state debug info");
+			uiDefButBitS(block, TOG, OB_SETSTBIT, B_SET_STATE_BIT, "All",(short)(xco+226), yco-10, 22, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Set all state bits");
+			uiDefButBitS(block, TOG, OB_INITSTBIT, B_INIT_STATE_BIT, "Ini",(short)(xco+248), yco-10, 22, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Set the initial state");
+			uiDefButBitS(block, TOG, OB_DEBUGSTATE, 0, "D",(short)(xco+270), yco-10, 15, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Print state debug info");
 			uiBlockEndAlign(block);
 
 			yco-=35;
@@ -3142,17 +3142,17 @@ void logic_buttons(bContext *C, ARegion *ar)
 							if (act)
 								act->flag |= ACT_VISIBLE;
 						}
-						uiDefIconButBitS(block, TOG, CONT_DEL, B_DEL_CONT, ICON_X,	xco, yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Delete Controller");
-						uiDefIconButBitS(block, ICONTOG, CONT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Controller settings");
-						uiDefIconButBitS(block, TOG, CONT_PRIO, B_REDR, ICON_BOOKMARKS, (short)(xco+width-66), yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Mark controller for execution before all non-marked controllers (good for startup scripts)");
+						uiDefIconButBitS(block, TOG, CONT_DEL, B_DEL_CONT, ICON_X,	xco, yco, 22, UI_UNIT_Y, &cont->flag, 0, 0, 0, 0, "Delete Controller");
+						uiDefIconButBitS(block, ICONTOG, CONT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, UI_UNIT_Y, &cont->flag, 0, 0, 0, 0, "Controller settings");
+						uiDefIconButBitS(block, TOG, CONT_PRIO, B_REDR, ICON_BOOKMARKS, (short)(xco+width-66), yco, 22, UI_UNIT_Y, &cont->flag, 0, 0, 0, 0, "Mark controller for execution before all non-marked controllers (good for startup scripts)");
 
 						sprintf(name, "%d", first_bit(cont->state_mask)+1);
-						uiDefBlockBut(block, controller_state_mask_menu, cont, name, (short)(xco+width-44), yco, 22, 19, "Set controller state index (from 1 to 30)");
+						uiDefBlockBut(block, controller_state_mask_menu, cont, name, (short)(xco+width-44), yco, 22, UI_UNIT_Y, "Set controller state index (from 1 to 30)");
 				
 						if(cont->flag & CONT_SHOW) {
 							cont->otype= cont->type;
-							uiDefButS(block, MENU, B_CHANGE_CONT, controller_pup(),(short)(xco+22), yco, 70, 19, &cont->type, 0, 0, 0, 0, "Controller type");
-							but= uiDefBut(block, TEX, 1, "", (short)(xco+92), yco, (short)(width-158), 19, cont->name, 0, 31, 0, 0, "Controller name");
+							uiDefButS(block, MENU, B_CHANGE_CONT, controller_pup(),(short)(xco+22), yco, 70, UI_UNIT_Y, &cont->type, 0, 0, 0, 0, "Controller type");
+							but= uiDefBut(block, TEX, 1, "", (short)(xco+92), yco, (short)(width-158), UI_UNIT_Y, cont->name, 0, 31, 0, 0, "Controller name");
 							uiButSetFunc(but, make_unique_prop_names_cb, cont->name, (void*) 0);
 				
 							ycoo= yco;
@@ -3162,17 +3162,17 @@ void logic_buttons(bContext *C, ARegion *ar)
 						else {
 							cpack(0x999999);
 							glRecti(xco+22, yco, xco+width-22,yco+19);
-							but= uiDefBut(block, LABEL, 0, controller_name(cont->type), (short)(xco+22), yco, 70, 19, cont, 0, 0, 0, 0, "Controller type");
+							but= uiDefBut(block, LABEL, 0, controller_name(cont->type), (short)(xco+22), yco, 70, UI_UNIT_Y, cont, 0, 0, 0, 0, "Controller type");
 							uiButSetFunc(but, sca_move_controller, cont, NULL);
-							but= uiDefBut(block, LABEL, 0, cont->name,(short)(xco+92), yco,(short)(width-158), 19, cont, 0, 0, 0, 0, "Controller name");
+							but= uiDefBut(block, LABEL, 0, cont->name,(short)(xco+92), yco,(short)(width-158), UI_UNIT_Y, cont, 0, 0, 0, 0, "Controller name");
 							uiButSetFunc(but, sca_move_controller, cont, NULL);
 							ycoo= yco;
 						}
 				
-						but= uiDefIconBut(block, LINK, 0, ICON_LINK,	(short)(xco+width), ycoo, 19, 19, NULL, 0, 0, 0, 0, "");
+						but= uiDefIconBut(block, LINK, 0, ICON_LINK,	(short)(xco+width), ycoo, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
 						uiSetButLink(but, NULL, (void ***)&(cont->links), &cont->totlinks, LINK_CONTROLLER, LINK_ACTUATOR);
 				
-						uiDefIconBut(block, INLINK, 0, ICON_INLINK,(short)(xco-19), ycoo, 19, 19, cont, LINK_CONTROLLER, 0, 0, 0, "");
+						uiDefIconBut(block, INLINK, 0, ICON_INLINK,(short)(xco-19), ycoo, UI_UNIT_X, UI_UNIT_Y, cont, LINK_CONTROLLER, 0, 0, 0, "");
 						/* offset is >0 if at least one controller was displayed */
 						offset++;
 						yco-=20;
@@ -3188,13 +3188,13 @@ void logic_buttons(bContext *C, ARegion *ar)
 	/* ******************************* */
 	xco= 10; yco= 170; width= 400;
 
-	uiDefPulldownBut(block, sensor_menu, NULL, "Sensors", xco-10, yco+35, 70, 19, "");
+	uiDefBlockBut(block, sensor_menu, NULL, "Sensors", xco-10, yco+35, 70, UI_UNIT_Y, "");
 	
 	uiBlockBeginAlign(block);
-	uiDefButBitS(block, TOG, BUTS_SENS_SEL, B_REDR, "Sel", xco+80, yco+35, (width-70)/4, 19, &slogic->scaflag, 0, 0, 0, 0, "Show all selected Objects");
-	uiDefButBitS(block, TOG, BUTS_SENS_ACT, B_REDR, "Act", xco+80+(width-70)/4, yco+35, (width-70)/4, 19, &slogic->scaflag, 0, 0, 0, 0, "Show active Object");
-	uiDefButBitS(block, TOG, BUTS_SENS_LINK, B_REDR, "Link", xco+80+2*(width-70)/4, yco+35, (width-70)/4, 19, &slogic->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller");
-	uiDefButBitS(block, TOG, BUTS_SENS_STATE, B_REDR, "State", xco+80+3*(width-70)/4, yco+35, (width-70)/4, 19, &slogic->scaflag, 0, 0, 0, 0, "Show only sensors connected to active states");
+	uiDefButBitS(block, TOG, BUTS_SENS_SEL, B_REDR, "Sel", xco+80, yco+35, (width-70)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show all selected Objects");
+	uiDefButBitS(block, TOG, BUTS_SENS_ACT, B_REDR, "Act", xco+80+(width-70)/4, yco+35, (width-70)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show active Object");
+	uiDefButBitS(block, TOG, BUTS_SENS_LINK, B_REDR, "Link", xco+80+2*(width-70)/4, yco+35, (width-70)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller");
+	uiDefButBitS(block, TOG, BUTS_SENS_STATE, B_REDR, "State", xco+80+3*(width-70)/4, yco+35, (width-70)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show only sensors connected to active states");
 	uiBlockEndAlign(block);
 	
 	for(a=0; asensors.first) uiSetCurFont(block, UI_HELVB);
-		uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name+2,(short)(xco-10), yco, (short)(width-30), 19, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide sensors");
+		uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name+2,(short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide sensors");
 //		if(ob->sensors.first) uiSetCurFont(block, UI_HELV);
-		uiDefButBitS(block, TOG, OB_ADDSENS, B_ADD_SENS, "Add",(short)(xco+width-40), yco, 50, 19, &ob->scaflag, 0, 0, 0, 0, "Add a new Sensor");
+		uiDefButBitS(block, TOG, OB_ADDSENS, B_ADD_SENS, "Add",(short)(xco+width-40), yco, 50, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Add a new Sensor");
 		uiBlockEndAlign(block);
 		yco-=20;
 		
@@ -3226,17 +3226,17 @@ void logic_buttons(bContext *C, ARegion *ar)
 					pin = (slogic->scaflag & BUTS_SENS_STATE && (sens->flag & SENS_SHOW || sens->flag & SENS_PIN)) ? 1:0 ;
 					
 					sens->flag |= SENS_VISIBLE;
-					uiDefIconButBitS(block, TOG, SENS_DEL, B_DEL_SENS, ICON_X,	xco, yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Delete Sensor");
+					uiDefIconButBitS(block, TOG, SENS_DEL, B_DEL_SENS, ICON_X,	xco, yco, 22, UI_UNIT_Y, &sens->flag, 0, 0, 0, 0, "Delete Sensor");
 					if (pin)
-						uiDefIconButBitS(block, ICONTOG, SENS_PIN, B_REDR, ICON_PINNED, (short)(xco+width-44), yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Display when not linked to a visible states controller");
+						uiDefIconButBitS(block, ICONTOG, SENS_PIN, B_REDR, ICON_PINNED, (short)(xco+width-44), yco, 22, UI_UNIT_Y, &sens->flag, 0, 0, 0, 0, "Display when not linked to a visible states controller");
 					
-					uiDefIconButBitS(block, ICONTOG, SENS_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Sensor settings");
+					uiDefIconButBitS(block, ICONTOG, SENS_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, UI_UNIT_Y, &sens->flag, 0, 0, 0, 0, "Sensor settings");
 
 					ycoo= yco;
 					if(sens->flag & SENS_SHOW)
 					{
-						uiDefButS(block, MENU, B_CHANGE_SENS, sensor_pup(),	(short)(xco+22), yco, 80, 19, &sens->type, 0, 0, 0, 0, "Sensor type");
-						but= uiDefBut(block, TEX, 1, "", (short)(xco+102), yco, (short)(width-(pin?146:124)), 19, sens->name, 0, 31, 0, 0, "Sensor name");
+						uiDefButS(block, MENU, B_CHANGE_SENS, sensor_pup(),	(short)(xco+22), yco, 80, UI_UNIT_Y, &sens->type, 0, 0, 0, 0, "Sensor type");
+						but= uiDefBut(block, TEX, 1, "", (short)(xco+102), yco, (short)(width-(pin?146:124)), UI_UNIT_Y, sens->name, 0, 31, 0, 0, "Sensor name");
 						uiButSetFunc(but, make_unique_prop_names_cb, sens->name, (void*) 0);
 
 						sens->otype= sens->type;
@@ -3246,13 +3246,13 @@ void logic_buttons(bContext *C, ARegion *ar)
 					else {
 						set_col_sensor(sens->type, 1);
 						glRecti(xco+22, yco, xco+width-22,yco+19);
-						but= uiDefBut(block, LABEL, 0, sensor_name(sens->type),	(short)(xco+22), yco, 80, 19, sens, 0, 0, 0, 0, "");
+						but= uiDefBut(block, LABEL, 0, sensor_name(sens->type),	(short)(xco+22), yco, 80, UI_UNIT_Y, sens, 0, 0, 0, 0, "");
 						uiButSetFunc(but, sca_move_sensor, sens, NULL);
-						but= uiDefBut(block, LABEL, 0, sens->name, (short)(xco+102), yco, (short)(width-(pin?146:124)), 19, sens, 0, 31, 0, 0, "");
+						but= uiDefBut(block, LABEL, 0, sens->name, (short)(xco+102), yco, (short)(width-(pin?146:124)), UI_UNIT_Y, sens, 0, 31, 0, 0, "");
 						uiButSetFunc(but, sca_move_sensor, sens, NULL);
 					}
 
-					but= uiDefIconBut(block, LINK, 0, ICON_LINK,	(short)(xco+width), ycoo, 19, 19, NULL, 0, 0, 0, 0, "");
+					but= uiDefIconBut(block, LINK, 0, ICON_LINK,	(short)(xco+width), ycoo, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
 					uiSetButLink(but, NULL, (void ***)&(sens->links), &sens->totlinks, LINK_SENSOR, LINK_CONTROLLER);
 
 					yco-=20;
@@ -3266,13 +3266,13 @@ void logic_buttons(bContext *C, ARegion *ar)
 	/* ******************************* */
 	xco= 900; yco= 170; width= 400;
 	
-	uiDefPulldownBut(block, actuator_menu, NULL, "Actuators", xco-10, yco+35, 90, 19, "");
+	uiDefBlockBut(block, actuator_menu, NULL, "Actuators", xco-10, yco+35, 90, UI_UNIT_Y, "");
 
 	uiBlockBeginAlign(block);
-	uiDefButBitS(block, TOG, BUTS_ACT_SEL, B_REDR, "Sel", xco+110, yco+35, (width-100)/4, 19, &slogic->scaflag, 0, 0, 0, 0, "Show all selected Objects");
-	uiDefButBitS(block, TOG, BUTS_ACT_ACT, B_REDR, "Act", xco+110+(width-100)/4, yco+35, (width-100)/4, 19, &slogic->scaflag, 0, 0, 0, 0, "Show active Object");
-	uiDefButBitS(block, TOG, BUTS_ACT_LINK, B_REDR, "Link", xco+110+2*(width-100)/4, yco+35, (width-100)/4, 19, &slogic->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller");
-	uiDefButBitS(block, TOG, BUTS_ACT_STATE, B_REDR, "State", xco+110+3*(width-100)/4, yco+35, (width-100)/4, 19, &slogic->scaflag, 0, 0, 0, 0, "Show only actuators connected to active states");
+	uiDefButBitS(block, TOG, BUTS_ACT_SEL, B_REDR, "Sel", xco+110, yco+35, (width-100)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show all selected Objects");
+	uiDefButBitS(block, TOG, BUTS_ACT_ACT, B_REDR, "Act", xco+110+(width-100)/4, yco+35, (width-100)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show active Object");
+	uiDefButBitS(block, TOG, BUTS_ACT_LINK, B_REDR, "Link", xco+110+2*(width-100)/4, yco+35, (width-100)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller");
+	uiDefButBitS(block, TOG, BUTS_ACT_STATE, B_REDR, "State", xco+110+3*(width-100)/4, yco+35, (width-100)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show only actuators connected to active states");
 	uiBlockEndAlign(block);
 	for(a=0; aactuators.first) uiSetCurFont(block, UI_HELVB);
-		uiDefButBitS(block, TOG, OB_SHOWACT, B_REDR, ob->id.name+2,(short)(xco-10), yco,(short)(width-30), 19, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide actuators");
+		uiDefButBitS(block, TOG, OB_SHOWACT, B_REDR, ob->id.name+2,(short)(xco-10), yco,(short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide actuators");
 //		if(ob->actuators.first) uiSetCurFont(block, UI_HELV);
-		uiDefButBitS(block, TOG, OB_ADDACT, B_ADD_ACT, "Add",(short)(xco+width-40), yco, 50, 19, &ob->scaflag, 0, 0, 0, 0, "Add a new Actuator");
+		uiDefButBitS(block, TOG, OB_ADDACT, B_ADD_ACT, "Add",(short)(xco+width-40), yco, 50, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Add a new Actuator");
 		uiBlockEndAlign(block);
 		yco-=20;
 		
@@ -3301,15 +3301,15 @@ void logic_buttons(bContext *C, ARegion *ar)
 					pin = (slogic->scaflag & BUTS_ACT_STATE && (act->flag & SENS_SHOW || act->flag & SENS_PIN)) ? 1:0 ;
 					
 					act->flag |= ACT_VISIBLE;	/* mark the actuator as visible to help implementing the up/down action */
-					uiDefIconButBitS(block, TOG, ACT_DEL, B_DEL_ACT, ICON_X,	xco, yco, 22, 19, &act->flag, 0, 0, 0, 0, "Delete Actuator");
+					uiDefIconButBitS(block, TOG, ACT_DEL, B_DEL_ACT, ICON_X,	xco, yco, 22, UI_UNIT_Y, &act->flag, 0, 0, 0, 0, "Delete Actuator");
 					if (pin)
-						uiDefIconButBitS(block, ICONTOG, ACT_PIN, B_REDR, ICON_PINNED, (short)(xco+width-44), yco, 22, 19, &act->flag, 0, 0, 0, 0, "Display when not linked to a visible states controller");
-					uiDefIconButBitS(block, ICONTOG, ACT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &act->flag, 0, 0, 0, 0, "Display the actuator");
+						uiDefIconButBitS(block, ICONTOG, ACT_PIN, B_REDR, ICON_PINNED, (short)(xco+width-44), yco, 22, UI_UNIT_Y, &act->flag, 0, 0, 0, 0, "Display when not linked to a visible states controller");
+					uiDefIconButBitS(block, ICONTOG, ACT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, UI_UNIT_Y, &act->flag, 0, 0, 0, 0, "Display the actuator");
 					
 					if(act->flag & ACT_SHOW) {
 						act->otype= act->type;
-						uiDefButS(block, MENU, B_CHANGE_ACT, actuator_pup(ob),	(short)(xco+22), yco, 90, 19, &act->type, 0, 0, 0, 0, "Actuator type");
-						but= uiDefBut(block, TEX, 1, "", (short)(xco+112), yco, (short)(width-(pin?156:134)), 19, act->name, 0, 31, 0, 0, "Actuator name");
+						uiDefButS(block, MENU, B_CHANGE_ACT, actuator_pup(ob),	(short)(xco+22), yco, 90, UI_UNIT_Y, &act->type, 0, 0, 0, 0, "Actuator type");
+						but= uiDefBut(block, TEX, 1, "", (short)(xco+112), yco, (short)(width-(pin?156:134)), UI_UNIT_Y, act->name, 0, 31, 0, 0, "Actuator name");
 						uiButSetFunc(but, make_unique_prop_names_cb, act->name, (void*) 0);
 
 						ycoo= yco;
@@ -3319,14 +3319,14 @@ void logic_buttons(bContext *C, ARegion *ar)
 					else {
 						set_col_actuator(act->type, 1);
 						glRecti((short)(xco+22), yco, (short)(xco+width-22),(short)(yco+19));
-						but= uiDefBut(block, LABEL, 0, actuator_name(act->type), (short)(xco+22), yco, 90, 19, act, 0, 0, 0, 0, "Actuator type");
+						but= uiDefBut(block, LABEL, 0, actuator_name(act->type), (short)(xco+22), yco, 90, UI_UNIT_Y, act, 0, 0, 0, 0, "Actuator type");
 						uiButSetFunc(but, sca_move_actuator, act, NULL);
-						but= uiDefBut(block, LABEL, 0, act->name, (short)(xco+112), yco, (short)(width-(pin?156:134)), 19, act, 0, 0, 0, 0, "Actuator name");
+						but= uiDefBut(block, LABEL, 0, act->name, (short)(xco+112), yco, (short)(width-(pin?156:134)), UI_UNIT_Y, act, 0, 0, 0, 0, "Actuator name");
 						uiButSetFunc(but, sca_move_actuator, act, NULL);
 						ycoo= yco;
 					}
 
-					uiDefIconBut(block, INLINK, 0, ICON_INLINK,(short)(xco-19), ycoo, 19, 19, act, LINK_ACTUATOR, 0, 0, 0, "");
+					uiDefIconBut(block, INLINK, 0, ICON_INLINK,(short)(xco-19), ycoo, UI_UNIT_X, UI_UNIT_Y, act, LINK_ACTUATOR, 0, 0, 0, "");
 
 					yco-=20;
 				}
diff --git a/source/blender/editors/space_nla/Makefile b/source/blender/editors/space_nla/Makefile
index 43f010e6adc..d7c9477dc83 100644
--- a/source/blender/editors/space_nla/Makefile
+++ b/source/blender/editors/space_nla/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/space_nla/nla_header.c b/source/blender/editors/space_nla/nla_header.c
index 2366a888d3b..0f6b77da6f5 100644
--- a/source/blender/editors/space_nla/nla_header.c
+++ b/source/blender/editors/space_nla/nla_header.c
@@ -1,5 +1,5 @@
 /**
- * $Id: nla_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_node/Makefile b/source/blender/editors/space_node/Makefile
index 60f81255a74..5bd6e95e28c 100644
--- a/source/blender/editors/space_node/Makefile
+++ b/source/blender/editors/space_node/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 0670dd9e01f..f2e2486075b 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -1,5 +1,5 @@
 /**
- * $Id: drawnode.c 17439 2008-11-13 09:57:11Z kakbarnf $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_node/node_header.c b/source/blender/editors/space_node/node_header.c
index 1031ad213f4..8c48d4b54e1 100644
--- a/source/blender/editors/space_node/node_header.c
+++ b/source/blender/editors/space_node/node_header.c
@@ -1,5 +1,5 @@
 /**
- * $Id: node_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_outliner/Makefile b/source/blender/editors/space_outliner/Makefile
index 19d40a4a31e..8d7cd017e0b 100644
--- a/source/blender/editors/space_outliner/Makefile
+++ b/source/blender/editors/space_outliner/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c
index 16748af39d5..8017b8437ff 100644
--- a/source/blender/editors/space_outliner/outliner.c
+++ b/source/blender/editors/space_outliner/outliner.c
@@ -1031,7 +1031,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
 	}
 	else if(ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
 		PointerRNA pptr, propptr, *ptr= (PointerRNA*)idv;
-		PropertyRNA *prop, *iterprop, *nameprop;
+		PropertyRNA *prop, *iterprop;
 		PropertyType proptype;
 		PropertySubType propsubtype;
 		int a, tot;
@@ -1043,12 +1043,10 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
 		}
 		else if(type == TSE_RNA_STRUCT) {
 			/* struct */
-			nameprop= RNA_struct_name_property(ptr->type);
+			te->name= RNA_struct_name_get_alloc(ptr, NULL, 0);
 
-			if(nameprop) {
-				te->name= RNA_property_string_get_alloc(ptr, nameprop, NULL, 0);
+			if(te->name)
 				te->flag |= TE_FREE_NAME;
-			}
 			else
 				te->name= (char*)RNA_struct_ui_name(ptr->type);
 
@@ -3075,7 +3073,7 @@ static void tree_element_to_path(SpaceOops *soops, TreeElement *te, TreeStoreEle
 	TreeElement *tem, *temnext, *temsub;
 	TreeStoreElem *tse, *tsenext;
 	PointerRNA *ptr, *nextptr;
-	PropertyRNA *prop, *nameprop;
+	PropertyRNA *prop;
 	char *newpath=NULL;
 	
 	/* optimise tricks:
@@ -3119,17 +3117,16 @@ static void tree_element_to_path(SpaceOops *soops, TreeElement *te, TreeStoreEle
 					newpath= RNA_path_append(*path, ptr, prop, 0, NULL);
 				}
 				else if(RNA_property_type(prop) == PROP_COLLECTION) {
+					char buf[128], *name;
+
 					temnext= (TreeElement*)(ld->next->data);
 					tsenext= TREESTORE(temnext);
 					
 					nextptr= &temnext->rnaptr;
-					nameprop= RNA_struct_name_property(nextptr->type);
+					name= RNA_struct_name_get_alloc(nextptr, buf, sizeof(buf));
 					
-					if(nameprop) {
+					if(name) {
 						/* if possible, use name as a key in the path */
-						char buf[128], *name;
-						name= RNA_property_string_get_alloc(nextptr, nameprop, buf, sizeof(buf));
-						
 						newpath= RNA_path_append(*path, NULL, prop, 0, name);
 						
 						if(name != buf)
diff --git a/source/blender/editors/space_outliner/outliner_header.c b/source/blender/editors/space_outliner/outliner_header.c
index b630eb2acf3..fe2f054899c 100644
--- a/source/blender/editors/space_outliner/outliner_header.c
+++ b/source/blender/editors/space_outliner/outliner_header.c
@@ -1,5 +1,5 @@
 /**
- * $Id: outliner_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index cc7880fcae7..4ddb586beb4 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -1,5 +1,5 @@
 /**
- * $Id: space_outliner.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_script/Makefile b/source/blender/editors/space_script/Makefile
index 48e1cd8e861..3322cb61a7f 100644
--- a/source/blender/editors/space_script/Makefile
+++ b/source/blender/editors/space_script/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/space_script/script_header.c b/source/blender/editors/space_script/script_header.c
index 548ed8d2331..d9851df4185 100644
--- a/source/blender/editors/space_script/script_header.c
+++ b/source/blender/editors/space_script/script_header.c
@@ -1,5 +1,5 @@
 /**
- * $Id: script_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_sequencer/Makefile b/source/blender/editors/space_sequencer/Makefile
index 80699db4baa..7be0bc9cfef 100644
--- a/source/blender/editors/space_sequencer/Makefile
+++ b/source/blender/editors/space_sequencer/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/space_sequencer/sequencer_buttons.c b/source/blender/editors/space_sequencer/sequencer_buttons.c
index f127ab4b0cf..cc4f5cf5ce3 100644
--- a/source/blender/editors/space_sequencer/sequencer_buttons.c
+++ b/source/blender/editors/space_sequencer/sequencer_buttons.c
@@ -1,5 +1,5 @@
 /**
- * $Id: sequencer_buttons.c 20279 2009-05-19 17:13:33Z blendix $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_sound/Makefile b/source/blender/editors/space_sound/Makefile
index 4d375282223..a072684d543 100644
--- a/source/blender/editors/space_sound/Makefile
+++ b/source/blender/editors/space_sound/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/space_sound/sound_header.c b/source/blender/editors/space_sound/sound_header.c
index b674438210d..ae3410663c2 100644
--- a/source/blender/editors/space_sound/sound_header.c
+++ b/source/blender/editors/space_sound/sound_header.c
@@ -1,5 +1,5 @@
 /**
- * $Id: sound_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_text/Makefile b/source/blender/editors/space_text/Makefile
index 33e12dc1abb..50871017085 100644
--- a/source/blender/editors/space_text/Makefile
+++ b/source/blender/editors/space_text/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c
index 1a3f998bb8a..c761587198f 100644
--- a/source/blender/editors/space_text/text_header.c
+++ b/source/blender/editors/space_text/text_header.c
@@ -1,5 +1,5 @@
 /**
- * $Id: text_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -88,6 +88,7 @@
 /* ************************ header area region *********************** */
 
 #ifndef DISABLE_PYTHON
+#if 0
 static void do_text_template_scriptsmenu(bContext *C, void *arg, int event)
 {
 	// XXX BPY_menu_do_python(PYMENU_SCRIPTTEMPLATE, event);
@@ -154,6 +155,7 @@ static uiBlock *text_plugin_scriptsmenu(bContext *C, void *args_unused)
 	return block;
 }
 #endif
+#endif
 
 /************************** properties ******************************/
 
diff --git a/source/blender/editors/space_text/text_python.c b/source/blender/editors/space_text/text_python.c
index e4c697dc2b5..4fa54cdf27b 100644
--- a/source/blender/editors/space_text/text_python.c
+++ b/source/blender/editors/space_text/text_python.c
@@ -1,5 +1,5 @@
 /**
- * $Id: text_python.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_time/Makefile b/source/blender/editors/space_time/Makefile
index 20877b48559..e0bf3943dd8 100644
--- a/source/blender/editors/space_time/Makefile
+++ b/source/blender/editors/space_time/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c
index 67759bb1b46..c4ca4d8522f 100644
--- a/source/blender/editors/space_time/space_time.c
+++ b/source/blender/editors/space_time/space_time.c
@@ -1,5 +1,5 @@
 /**
- * $Id: space_time.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/space_time/time_header.c b/source/blender/editors/space_time/time_header.c
index 2b00459fc17..29f31671670 100644
--- a/source/blender/editors/space_time/time_header.c
+++ b/source/blender/editors/space_time/time_header.c
@@ -1,5 +1,5 @@
 /**
- * $Id: time_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -567,12 +567,12 @@ void time_header_buttons(const bContext *C, ARegion *ar)
 	
 	uiBlockBeginAlign(block);
 		uiDefIconButBitS(block, TOG, AUTOKEY_ON, B_REDRAWALL, ICON_REC,
-						 xco, yco, XIC, YIC, &(scene->autokey_mode), 0, 0, 0, 0, "Automatic keyframe insertion for Objects and Bones");
+						 xco, yco, XIC, YIC, &(scene->toolsettings->autokey_mode), 0, 0, 0, 0, "Automatic keyframe insertion for Objects and Bones");
 		xco+= XIC;
 		if (IS_AUTOKEY_ON(scene)) {
 			uiDefButS(block, MENU, B_REDRAWALL, 
 					  "Auto-Keying Mode %t|Add/Replace Keys%x3|Replace Keys %x5", 
-					  xco, yco, (int)5.5*XIC, YIC, &(scene->autokey_mode), 0, 1, 0, 0, 
+					  xco, yco, (int)5.5*XIC, YIC, &(scene->toolsettings->autokey_mode), 0, 1, 0, 0, 
 					  "Mode of automatic keyframe insertion for Objects and Bones");
 			xco+= (6*XIC);
 		}
diff --git a/source/blender/editors/space_view3d/Makefile b/source/blender/editors/space_view3d/Makefile
index dd4eab89411..5e6f8a6c426 100644
--- a/source/blender/editors/space_view3d/Makefile
+++ b/source/blender/editors/space_view3d/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index a67e8c8a1c3..05490e2fce1 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -117,7 +117,7 @@
 	(vd->drawtype==OB_SOLID && vd->flag2 & V3D_SOLID_TEX))
 
 #define CHECK_OB_DRAWFACEDOT(sce, vd, dt) \
-(	(sce->selectmode & SCE_SELECT_FACE) && \
+(	(sce->toolsettings->selectmode & SCE_SELECT_FACE) && \
 	(vd->drawtype<=OB_SOLID) && \
 	(((vd->drawtype==OB_SOLID) && (dt>=OB_SOLID) && (vd->flag2 & V3D_SOLID_TEX) && (vd->flag & V3D_ZBUF_SELECT)) == 0) \
 	)
@@ -1493,14 +1493,14 @@ void nurbs_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, Nurb
 
 static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no)
 {
-	Scene *scene= (Scene *)userData;
+	ToolSettings *ts= ((Scene *)userData)->toolsettings;
 	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);
+		glVertex3f(	cent[0] + no[0]*ts->normalsize,
+					cent[1] + no[1]*ts->normalsize,
+					cent[2] + no[2]*ts->normalsize);
 	}
 }
 static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm) 
@@ -1529,19 +1529,20 @@ static void draw_dm_face_centers(DerivedMesh *dm, int sel)
 static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
 {
 	Scene *scene= (Scene *)userData;
+	ToolSettings *ts= scene->toolsettings;
 	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);
+			glVertex3f(	co[0] + no_f[0]*ts->normalsize,
+						co[1] + no_f[1]*ts->normalsize,
+						co[2] + no_f[2]*ts->normalsize);
 		} 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);
+			glVertex3f(	co[0] + no_s[0]*ts->normalsize/32767.0f,
+						co[1] + no_s[1]*ts->normalsize/32767.0f,
+						co[2] + no_s[2]*ts->normalsize/32767.0f);
 		}
 	}
 }
@@ -1762,7 +1763,9 @@ static void draw_dm_bweights__mapFunc(void *userData, int index, float *co, floa
 }
 static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
 {
-	if (scene->selectmode & SCE_SELECT_VERTEX) {
+	ToolSettings *ts= scene->toolsettings;
+
+	if (ts->selectmode & SCE_SELECT_VERTEX) {
 		glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2);
 		bglBegin(GL_POINTS);
 		dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, NULL);
@@ -1786,6 +1789,7 @@ static void draw_dm_bweights(Scene *scene, DerivedMesh *dm)
 
 static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditMesh *em, DerivedMesh *cageDM, EditVert *eve_act)
 {
+	ToolSettings *ts= scene->toolsettings;
 	int sel;
 
 	if(v3d->zbuf) glDepthMask(0);		// disable write in zbuffer, zbuf select
@@ -1817,7 +1821,7 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditM
 				col[3] = fcol[3] = 255;
 			}
 				
-			if(scene->selectmode & SCE_SELECT_VERTEX) {
+			if(ts->selectmode & SCE_SELECT_VERTEX) {
 				glPointSize(size);
 				glColor4ubv((GLubyte *)col);
 				draw_dm_verts(cageDM, sel, eve_act);
@@ -1842,6 +1846,7 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, EditM
 
 static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh *cageDM, short sel_only, EditEdge *eed_act)
 {
+	ToolSettings *ts= scene->toolsettings;
 	int pass;
 	unsigned char wireCol[4], selCol[4], actCol[4];
 
@@ -1871,11 +1876,11 @@ static void draw_em_fancy_edges(Scene *scene, View3D *v3d, Mesh *me, DerivedMesh
 			if (!sel_only) wireCol[3] = 255;
 		}
 
-		if(scene->selectmode == SCE_SELECT_FACE) {
+		if(ts->selectmode == SCE_SELECT_FACE) {
 			draw_dm_edges_sel(cageDM, wireCol, selCol, actCol, eed_act);
 		}	
-		else if( (me->drawflag & ME_DRAWEDGES) || (scene->selectmode & SCE_SELECT_EDGE) ) {	
-			if(cageDM->drawMappedEdgesInterp && (scene->selectmode & SCE_SELECT_VERTEX)) {
+		else if( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) {	
+			if(cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) {
 				glShadeModel(GL_SMOOTH);
 				draw_dm_edges_sel_interp(cageDM, wireCol, selCol);
 				glShadeModel(GL_FLAT);
@@ -3239,6 +3244,9 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
 			if(draw_as!=PART_DRAW_PATH){
 				state.time=cfra;
 				if(psys_get_particle_state(scene,ob,psys,a,&state,0)){
+					if(psys->parent)
+						Mat4MulVecfl(psys->parent->obmat, state.co);
+
 					/* create actiual particle data */
 					switch(draw_as){
 						case PART_DRAW_DOT:
@@ -3661,13 +3669,13 @@ static void draw_particle_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Ob
 	}
 
 	/* draw edit vertices */
-	if(scene->selectmode!=SCE_SELECT_PATH){
+	if(pset->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){
+		if(pset->selectmode==SCE_SELECT_POINT){
 			float *cd=0,*cdata=0;
 			cd=cdata=MEM_callocN(edit->totkeys*(timed?4:3)*sizeof(float), "particle edit color data");
 
@@ -3706,7 +3714,7 @@ static void draw_particle_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Ob
 				MEM_freeN(cdata);
 			cd=cdata=0;
 		}
-		else if(scene->selectmode == SCE_SELECT_END){
+		else if(pset->selectmode == SCE_SELECT_END){
 			for(i=0, pa=psys->particles; iflag & PARS_HIDE)==0){
 					key = edit->keys[i] + pa->totkey - 1;
@@ -3944,6 +3952,7 @@ static void draw_editnurb(Object *ob, Nurb *nurb, int sel)
 
 static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb, int dt)
 {
+	ToolSettings *ts= scene->toolsettings;
 	Object *ob= base->object;
 	Curve *cu = ob->data;
 	Nurb *nu;
@@ -3975,7 +3984,7 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
 
 	/*	direction vectors for 3d curve paths
 		when at its lowest, dont render normals */
-	if(cu->flag & CU_3D && scene->editbutsize > 0.0015) {
+	if(cu->flag & CU_3D && ts->normalsize > 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);		
@@ -3983,7 +3992,7 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
 			int skip= nu->resolu/16;
 			
 			while (nr-->0) { /* accounts for empty bevel lists */
-				float fac= bevp->radius * scene->editbutsize;
+				float fac= bevp->radius * ts->normalsize;
 				float ox,oy,oz; // Offset perpendicular to the curve
 				float dx,dy,dz; // Delta along the curve
 				
@@ -5405,6 +5414,7 @@ static void bbs_mesh_solid(Scene *scene, View3D *v3d, Object *ob)
 
 void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
 {
+	ToolSettings *ts= scene->toolsettings;
 
 	wmMultMatrix(ob->obmat);
 
@@ -5422,8 +5432,8 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
 
 			EM_init_index_arrays(em, 1, 1, 1);
 
-			bbs_mesh_solid_EM(scene, v3d, ob, dm, scene->selectmode & SCE_SELECT_FACE);
-			if(scene->selectmode & SCE_SELECT_FACE)
+			bbs_mesh_solid_EM(scene, v3d, ob, dm, ts->selectmode & SCE_SELECT_FACE);
+			if(ts->selectmode & SCE_SELECT_FACE)
 				em_solidoffs = 1+em->totface;
 			else
 				em_solidoffs= 1;
@@ -5435,7 +5445,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
 			em_wireoffs= em_solidoffs + em->totedge;
 			
 			// we draw verts if vert select mode or if in transform (for snap).
-			if(scene->selectmode & SCE_SELECT_VERTEX || G.moving & G_TRANSFORM_EDIT) {
+			if(ts->selectmode & SCE_SELECT_VERTEX || G.moving & G_TRANSFORM_EDIT) {
 				bbs_mesh_verts(dm, em_wireoffs);
 				em_vertoffs= em_wireoffs + em->totvert;
 			}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 2d6a57d5a34..625b1838951 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -122,6 +122,24 @@ ARegion *view3d_has_tools_region(ScrArea *sa)
 	return arnew;
 }
 
+/* ****************************************************** */
+
+/* function to always find a regionview3d context inside 3D window */
+RegionView3D *ED_view3d_context_rv3d(bContext *C)
+{
+	RegionView3D *rv3d= CTX_wm_region_view3d(C);
+	
+	if(rv3d==NULL) {
+		ScrArea *sa =CTX_wm_area(C);
+		if(sa->spacetype==SPACE_VIEW3D) {
+			ARegion *ar;
+			for(ar= sa->regionbase.first; ar; ar= ar->next)
+				if(ar->regiontype==RGN_TYPE_WINDOW)
+					return ar->regiondata;
+		}
+	}
+	return rv3d;
+}
 
 
 /* ******************** default callbacks for view3d space ***************** */
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index b6e9e05b120..91565235591 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -1663,7 +1663,7 @@ static void view3d_panel_bonesketch_spaces(const bContext *C, Panel *pa)
 
 	uiBlockEndAlign(block);
 	
-	uiDefButBitS(block, TOG, SCE_SNAP_PEEL_OBJECT, B_NOP, "Peel Objects", 10, yco, 200, 20, &scene->snap_flag, 0, 0, 0, 0, "Peel whole objects as one");
+	uiDefButBitS(block, TOG, SCE_SNAP_PEEL_OBJECT, B_NOP, "Peel Objects", 10, yco, 200, 20, &scene->toolsettings->snap_flag, 0, 0, 0, 0, "Peel whole objects as one");
 }
 
 
@@ -1710,7 +1710,7 @@ static void view3d_panel_operator_redo(const bContext *C, Panel *pa)
 	}
 	
 	RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
-	uiDefAutoButsRNA(C, pa->layout, &ptr);
+	uiDefAutoButsRNA(C, pa->layout, &ptr, 2);
 }
 
 void view3d_buttons_register(ARegionType *art)
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 1c528aac6a3..5edcd203e16 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -1,5 +1,5 @@
 /**
- * $Id: view3d_header.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -1812,6 +1812,7 @@ static void do_view3d_transformmenu(bContext *C, void *arg, int event)
 {
 #if 0
 	Scene *scene= CTX_data_scene(C);
+	ToolSettings *ts= CTX_data_tool_settings(C);
 	
 	switch(event) {
 	case 1:
@@ -1870,22 +1871,22 @@ static void do_view3d_transformmenu(bContext *C, void *arg, int event)
 		Transform();
 		break;
 	case 15:
-		scene->snap_flag &= ~SCE_SNAP;
+		ts->snap_flag &= ~SCE_SNAP;
 		break;
 	case 16:
-		scene->snap_flag |= SCE_SNAP;
+		ts->snap_flag |= SCE_SNAP;
 		break;
 	case 17:
-		scene->snap_target = SCE_SNAP_TARGET_CLOSEST;
+		ts->snap_target = SCE_SNAP_TARGET_CLOSEST;
 		break;
 	case 18:
-		scene->snap_target = SCE_SNAP_TARGET_CENTER;
+		ts->snap_target = SCE_SNAP_TARGET_CENTER;
 		break;
 	case 19:
-		scene->snap_target = SCE_SNAP_TARGET_MEDIAN;
+		ts->snap_target = SCE_SNAP_TARGET_MEDIAN;
 		break;
 	case 20:
-		scene->snap_target = SCE_SNAP_TARGET_ACTIVE;
+		ts->snap_target = SCE_SNAP_TARGET_ACTIVE;
 		break;
 	case 21:
 		alignmenu();
@@ -1896,7 +1897,7 @@ static void do_view3d_transformmenu(bContext *C, void *arg, int event)
 
 static uiBlock *view3d_transformmenu(bContext *C, ARegion *ar, void *arg_unused)
 {
-	Scene *scene= CTX_data_scene(C);
+	ToolSettings *ts= CTX_data_tool_settings(C);
 	Object *obedit = CTX_data_edit_object(C);
 	uiBlock *block;
 	short yco = 20, menuwidth = 120;
@@ -1948,7 +1949,7 @@ static uiBlock *view3d_transformmenu(bContext *C, ARegion *ar, void *arg_unused)
 	{
 		uiDefBut(block, SEPR, 0, "",                    0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
 	
-		if (scene->snap_flag & SCE_SNAP)
+		if (ts->snap_flag & SCE_SNAP)
 		{
 			uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Grid",			0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
 			uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap",			0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, "");
@@ -1961,7 +1962,7 @@ static uiBlock *view3d_transformmenu(bContext *C, ARegion *ar, void *arg_unused)
 			
 		uiDefBut(block, SEPR, 0, "",                    0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
 
-		switch(scene->snap_target)
+		switch(ts->snap_target)
 		{
 			case SCE_SNAP_TARGET_CLOSEST:
 				uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Snap Closest",				0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, "");
@@ -2650,34 +2651,34 @@ static uiBlock *view3d_edit_objectmenu(bContext *C, ARegion *ar, void *arg_unuse
 
 static void do_view3d_edit_propfalloffmenu(bContext *C, void *arg, int event)
 {
-	Scene *scene= CTX_data_scene(C);
+	ToolSettings *ts= CTX_data_tool_settings(C);
 	
-	scene->prop_mode= event;
+	ts->prop_mode= event;
 	
 }
 
 static uiBlock *view3d_edit_propfalloffmenu(bContext *C, ARegion *ar, void *arg_unused)
 {
-	Scene *scene= CTX_data_scene(C);
+	ToolSettings *ts= CTX_data_tool_settings(C);
 	uiBlock *block;
 	short yco = 20, menuwidth = 120;
 
 	block= uiBeginBlock(C, ar, "view3d_edit_propfalloffmenu", UI_EMBOSSP);
 	uiBlockSetButmFunc(block, do_view3d_edit_propfalloffmenu, NULL);
 	
-	if (scene->prop_mode==PROP_SMOOTH) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Smooth|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SMOOTH, "");
+	if (ts->prop_mode==PROP_SMOOTH) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Smooth|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SMOOTH, "");
 	else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Smooth|Shift O",	0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SMOOTH, "");
-	if (scene->prop_mode==PROP_SPHERE) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Sphere|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SPHERE, "");
+	if (ts->prop_mode==PROP_SPHERE) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Sphere|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SPHERE, "");
 	else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Sphere|Shift O",	0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SPHERE, "");
-	if (scene->prop_mode==PROP_ROOT) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Root|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_ROOT, "");
+	if (ts->prop_mode==PROP_ROOT) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Root|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_ROOT, "");
 	else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Root|Shift O",	0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_ROOT, "");
-	if (scene->prop_mode==PROP_SHARP) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Sharp|Shift O",	0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SHARP, "");
+	if (ts->prop_mode==PROP_SHARP) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Sharp|Shift O",	0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SHARP, "");
 	else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Sharp|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_SHARP, "");
-	if (scene->prop_mode==PROP_LIN) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Linear|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_LIN, "");
+	if (ts->prop_mode==PROP_LIN) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Linear|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_LIN, "");
 	else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Linear|Shift O",	0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_LIN, "");
-	if (scene->prop_mode==PROP_RANDOM) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Random|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_RANDOM, "");
+	if (ts->prop_mode==PROP_RANDOM) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Random|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_RANDOM, "");
 	else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Random|Shift O",	0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_RANDOM, "");
-	if (scene->prop_mode==PROP_CONST) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Constant|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_CONST, "");
+	if (ts->prop_mode==PROP_CONST) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Constant|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_CONST, "");
 	else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Constant|Shift O",	0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, PROP_CONST, "");
 		
 	uiBlockSetDirection(block, UI_RIGHT);
@@ -2698,7 +2699,7 @@ void do_view3d_edit_mesh_verticesmenu(bContext *C, void *arg, int event)
 		make_parent();
 		break;
 	case 1: /* remove doubles */
-		count= removedoublesflag(1, 0, scene->toolsettings->doublimit);
+		count= removedoublesflag(1, 0, ts->doublimit);
 		notice("Removed: %d", count);
 		if (count) { /* only undo and redraw if an action is taken */
 			DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
@@ -2768,18 +2769,18 @@ void do_view3d_edit_mesh_edgesmenu(bContext *C, void *arg, int event)
 	switch(event) {
 		 
 	case 0: /* subdivide smooth */
-		esubdivideflag(1, 0.0, scene->toolsettings->editbutflag | B_SMOOTH,1,0);
+		esubdivideflag(1, 0.0, ts->editbutflag | B_SMOOTH,1,0);
 		ED_undo_push(C, "Subdivide Smooth");
 		break;
 	case 1: /*subdivide fractal */
 		randfac= 10;
 		if(button(&randfac, 1, 100, "Rand fac:")==0) return;
 		fac= -( (float)randfac )/100;
-		esubdivideflag(1, fac, scene->toolsettings->editbutflag,1,0);
+		esubdivideflag(1, fac, ts->editbutflag,1,0);
 		ED_undo_push(C, "Subdivide Fractal");
 		break;
 	case 2: /* subdivide */
-		esubdivideflag(1, 0.0, scene->toolsettings->editbutflag,1,0);
+		esubdivideflag(1, 0.0, ts->editbutflag,1,0);
 		ED_undo_push(C, "Subdivide");
 		break;
 	case 3: /* knife subdivide */
@@ -3142,6 +3143,7 @@ static uiBlock *view3d_edit_mesh_scriptsmenu(bContext *C, ARegion *ar, void *arg
 static void do_view3d_edit_meshmenu(bContext *C, void *arg, int event)
 {
 #if 0
+	ToolSettings *ts= CTX_data_tool_settings(C);
 	Scene *scene= CTX_data_scene(C);
 	ScrArea *sa= CTX_wm_area(C);
 	View3D *v3d= sa->spacedata.first;
@@ -3185,12 +3187,12 @@ static void do_view3d_edit_meshmenu(bContext *C, void *arg, int event)
 		Transform();
 		break;
 	case 12: /* proportional edit (toggle) */
-		if(scene->proportional) scene->proportional= 0;
-		else scene->proportional= 1;
+		if(ts->proportional) ts->proportional= 0;
+		else ts->proportional= 1;
 		break;
 	case 13: /* automerge edit (toggle) */
-		if(scene->automerge) scene->automerge= 0;
-		else scene->automerge= 1;
+		if(ts->automerge) ts->automerge= 0;
+		else ts->automerge= 1;
 		break;
 	case 15:
 		uv_autocalc_tface();
@@ -3204,7 +3206,7 @@ static void do_view3d_edit_meshmenu(bContext *C, void *arg, int event)
 
 static uiBlock *view3d_edit_meshmenu(bContext *C, ARegion *ar, void *arg_unused)
 {
-	Scene *scene= CTX_data_scene(C);
+	ToolSettings *ts= CTX_data_tool_settings(C);
 	Object *obedit = CTX_data_edit_object(C);
 	uiBlock *block;
 	short yco= 0, menuwidth=120;
@@ -3250,7 +3252,7 @@ static uiBlock *view3d_edit_meshmenu(bContext *C, ARegion *ar, void *arg_unused)
 		
 	
 	
-	if(scene->proportional) {
+	if(ts->proportional) {
 		uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Proportional Editing|O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
 	} else {
 		uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Proportional Editing|O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
@@ -3261,7 +3263,7 @@ static uiBlock *view3d_edit_meshmenu(bContext *C, ARegion *ar, void *arg_unused)
 	
 	/* PITA but we should let users know that automerge cant work with multires :/ */
 	uiDefIconTextBut(block, BUTM, 1,
-			scene->automerge ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT,
+			ts->automerge ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT,
 			((Mesh*)obedit->data)->mr ? "AutoMerge Editing (disabled by multires)" : "AutoMerge Editing",
 			0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
 	
@@ -3536,8 +3538,8 @@ static void do_view3d_edit_latticemenu(bContext *C, void *arg, int event)
 		Transform();
 		break;
 	case 5: /* proportional edit (toggle) */
-		if(scene->proportional) scene->proportional= 0;
-		else scene->proportional= 1;
+		if(ts->proportional) ts->proportional= 0;
+		else ts->proportional= 1;
 		break;
 	case 7: /* delete keyframe */
 		common_deletekey();
@@ -3548,7 +3550,7 @@ static void do_view3d_edit_latticemenu(bContext *C, void *arg, int event)
 
 static uiBlock *view3d_edit_latticemenu(bContext *C, ARegion *ar, void *arg_unused)
 {
-	Scene *scene= CTX_data_scene(C);
+	ToolSettings *ts= CTX_data_tool_settings(C);
 	uiBlock *block;
 	short yco= 0, menuwidth=120;
 		
@@ -3574,7 +3576,7 @@ static uiBlock *view3d_edit_latticemenu(bContext *C, ARegion *ar, void *arg_unus
 	
 	uiDefBut(block, SEPR, 0, "",				0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
 	
-	if(scene->proportional) {
+	if(ts->proportional) {
 		uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Proportional Editing|O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
 	} else {
 		uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Proportional Editing|O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
@@ -4555,6 +4557,7 @@ static void view3d_sculpt_menu(bContext *C, uiLayout *layout, void *arg_unused)
 	uiItemR(layout, NULL, 0, &rna, "rake", 0, 0, 0);
 	uiItemR(layout, NULL, 0, &rna, "anchored", 0, 0, 0);
 	uiItemR(layout, NULL, 0, &rna, "space", 0, 0, 0);
+	uiItemR(layout, NULL, 0, &rna, "smooth_stroke", 0, 0, 0);
 
 	uiItemR(layout, NULL, 0, &rna, "flip_direction", 0, 0, 0);
 }
@@ -4695,7 +4698,7 @@ static uiBlock *view3d_faceselmenu(bContext *C, ARegion *ar, void *arg_unused)
 
 static void view3d_select_particlemenu(bContext *C, uiLayout *layout, void *arg_unused)
 {
-	Scene *scene= CTX_data_scene(C);
+	ToolSettings *ts= CTX_data_tool_settings(C);
 
 	uiItemO(layout, NULL, 0, "VIEW3D_OT_select_border");
 
@@ -4704,7 +4707,7 @@ static void view3d_select_particlemenu(bContext *C, uiLayout *layout, void *arg_
 	uiItemO(layout, NULL, 0, "PARTICLE_OT_select_all_toggle");
 	uiItemO(layout, NULL, 0, "PARTICLE_OT_select_linked");
 
-	if(scene->selectmode & SCE_SELECT_POINT) {
+	if(ts->particle.selectmode & SCE_SELECT_POINT) {
 		uiItemO(layout, NULL, 0, "PARTICLE_OT_select_last"); // |W, 4
 		uiItemO(layout, NULL, 0, "PARTICLE_OT_select_first"); // |W, 3
 	}
@@ -4724,7 +4727,7 @@ static void view3d_particle_showhidemenu(bContext *C, uiLayout *layout, void *ar
 
 static void view3d_particlemenu(bContext *C, uiLayout *layout, void *arg_unused)
 {
-	Scene *scene= CTX_data_scene(C);
+	ToolSettings *ts= CTX_data_tool_settings(C);
 
 	// XXX uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Particle Edit Properties|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
 	// add_blockhandler(sa, VIEW3D_HANDLER_OBJECT, UI_PNL_UNSTOW);
@@ -4739,7 +4742,7 @@ static void view3d_particlemenu(bContext *C, uiLayout *layout, void *arg_unused)
 
 	uiItemO(layout, NULL, 0, "PARTICLE_OT_remove_doubles"); // |W, 5
 	uiItemO(layout, NULL, 0, "PARTICLE_OT_delete");
-	if(scene->selectmode & SCE_SELECT_POINT)
+	if(ts->particle.selectmode & SCE_SELECT_POINT)
 		uiItemO(layout, NULL, 0, "PARTICLE_OT_subdivide"); // |W, 2
 	uiItemO(layout, NULL, 0, "PARTICLE_OT_rekey"); // |W, 1
 
@@ -4873,6 +4876,7 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event)
 {
 	wmWindow *win= CTX_wm_window(C);
 	Scene *scene= CTX_data_scene(C);
+	ToolSettings *ts= CTX_data_tool_settings(C);
 	ScrArea *sa= CTX_wm_area(C);
 	View3D *v3d= sa->spacedata.first;
 	Base *basact= CTX_data_active_base(C);
@@ -5007,7 +5011,7 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event)
 		if(em) {
 			if(shift==0 || em->selectmode==0)
 				em->selectmode= SCE_SELECT_VERTEX;
-			scene->selectmode= em->selectmode;
+			ts->selectmode= em->selectmode;
 			EM_selectmode_set(em);
 			WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 			ED_undo_push(C, "Selectmode Set: Vertex");
@@ -5021,7 +5025,7 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event)
 				}
 				em->selectmode = SCE_SELECT_EDGE;
 			}
-			scene->selectmode= em->selectmode;
+			ts->selectmode= em->selectmode;
 			EM_selectmode_set(em);
 			WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 			ED_undo_push(C, "Selectmode Set: Edge");
@@ -5030,12 +5034,12 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event)
 	case B_SEL_FACE:
 		if(em) {
 			if( shift==0 || em->selectmode==0){
-				if( ((scene->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || ((scene->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)){
-					if(ctrl) EM_convertsel(em, (scene->selectmode ^ SCE_SELECT_FACE),SCE_SELECT_FACE);
+				if( ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)){
+					if(ctrl) EM_convertsel(em, (ts->selectmode ^ SCE_SELECT_FACE),SCE_SELECT_FACE);
 				}
 				em->selectmode = SCE_SELECT_FACE;
 			}
-			scene->selectmode= em->selectmode;
+			ts->selectmode= em->selectmode;
 			EM_selectmode_set(em);
 			WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 			ED_undo_push(C, "Selectmode Set: Face");
@@ -5043,15 +5047,15 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event)
 		break;	
 
 	case B_SEL_PATH:
-		scene->selectmode= SCE_SELECT_PATH;
+		ts->particle.selectmode= SCE_SELECT_PATH;
 		ED_undo_push(C, "Selectmode Set: Path");
 		break;
 	case B_SEL_POINT:
-		scene->selectmode = SCE_SELECT_POINT;
+		ts->particle.selectmode = SCE_SELECT_POINT;
 		ED_undo_push(C, "Selectmode Set: Point");
 		break;
 	case B_SEL_END:
-		scene->selectmode = SCE_SELECT_END;
+		ts->particle.selectmode = SCE_SELECT_END;
 		ED_undo_push(C, "Selectmode Set: End point");
 		break;	
 	
@@ -5280,6 +5284,7 @@ void view3d_header_buttons(const bContext *C, ARegion *ar)
 	ScrArea *sa= CTX_wm_area(C);
 	View3D *v3d= sa->spacedata.first;
 	Scene *scene= CTX_data_scene(C);
+	ToolSettings *ts= CTX_data_tool_settings(C);
 	Object *ob= OBACT;
 	Object *obedit = CTX_data_edit_object(C);
 	uiBlock *block;
@@ -5449,11 +5454,11 @@ void view3d_header_buttons(const bContext *C, ARegion *ar)
 		if((obedit && (obedit->type == OB_MESH || obedit->type == OB_CURVE || obedit->type == OB_SURF || obedit->type == OB_LATTICE)) || G.f & G_PARTICLEEDIT) {
 		
 			uiBlockBeginAlign(block);
-			uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_PROP_OFF, "Proportional %t|Off %x0|On %x1|Connected %x2", xco,yco,XIC+10,YIC, &(scene->proportional), 0, 1.0, 0, 0, "Proportional Edit Falloff (Hotkeys: O, Alt O) ");
+			uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_PROP_OFF, "Proportional %t|Off %x0|On %x1|Connected %x2", xco,yco,XIC+10,YIC, &(ts->proportional), 0, 1.0, 0, 0, "Proportional Edit Falloff (Hotkeys: O, Alt O) ");
 			xco+= XIC+10;
 		
-			if(scene->proportional) {
-				uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_SMOOTHCURVE, propfalloff_pup(), xco,yco,XIC+10,YIC, &(scene->prop_mode), 0.0, 0.0, 0, 0, "Proportional Edit Falloff (Hotkey: Shift O) ");
+			if(ts->proportional) {
+				uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_SMOOTHCURVE, propfalloff_pup(), xco,yco,XIC+10,YIC, &(ts->prop_mode), 0.0, 0.0, 0, 0, "Proportional Edit Falloff (Hotkey: Shift O) ");
 				xco+= XIC+10;
 			}
 			uiBlockEndAlign(block);
@@ -5464,21 +5469,21 @@ void view3d_header_buttons(const bContext *C, ARegion *ar)
 		if (BIF_snappingSupported(obedit)) {
 			uiBlockBeginAlign(block);
 
-			if (scene->snap_flag & SCE_SNAP) {
-				uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEO,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab)");
+			if (ts->snap_flag & SCE_SNAP) {
+				uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEO,xco,yco,XIC,YIC, &ts->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab)");
 				xco+= XIC;
-				uiDefIconButBitS(block, TOG, SCE_SNAP_ROTATE, B_REDR, ICON_SNAP_NORMAL,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Align rotation with the snapping target");	
+				uiDefIconButBitS(block, TOG, SCE_SNAP_ROTATE, B_REDR, ICON_SNAP_NORMAL,xco,yco,XIC,YIC, &ts->snap_flag, 0, 0, 0, 0, "Align rotation with the snapping target");	
 				xco+= XIC;
-				if (scene->snap_mode == SCE_SNAP_MODE_VOLUME) {
-					uiDefIconButBitS(block, TOG, SCE_SNAP_PEEL_OBJECT, B_REDR, ICON_SNAP_PEEL_OBJECT,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Consider objects as whole when finding volume center");	
+				if (ts->snap_mode == SCE_SNAP_MODE_VOLUME) {
+					uiDefIconButBitS(block, TOG, SCE_SNAP_PEEL_OBJECT, B_REDR, ICON_SNAP_PEEL_OBJECT,xco,yco,XIC,YIC, &ts->snap_flag, 0, 0, 0, 0, "Consider objects as whole when finding volume center");	
 					xco+= XIC;
 				}
-				uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_SNAP_VERTEX, snapmode_pup(), xco,yco,XIC+10,YIC, &(scene->snap_mode), 0.0, 0.0, 0, 0, "Snapping mode");
+				uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_SNAP_VERTEX, snapmode_pup(), xco,yco,XIC+10,YIC, &(ts->snap_mode), 0.0, 0.0, 0, 0, "Snapping mode");
 				xco+= XIC;
-				uiDefButS(block, MENU, B_NOP, "Snap Mode%t|Closest%x0|Center%x1|Median%x2|Active%x3",xco,yco,70,YIC, &scene->snap_target, 0, 0, 0, 0, "Snap Target Mode");
+				uiDefButS(block, MENU, B_NOP, "Snap Mode%t|Closest%x0|Center%x1|Median%x2|Active%x3",xco,yco,70,YIC, &ts->snap_target, 0, 0, 0, 0, "Snap Target Mode");
 				xco+= XIC+70;
 			} else {
-				uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEAR,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab)");	
+				uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEAR,xco,yco,XIC,YIC, &ts->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab)");	
 				xco+= XIC;
 			}
 
@@ -5509,11 +5514,11 @@ void view3d_header_buttons(const bContext *C, ARegion *ar)
 		}
 		else if(G.f & G_PARTICLEEDIT) {
 			uiBlockBeginAlign(block);
-			uiDefIconButBitS(block, TOG, SCE_SELECT_PATH, B_SEL_PATH, ICON_EDGESEL, xco,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Path edit mode");
+			uiDefIconButBitI(block, TOG, SCE_SELECT_PATH, B_SEL_PATH, ICON_EDGESEL, xco,yco,XIC,YIC, &ts->particle.selectmode, 1.0, 0.0, 0, 0, "Path edit mode");
 			xco+= XIC;
-			uiDefIconButBitS(block, TOG, SCE_SELECT_POINT, B_SEL_POINT, ICON_VERTEXSEL, xco,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Point select mode");
+			uiDefIconButBitI(block, TOG, SCE_SELECT_POINT, B_SEL_POINT, ICON_VERTEXSEL, xco,yco,XIC,YIC, &ts->particle.selectmode, 1.0, 0.0, 0, 0, "Point select mode");
 			xco+= XIC;
-			uiDefIconButBitS(block, TOG, SCE_SELECT_END, B_SEL_END, ICON_FACESEL, xco,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Tip select mode");
+			uiDefIconButBitI(block, TOG, SCE_SELECT_END, B_SEL_END, ICON_FACESEL, xco,yco,XIC,YIC, &ts->particle.selectmode, 1.0, 0.0, 0, 0, "Tip select mode");
 			xco+= XIC;
 			uiBlockEndAlign(block);
 			
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index e0e8ac7c7a7..a153f795292 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -438,6 +438,7 @@ static void do_lasso_select_mesh__doSelectFace(void *userData, EditFace *efa, in
 static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves, short select)
 {
 	struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } data;
+	ToolSettings *ts= vc->scene->toolsettings;
 	rcti rect;
 	int bbsel;
 	
@@ -456,14 +457,14 @@ static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves
 
 	bbsel= EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
 	
-	if(vc->scene->selectmode & SCE_SELECT_VERTEX) {
+	if(ts->selectmode & SCE_SELECT_VERTEX) {
 		if (bbsel) {
 			EM_backbuf_checkAndSelectVerts(vc->em, select);
 		} else {
 			mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, 1);
 		}
 	}
-	if(vc->scene->selectmode & SCE_SELECT_EDGE) {
+	if(ts->selectmode & SCE_SELECT_EDGE) {
 			/* Does both bbsel and non-bbsel versions (need screen cos for both) */
 
 		data.pass = 0;
@@ -475,7 +476,7 @@ static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves
 		}
 	}
 	
-	if(vc->scene->selectmode & SCE_SELECT_FACE) {
+	if(ts->selectmode & SCE_SELECT_FACE) {
 		if (bbsel) {
 			EM_backbuf_checkAndSelectFaces(vc->em, select);
 		} else {
@@ -1277,6 +1278,7 @@ static void do_mesh_box_select__doSelectFace(void *userData, EditFace *efa, int
 static void do_mesh_box_select(ViewContext *vc, rcti *rect, int select)
 {
 	struct { ViewContext vc; rcti *rect; short select, pass, done; } data;
+	ToolSettings *ts= vc->scene->toolsettings;
 	int bbsel;
 	
 	data.vc= *vc;
@@ -1287,14 +1289,14 @@ static void do_mesh_box_select(ViewContext *vc, rcti *rect, int select)
 
 	bbsel= EM_init_backbuf_border(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
 
-	if(vc->scene->selectmode & SCE_SELECT_VERTEX) {
+	if(ts->selectmode & SCE_SELECT_VERTEX) {
 		if (bbsel) {
 			EM_backbuf_checkAndSelectVerts(vc->em, select);
 		} else {
 			mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, 1);
 		}
 	}
-	if(vc->scene->selectmode & SCE_SELECT_EDGE) {
+	if(ts->selectmode & SCE_SELECT_EDGE) {
 			/* Does both bbsel and non-bbsel versions (need screen cos for both) */
 
 		data.pass = 0;
@@ -1306,7 +1308,7 @@ static void do_mesh_box_select(ViewContext *vc, rcti *rect, int select)
 		}
 	}
 	
-	if(vc->scene->selectmode & SCE_SELECT_FACE) {
+	if(ts->selectmode & SCE_SELECT_FACE) {
 		if(bbsel) {
 			EM_backbuf_checkAndSelectFaces(vc->em, select);
 		} else {
@@ -1639,6 +1641,7 @@ static void mesh_circle_doSelectFace(void *userData, EditFace *efa, int x, int y
 
 static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, float rad)
 {
+	ToolSettings *ts= vc->scene->toolsettings;
 	int bbsel;
 	
 	if(vc->obedit==NULL && (FACESEL_PAINT_TEST)) {
@@ -1666,7 +1669,7 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa
 		data.mval[1] = mval[1];
 		data.radius = rad;
 
-		if(vc->scene->selectmode & SCE_SELECT_VERTEX) {
+		if(ts->selectmode & SCE_SELECT_VERTEX) {
 			if(bbsel) {
 				EM_backbuf_checkAndSelectVerts(vc->em, selecting==LEFTMOUSE);
 			} else {
@@ -1674,7 +1677,7 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa
 			}
 		}
 
-		if(vc->scene->selectmode & SCE_SELECT_EDGE) {
+		if(ts->selectmode & SCE_SELECT_EDGE) {
 			if (bbsel) {
 				EM_backbuf_checkAndSelectEdges(vc->em, selecting==LEFTMOUSE);
 			} else {
@@ -1682,7 +1685,7 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa
 			}
 		}
 		
-		if(vc->scene->selectmode & SCE_SELECT_FACE) {
+		if(ts->selectmode & SCE_SELECT_FACE) {
 			if(bbsel) {
 				EM_backbuf_checkAndSelectFaces(vc->em, selecting==LEFTMOUSE);
 			} else {
diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c
index 1e55f2e4a9a..ea365d59ac7 100644
--- a/source/blender/editors/space_view3d/view3d_toolbar.c
+++ b/source/blender/editors/space_view3d/view3d_toolbar.c
@@ -120,8 +120,6 @@ static void redo_cb(bContext *C, void *arg_op, void *arg2)
 
 static void view3d_panel_operator_redo(const bContext *C, Panel *pa)
 {
-	/* XXX temp */
-	extern void uiDefAutoButsRNA_single(const bContext *C, uiLayout *layout, PointerRNA *ptr);
 	wmWindowManager *wm= CTX_wm_manager(C);
 	wmOperator *op;
 	PointerRNA ptr;
@@ -136,7 +134,7 @@ static void view3d_panel_operator_redo(const bContext *C, Panel *pa)
 	
 	if(op==NULL)
 		return;
-	if(op->type->poll && op->type->poll(C)==0)
+	if(op->type->poll && op->type->poll((bContext *)C)==0)
 		return;
 	
 	uiBlockSetFunc(block, redo_cb, op, NULL);
@@ -147,13 +145,132 @@ static void view3d_panel_operator_redo(const bContext *C, Panel *pa)
 	}
 	
 	RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
-	uiDefAutoButsRNA_single(C, pa->layout, &ptr);
+	uiDefAutoButsRNA(C, pa->layout, &ptr, 1);
 }
 
+/* ******************* */
+
+typedef struct CustomTool {
+	struct CustomTool *next, *prev;
+	char opname[OP_MAX_TYPENAME];
+} CustomTool;
+
+static void operator_call_cb(struct bContext *C, void *arg_listbase, void *arg2)
+{
+	wmOperatorType *ot= arg2;
+	
+	if(ot) {
+		CustomTool *ct= MEM_callocN(sizeof(CustomTool), "CustomTool");
+		
+		BLI_addtail(arg_listbase, ct);
+		BLI_strncpy(ct->opname, ot->idname, OP_MAX_TYPENAME);
+	}
+		
+}
+
+static void operator_search_cb(const struct bContext *C, void *arg, char *str, uiSearchItems *items)
+{
+	wmOperatorType *ot = WM_operatortype_first();
+	
+	for(; ot; ot= ot->next) {
+		
+		if(BLI_strcasestr(ot->name, str)) {
+			if(ot->poll==NULL || ot->poll((bContext *)C)) {
+				
+				if(0==uiSearchItemAdd(items, ot->name, ot, 0))
+					break;
+			}
+		}
+	}
+}
+
+
+/* ID Search browse menu, open */
+static uiBlock *tool_search_menu(bContext *C, ARegion *ar, void *arg_listbase)
+{
+	static char search[OP_MAX_TYPENAME];
+	wmEvent event;
+	wmWindow *win= CTX_wm_window(C);
+	uiBlock *block;
+	uiBut *but;
+	
+	/* clear initial search string, then all items show */
+	search[0]= 0;
+	
+	block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
+	uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
+	
+	/* fake button, it holds space for search items */
+	uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
+	
+	but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, OP_MAX_TYPENAME, 10, 0, 150, 19, "");
+	uiButSetSearchFunc(but, operator_search_cb, arg_listbase, operator_call_cb, NULL);
+	
+	uiBoundsBlock(block, 6);
+	uiBlockSetDirection(block, UI_DOWN);	
+	uiEndBlock(C, block);
+	
+	event= *(win->eventstate);	/* XXX huh huh? make api call */
+	event.type= EVT_BUT_OPEN;
+	event.val= KM_PRESS;
+	event.customdata= but;
+	event.customdatafree= FALSE;
+	wm_event_add(win, &event);
+	
+	return block;
+}
+
+
+static void view3d_panel_tools(const bContext *C, Panel *pa)
+{
+	static ListBase tools= {NULL, NULL};
+	Object *obedit= CTX_data_edit_object(C);
+//	Object *obact = CTX_data_active_object(C);
+	uiLayout *col;
+	
+	if(obedit) {
+		if(obedit->type==OB_MESH) {
+			
+			col= uiLayoutColumn(pa->layout, 1);
+			uiItemFullO(col, NULL, 0, "MESH_OT_spin", NULL, WM_OP_INVOKE_REGION_WIN);
+			uiItemFullO(col, NULL, 0, "MESH_OT_screw", NULL, WM_OP_INVOKE_REGION_WIN);
+			
+			if(tools.first) {
+				CustomTool *ct;
+				
+				for(ct= tools.first; ct; ct= ct->next) {
+					col= uiLayoutColumn(pa->layout, 1);
+					uiItemFullO(col, NULL, 0, ct->opname, NULL, WM_OP_INVOKE_REGION_WIN);
+				}
+			}
+			col= uiLayoutColumn(pa->layout, 1);
+			uiDefBlockBut(uiLayoutGetBlock(pa->layout), tool_search_menu, &tools, "Add Operator", 0, 0, UI_UNIT_X, UI_UNIT_Y, "Add tool");
+		}
+	}
+	else {
+		
+		col= uiLayoutColumn(pa->layout, 1);
+		uiItemFullO(col, NULL, 0, "OBJECT_OT_delete", NULL, WM_OP_INVOKE_REGION_WIN);
+		uiItemFullO(col, NULL, 0, "OBJECT_OT_primitive_add", NULL, WM_OP_INVOKE_REGION_WIN);
+		
+		col= uiLayoutColumn(pa->layout, 1);
+		uiItemFullO(col, NULL, 0, "OBJECT_OT_parent_set", NULL, WM_OP_INVOKE_REGION_WIN);
+		uiItemFullO(col, NULL, 0, "OBJECT_OT_parent_clear", NULL, WM_OP_INVOKE_REGION_WIN);
+		
+	}
+}
+
+
 void view3d_toolbar_register(ARegionType *art)
 {
 	PanelType *pt;
 
+	pt= MEM_callocN(sizeof(PanelType), "spacetype view3d panel tools");
+	strcpy(pt->idname, "VIEW3D_PT_tools");
+	strcpy(pt->label, "Tools");
+	pt->draw= view3d_panel_tools;
+	BLI_addtail(&art->paneltypes, pt);
+	
 	pt= MEM_callocN(sizeof(PanelType), "spacetype view3d panel last operator");
 	strcpy(pt->idname, "VIEW3D_PT_last_operator");
 	strcpy(pt->label, "Last Operator");
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 2db5f2c97fd..b57f4a91004 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -76,11 +76,12 @@
 #include "UI_resources.h"
 #include "UI_view2d.h"
 
+#include "GPU_draw.h"
+
 #include "PIL_time.h" /* smoothview */
 
 #include "view3d_intern.h"	// own include
 
-
 /* use this call when executing an operator,
    event system doesn't set for each event the
    opengl drawing context */
@@ -1430,6 +1431,9 @@ static int game_engine_exec(bContext *C, wmOperator *unused)
 	Scene *startscene = CTX_data_scene(C);
 	
 #if GAMEBLENDER == 1
+	
+	view3d_operator_needs_opengl(C);
+	
 	SaveState(C);
 	StartKetsjiShell(C, 1);
 	RestoreState(C);
diff --git a/source/blender/editors/transform/Makefile b/source/blender/editors/transform/Makefile
index bc3e08a2ae8..607038b413b 100644
--- a/source/blender/editors/transform/Makefile
+++ b/source/blender/editors/transform/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 674de81a9f5..3311fb7d0fe 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1134,7 +1134,7 @@ void drawTransform(const struct bContext *C, struct ARegion *ar, void *arg)
 
 void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
 {
-	Scene *sce = CTX_data_scene(C);
+	ToolSettings *ts = CTX_data_tool_settings(C);
 	int constraint_axis[3] = {0, 0, 0};
 	int proportional = 0;
 
@@ -1195,8 +1195,8 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
 	// XXX If modal, save settings back in scene
 	if (t->flag & T_MODAL)
 	{
-		sce->prop_mode = t->prop_mode;
-		sce->proportional = proportional;
+		ts->prop_mode = t->prop_mode;
+		ts->proportional = proportional;
 
 		if(t->spacetype == SPACE_VIEW3D)
 		{
@@ -2359,7 +2359,7 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) {
 		}
 		else if (t->flag & T_EDIT) {
 			
-			if(t->around==V3D_LOCAL && (t->scene->selectmode & SCE_SELECT_FACE)) {
+			if(t->around==V3D_LOCAL && (t->settings->selectmode & SCE_SELECT_FACE)) {
 				VECCOPY(center, td->center);
 			}
 			else {
@@ -2660,7 +2660,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
 		}
 		else {
 			/* !TODO! Make this if not rely on G */
-			if(around==V3D_LOCAL && (t->scene->selectmode & SCE_SELECT_FACE)) {
+			if(around==V3D_LOCAL && (t->settings->selectmode & SCE_SELECT_FACE)) {
 				center = td->center;
 			}
 		}
@@ -3126,7 +3126,7 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) {
 		sprintf(distvec, "%.4f", dist);
 		
 	if(t->flag & T_AUTOIK) {
-		short chainlen= t->scene->toolsettings->autoik_chainlen;
+		short chainlen= t->settings->autoik_chainlen;
 		
 		if(chainlen)
 			sprintf(autoik, "AutoIK-Len: %d", chainlen);
@@ -4251,7 +4251,7 @@ int Align(TransInfo *t, short mval[2])
 			VECCOPY(t->center, td->center);
 		}
 		else {
-			if(t->scene->selectmode & SCE_SELECT_FACE) {
+			if(t->settings->selectmode & SCE_SELECT_FACE) {
 				VECCOPY(t->center, td->center);
 			}
 		}
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index ee767fada58..534f142734a 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -257,6 +257,7 @@ typedef struct TransInfo {
 	struct ScrArea	*sa;
 	struct ARegion	*ar;
 	struct Scene	*scene;
+	struct ToolSettings *settings;
 	struct wmTimer *animtimer;
     short       mval[2];        /* current mouse position               */
     struct Object   *obedit;
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 6c7aa1ee49d..490ce820b30 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -777,7 +777,7 @@ static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen)
 /* change the chain-length of auto-ik */
 void transform_autoik_update (TransInfo *t, short mode)
 {
-	short *chainlen= &t->scene->toolsettings->autoik_chainlen;
+	short *chainlen= &t->settings->autoik_chainlen;
 	bPoseChannel *pchan;
 	
 	/* mode determines what change to apply to chainlen */
@@ -1631,7 +1631,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
 	int count = 0, hasselected = 0;
 	int propmode = t->flag & T_PROP_EDIT;
 
-	if(psys==NULL || t->scene->selectmode==SCE_SELECT_PATH) return;
+	if(psys==NULL || t->settings->particle.selectmode==SCE_SELECT_PATH) return;
 
 	psmd = psys_get_modifier(ob,psys);
 
@@ -2101,7 +2101,7 @@ void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
 
 static void createTransEditVerts(bContext *C, TransInfo *t)
 {
-	Scene *scene = CTX_data_scene(C);
+	ToolSettings *ts = CTX_data_tool_settings(C);
 	TransData *tob = NULL;
 	EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
 	EditVert *eve;
@@ -2119,7 +2119,7 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
 	}
 
 	// transform now requires awareness for select mode, so we tag the f1 flags in verts
-	if(scene->selectmode & SCE_SELECT_VERTEX) {
+	if(ts->selectmode & SCE_SELECT_VERTEX) {
 		for(eve= em->verts.first; eve; eve= eve->next) {
 			if(eve->h==0 && (eve->f & SELECT)) 
 				eve->f1= SELECT;
@@ -2127,7 +2127,7 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
 				eve->f1= 0;
 		}
 	}
-	else if(scene->selectmode & SCE_SELECT_EDGE) {
+	else if(ts->selectmode & SCE_SELECT_EDGE) {
 		EditEdge *eed;
 		for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
 		for(eed= em->edges.first; eed; eed= eed->next) {
@@ -4672,8 +4672,14 @@ void special_aftertrans_update(TransInfo *t)
 			
 			if (base->flag & SELECT && (t->mode != TFM_DUMMY)) {
 				/* pointcache refresh */
-				if (BKE_ptcache_object_reset(ob, PTCACHE_RESET_DEPSGRAPH))
+				if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH))
 					ob->recalc |= OB_RECALC_DATA;
+
+				/* Needed for proper updating of "quick cached" dynamics. */
+				/* Creates troubles for moving animated objects without */
+				/* autokey though, probably needed is an anim sys override? */
+				/* Please remove if some other solution is found. -jahka */
+				DAG_object_flush_update(scene, ob, OB_RECALC_OB);
 				
 				/* Set autokey if necessary */
 				if (!cancelled)
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 171665c9282..e157d7f68f9 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -665,6 +665,7 @@ void resetTransRestrictions(TransInfo *t)
 int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
 {
 	Scene *sce = CTX_data_scene(C);
+	ToolSettings *ts = CTX_data_tool_settings(C);
 	ARegion *ar = CTX_wm_region(C);
 	ScrArea *sa = CTX_wm_area(C);
 	Object *obedit = CTX_data_edit_object(C);
@@ -679,6 +680,7 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
 	t->sa = sa;
 	t->ar = ar;
 	t->obedit = obedit;
+	t->settings = ts;
 
 	t->data = NULL;
 	t->ext = NULL;
@@ -752,9 +754,10 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
 	}
 	else if(t->spacetype==SPACE_IMAGE || t->spacetype==SPACE_NODE)
 	{
+		SpaceImage *sima = sa->spacedata.first;
 		// XXX for now, get View2D  from the active region
 		t->view = &ar->v2d;
-		t->around = ar->v2d.around;
+		t->around = sima->around;
 	}
 	else
 	{
@@ -774,7 +777,7 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
 	// Need stuff to take it from edit mesh or whatnot here
 	else
 	{
-		if (t->obedit && t->obedit->type == OB_MESH && sce->toolsettings->editbutflag & B_MESH_X_MIRROR)
+		if (t->obedit && t->obedit->type == OB_MESH && ts->editbutflag & B_MESH_X_MIRROR)
 		{
 			t->flag |= T_MIRROR;
 		}
@@ -794,10 +797,10 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
 	}
 	else
 	{
-		if ((t->options & CTX_NO_PET) == 0 && (sce->proportional)) {
+		if ((t->options & CTX_NO_PET) == 0 && (ts->proportional)) {
 			t->flag |= T_PROP_EDIT;
 			
-			if(sce->proportional == 2)
+			if(ts->proportional == 2)
 				t->flag |= T_PROP_CONNECTED;	// yes i know, has to become define
 		}
 	}
@@ -808,7 +811,7 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
 	}
 	else
 	{
-		t->prop_size = sce->toolsettings->proportional_size;
+		t->prop_size = ts->proportional_size;
 	}
 	
 	if (op && RNA_struct_find_property(op->ptr, "proportional_editing_falloff") && RNA_property_is_set(op->ptr, "proportional_editing_falloff"))
@@ -817,7 +820,7 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
 	}
 	else
 	{
-		t->prop_mode = sce->prop_mode;
+		t->prop_mode = ts->prop_mode;
 	}
 
 	/* TRANSFORM_FIX_ME rna restrictions */
diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c
index 4d721a83c78..631eb1eb134 100644
--- a/source/blender/editors/transform/transform_input.c
+++ b/source/blender/editors/transform/transform_input.c
@@ -1,5 +1,5 @@
 /**
- * $Id: transform_input.c 18142 2008-12-29 07:19:16Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -26,6 +26,7 @@
 #include 
 
 #include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
 
 #include "BLI_arithb.h"
 
diff --git a/source/blender/editors/transform/transform_ndofinput.c b/source/blender/editors/transform/transform_ndofinput.c
index c52492ebd6b..9c2a1a7db6d 100644
--- a/source/blender/editors/transform/transform_ndofinput.c
+++ b/source/blender/editors/transform/transform_ndofinput.c
@@ -31,6 +31,7 @@
 #include "BKE_utildefines.h"	/* ABS */
 
 #include "DNA_view3d_types.h" /* for G.vd (view3d) */
+#include "DNA_windowmanager_types.h" /* for G.vd (view3d) */
 
 #include "WM_types.h"
 
diff --git a/source/blender/editors/transform/transform_numinput.c b/source/blender/editors/transform/transform_numinput.c
index 34976105db3..f5f1d5fac9e 100644
--- a/source/blender/editors/transform/transform_numinput.c
+++ b/source/blender/editors/transform/transform_numinput.c
@@ -34,6 +34,7 @@
 #include "BKE_utildefines.h"	/* ABS */
 
 #include "WM_types.h"
+#include "DNA_windowmanager_types.h"
 
 #include "transform.h"
 
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index e697b6dfa7d..9e4115f38f0 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -1,5 +1,5 @@
 /**
- * $Id: transform_ops.c 17542 2008-11-23 15:27:53Z theeth $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 72901110388..0b9a176dbdf 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -210,7 +210,7 @@ int  handleSnapping(TransInfo *t, wmEvent *event)
 	if (BIF_snappingSupported(t->obedit) && event->type == TABKEY && event->shift)
 	{
 		/* toggle snap and reinit */
-		t->scene->snap_flag ^= SCE_SNAP;
+		t->settings->snap_flag ^= SCE_SNAP;
 		initSnapping(t, NULL);
 		status = 1;
 	}
@@ -282,10 +282,10 @@ int validSnappingNormal(TransInfo *t)
 
 void initSnapping(TransInfo *t, wmOperator *op)
 {
-	Scene *scene = t->scene;
+	ToolSettings *ts = t->settings;
 	Object *obedit = t->obedit;
 	int snapping = 0;
-	short snap_mode = t->scene->snap_target;
+	short snap_mode = t->settings->snap_target;
 	
 	resetSnapping(t);
 	
@@ -310,8 +310,8 @@ void initSnapping(TransInfo *t, wmOperator *op)
 	}
 	else
 	{
-		snapping = ((scene->snap_flag & SCE_SNAP) == SCE_SNAP);
-		t->tsnap.align = ((t->scene->snap_flag & SCE_SNAP_ROTATE) == SCE_SNAP_ROTATE);
+		snapping = ((ts->snap_flag & SCE_SNAP) == SCE_SNAP);
+		t->tsnap.align = ((t->settings->snap_flag & SCE_SNAP_ROTATE) == SCE_SNAP_ROTATE);
 	}
 	
 	if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && // Only 3D view or UV
@@ -542,7 +542,7 @@ void CalcSnapGeometry(TransInfo *t, float *vec)
 		int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
 		SnapMode mode;
 		
-		if (t->scene->snap_mode == SCE_SNAP_MODE_VOLUME)
+		if (t->settings->snap_mode == SCE_SNAP_MODE_VOLUME)
 		{
 			ListBase depth_peels;
 			DepthPeel *p1, *p2;
@@ -575,7 +575,7 @@ void CalcSnapGeometry(TransInfo *t, float *vec)
 					p1->flag = 1;
 		
 					/* if peeling objects, take the first and last from each object */			
-					if (t->scene->snap_flag & SCE_SNAP_PEEL_OBJECT)
+					if (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT)
 					{
 						DepthPeel *peel;
 						for (peel = p1->next; peel; peel = peel->next)
@@ -1346,6 +1346,7 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E
 
 int snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth)
 {
+	ToolSettings *ts= scene->toolsettings;
 	int retval = 0;
 	
 	if (ob->type == OB_MESH) {
@@ -1363,13 +1364,13 @@ int snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obma
 			dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
 		}
 		
-		retval = snapDerivedMesh(scene->snap_mode, ar, ob, dm, em, obmat, ray_start, ray_normal, mval, loc, no, dist, depth);
+		retval = snapDerivedMesh(ts->snap_mode, ar, ob, dm, em, obmat, ray_start, ray_normal, mval, loc, no, dist, depth);
 
 		dm->release(dm);
 	}
 	else if (ob->type == OB_ARMATURE)
 	{
-		retval = snapArmature(scene->snap_mode, ar, ob, ob->data, obmat, ray_start, ray_normal, mval, loc, no, dist, depth);
+		retval = snapArmature(ts->snap_mode, ar, ob, ob->data, obmat, ray_start, ray_normal, mval, loc, no, dist, depth);
 	}
 	
 	return retval;
diff --git a/source/blender/editors/util/Makefile b/source/blender/editors/util/Makefile
index da701dc5d86..303079daeee 100644
--- a/source/blender/editors/util/Makefile
+++ b/source/blender/editors/util/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index 62ce76a7614..1d79c542fa9 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -183,6 +183,8 @@ void ED_undo_redo(bContext *C)
 
 static int ed_undo_exec(bContext *C, wmOperator *op)
 {
+	/* "last operator" should disappear, later we can tie ths with undo stack nicer */
+	WM_operator_stack_clear(C);
 	return ed_undo_step(C, 1);
 }
 static int ed_redo_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/uvedit/Makefile b/source/blender/editors/uvedit/Makefile
index b8a8f0bc8af..d589bbec3bc 100644
--- a/source/blender/editors/uvedit/Makefile
+++ b/source/blender/editors/uvedit/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 14 2002-10-13 15:57:19Z hans $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index aded5a4cff9..b811906f5e5 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -102,17 +102,19 @@ static void drawcursor_sima(SpaceImage *sima, ARegion *ar)
 
 static int draw_uvs_face_check(Scene *scene)
 {
+	ToolSettings *ts= scene->toolsettings;
+
 	/* checks if we are selecting only faces */
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
-		if(scene->selectmode == SCE_SELECT_FACE)
+	if(ts->uv_flag & UV_SYNC_SELECTION) {
+		if(ts->selectmode == SCE_SELECT_FACE)
 			return 2;
-		else if(scene->selectmode & SCE_SELECT_FACE)
+		else if(ts->selectmode & SCE_SELECT_FACE)
 			return 1;
 		else
 			return 0;
 	}
 	else
-		return (scene->toolsettings->uv_selectmode == UV_SELECT_FACE);
+		return (ts->uv_selectmode == UV_SELECT_FACE);
 }
 
 static void draw_uvs_shadow(SpaceImage *sima, Object *obedit)
@@ -418,7 +420,7 @@ static void draw_uvs_other(SpaceImage *sima, Scene *scene, Object *obedit, MTFac
 /* draws uv's in the image space */
 static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
 {
-	ToolSettings *settings;
+	ToolSettings *ts;
 	Mesh *me= obedit->data;
 	EditMesh *em;
 	EditFace *efa, *efa_act;
@@ -432,13 +434,13 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
 	em= BKE_mesh_get_editmesh(me);
 	activetf= EM_get_active_mtface(em, &efa_act, NULL, 0); /* will be set to NULL if hidden */
 
-	settings= scene->toolsettings;
+	ts= scene->toolsettings;
 
 	drawfaces= draw_uvs_face_check(scene);
-	if(settings->uv_flag & UV_SYNC_SELECTION)
-		interpedges= (scene->selectmode & SCE_SELECT_VERTEX);
+	if(ts->uv_flag & UV_SYNC_SELECTION)
+		interpedges= (ts->selectmode & SCE_SELECT_VERTEX);
 	else
-		interpedges= (settings->uv_selectmode == UV_SELECT_VERTEX);
+		interpedges= (ts->uv_selectmode == UV_SELECT_VERTEX);
 	
 	/* draw other uvs */
 	if(sima->flag & SI_DRAW_OTHER)
@@ -454,7 +456,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
 
 			/* when sync selection is enabled, all faces are drawn (except for hidden)
 			 * so if cage is the same as the final, theres no point in drawing this */
-			if(!((settings->uv_flag & UV_SYNC_SELECTION) && (cagedm == finaldm)))
+			if(!((ts->uv_flag & UV_SYNC_SELECTION) && (cagedm == finaldm)))
 				draw_uvs_dm_shadow(finaldm);
 			
 			/* release derivedmesh again */
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 7dca4d34c48..7582145c63b 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -191,7 +191,9 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist
 
 int uvedit_face_visible_nolocal(Scene *scene, EditFace *efa)
 {
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION)
+	ToolSettings *ts= scene->toolsettings;
+
+	if(ts->uv_flag & UV_SYNC_SELECTION)
 		return (efa->h==0);
 	else
 		return (efa->h==0 && (efa->f & SELECT));
@@ -199,7 +201,9 @@ int uvedit_face_visible_nolocal(Scene *scene, EditFace *efa)
 
 int uvedit_face_visible(Scene *scene, Image *ima, EditFace *efa, MTFace *tf)
 {
-	if(scene->toolsettings->uv_flag & UV_SHOW_SAME_IMAGE)
+	ToolSettings *ts= scene->toolsettings;
+
+	if(ts->uv_flag & UV_SHOW_SAME_IMAGE)
 		return (tf->tpage==ima)? uvedit_face_visible_nolocal(scene, efa): 0;
 	else
 		return uvedit_face_visible_nolocal(scene, efa);
@@ -207,7 +211,9 @@ int uvedit_face_visible(Scene *scene, Image *ima, EditFace *efa, MTFace *tf)
 
 int uvedit_face_selected(Scene *scene, EditFace *efa, MTFace *tf)
 {
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION)
+	ToolSettings *ts= scene->toolsettings;
+
+	if(ts->uv_flag & UV_SYNC_SELECTION)
 		return (efa->f & SELECT);
 	else
 		return (!(~tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3)) &&(!efa->v4 || tf->flag & TF_SEL4));
@@ -215,7 +221,9 @@ int uvedit_face_selected(Scene *scene, EditFace *efa, MTFace *tf)
 
 void uvedit_face_select(Scene *scene, EditFace *efa, MTFace *tf)
 {
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION)
+	ToolSettings *ts= scene->toolsettings;
+
+	if(ts->uv_flag & UV_SYNC_SELECTION)
 		EM_select_face(efa, 1);
 	else
 		tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
@@ -223,7 +231,9 @@ void uvedit_face_select(Scene *scene, EditFace *efa, MTFace *tf)
 
 void uvedit_face_deselect(Scene *scene, EditFace *efa, MTFace *tf)
 {
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION)
+	ToolSettings *ts= scene->toolsettings;
+
+	if(ts->uv_flag & UV_SYNC_SELECTION)
 		EM_select_face(efa, 0);
 	else
 		tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
@@ -231,12 +241,13 @@ void uvedit_face_deselect(Scene *scene, EditFace *efa, MTFace *tf)
 
 int uvedit_edge_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
 {
+	ToolSettings *ts= scene->toolsettings;
 	int nvert= (efa->v4)? 4: 3;
 
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
-		if(scene->selectmode == SCE_SELECT_FACE)
+	if(ts->uv_flag & UV_SYNC_SELECTION) {
+		if(ts->selectmode == SCE_SELECT_FACE)
 			return (efa->f & SELECT);
-		else if(scene->selectmode == SCE_SELECT_EDGE)
+		else if(ts->selectmode == SCE_SELECT_EDGE)
 			return (*(&efa->e1 + i))->f & SELECT;
 		else
 			return (((efa->v1 + i)->f & SELECT) && ((efa->v1 + (i+1)%nvert)->f & SELECT));
@@ -247,12 +258,13 @@ int uvedit_edge_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
 
 void uvedit_edge_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
 {
+	ToolSettings *ts= scene->toolsettings;
 	int nvert= (efa->v4)? 4: 3;
 
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
-		if(scene->selectmode == SCE_SELECT_FACE)
+	if(ts->uv_flag & UV_SYNC_SELECTION) {
+		if(ts->selectmode == SCE_SELECT_FACE)
 			EM_select_face(efa, 1);
-		else if(scene->selectmode == SCE_SELECT_EDGE)
+		else if(ts->selectmode == SCE_SELECT_EDGE)
 			EM_select_edge((*(&efa->e1 + i)), 1);
 		else {
 			(efa->v1 + i)->f |= SELECT;
@@ -265,12 +277,13 @@ void uvedit_edge_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
 
 void uvedit_edge_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i)
 {
+	ToolSettings *ts= scene->toolsettings;
 	int nvert= (efa->v4)? 4: 3;
 
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
-		if(scene->selectmode == SCE_SELECT_FACE)
+	if(ts->uv_flag & UV_SYNC_SELECTION) {
+		if(ts->selectmode == SCE_SELECT_FACE)
 			EM_select_face(efa, 0);
-		else if(scene->selectmode == SCE_SELECT_EDGE)
+		else if(ts->selectmode == SCE_SELECT_EDGE)
 			EM_select_edge((*(&efa->e1 + i)), 0);
 		else {
 			(efa->v1 + i)->f &= ~SELECT;
@@ -283,8 +296,10 @@ void uvedit_edge_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i)
 
 int uvedit_uv_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
 {
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
-		if(scene->selectmode == SCE_SELECT_FACE)
+	ToolSettings *ts= scene->toolsettings;
+
+	if(ts->uv_flag & UV_SYNC_SELECTION) {
+		if(ts->selectmode == SCE_SELECT_FACE)
 			return (efa->f & SELECT);
 		else
 			return (*(&efa->v1 + i))->f & SELECT;
@@ -295,8 +310,10 @@ int uvedit_uv_selected(Scene *scene, EditFace *efa, MTFace *tf, int i)
 
 void uvedit_uv_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
 {
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
-		if(scene->selectmode == SCE_SELECT_FACE)
+	ToolSettings *ts= scene->toolsettings;
+
+	if(ts->uv_flag & UV_SYNC_SELECTION) {
+		if(ts->selectmode == SCE_SELECT_FACE)
 			EM_select_face(efa, 1);
 		else
 			(*(&efa->v1 + i))->f |= SELECT;
@@ -307,8 +324,10 @@ void uvedit_uv_select(Scene *scene, EditFace *efa, MTFace *tf, int i)
 
 void uvedit_uv_deselect(Scene *scene, EditFace *efa, MTFace *tf, int i)
 {
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
-		if(scene->selectmode == SCE_SELECT_FACE)
+	ToolSettings *ts= scene->toolsettings;
+
+	if(ts->uv_flag & UV_SYNC_SELECTION) {
+		if(ts->selectmode == SCE_SELECT_FACE)
 			EM_select_face(efa, 0);
 		else
 			(*(&efa->v1 + i))->f &= ~SELECT;
@@ -1289,6 +1308,7 @@ void UV_OT_stitch(wmOperatorType *ot)
 static int select_inverse_exec(bContext *C, wmOperator *op)
 {
 	Scene *scene;
+	ToolSettings *ts;
 	Object *obedit;
 	EditMesh *em;
 	EditFace *efa;
@@ -1296,11 +1316,12 @@ static int select_inverse_exec(bContext *C, wmOperator *op)
 	MTFace *tf;
 	
 	scene= CTX_data_scene(C);
+	ts= CTX_data_tool_settings(C);
 	obedit= CTX_data_edit_object(C);
 	em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 	ima= CTX_data_edit_image(C);
 
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+	if(ts->uv_flag & UV_SYNC_SELECTION) {
 		EM_select_swap(em);
 	}
 	else {
@@ -1339,6 +1360,7 @@ void UV_OT_select_invert(wmOperatorType *ot)
 static int de_select_all_exec(bContext *C, wmOperator *op)
 {
 	Scene *scene;
+	ToolSettings *ts;
 	Object *obedit;
 	EditMesh *em;
 	EditFace *efa;
@@ -1347,11 +1369,12 @@ static int de_select_all_exec(bContext *C, wmOperator *op)
 	int sel;
 	
 	scene= CTX_data_scene(C);
+	ts= CTX_data_tool_settings(C);
 	obedit= CTX_data_edit_object(C);
 	em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 	ima= CTX_data_edit_image(C);
 	
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+	if(ts->uv_flag & UV_SYNC_SELECTION) {
 		EM_toggle_select_all(em);
 	}
 	else {
@@ -1431,6 +1454,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
 {
 	SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
 	Scene *scene= CTX_data_scene(C);
+	ToolSettings *ts= CTX_data_tool_settings(C);
 	Object *obedit= CTX_data_edit_object(C);
 	Image *ima= CTX_data_edit_image(C);
 	EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
@@ -1445,12 +1469,12 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
 	uvedit_pixel_to_float(sima, penalty, 5.0f);
 
 	/* retrieve operation mode */
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+	if(ts->uv_flag & UV_SYNC_SELECTION) {
 		sync= 1;
 
-		if(scene->selectmode & SCE_SELECT_FACE)
+		if(ts->selectmode & SCE_SELECT_FACE)
 			selectmode= UV_SELECT_FACE;
-		else if(scene->selectmode & SCE_SELECT_EDGE)
+		else if(ts->selectmode & SCE_SELECT_EDGE)
 			selectmode= UV_SELECT_EDGE;
 		else
 			selectmode= UV_SELECT_VERTEX;
@@ -1459,7 +1483,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
 	}
 	else {
 		sync= 0;
-		selectmode= scene->toolsettings->uv_selectmode;
+		selectmode= ts->uv_selectmode;
 		sticky= sima->sticky;
 	}
 
@@ -1681,7 +1705,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
 	
 	if(sync) {
 		/* flush for mesh selection */
-		if(scene->selectmode != SCE_SELECT_FACE) {
+		if(ts->selectmode != SCE_SELECT_FACE) {
 			if(flush==1)		EM_select_flush(em);
 			else if(flush==-1)	EM_deselect_flush(em);
 		}
@@ -1794,13 +1818,14 @@ static int select_linked_exec(bContext *C, wmOperator *op)
 {
 	SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
 	Scene *scene= CTX_data_scene(C);
+	ToolSettings *ts= CTX_data_tool_settings(C);
 	Object *obedit= CTX_data_edit_object(C);
 	Image *ima= CTX_data_edit_image(C);
 	EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 	float limit[2];
 	int extend;
 
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+	if(ts->uv_flag & UV_SYNC_SELECTION) {
 		BKE_report(op->reports, RPT_ERROR, "Can't select linked when sync selection is enabled.");
 		BKE_mesh_end_editmesh(obedit->data, em);
 		return OPERATOR_CANCELLED;
@@ -1838,13 +1863,14 @@ void UV_OT_select_linked(wmOperatorType *ot)
 static int unlink_selection_exec(bContext *C, wmOperator *op)
 {
 	Scene *scene= CTX_data_scene(C);
+	ToolSettings *ts= CTX_data_tool_settings(C);
 	Object *obedit= CTX_data_edit_object(C);
 	Image *ima= CTX_data_edit_image(C);
 	EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 	EditFace *efa;
 	MTFace *tf;
 
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+	if(ts->uv_flag & UV_SYNC_SELECTION) {
 		BKE_report(op->reports, RPT_ERROR, "Can't unlink selection when sync selection is enabled.");
 		BKE_mesh_end_editmesh(obedit->data, em);
 		return OPERATOR_CANCELLED;
@@ -1901,12 +1927,13 @@ static void uv_faces_do_sticky(bContext *C, SpaceImage *sima, Scene *scene, Obje
 	 * This only needs to be done when the Mesh is not used for
 	 * selection (so for sticky modes, vertex or location based). */
 	
+	ToolSettings *ts= CTX_data_tool_settings(C);
 	EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 	EditFace *efa;
 	MTFace *tf;
 	int nverts, i;
 	
-	if((scene->toolsettings->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_VERTEX) {
+	if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_VERTEX) {
 		/* Tag all verts as untouched, then touch the ones that have a face center
 		 * in the loop and select all MTFace UV's that use a touched vert. */
 		EditVert *eve;
@@ -1937,7 +1964,7 @@ static void uv_faces_do_sticky(bContext *C, SpaceImage *sima, Scene *scene, Obje
 			}
 		}
 	}
-	else if((scene->toolsettings->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_LOC) {
+	else if((ts->uv_flag & UV_SYNC_SELECTION)==0 && sima->sticky == SI_STICKY_LOC) {
 		EditFace *efa_vlist;
 		MTFace *tf_vlist;
 		UvMapVert *start_vlist=NULL, *vlist_iter;
@@ -2008,7 +2035,7 @@ static void uv_faces_do_sticky(bContext *C, SpaceImage *sima, Scene *scene, Obje
 		EM_free_uv_vert_map(vmap);
 		
 	}
-	else { /* SI_STICKY_DISABLE or scene->toolsettings->uv_flag & UV_SYNC_SELECTION */
+	else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */
 		for(efa= em->faces.first; efa; efa= efa->next) {
 			if(efa->tmp.l) {
 				tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
@@ -2026,6 +2053,7 @@ static int border_select_exec(bContext *C, wmOperator *op)
 {
 	SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
 	Scene *scene= CTX_data_scene(C);
+	ToolSettings *ts= CTX_data_tool_settings(C);
 	Object *obedit= CTX_data_edit_object(C);
 	Image *ima= CTX_data_edit_image(C);
 	ARegion *ar= CTX_wm_region(C);
@@ -2049,10 +2077,10 @@ static int border_select_exec(bContext *C, wmOperator *op)
 	select= (RNA_int_get(op->ptr, "event_type") == LEFTMOUSE); // XXX hardcoded
 	pinned= RNA_boolean_get(op->ptr, "pinned");
 	
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION)
-		faces= (scene->selectmode == SCE_SELECT_FACE);
+	if(ts->uv_flag & UV_SYNC_SELECTION)
+		faces= (ts->selectmode == SCE_SELECT_FACE);
 	else
-		faces= (scene->toolsettings->uv_selectmode == UV_SELECT_FACE);
+		faces= (ts->uv_selectmode == UV_SELECT_FACE);
 
 	/* do actual selection */
 	if(faces && !pinned) {
@@ -2084,7 +2112,7 @@ static int border_select_exec(bContext *C, wmOperator *op)
 		for(efa= em->faces.first; efa; efa= efa->next) {
 			tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 			if(uvedit_face_visible(scene, ima, efa, tface)) {
-				if(!pinned || (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) ) {
+				if(!pinned || (ts->uv_flag & UV_SYNC_SELECTION) ) {
 					/* UV_SYNC_SELECTION - can't do pinned selection */
 					if(BLI_in_rctf(&rectf, tface->uv[0][0], tface->uv[0][1])) {
 						if(select)	uvedit_uv_select(scene, efa, tface, 0);
@@ -2133,8 +2161,8 @@ static int border_select_exec(bContext *C, wmOperator *op)
 
 	if(change) {
 		/* make sure newly selected vert selection is updated*/
-		if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
-			if(scene->selectmode != SCE_SELECT_FACE) {
+		if(ts->uv_flag & UV_SYNC_SELECTION) {
+			if(ts->selectmode != SCE_SELECT_FACE) {
 				if(select)	EM_select_flush(em);
 				else		EM_deselect_flush(em);
 			}
@@ -2668,14 +2696,14 @@ void UV_OT_select_pinned(wmOperatorType *ot)
 static int hide_exec(bContext *C, wmOperator *op)
 {
 	SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
-	Scene *scene= CTX_data_scene(C);
+	ToolSettings *ts= CTX_data_tool_settings(C);
 	Object *obedit= CTX_data_edit_object(C);
 	EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 	EditFace *efa;
 	MTFace *tf;
 	int swap= RNA_boolean_get(op->ptr, "unselected");
 
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+	if(ts->uv_flag & UV_SYNC_SELECTION) {
 		EM_hide_mesh(em, swap);
 		WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 
@@ -2811,14 +2839,14 @@ void UV_OT_hide(wmOperatorType *ot)
 static int reveal_exec(bContext *C, wmOperator *op)
 {
 	SpaceImage *sima= (SpaceImage*)CTX_wm_space_data(C);
-	Scene *scene= CTX_data_scene(C);
+	ToolSettings *ts= CTX_data_tool_settings(C);
 	Object *obedit= CTX_data_edit_object(C);
 	EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
 	EditFace *efa;
 	MTFace *tf;
 	
 	/* call the mesh function if we are in mesh sync sel */
-	if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
+	if(ts->uv_flag & UV_SYNC_SELECTION) {
 		EM_reveal_mesh(em);
 		WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
 
diff --git a/source/blender/gpu/intern/Makefile b/source/blender/gpu/intern/Makefile
index 733ee3f764c..3a3ac20ff6c 100644
--- a/source/blender/gpu/intern/Makefile
+++ b/source/blender/gpu/intern/Makefile
@@ -35,7 +35,7 @@ DIR = $(OCGDIR)/blender/$(LIBNAME)
 
 include nan_compile.mk
 
-ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
+ifeq ($(OS),$(findstring $(OS), "darwin freebsd linux openbsd solaris windows"))
     CFLAGS += -funsigned-char
 endif
 
diff --git a/source/blender/imbuf/intern/imbuf.h b/source/blender/imbuf/intern/imbuf.h
index bd2a0d3082f..7b5d668ce2b 100644
--- a/source/blender/imbuf/intern/imbuf.h
+++ b/source/blender/imbuf/intern/imbuf.h
@@ -51,7 +51,7 @@
 #include 
 #endif
 
-#if !defined(WIN32) && !defined(__BeOS)
+#if !defined(WIN32)
 #define O_BINARY 0
 #endif
 
diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c
index 6df92f69fff..1a6ab104bcf 100644
--- a/source/blender/imbuf/intern/readimage.c
+++ b/source/blender/imbuf/intern/readimage.c
@@ -244,26 +244,6 @@ struct ImBuf *IMB_loadifffile(int file, int flags) {
 
 	size = BLI_filesize(file);
 
-#if defined(AMIGA) || defined(__BeOS)
-	mem= (int *)malloc(size);
-	if (mem==0) {
-		printf("Out of mem\n");
-		return (0);
-	}
-
-	if (read(file, mem, size)!=size){
-		printf("Read Error\n");
-		free(mem);
-		return (0);
-	}
-
-	ibuf = IMB_ibImageFromMemory(mem, size, flags);
-	free(mem);
-
-	/* for jpeg read */
-	lseek(file, 0L, SEEK_SET);
-
-#else
 	mem= (int *)mmap(0,size,PROT_READ,MAP_SHARED,file,0);
 	if (mem==(int *)-1){
 		printf("Couldn't get mapping\n");
@@ -275,7 +255,6 @@ struct ImBuf *IMB_loadifffile(int file, int flags) {
 	if (munmap( (void *) mem, size)){
 		printf("Couldn't unmap file.\n");
 	}
-#endif
 	return(ibuf);
 }
 
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 8ce0b439b29..93a974c1180 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -84,6 +84,7 @@ typedef struct Brush {
 #define BRUSH_ANCHORED		256
 #define BRUSH_DIR_IN		512
 #define BRUSH_SPACE		1024
+#define BRUSH_SMOOTH_STROKE	2048
 
 /* Brush.blend */
 #define BRUSH_BLEND_MIX 		0
diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h
index 718d1a17834..88d9894cf7a 100644
--- a/source/blender/makesdna/DNA_object_force.h
+++ b/source/blender/makesdna/DNA_object_force.h
@@ -33,6 +33,8 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+
+#include "DNA_listBase.h"
 	
 typedef struct PartDeflect {
 	short deflect;		/* Deflection flag - does mesh deflect particles*/
@@ -72,12 +74,26 @@ typedef struct PartDeflect {
 	int seed; /* wind noise random seed */
 } PartDeflect;
 
+typedef struct PTCacheMem {
+	struct PTCacheMem *next, *prev;
+	int frame, totpoint;
+	float *data;	/* data points */
+	void *xdata;	/* extra data */
+} PTCacheMem;
+
 typedef struct PointCache {
 	int flag;		/* generic flag */
+	int step;		/* frames between cached frames */
 	int simframe;	/* current frame of simulation (only if SIMULATION_VALID) */
 	int startframe;	/* simulation start frame */
 	int endframe;	/* simulation end frame */
 	int editframe;	/* frame being edited (runtime only) */
+	int last_exact; /* last exact frame that's cached */
+	int xdata_type;	/* type of extra data */
+	char name[64];
+	char prev_name[64];
+	char info[64];
+	struct ListBase mem_cache;
 } PointCache;
 
 typedef struct SBVertex {
@@ -247,6 +263,12 @@ typedef struct SoftBody {
 #define PTCACHE_BAKING				8
 #define PTCACHE_BAKE_EDIT			16
 #define PTCACHE_BAKE_EDIT_ACTIVE	32
+#define PTCACHE_DISK_CACHE			64
+#define PTCACHE_QUICK_CACHE			128
+#define PTCACHE_FRAMES_SKIPPED		256
+
+/* PTCACHE_OUTDATED + PTCACHE_FRAMES_SKIPPED */
+#define PTCACHE_REDO_NEEDED			258
 
 /* ob->softflag */
 #define OB_SB_ENABLE	1
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index 6805082d094..05f1cc1f351 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -34,6 +34,8 @@
 
 #include "DNA_ID.h"
 
+struct AnimData;
+
 typedef struct HairKey {
 	float co[3];	/* location of hair vertex */
 	float time;		/* time along hair, default 0-100 */
@@ -100,6 +102,7 @@ typedef struct ParticleData {
 
 typedef struct ParticleSettings {
 	ID id;
+	struct AnimData *adt;
 
 	int flag;
 	short type, from, distr;
@@ -167,7 +170,7 @@ typedef struct ParticleSettings {
 	struct Group *eff_group;
 	struct Object *dup_ob;
 	struct Object *bb_ob;
-	struct Ipo *ipo;
+	struct Ipo *ipo;				// xxx depreceated... old animation system
 	struct PartDeflect *pd;
 	struct PartDeflect *pd2;
 } ParticleSettings;
@@ -192,6 +195,7 @@ typedef struct ParticleSystem{				/* note, make sure all (runtime) are NULL's in
 	struct Object *target_ob;
 	struct Object *keyed_ob;
 	struct Object *lattice;
+	struct Object *parent;					/* particles from global space -> parent space */
 
 	struct ListBase effectors, reactevents;	/* runtime */
 	
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index e8279604100..1199bd1e2b1 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -39,7 +39,6 @@ extern "C" {
 #include "DNA_scriptlink_types.h"
 #include "DNA_ID.h"
 
-struct Radio;
 struct Object;
 struct World;
 struct Scene;
@@ -48,6 +47,7 @@ struct Group;
 struct Text;
 struct bNodeTree;
 struct AnimData;
+struct Editing;
 
 typedef struct Base {
 	struct Base *next, *prev;
@@ -158,7 +158,7 @@ typedef struct SceneRenderLayer {
 #define SCE_PASS_REFRACT	1024
 #define SCE_PASS_INDEXOB	2048
 #define SCE_PASS_UV			4096
-#define SCE_PASS_RADIO		8192
+#define SCE_PASS_RADIO		8192 /* Radio removed, can use for new GI? */
 #define SCE_PASS_MIST		16384
 
 /* note, srl->passflag is treestore element 'nr' in outliner, short still... */
@@ -385,6 +385,8 @@ typedef struct ParticleEditSettings {
 
 	float emitterdist;
 	int draw_timed;
+
+	int selectmode, pad;
 } ParticleEditSettings;
 
 typedef struct TransformOrientation {
@@ -439,19 +441,27 @@ typedef struct ToolSettings {
 	VPaint *wpaint;		/* weight paint */
 	Sculpt *sculpt;
 	
+	/* Vertex groups */
+	float vgroup_weight;
+
 	/* Subdivide Settings */
 	short cornertype;
 	short editbutflag;
 	/*Triangle to Quad conversion threshold*/
 	float jointrilimit;
-	/* Extrude Tools */
+	/* Editmode Tools */
 	float degr; 
 	short step;
 	short turn; 
 	
-	float extr_offs; 
-	float doublimit;
-	
+	float extr_offs; 	/* extrude offset */
+	float doublimit;	/* remove doubles limit */
+	float normalsize;	/* size of normals */
+	short automerge;
+
+	/* Selection Mode for Mesh */
+	short selectmode;
+
 	/* Primitive Settings */
 	/* UV Sphere */
 	short segments;
@@ -465,7 +475,6 @@ typedef struct ToolSettings {
 	float uvcalc_radius;
 	float uvcalc_cubesize;
 	float uvcalc_margin;
-	float pad;
 	short uvcalc_mapdir;
 	short uvcalc_mapalign;
 	short uvcalc_flag;
@@ -487,8 +496,11 @@ typedef struct ToolSettings {
 	/* Select Group Threshold */
 	float select_thresh;
 	
-	/* IPO-Editor */
+	/* Graph Editor */
 	float clean_thresh;
+
+	/* Auto-Keying Mode */
+	short autokey_mode, pad2;	/* defines in DNA_userdef_types.h */
 	
 	/* Retopo */
 	char retopo_mode;
@@ -515,7 +527,6 @@ typedef struct ToolSettings {
 	char  skgen_postpro_passes;
 	char  skgen_subdivisions[3];
 	char  skgen_multi_level;
-	int   skgen_pad;
 	
 	/* Skeleton Sketching */
 	struct Object *skgen_template;
@@ -529,7 +540,10 @@ typedef struct ToolSettings {
 	
 	/* Alt+RMB option */
 	char edge_mode;
-	char pad3[2];
+
+	/* Transform */
+	short snap_mode, snap_flag, snap_target;
+	short proportional, prop_mode;
 } ToolSettings;
 
 typedef struct bStats {
@@ -550,29 +564,22 @@ typedef struct Scene {
 	struct Image *ima;
 	
 	ListBase base;
-	struct Base *basact;
+	struct Base *basact;		/* active base */
 	struct Object *obedit;		/* name replaces old G.obedit */
 	
-	float cursor[3];
+	float cursor[3];			/* 3d cursor location */
 	float twcent[3];			/* center for transform widget */
 	float twmin[3], twmax[3];	/* boundbox of selection for transform widget */
 	unsigned int lay;
 	
-	/* editmode stuff */
-	float editbutsize;                      /* size of normals */
-	short selectmode;						/* for mesh only! */
-	short proportional, prop_mode;
-	short automerge, pad5;
 	
 	short flag;								/* various settings */
-	short autokey_mode; 					/* mode for autokeying (defines in DNA_userdef_types.h) */
 	
 	short use_nodes;
 	
 	struct bNodeTree *nodetree;	
 	
-	void *ed;								/* sequence editor data is allocated here */
-	struct Radio *radio;
+	struct Editing *ed;								/* sequence editor data is allocated here */
 	
 	struct GameFraming framing;
 
@@ -582,20 +589,20 @@ typedef struct Scene {
 	/* migrate or replace? depends on some internal things... */
 	/* no, is on the right place (ton) */
 	struct RenderData r;
-	struct AudioData audio;		/* DEPRICATED 2.5 */
+	struct AudioData audio;		/* DEPRECATED 2.5 */
 	
 	ScriptLink scriptlink;
 	
 	ListBase markers;
 	ListBase transform_spaces;
 	
-	short jumpframe;
-	short snap_mode, snap_flag, snap_target;
 	
 	/* none of the dependancy graph  vars is mean to be saved */
 	struct  DagForest *theDag;
 	short dagisvalid, dagflags;
-	short pad4, recalc;				/* recalc = counterpart of ob->recalc */
+	short recalc;				/* recalc = counterpart of ob->recalc */
+
+	short jumpframe;
 
 	/* frame step. */
 	int frame_step;
@@ -801,27 +808,27 @@ typedef struct Scene {
 
 /* base->flag is in DNA_object_types.h */
 
-/* scene->snap_flag */
+/* toolsettings->snap_flag */
 #define SCE_SNAP				1
 #define SCE_SNAP_ROTATE			2
 #define SCE_SNAP_PEEL_OBJECT	4
-/* scene->snap_target */
+/* toolsettings->snap_target */
 #define SCE_SNAP_TARGET_CLOSEST	0
 #define SCE_SNAP_TARGET_CENTER	1
 #define SCE_SNAP_TARGET_MEDIAN	2
 #define SCE_SNAP_TARGET_ACTIVE	3
-/* scene->snap_mode */
+/* toolsettings->snap_mode */
 #define SCE_SNAP_MODE_VERTEX	0
 #define SCE_SNAP_MODE_EDGE		1
 #define SCE_SNAP_MODE_FACE		2
 #define SCE_SNAP_MODE_VOLUME	3
 
-/* sce->selectmode */
+/* toolsettings->selectmode */
 #define SCE_SELECT_VERTEX	1 /* for mesh */
 #define SCE_SELECT_EDGE		2
 #define SCE_SELECT_FACE		4
 
-/* sce->selectmode for particles */
+/* toolsettings->particle.selectmode for particles */
 #define SCE_SELECT_PATH		1
 #define SCE_SELECT_POINT	2
 #define SCE_SELECT_END		4
@@ -829,7 +836,7 @@ typedef struct Scene {
 /* sce->recalc (now in use by previewrender) */
 #define SCE_PRV_CHANGED		1
 
-/* sce->prop_mode (proportional falloff) */
+/* toolsettings->prop_mode (proportional falloff) */
 #define PROP_SMOOTH            0
 #define PROP_SPHERE            1
 #define PROP_ROOT              2
@@ -896,7 +903,7 @@ typedef enum SculptFlags {
 
 /* toolsettings->uv_selectmode */
 #define UV_SELECT_VERTEX	1
-#define UV_SELECT_EDGE		2 /* not implemented */
+#define UV_SELECT_EDGE		2
 #define UV_SELECT_FACE		4
 #define UV_SELECT_ISLAND	8
 
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index 4891f44e1cd..d9d68490425 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -53,6 +53,7 @@ typedef struct bScreen {
 	ListBase regionbase;				/* screen level regions (menus), runtime only */
 	
 	struct Scene *scene;
+	struct Scene *newscene;				/* temporary when switching */
 	
 	short full;							/* fade out? */
 	short winid;						/* winid from WM, starts with 1 */
@@ -104,6 +105,9 @@ typedef struct Panel {		/* the part from uiBlock that needs saved in file */
 	int sortorder;			/* panels are aligned according to increasing sortorder */
 	struct Panel *paneltab;		/* this panel is tabbed in *paneltab */
 	void *activedata;			/* runtime for panel manipulation */
+
+	int list_scroll, list_size;
+	char list_search[64];
 } Panel;
 
 typedef struct Header {
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 416acd7467e..53dc5ed26e8 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -165,6 +165,48 @@ typedef struct SpaceSeq {
 	struct bGPdata *gpd;		/* grease-pencil data */
 } SpaceSeq;
 
+typedef struct FileSelectParams {
+	char title[24]; /* title, also used for the text of the execute button */
+	char dir[240]; /* directory */
+	char file[80]; /* file */
+
+	short flag; /* settings for filter, hiding files and display mode */
+	short sort; /* sort order */
+	short display; /* display mode flag */
+	short filter; /* filter when (flags & FILE_FILTER) is true */
+
+	/* XXX - temporary, better move to filelist */
+	short active_bookmark;
+	short pad;
+	int	active_file;
+	int selstate;
+
+	/* XXX --- still unused -- */
+	short f_fp; /* show font preview */
+	short menu; /* currently selected option in pupmenu */
+	char fp_str[8]; /* string to use for font preview */
+	
+	char *pupmenu; /* allows menu for save options - result stored in menup */
+	
+	/* XXX --- end unused -- */
+} FileSelectParams;
+
+/* FileSelectParams.display */
+enum FileDisplayTypeE {
+	FILE_SHORTDISPLAY = 1,
+	FILE_LONGDISPLAY,
+	FILE_IMGDISPLAY
+};
+
+/* FileSelectParams.sort */
+enum FileSortTypeE {
+	FILE_SORT_NONE = 0,
+	FILE_SORT_ALPHA = 1,
+	FILE_SORT_EXTENSION,
+	FILE_SORT_TIME,
+	FILE_SORT_SIZE
+};
+
 typedef struct SpaceFile {
 	SpaceLink *next, *prev;
 	ListBase regionbase;		/* storage of regions for inactive spaces */
@@ -229,7 +271,7 @@ typedef struct SpaceImage {
 	char dt_uv; /* UV draw type */
 	char sticky; /* sticky selection type */
 	char dt_uvstretch;
-	char pad;
+	char around;
 	
 	float xof, yof;					/* user defined offset, image is centered */
 	float zoom, pad4;				/* user defined zoom level */
@@ -554,12 +596,6 @@ typedef struct SpaceImaSel {
 #define FILE_FILTER			256
 #define FILE_BOOKMARKS		512
 
-/* sfile->sort */
-#define FILE_SORTALPHA		0
-#define FILE_SORTDATE		1
-#define FILE_SORTSIZE		2
-#define FILE_SORTEXTENS		3
-
 /* files in filesel list: 2=ACTIVE  */
 #define HILITE				1
 #define BLENDERFILE			4
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 9d554c88a95..771a7e43793 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -67,7 +67,8 @@ typedef struct uiFontStyle {
 	short uifont_id;		/* saved in file, 0 is default */
 	short points;			/* actual size depends on 'global' dpi */
 	float kerning;			/* kerning space between characters. */
-	float pad;
+	short overlap;			/* check overlaped characters. */
+	short pad;
 	short italic, bold;		/* style hint */
 	short shadow;			/* value is amount of pixels blur */
 	short shadx, shady;		/* shadow offset in pixels */
@@ -123,10 +124,11 @@ typedef struct uiWidgetColors {
 typedef struct ThemeUI {
 	
 	/* Interface Elements (buttons, menus, icons) */
-	uiWidgetColors wcol_regular, wcol_tool, wcol_radio, wcol_text, wcol_option;
+	uiWidgetColors wcol_regular, wcol_tool, wcol_text;
+	uiWidgetColors wcol_radio, wcol_option, wcol_toggle;
 	uiWidgetColors wcol_num, wcol_numslider;
 	uiWidgetColors wcol_menu, wcol_pulldown, wcol_menu_back, wcol_menu_item;
-	uiWidgetColors wcol_box;
+	uiWidgetColors wcol_box, wcol_scroll;
 	
 	char iconfile[80];	// FILE_MAXFILE length
 	
@@ -379,7 +381,7 @@ extern UserDef U; /* from blenkernel blender.c */
 #define USER_ZOOM_TO_MOUSEPOS	(1 << 20)
 #define USER_SHOW_FPS			(1 << 21)
 #define USER_MMB_PASTE			(1 << 22)
-#define USER_DIRECTIONALORDER	(1 << 23)
+#define USER_MENUFIXEDORDER		(1 << 23)
 
 /* Auto-Keying mode */
 	/* AUTOKEY_ON is a bitflag */
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index 7d6b5ec8764..b63fb35c193 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -88,7 +88,8 @@ typedef struct wmWindow {
 	
 	int winid, pad;		/* winid also in screens, is for retrieving this window after read */
 	
-	struct bScreen *screen;	/* active screen */
+	struct bScreen *screen;		/* active screen */
+	struct bScreen *newscreen;	/* temporary when switching */
 	char screenname[32];	/* MAX_ID_NAME for matching window with active screen after file read */
 	
 	short posx, posy, sizex, sizey;	/* window coords */
@@ -222,5 +223,36 @@ typedef enum wmRadialControlMode {
 	WM_RADIALCONTROL_ANGLE
 } wmRadialControlMode;
 
+/* ************** wmEvent ************************ */
+/* for read-only rna access, dont save this */
+
+/* each event should have full modifier state */
+/* event comes from eventmanager and from keymap */
+typedef struct wmEvent {
+	struct wmEvent *next, *prev;
+	
+	short type;			/* event code itself (short, is also in keymap) */
+	short val;			/* press, release, scrollvalue */
+	short x, y;			/* mouse pointer position, screen coord */
+	short mval[2];		/* region mouse position, name convention pre 2.5 :) */
+	short prevx, prevy;	/* previous mouse pointer position */
+	short unicode;		/* future, ghost? */
+	char ascii;			/* from ghost */
+	char pad;
+	
+	/* modifier states */
+	short shift, ctrl, alt, oskey;	/* oskey is apple or windowskey, value denotes order of pressed */
+	short keymodifier;				/* rawkey modifier */
+	
+	/* keymap item, set by handler (weak?) */
+	const char *keymap_idname;
+	
+	/* custom data */
+	short custom;	/* custom data type, stylus, 6dof, see wm_event_types.h */
+	void *customdata;	/* ascii, unicode, mouse coords, angles, vectors, dragdrop info */
+	short customdatafree;
+	
+} wmEvent;
+
 #endif /* DNA_WINDOWMANAGER_TYPES_H */
 
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index bf2f0f3900e..91e9e617ea9 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -98,7 +98,6 @@ char *includefiles[] = {
 	"DNA_object_force.h",
 	"DNA_object_fluidsim.h",
 	"DNA_world_types.h",
-	"DNA_radio_types.h",
 	"DNA_scene_types.h",
 	"DNA_view3d_types.h",
 	"DNA_view2d_types.h",	
@@ -1124,7 +1123,6 @@ int main(int argc, char ** argv)
 #include "DNA_object_force.h"
 #include "DNA_object_fluidsim.h"
 #include "DNA_world_types.h"
-#include "DNA_radio_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_view3d_types.h"
 #include "DNA_view2d_types.h"	
diff --git a/source/blender/makesrna/Makefile b/source/blender/makesrna/Makefile
index 25625af57a6..bed3e85550d 100644
--- a/source/blender/makesrna/Makefile
+++ b/source/blender/makesrna/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 21247 2009-06-29 21:50:53Z jaguarandi $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index c1a659fee9b..d69439e25bc 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -1,5 +1,5 @@
 /**
- * $Id: RNA_access.h 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -172,7 +172,9 @@ extern StructRNA RNA_EnvironmentMap;
 extern StructRNA RNA_EnvironmentMapTexture;
 extern StructRNA RNA_ExplodeModifier;
 extern StructRNA RNA_ExpressionController;
+extern StructRNA RNA_Event;
 extern StructRNA RNA_FCurve;
+extern StructRNA RNA_FileSelectParams;
 extern StructRNA RNA_FModifier;
 extern StructRNA RNA_FModifierCycles;
 extern StructRNA RNA_FModifierEnvelope;
@@ -368,6 +370,7 @@ extern StructRNA RNA_SpaceImageEditor;
 extern StructRNA RNA_SpaceOutliner;
 extern StructRNA RNA_SpaceSequenceEditor;
 extern StructRNA RNA_SpaceTextEditor;
+extern StructRNA RNA_SpaceFileBrowser;
 extern StructRNA RNA_SpaceUVEditor;
 extern StructRNA RNA_SpeedControlSequence;
 extern StructRNA RNA_SpotLamp;
@@ -513,6 +516,8 @@ const struct ListBase *RNA_struct_defined_properties(StructRNA *srna);
 FunctionRNA *RNA_struct_find_function(PointerRNA *ptr, const char *identifier);
 const struct ListBase *RNA_struct_defined_functions(StructRNA *srna);
 
+char *RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen);
+
 /* Properties
  *
  * Access to struct properties. All this works with RNA pointers rather than
@@ -541,6 +546,9 @@ void RNA_property_int_ui_range(PointerRNA *ptr, PropertyRNA *prop, int *softmin,
 void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin, float *hardmax);
 void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *softmin, float *softmax, float *step, float *precision);
 
+int RNA_enum_identifier(const EnumPropertyItem *item, const int value, const char **identifier);
+int RNA_enum_name(const EnumPropertyItem *item, const int value, const char **name);
+
 void RNA_property_enum_items(PointerRNA *ptr, PropertyRNA *prop, const EnumPropertyItem **item, int *totitem);
 int RNA_property_enum_value(PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *value);
 int RNA_property_enum_identifier(PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier);
@@ -594,6 +602,14 @@ int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop);
 int RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr);
 int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr);
 
+/* efficient functions to set properties for arrays */
+int RNA_property_collection_raw_array(PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, RawArray *array);
+int RNA_property_collection_raw_get(struct ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *array, RawPropertyType type, int len);
+int RNA_property_collection_raw_set(struct ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *array, RawPropertyType type, int len);
+int RNA_raw_type_sizeof(RawPropertyType type);
+RawPropertyType RNA_property_raw_type(PropertyRNA *prop);
+
+
 /* to create ID property groups */
 void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop);
 void RNA_property_pointer_remove(PointerRNA *ptr, PropertyRNA *prop);
@@ -689,6 +705,28 @@ void RNA_collection_clear(PointerRNA *ptr, const char *name);
 		RNA_property_collection_end(&rna_macro_iter); \
 	}
 
+#define RNA_PROP_BEGIN(sptr, itemptr, prop) \
+	{ \
+		CollectionPropertyIterator rna_macro_iter; \
+		for(RNA_property_collection_begin(sptr, prop, &rna_macro_iter); rna_macro_iter.valid; RNA_property_collection_next(&rna_macro_iter)) { \
+			PointerRNA itemptr= rna_macro_iter.ptr;
+
+#define RNA_PROP_END \
+		} \
+		RNA_property_collection_end(&rna_macro_iter); \
+	}
+
+#define RNA_STRUCT_BEGIN(sptr, prop) \
+	{ \
+		CollectionPropertyIterator rna_macro_iter; \
+		for(RNA_property_collection_begin(sptr, RNA_struct_iterator_property(sptr->type), &rna_macro_iter); rna_macro_iter.valid; RNA_property_collection_next(&rna_macro_iter)) { \
+			PropertyRNA *prop= rna_macro_iter.ptr.data;
+
+#define RNA_STRUCT_END \
+		} \
+		RNA_property_collection_end(&rna_macro_iter); \
+	}
+
 /* check if the idproperty exists, for operators */
 int RNA_property_is_set(PointerRNA *ptr, const char *name);
 
diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h
index 91669616d89..85a148be2e2 100644
--- a/source/blender/makesrna/RNA_define.h
+++ b/source/blender/makesrna/RNA_define.h
@@ -1,5 +1,5 @@
 /**
- * $Id: RNA_define.h 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -80,7 +80,7 @@ PropertyRNA *RNA_def_string(StructOrFunctionRNA *cont, const char *identifier, c
 PropertyRNA *RNA_def_string_file_path(StructOrFunctionRNA *cont, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description);
 PropertyRNA *RNA_def_string_dir_path(StructOrFunctionRNA *cont, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description);
 
-PropertyRNA *RNA_def_enum(StructOrFunctionRNA *cont, const char *identifier, EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description);
+PropertyRNA *RNA_def_enum(StructOrFunctionRNA *cont, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description);
 
 PropertyRNA *RNA_def_float(StructOrFunctionRNA *cont, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax);
 PropertyRNA *RNA_def_float_vector(StructOrFunctionRNA *cont, const char *identifier, int len, const float *default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax);
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 841b397f276..276f421c586 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -1,5 +1,5 @@
 /**
- * $Id: RNA_enum_types.h 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -40,6 +40,9 @@ extern EnumPropertyItem beztriple_interpolation_mode_items[];
 
 extern EnumPropertyItem fmodifier_type_items[];
 
+extern EnumPropertyItem event_value_items[];
+extern EnumPropertyItem event_type_items[];
+
 #endif /* RNA_ENUM_TYPES */
 
 
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index a0fa2cc3344..923191cba78 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -1,5 +1,5 @@
 /**
- * $Id: RNA_types.h 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -110,7 +110,9 @@ typedef enum PropertyFlag {
 	PROP_BUILTIN = 128,
 	PROP_EXPORT = 256,
 	PROP_RUNTIME = 512,
-	PROP_IDPROPERTY = 1024
+	PROP_IDPROPERTY = 1024,
+	PROP_RAW_ACCESS = 8192,
+	PROP_RAW_ARRAY = 16384,
 } PropertyFlag;
 
 typedef struct CollectionPropertyIterator {
@@ -132,6 +134,21 @@ typedef struct CollectionPointerLink {
 	PointerRNA ptr;
 } CollectionPointerLink;
 
+typedef enum RawPropertyType {
+	PROP_RAW_CHAR,
+	PROP_RAW_SHORT,
+	PROP_RAW_INT,
+	PROP_RAW_FLOAT,
+	PROP_RAW_DOUBLE
+} RawPropertyType;
+
+typedef struct RawArray {
+	void *array;
+	RawPropertyType type;
+	int len;
+	int stride;
+} RawArray;
+
 /* Iterator Utility */
 
 typedef struct EnumPropertyItem {
diff --git a/source/blender/makesrna/intern/Makefile b/source/blender/makesrna/intern/Makefile
index 03f75f0bea6..1694e55ed4c 100644
--- a/source/blender/makesrna/intern/Makefile
+++ b/source/blender/makesrna/intern/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile 13161 2008-01-07 19:13:47Z hos $
+# $Id$
 #
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 1db61a842e5..c42bc866f99 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -1,5 +1,5 @@
 /**
- * $Id: makesrna.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -36,7 +36,7 @@
 
 #include "rna_internal.h"
 
-#define RNA_VERSION_DATE "$Id: makesrna.c 21247 2009-06-29 21:50:53Z jaguarandi $"
+#define RNA_VERSION_DATE "$Id$"
 
 #ifdef _WIN32
 #ifndef snprintf
@@ -248,8 +248,7 @@ static const char *rna_parameter_type_name(PropertyRNA *parm)
 				return rna_find_dna_type((const char *)pparm->type);
 		}
 		case PROP_COLLECTION: {
-			CollectionPropertyRNA *cparm= (CollectionPropertyRNA*)parm;
-			return rna_find_dna_type((const char *)cparm->type);
+			return "ListBase";
 		}
 		default:
 			return "";
@@ -763,6 +762,42 @@ static char *rna_def_property_end_func(FILE *f, StructRNA *srna, PropertyRNA *pr
 	return func;
 }
 
+static void rna_set_raw_property(PropertyDefRNA *dp, PropertyRNA *prop)
+{
+	if(dp->dnapointerlevel != 0)
+		return;
+	if(!dp->dnatype || !dp->dnaname || !dp->dnastructname)
+		return;
+	
+	if(strcmp(dp->dnatype, "char") == 0) {
+		prop->rawtype= PROP_RAW_CHAR;
+		prop->flag |= PROP_RAW_ACCESS;
+	}
+	else if(strcmp(dp->dnatype, "short") == 0) {
+		prop->rawtype= PROP_RAW_SHORT;
+		prop->flag |= PROP_RAW_ACCESS;
+	}
+	else if(strcmp(dp->dnatype, "int") == 0) {
+		prop->rawtype= PROP_RAW_INT;
+		prop->flag |= PROP_RAW_ACCESS;
+	}
+	else if(strcmp(dp->dnatype, "float") == 0) {
+		prop->rawtype= PROP_RAW_FLOAT;
+		prop->flag |= PROP_RAW_ACCESS;
+	}
+	else if(strcmp(dp->dnatype, "double") == 0) {
+		prop->rawtype= PROP_RAW_DOUBLE;
+		prop->flag |= PROP_RAW_ACCESS;
+	}
+}
+
+static void rna_set_raw_offset(FILE *f, StructRNA *srna, PropertyRNA *prop)
+{
+	PropertyDefRNA *dp= rna_find_struct_property_def(srna, prop);
+
+	fprintf(f, "\toffsetof(%s, %s), %d", dp->dnastructname, dp->dnaname, prop->rawtype);
+}
+
 static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
 {
 	PropertyRNA *prop;
@@ -774,6 +809,9 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
 			BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
 
 			if(!prop->arraylength) {
+				if(!bprop->get && !bprop->set && !dp->booleanbit)
+					rna_set_raw_property(dp, prop);
+
 				bprop->get= (void*)rna_def_property_get_func(f, srna, prop, dp, (char*)bprop->get);
 				bprop->set= (void*)rna_def_property_set_func(f, srna, prop, dp, (char*)bprop->set);
 			}
@@ -787,10 +825,16 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
 			IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
 
 			if(!prop->arraylength) {
+				if(!iprop->get && !iprop->set)
+					rna_set_raw_property(dp, prop);
+
 				iprop->get= (void*)rna_def_property_get_func(f, srna, prop, dp, (char*)iprop->get);
 				iprop->set= (void*)rna_def_property_set_func(f, srna, prop, dp, (char*)iprop->set);
 			}
 			else {
+				if(!iprop->getarray && !iprop->setarray)
+					rna_set_raw_property(dp, prop);
+
 				iprop->getarray= (void*)rna_def_property_get_func(f, srna, prop, dp, (char*)iprop->getarray);
 				iprop->setarray= (void*)rna_def_property_set_func(f, srna, prop, dp, (char*)iprop->setarray);
 			}
@@ -800,10 +844,16 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
 			FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
 
 			if(!prop->arraylength) {
+				if(!fprop->get && !fprop->set)
+					rna_set_raw_property(dp, prop);
+
 				fprop->get= (void*)rna_def_property_get_func(f, srna, prop, dp, (char*)fprop->get);
 				fprop->set= (void*)rna_def_property_set_func(f, srna, prop, dp, (char*)fprop->set);
 			}
 			else {
+				if(!fprop->getarray && !fprop->setarray)
+					rna_set_raw_property(dp, prop);
+
 				fprop->getarray= (void*)rna_def_property_get_func(f, srna, prop, dp, (char*)fprop->getarray);
 				fprop->setarray= (void*)rna_def_property_set_func(f, srna, prop, dp, (char*)fprop->setarray);
 			}
@@ -842,6 +892,13 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
 			else if(dp->dnalengthname || dp->dnalengthfixed)
 				cprop->length= (void*)rna_def_property_length_func(f, srna, prop, dp, (char*)cprop->length);
 
+			/* test if we can allow raw array access, if it is using our standard
+			 * array get/next function, we can be sure it is an actual array */
+			if(cprop->next && cprop->get)
+				if(strcmp((char*)cprop->next, "rna_iterator_array_next") == 0 &&
+				   strcmp((char*)cprop->get, "rna_iterator_array_get") == 0)
+					prop->flag |= PROP_RAW_ARRAY;
+
 			cprop->get= (void*)rna_def_property_get_func(f, srna, prop, dp, (char*)cprop->get);
 			cprop->begin= (void*)rna_def_property_begin_func(f, srna, prop, dp, (char*)cprop->begin);
 			cprop->next= (void*)rna_def_property_next_func(f, srna, prop, dp, (char*)cprop->next);
@@ -1116,9 +1173,11 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
 
 	funcname= rna_alloc_function_name(srna->identifier, func->identifier, "call");
 
+	/* function definition */
 	fprintf(f, "void %s(bContext *C, ReportList *reports, PointerRNA *_ptr, ParameterList *_parms)", funcname);
 	fprintf(f, "\n{\n");
 
+	/* variable definitions */
 	if((func->flag & FUNC_NO_SELF)==0) {
 		if(dsrna->dnaname) fprintf(f, "\tstruct %s *_self;\n", dsrna->dnaname);
 		else fprintf(f, "\tstruct %s *_self;\n", srna->identifier);
@@ -1135,6 +1194,7 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
 	fprintf(f, ";\n");
 	fprintf(f, "\t\n");
 
+	/* assign self */
 	if((func->flag & FUNC_NO_SELF)==0) {
 		if(dsrna->dnaname) fprintf(f, "\t_self= (struct %s *)_ptr->data;\n", dsrna->dnaname);
 		else fprintf(f, "\t_self= (struct %s *)_ptr->data;\n", srna->identifier);
@@ -1405,6 +1465,7 @@ static void rna_generate_static_parameter_prototypes(BlenderRNA *brna, StructRNA
 	dsrna= rna_find_struct_def(srna);
 	func= dfunc->func;
 
+	/* return type */
 	for(dparm= dfunc->cont.properties.first; dparm; dparm= dparm->next) {
 		if(dparm->prop==func->ret) {
 			if(dparm->prop->arraylength)
@@ -1418,13 +1479,16 @@ static void rna_generate_static_parameter_prototypes(BlenderRNA *brna, StructRNA
 		}
 	}
 
+	/* void if nothing to return */
 	if(!dparm)
 		fprintf(f, "void ");
 
+	/* function name */
 	fprintf(f, "%s(", dfunc->call);
 
 	first= 1;
 
+	/* self, context and reports parameters */
 	if((func->flag & FUNC_NO_SELF)==0) {
 		if(dsrna->dnaname) fprintf(f, "struct %s *_self", dsrna->dnaname);
 		else fprintf(f, "struct %s *_self", srna->identifier);
@@ -1443,6 +1507,7 @@ static void rna_generate_static_parameter_prototypes(BlenderRNA *brna, StructRNA
 		fprintf(f, "ReportList *reports");
 	}
 
+	/* defined parameters */
 	for(dparm= dfunc->cont.properties.first; dparm; dparm= dparm->next) {
 		if(dparm->prop==func->ret)
 			continue;
@@ -1531,7 +1596,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
 					DefRNA.error= 1;
 				}
 				break;
-											}
+			}
 			case PROP_BOOLEAN: {
 				BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
 				unsigned int i;
@@ -1551,7 +1616,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
 					fprintf(f, "};\n\n");
 				}
 				break;
-												 }
+			}
 			case PROP_INT: {
 				IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
 				unsigned int i;
@@ -1571,7 +1636,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
 					fprintf(f, "};\n\n");
 				}
 				break;
-										 }
+			}
 			case PROP_FLOAT: {
 				FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
 				unsigned int i;
@@ -1591,7 +1656,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
 					fprintf(f, "};\n\n");
 				}
 				break;
-											 }
+			}
 			default:
 				break;
 	}
@@ -1606,10 +1671,14 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
 	rna_print_c_string(f, prop->identifier);
 	fprintf(f, ", %d, ", prop->flag);
 	rna_print_c_string(f, prop->name); fprintf(f, ",\n\t");
-	rna_print_c_string(f, prop->description); fprintf(f, ",\n");
-	fprintf(f, "%d, ", prop->icon);
+	rna_print_c_string(f, prop->description); fprintf(f, ",\n\t");
+	fprintf(f, "%d,\n", prop->icon);
 	fprintf(f, "\t%s, %s, %d,\n", rna_property_typename(prop->type), rna_property_subtypename(prop->subtype), prop->arraylength);
-	fprintf(f, "\t%s, %d, %s},\n", rna_function_string(prop->update), prop->noteflag, rna_function_string(prop->editable));
+	fprintf(f, "\t%s, %d, %s,\n", rna_function_string(prop->update), prop->noteflag, rna_function_string(prop->editable));
+
+	if(prop->flag & PROP_RAW_ACCESS) rna_set_raw_offset(f, srna, prop);
+	else fprintf(f, "\t0, 0");
+	fprintf(f, "},\n");
 
 	switch(prop->type) {
 			case PROP_BOOLEAN: {
@@ -1618,7 +1687,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
 				if(prop->arraylength) fprintf(f, "rna_%s%s_%s_default\n", srna->identifier, strnest, prop->identifier);
 				else fprintf(f, "NULL\n");
 				break;
-												 }
+			}
 			case PROP_INT: {
 				IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
 				fprintf(f, "\t%s, %s, %s, %s, %s,\n\t", rna_function_string(iprop->get), rna_function_string(iprop->set), rna_function_string(iprop->getarray), rna_function_string(iprop->setarray), rna_function_string(iprop->range));
@@ -1631,7 +1700,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
 				if(prop->arraylength) fprintf(f, "rna_%s%s_%s_default\n", srna->identifier, strnest, prop->identifier);
 				else fprintf(f, "NULL\n");
 				break;
-										 }
+			 }
 			case PROP_FLOAT: {
 				FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
 				fprintf(f, "\t%s, %s, %s, %s, %s, ", rna_function_string(fprop->get), rna_function_string(fprop->set), rna_function_string(fprop->getarray), rna_function_string(fprop->setarray), rna_function_string(fprop->range));
@@ -1645,13 +1714,13 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
 				if(prop->arraylength) fprintf(f, "rna_%s%s_%s_default\n", srna->identifier, strnest, prop->identifier);
 				else fprintf(f, "NULL\n");
 				break;
-											 }
+			 }
 			case PROP_STRING: {
 				StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
 				fprintf(f, "\t%s, %s, %s, %d, ", rna_function_string(sprop->get), rna_function_string(sprop->length), rna_function_string(sprop->set), sprop->maxlength);
 				rna_print_c_string(f, sprop->defaultvalue); fprintf(f, "\n");
 				break;
-												}
+			}
 			case PROP_ENUM: {
 				EnumPropertyRNA *eprop= (EnumPropertyRNA*)prop;
 				fprintf(f, "\t%s, %s, %s, ", rna_function_string(eprop->get), rna_function_string(eprop->set), rna_function_string(eprop->itemf));
@@ -1661,14 +1730,14 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
 					fprintf(f, "NULL, ");
 				fprintf(f, "%d, %d\n", eprop->totitem, eprop->defaultvalue);
 				break;
-											}
+			}
 			case PROP_POINTER: {
 				PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop;
 				fprintf(f, "\t%s, %s, %s, ", rna_function_string(pprop->get), rna_function_string(pprop->set), rna_function_string(pprop->typef));
 				if(pprop->type) fprintf(f, "&RNA_%s\n", (char*)pprop->type);
 				else fprintf(f, "NULL\n");
 				break;
-												 }
+			 }
 			case PROP_COLLECTION: {
 				CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
 				fprintf(f, "\t%s, %s, %s, %s, %s, %s, %s, ", rna_function_string(cprop->begin), rna_function_string(cprop->next), rna_function_string(cprop->end), rna_function_string(cprop->get), rna_function_string(cprop->length), rna_function_string(cprop->lookupint), rna_function_string(cprop->lookupstring));
@@ -1853,7 +1922,6 @@ RNAProcessItem PROCESS_ITEMS[]= {
 	{"rna_particle.c", NULL, RNA_def_particle},
 	{"rna_pose.c", NULL, RNA_def_pose},
 	{"rna_property.c", NULL, RNA_def_gameproperty},
-	{"rna_radio.c", NULL, RNA_def_radio},
 	{"rna_scene.c", NULL, RNA_def_scene},
 	{"rna_screen.c", NULL, RNA_def_screen},
 	{"rna_scriptlink.c", NULL, RNA_def_scriptlink},
@@ -1884,6 +1952,7 @@ static void rna_generate(BlenderRNA *brna, FILE *f, char *filename, char *api_fi
 	fprintf(f, "#include \n");
 	fprintf(f, "#include \n");
 	fprintf(f, "#include \n\n");
+	fprintf(f, "#include \n\n");
 
 	fprintf(f, "#include \"DNA_ID.h\"\n");
 
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index e70cd6ff8d3..7d8bab8bee8 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_ID.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 3073029d9b4..cc8704dc350 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_access.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -426,23 +426,16 @@ PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
 /* Find the property which uses the given nested struct */
 PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna)
 {
-	CollectionPropertyIterator iter;
-	PropertyRNA *iterprop, *prop;
-	int i = 0;
+	PropertyRNA *prop= NULL;
 
-	iterprop= RNA_struct_iterator_property(ptr->type);
-	RNA_property_collection_begin(ptr, iterprop, &iter);
-	prop= NULL;
-
-	for(; iter.valid; RNA_property_collection_next(&iter), i++) {
+	RNA_STRUCT_BEGIN(ptr, iprop) {
 		/* This assumes that there can only be one user of this nested struct */
-		if (RNA_property_pointer_type(ptr, iter.ptr.data) == srna) {
-			prop= iter.ptr.data;
+		if (RNA_property_pointer_type(ptr, iprop) == srna) {
+			prop= iprop;
 			break;
 		}
 	}
-
-	RNA_property_collection_end(&iter);
+	RNA_PROP_END;
 
 	return prop;
 }
@@ -455,25 +448,21 @@ const struct ListBase *RNA_struct_defined_properties(StructRNA *srna)
 FunctionRNA *RNA_struct_find_function(PointerRNA *ptr, const char *identifier)
 {
 	PointerRNA tptr;
-	CollectionPropertyIterator iter;
 	PropertyRNA *iterprop;
 	FunctionRNA *func;
-	int i = 0;
 
 	RNA_pointer_create(NULL, &RNA_Struct, ptr->type, &tptr);
 	iterprop= RNA_struct_find_property(&tptr, "functions");
 
-	RNA_property_collection_begin(&tptr, iterprop, &iter);
 	func= NULL;
 
-	for(; iter.valid; RNA_property_collection_next(&iter), i++) {
-		if(strcmp(identifier, RNA_function_identifier(iter.ptr.data)) == 0) {
-			func= iter.ptr.data;
+	RNA_PROP_BEGIN(&tptr, funcptr, iterprop) {
+		if(strcmp(identifier, RNA_function_identifier(funcptr.data)) == 0) {
+			func= funcptr.data;
 			break;
 		}
 	}
-
-	RNA_property_collection_end(&iter);
+	RNA_PROP_END;
 
 	return func;
 }
@@ -518,6 +507,16 @@ void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type)
 	srna->blender_type= blender_type;
 }
 
+char *RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen)
+{
+	PropertyRNA *nameprop;
+
+	if(ptr->data && (nameprop = RNA_struct_name_property(ptr->type)))
+		return RNA_property_string_get_alloc(ptr, nameprop, fixedbuf, fixedlen);
+
+	return NULL;
+}
+
 /* Property Information */
 
 const char *RNA_property_identifier(PropertyRNA *prop)
@@ -643,25 +642,27 @@ void RNA_property_enum_items(PointerRNA *ptr, PropertyRNA *prop, const EnumPrope
 
 	if(eprop->itemf) {
 		*item= eprop->itemf(ptr);
-		for(tot=0; (*item)[tot].identifier; tot++);
-		*totitem= tot;
+		if(totitem) {
+			for(tot=0; (*item)[tot].identifier; tot++);
+			*totitem= tot;
+		}
 	}
 	else {
 		*item= eprop->item;
-		*totitem= eprop->totitem;
+		if(totitem)
+			*totitem= eprop->totitem;
 	}
 }
 
 int RNA_property_enum_value(PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *value)
 {	
 	const EnumPropertyItem *item;
-	int totitem, i;
 	
-	RNA_property_enum_items(ptr, prop, &item, &totitem);
+	RNA_property_enum_items(ptr, prop, &item, NULL);
 	
-	for(i=0; iidentifier; item++) {
+		if(strcmp(item->identifier, identifier)==0) {
+			*value = item->value;
 			return 1;
 		}
 	}
@@ -669,23 +670,36 @@ int RNA_property_enum_value(PointerRNA *ptr, PropertyRNA *prop, const char *iden
 	return 0;
 }
 
-int RNA_property_enum_identifier(PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier)
-{	
-	const EnumPropertyItem *item;
-	int totitem, i;
-	
-	RNA_property_enum_items(ptr, prop, &item, &totitem);
-	
-	for(i=0; iidentifier; item++) {
+		if(item->value==value) {
+			*identifier = item->identifier;
 			return 1;
 		}
 	}
-	
 	return 0;
 }
 
+int RNA_enum_name(const EnumPropertyItem *item, const int value, const char **name)
+{
+	for (; item->identifier; item++) {
+		if(item->value==value) {
+			*name = item->name;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+int RNA_property_enum_identifier(PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier)
+{	
+	const EnumPropertyItem *item= NULL;
+	
+	RNA_property_enum_items(ptr, prop, &item, NULL);
+	return RNA_enum_identifier(item, value, identifier);
+}
+
 const char *RNA_property_ui_name(PropertyRNA *prop)
 {
 	return rna_ensure_property_name(prop);
@@ -1508,6 +1522,323 @@ int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, co
 	}
 }
 
+int RNA_property_collection_raw_array(PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, RawArray *array)
+{
+	CollectionPropertyIterator iter;
+	ArrayIterator *internal;
+	char *arrayp;
+
+	if(!(prop->flag & PROP_RAW_ARRAY) || !(itemprop->flag & PROP_RAW_ACCESS))
+		return 0;
+
+	RNA_property_collection_begin(ptr, prop, &iter);
+
+	if(iter.valid) {
+		/* get data from array iterator and item property */
+		internal= iter.internal;
+		arrayp= (iter.valid)? iter.ptr.data: NULL;
+
+		if(internal->skip || !RNA_property_editable(&iter.ptr, itemprop)) {
+			/* we might skip some items, so it's not a proper array */
+			RNA_property_collection_end(&iter);
+			return 0;
+		}
+
+		array->array= arrayp + itemprop->rawoffset;
+		array->stride= internal->itemsize;
+		array->len= ((char*)internal->endptr - arrayp)/internal->itemsize;
+		array->type= itemprop->rawtype;
+	}
+	else
+		memset(array, 0, sizeof(RawArray));
+
+	RNA_property_collection_end(&iter);
+
+	return 1;
+}
+
+#define RAW_GET(dtype, var, raw, a) \
+{ \
+	switch(raw.type) { \
+		case PROP_RAW_CHAR: var = (dtype)((char*)raw.array)[a]; break; \
+		case PROP_RAW_SHORT: var = (dtype)((short*)raw.array)[a]; break; \
+		case PROP_RAW_INT: var = (dtype)((int*)raw.array)[a]; break; \
+		case PROP_RAW_FLOAT: var = (dtype)((float*)raw.array)[a]; break; \
+		case PROP_RAW_DOUBLE: var = (dtype)((double*)raw.array)[a]; break; \
+		default: var = (dtype)0; \
+	} \
+}
+
+#define RAW_SET(dtype, raw, a, var) \
+{ \
+	switch(raw.type) { \
+		case PROP_RAW_CHAR: ((char*)raw.array)[a] = (char)var; break; \
+		case PROP_RAW_SHORT: ((short*)raw.array)[a] = (short)var; break; \
+		case PROP_RAW_INT: ((int*)raw.array)[a] = (int)var; break; \
+		case PROP_RAW_FLOAT: ((float*)raw.array)[a] = (float)var; break; \
+		case PROP_RAW_DOUBLE: ((double*)raw.array)[a] = (double)var; break; \
+	} \
+}
+
+int RNA_raw_type_sizeof(RawPropertyType type)
+{
+	switch(type) {
+		case PROP_RAW_CHAR: return sizeof(char);
+		case PROP_RAW_SHORT: return sizeof(short);
+		case PROP_RAW_INT: return sizeof(int);
+		case PROP_RAW_FLOAT: return sizeof(float);
+		case PROP_RAW_DOUBLE: return sizeof(double);
+		default: return 0;
+	}
+}
+
+static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *inarray, RawPropertyType intype, int inlen, int set)
+{
+	StructRNA *ptype;
+	PointerRNA itemptr;
+	PropertyRNA *itemprop, *iprop;
+	PropertyType itemtype;
+	RawArray in;
+	int itemlen= 0;
+
+	/* initialize in array, stride assumed 0 in following code */
+	in.array= inarray;
+	in.type= intype;
+	in.len= inlen;
+	in.stride= 0;
+
+	ptype= RNA_property_pointer_type(ptr, prop);
+
+	/* try to get item property pointer */
+	RNA_pointer_create(NULL, ptype, NULL, &itemptr);
+	itemprop= RNA_struct_find_property(&itemptr, propname);
+
+	if(itemprop) {
+		/* we have item property pointer */
+		RawArray out;
+
+		/* check type */
+		itemtype= RNA_property_type(itemprop);
+
+		if(!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
+			BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported.");
+			return 0;
+		}
+
+		/* check item array */
+		itemlen= RNA_property_array_length(itemprop);
+
+		/* try to access as raw array */
+		if(RNA_property_collection_raw_array(ptr, prop, itemprop, &out)) {
+			if(in.len != itemlen*out.len) {
+				BKE_reportf(reports, RPT_ERROR, "Array length mismatch (expected %d, got %d).", out.len*itemlen, in.len);
+				return 0;
+			}
+			
+			/* matching raw types */
+			if(out.type == in.type) {
+				void *inp= in.array;
+				void *outp= out.array;
+				int a, size;
+
+				itemlen= (itemlen == 0)? 1: itemlen;
+				size= RNA_raw_type_sizeof(out.type) * itemlen;
+
+				for(a=0; a in.len) {
+						BKE_reportf(reports, RPT_ERROR, "Array length mismatch (got %d, expected more).", in.len);
+						err= 1;
+						break;
+					}
+
+					if(itemlen == 0) {
+						/* handle conversions */
+						if(set) {
+							switch(itemtype) {
+								case PROP_BOOLEAN: {
+									int b;
+									RAW_GET(int, b, in, a);
+									RNA_property_boolean_set(&itemptr, iprop, b);
+									break;
+								}
+								case PROP_INT: {
+									int i;
+									RAW_GET(int, i, in, a);
+									RNA_property_int_set(&itemptr, iprop, i);
+									break;
+								}
+								case PROP_FLOAT: {
+									float f;
+									RAW_GET(float, f, in, a);
+									RNA_property_float_set(&itemptr, iprop, f);
+									break;
+								}
+								default:
+									break;
+							}
+						}
+						else {
+							switch(itemtype) {
+								case PROP_BOOLEAN: {
+									int b= RNA_property_boolean_get(&itemptr, iprop);
+									RAW_SET(int, in, a, b);
+									break;
+								}
+								case PROP_INT: {
+									int i= RNA_property_int_get(&itemptr, iprop);
+									RAW_SET(int, in, a, i);
+									break;
+								}
+								case PROP_FLOAT: {
+									float f= RNA_property_float_get(&itemptr, iprop);
+									RAW_SET(float, in, a, f);
+									break;
+								}
+								default:
+									break;
+							}
+						}
+						a++;
+					}
+					else {
+						/* allocate temporary array if needed */
+						if(tmparray && tmplen != itemlen) {
+							MEM_freeN(tmparray);
+							tmparray= NULL;
+						}
+						if(!tmparray) {
+							tmparray= MEM_callocN(sizeof(float)*itemlen, "RNA tmparray\n");
+							tmplen= itemlen;
+						}
+
+						/* handle conversions */
+						if(set) {
+							switch(itemtype) {
+								case PROP_BOOLEAN: {
+									for(j=0; jrawtype;
+}
+
+int RNA_property_collection_raw_get(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *array, RawPropertyType type, int len)
+{
+	return rna_raw_access(reports, ptr, prop, propname, array, type, len, 0);
+}
+
+int RNA_property_collection_raw_set(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *array, RawPropertyType type, int len)
+{
+	return rna_raw_access(reports, ptr, prop, propname, array, type, len, 1);
+}
+
 /* Standard iterator functions */
 
 void rna_iterator_listbase_begin(CollectionPropertyIterator *iter, ListBase *lb, IteratorSkipFunc skip)
@@ -2052,14 +2383,13 @@ int RNA_enum_is_equal(PointerRNA *ptr, const char *name, const char *enumname)
 {
 	PropertyRNA *prop= RNA_struct_find_property(ptr, name);
 	const EnumPropertyItem *item;
-	int a, totitem;
 
 	if(prop) {
-		RNA_property_enum_items(ptr, prop, &item, &totitem);
+		RNA_property_enum_items(ptr, prop, &item, NULL);
 
-		for(a=0; aidentifier; item++)
+			if(strcmp(item->identifier, enumname) == 0)
+				return (item->value == RNA_property_enum_get(ptr, prop));
 
 		printf("RNA_enum_is_equal: %s.%s item %s not found.\n", ptr->type->identifier, name, enumname);
 		return 0;
@@ -2232,17 +2562,12 @@ char *RNA_pointer_as_string(PointerRNA *ptr)
 	DynStr *dynstr= BLI_dynstr_new();
 	char *cstring;
 	
-	PropertyRNA *prop, *iterprop;
-	CollectionPropertyIterator iter;
 	const char *propname;
 	int first_time = 1;
 	
 	BLI_dynstr_append(dynstr, "{");
 	
-	iterprop= RNA_struct_iterator_property(ptr->type);
-
-	for(RNA_property_collection_begin(ptr, iterprop, &iter); iter.valid; RNA_property_collection_next(&iter)) {
-		prop= iter.ptr.data;
+	RNA_STRUCT_BEGIN(ptr, prop) {
 		propname = RNA_property_identifier(prop);
 		
 		if(strcmp(propname, "rna_type")==0)
@@ -2256,8 +2581,8 @@ char *RNA_pointer_as_string(PointerRNA *ptr)
 		BLI_dynstr_appendf(dynstr, "\"%s\":%s", propname, cstring);
 		MEM_freeN(cstring);
 	}
+	RNA_STRUCT_END;
 
-	RNA_property_collection_end(&iter);
 	BLI_dynstr_append(dynstr, "}");	
 	
 	
@@ -2449,6 +2774,17 @@ ParameterList *RNA_parameter_list_create(PointerRNA *ptr, FunctionRNA *func)
 
 void RNA_parameter_list_free(ParameterList *parms)
 {
+	PropertyRNA *parm;
+	int tot;
+
+	parm= parms->func->cont.properties.first;
+	for(tot= 0; parm; parm= parm->next) {
+		if(parm->type == PROP_COLLECTION)
+			BLI_freelistN((ListBase*)((char*)parms->data+tot));
+
+		tot+= rna_parameter_size(parm);
+	}
+
 	MEM_freeN(parms->data);
 	parms->data= NULL;
 
@@ -2714,23 +3050,46 @@ static int rna_function_parameter_parse(PointerRNA *ptr, PropertyRNA *prop, Prop
 
 			if(prop->flag & PROP_RNAPTR) {
 				*((PointerRNA*)dest)= *((PointerRNA*)src);
+				break;
+ 			}
+			
+			if (ptype!=srna && !RNA_struct_is_a(srna, ptype)) {
+				fprintf(stderr, "%s.%s: wrong type for parameter %s, an object of type %s was expected, passed an object of type %s\n", tid, fid, pid, RNA_struct_identifier(ptype), RNA_struct_identifier(srna));
+				return -1;
 			}
-			else if (ptype!=srna) {
-				if (!RNA_struct_is_a(srna, ptype)) {
-					fprintf(stderr, "%s.%s: wrong type for parameter %s, an object of type %s was expected, passed an object of type %s\n", tid, fid, pid, RNA_struct_identifier(ptype), RNA_struct_identifier(ptype));
-					return -1;
-				}
-
-				*((void**)dest)= *((void**)src);
-			}
+ 
+			*((void**)dest)= *((void**)src);
 
 			break;
 		}
 	case PROP_COLLECTION:
 		{
-			/* XXX collections are not supported yet */
-			fprintf(stderr, "%s.%s: for parameter %s, collections are not supported yet\n", tid, fid, pid);
-			return -1;
+			StructRNA *ptype;
+			ListBase *lb, *clb;
+			Link *link;
+			CollectionPointerLink *clink;
+
+			if (ftype!='C') {
+				fprintf(stderr, "%s.%s: wrong type for parameter %s, a collection was expected\n", tid, fid, pid);
+				return -1;
+			}
+
+			lb= (ListBase *)src;
+			clb= (ListBase *)dest;
+			ptype= RNA_property_pointer_type(ptr, prop);
+			
+			if (ptype!=srna && !RNA_struct_is_a(srna, ptype)) {
+				fprintf(stderr, "%s.%s: wrong type for parameter %s, a collection of objects of type %s was expected, passed a collection of objects of type %s\n", tid, fid, pid, RNA_struct_identifier(ptype), RNA_struct_identifier(srna));
+				return -1;
+			}
+
+			for (link= lb->first; link; link= link->next) {
+				clink= MEM_callocN(sizeof(CollectionPointerLink), "CCollectionPointerLink");
+				RNA_pointer_create(NULL, srna, link, &clink->ptr);
+				BLI_addtail(clb, clink);
+			}
+
+			break;
 		}
 	default: 
 		{
@@ -2828,6 +3187,13 @@ int RNA_function_call_direct_va(bContext *C, ReportList *reports, PointerRNA *pt
 				err= rna_function_parameter_parse(&funcptr, parm, type, ftype, len, iter.data, &arg, srna, tid, fid, pid);
 				break;
 			}
+		case PROP_COLLECTION:
+			{
+				StructRNA *srna= va_arg(args, StructRNA*);
+				ListBase *arg= va_arg(args, ListBase*);
+				err= rna_function_parameter_parse(&funcptr, parm, type, ftype, len, iter.data, &arg, srna, tid, fid, pid);
+				break;
+			}
 		default:
 			{
 				/* handle errors */
@@ -2885,6 +3251,13 @@ int RNA_function_call_direct_va(bContext *C, ReportList *reports, PointerRNA *pt
 					err= rna_function_parameter_parse(&funcptr, parm, type, ftype, len, arg, retdata, srna, tid, fid, pid);
 					break;
 				}
+			case PROP_COLLECTION:
+				{
+					StructRNA *srna= va_arg(args, StructRNA*);
+					ListBase **arg= va_arg(args, ListBase**);
+					err= rna_function_parameter_parse(&funcptr, parm, type, ftype, len, arg, retdata, srna, tid, fid, pid);
+					break;
+				}			
 			default:
 				{
 					/* handle errors */
@@ -2913,3 +3286,4 @@ int RNA_function_call_direct_va_lookup(bContext *C, ReportList *reports, Pointer
 	return 0;
 }
 
+
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index 588c94380dc..3639d6d3fff 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_action.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c
index 05d55d284a7..3eb88e706e9 100644
--- a/source/blender/makesrna/intern/rna_actuator.c
+++ b/source/blender/makesrna/intern/rna_actuator.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_actuator.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index d119783766d..2ed47effec1 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_animation.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index 389257e9331..caa970eff57 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_armature.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -443,6 +443,30 @@ void rna_EditBone_tail_selected_set(PointerRNA *ptr, int value)
 	else data->flag &= ~BONE_TIPSEL;
 }
 
+static void rna_Armature_bones_next(CollectionPropertyIterator *iter)
+{
+	ListBaseIterator *internal= iter->internal;
+	Bone *bone= (Bone*)internal->link;
+
+	if(bone->childbase.first)
+		internal->link= (Link*)bone->childbase.first;
+	else if(bone->next)
+		internal->link= (Link*)bone->next;
+	else {
+		internal->link= NULL;
+
+		do {
+			bone= bone->parent;
+			if(bone && bone->next) {
+				internal->link= (Link*)bone->next;
+				break;
+			}
+		} while(bone);
+	}
+
+	iter->valid= (internal->link != NULL);
+}
+
 #else
 
 static void rna_def_bone_common(StructRNA *srna, int editbone)
@@ -660,6 +684,7 @@ void rna_def_armature(BlenderRNA *brna)
 	/* Collections */
 	prop= RNA_def_property(srna, "bones", PROP_COLLECTION, PROP_NONE);
 	RNA_def_property_collection_sdna(prop, NULL, "bonebase", NULL);
+	RNA_def_property_collection_funcs(prop, 0, "rna_Armature_bones_next", 0, 0, 0, 0, 0, 0, 0);
 	RNA_def_property_struct_type(prop, "Bone");
 	RNA_def_property_ui_text(prop, "Bones", "");
 
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index d3213c01846..7355261c5aa 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_brush.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -184,6 +184,10 @@ void rna_def_brush(BlenderRNA *brna)
 	prop= RNA_def_property(srna, "space", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_SPACE);
 	RNA_def_property_ui_text(prop, "Space", "Limit brush application to the distance specified by spacing.");
+
+	prop= RNA_def_property(srna, "smooth_stroke", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_SMOOTH_STROKE);
+	RNA_def_property_ui_text(prop, "Smooth Stroke", "Brush lags behind mouse and follows a smoother path.");
 	
 	/* not exposed in the interface yet
 	prop= RNA_def_property(srna, "fixed_tex", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c
index 928086b951c..4814f9583a9 100644
--- a/source/blender/makesrna/intern/rna_camera.c
+++ b/source/blender/makesrna/intern/rna_camera.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_camera.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c
index 7f61125bc11..cefd2316fbf 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_cloth.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -34,9 +34,24 @@
 #include "BKE_modifier.h"
 
 #include "DNA_cloth_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "WM_types.h"
 
 #ifdef RNA_RUNTIME
 
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+
+static void rna_cloth_update(bContext *C, PointerRNA *ptr)
+{
+	Scene *scene = CTX_data_scene(C);
+	Object *ob = ptr->id.data;
+
+	DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+}
+
 static void rna_ClothSettings_max_bend_set(struct PointerRNA *ptr, float value)
 {
 	ClothSimSettings *settings = (ClothSimSettings*)ptr->data;
@@ -165,42 +180,50 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
 	RNA_def_property_float_sdna(prop, NULL, "mingoal");
 	RNA_def_property_range(prop, 0.0f, 1.0f);
 	RNA_def_property_ui_text(prop, "Goal Minimum", "Goal minimum, vertex group weights are scaled to match this range.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	prop= RNA_def_property(srna, "goal_max", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_float_sdna(prop, NULL, "maxgoal");
 	RNA_def_property_range(prop, 0.0f, 1.0f);
 	RNA_def_property_ui_text(prop, "Goal Maximum", "Goal maximum, vertex group weights are scaled to match this range.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	prop= RNA_def_property(srna, "goal_default", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_float_sdna(prop, NULL, "defgoal");
 	RNA_def_property_range(prop, 0.0f, 1.0f);
 	RNA_def_property_ui_text(prop, "Goal Default", "Default Goal (vertex target position) value, when no Vertex Group used.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 	
 	prop= RNA_def_property(srna, "goal_spring", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_float_sdna(prop, NULL, "goalspring");
 	RNA_def_property_range(prop, 0.0f, 0.999f);
 	RNA_def_property_ui_text(prop, "Goal Stiffness", "Goal (vertex target position) spring stiffness.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 	
 	prop= RNA_def_property(srna, "goal_friction", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_float_sdna(prop, NULL, "goalfrict");
 	RNA_def_property_range(prop, 0.0f, 50.0f);
 	RNA_def_property_ui_text(prop, "Goal Damping", "Goal (vertex target position) friction.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	/* mass */
 
 	prop= RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_range(prop, 0.0f, 10.0f);
 	RNA_def_property_ui_text(prop, "Mass", "Mass of cloth material.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	prop= RNA_def_property(srna, "mass_vertex_group", PROP_STRING, PROP_NONE);
 	RNA_def_property_string_funcs(prop, "rna_ClothSettings_mass_vgroup_get", "rna_ClothSettings_mass_vgroup_length", "rna_ClothSettings_mass_vgroup_set");
 	RNA_def_property_ui_text(prop, "Mass Vertex Group", "Vertex group for fine control over mass distribution.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 	
 	prop= RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_VECTOR);
 	RNA_def_property_array(prop, 3);
 	RNA_def_property_range(prop, -100.0, 100.0);
 	RNA_def_property_float_funcs(prop, "rna_ClothSettings_gravity_get", "rna_ClothSettings_gravity_set", NULL);
 	RNA_def_property_ui_text(prop, "Gravity", "Gravity or external force vector.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	/* various */
 
@@ -208,61 +231,73 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
 	RNA_def_property_float_sdna(prop, NULL, "Cvi");
 	RNA_def_property_range(prop, 0.0f, 10.0f);
 	RNA_def_property_ui_text(prop, "Air Damping", "Air has normally some thickness which slows falling things down.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	prop= RNA_def_property(srna, "pin_cloth", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_GOAL);
 	RNA_def_property_ui_text(prop, "Pin Cloth", "Define forces for vertices to stick to animated position.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	prop= RNA_def_property(srna, "pin_stiffness", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_float_sdna(prop, NULL, "goalspring");
 	RNA_def_property_range(prop, 0.0f, 50.0);
 	RNA_def_property_ui_text(prop, "Pin Stiffness", "Pin (vertex target position) spring stiffness.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	prop= RNA_def_property(srna, "quality", PROP_INT, PROP_NONE);
 	RNA_def_property_int_sdna(prop, NULL, "stepsPerFrame");
 	RNA_def_property_range(prop, 4, 80);
 	RNA_def_property_ui_text(prop, "Quality", "Quality of the simulation in steps per frame (higher is better quality but slower).");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	/* springs */
 
 	prop= RNA_def_property(srna, "stiffness_scaling", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_SCALING);
 	RNA_def_property_ui_text(prop, "Stiffness Scaling", "If enabled, stiffness can be scaled along a weight painted vertex group.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 	
 	prop= RNA_def_property(srna, "spring_damping", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_float_sdna(prop, NULL, "Cdis");
 	RNA_def_property_range(prop, 0.0f, 50.0f);
 	RNA_def_property_ui_text(prop, "Spring Damping", "Damping of cloth velocity (higher = more smooth, less jiggling)");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 	
 	prop= RNA_def_property(srna, "structural_stiffness", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_float_sdna(prop, NULL, "structural");
 	RNA_def_property_range(prop, 1.0f, 10000.0f);
 	RNA_def_property_ui_text(prop, "Structural Stiffness", "Overall stiffness of structure.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	prop= RNA_def_property(srna, "structural_stiffness_max", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_float_sdna(prop, NULL, "max_struct");
 	RNA_def_property_range(prop, 0.0f, 10000.0f);
 	RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_struct_set", NULL);
 	RNA_def_property_ui_text(prop, "Structural Stiffness Maximum", "Maximum structural stiffness value.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	prop= RNA_def_property(srna, "structural_stiffness_vertex_group", PROP_STRING, PROP_NONE);
 	RNA_def_property_string_funcs(prop, "rna_ClothSettings_struct_vgroup_get", "rna_ClothSettings_struct_vgroup_length", "rna_ClothSettings_struct_vgroup_set");
 	RNA_def_property_ui_text(prop, "Structural Stiffness Vertex Group", "Vertex group for fine control over structural stiffness.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	prop= RNA_def_property(srna, "bending_stiffness", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_float_sdna(prop, NULL, "bending");
 	RNA_def_property_range(prop, 0.0f, 10000.0f);
 	RNA_def_property_ui_text(prop, "Bending Stiffness", "Wrinkle coefficient (higher = less smaller but more big wrinkles).");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	prop= RNA_def_property(srna, "bending_stiffness_max", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_float_sdna(prop, NULL, "max_bend");
 	RNA_def_property_range(prop, 0.0f, 10000.0f);
 	RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_bend_set", NULL);
 	RNA_def_property_ui_text(prop, "Bending Stiffness Maximum", "Maximum bending stiffness value.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	prop= RNA_def_property(srna, "bending_vertex_group", PROP_STRING, PROP_NONE);
 	RNA_def_property_string_funcs(prop, "rna_ClothSettings_bend_vgroup_get", "rna_ClothSettings_bend_vgroup_length", "rna_ClothSettings_bend_vgroup_set");
 	RNA_def_property_ui_text(prop, "Bending Stiffness Vertex Group", "Vertex group for fine control over bending stiffness.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	/* unused */
 
@@ -323,40 +358,48 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna)
 	prop= RNA_def_property(srna, "enable_collision", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_COLLSETTINGS_FLAG_ENABLED);
 	RNA_def_property_ui_text(prop, "Enable Collision", "Enable collisions with other objects.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 	
 	prop= RNA_def_property(srna, "min_distance", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_float_sdna(prop, NULL, "epsilon");
 	RNA_def_property_range(prop, 0.001f, 1.0f);
 	RNA_def_property_ui_text(prop, "Minimum Distance", "Minimum distance between collision objects before collision response takes in, can be changed for each frame.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	prop= RNA_def_property(srna, "friction", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_range(prop, 0.0f, 80.0f);
 	RNA_def_property_ui_text(prop, "Friction", "Friction force if a collision happened (0=movement not changed, 100=no movement left)");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	prop= RNA_def_property(srna, "collision_quality", PROP_INT, PROP_NONE);
 	RNA_def_property_int_sdna(prop, NULL, "loop_count");
 	RNA_def_property_range(prop, 1, 20);
 	RNA_def_property_ui_text(prop, "Collision Quality", "How many collision iterations should be done. (higher is better quality but slower)");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	/* self collision */
 
 	prop= RNA_def_property(srna, "enable_self_collision", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_COLLSETTINGS_FLAG_SELF);
 	RNA_def_property_ui_text(prop, "Enable Self Collision", "Enable self collisions.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 	
 	prop= RNA_def_property(srna, "self_min_distance", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_float_sdna(prop, NULL, "selfepsilon");
 	RNA_def_property_range(prop, 0.5f, 1.0f);
 	RNA_def_property_ui_text(prop, "Self Minimum Distance", "0.5 means no distance at all, 1.0 is maximum distance");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 	
 	prop= RNA_def_property(srna, "self_friction", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_range(prop, 0.0f, 80.0f);
 	RNA_def_property_ui_text(prop, "Self Friction", "Friction/damping with self contact.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 
 	prop= RNA_def_property(srna, "self_collision_quality", PROP_INT, PROP_NONE);
 	RNA_def_property_int_sdna(prop, NULL, "self_loop_count");
 	RNA_def_property_range(prop, 1, 10);
 	RNA_def_property_ui_text(prop, "Self Collision Quality", "How many self collision iterations should be done. (higher is better quality but slower), can be changed for each frame.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
 }
 
 void RNA_def_cloth(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index c1464ec87f2..179808ab66d 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_color.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index ec1676eea95..5c4b6a95524 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_constraint.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -534,6 +534,12 @@ static void rna_def_constraint_locate_like(BlenderRNA *brna)
 
 	srna= RNA_def_struct(brna, "CopyLocationConstraint", "Constraint");
 	RNA_def_struct_ui_text(srna, "Copy Location Constraint", "Copies the location of the target.");
+
+	prop= RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_PERCENTAGE);
+	RNA_def_property_float_sdna(prop, "bConstraint", "headtail");
+	RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
+
 	RNA_def_struct_sdna_from(srna, "bLocateLikeConstraint", "data");
 
 	prop= RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
@@ -582,13 +588,6 @@ static void rna_def_constraint_locate_like(BlenderRNA *brna)
 	RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_OFFSET);
 	RNA_def_property_ui_text(prop, "Offset", "Add original location into copied location.");
 	RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
-
-	RNA_def_struct_sdna(srna, "bConstraint");
-
-	prop= RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_PERCENTAGE);
-	RNA_def_property_float_sdna(prop, NULL, "headtail");
-	RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1.");
-	RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
 }
 
 static void rna_def_constraint_minmax(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c
index 7624d4a1144..7fa27348002 100644
--- a/source/blender/makesrna/intern/rna_context.c
+++ b/source/blender/makesrna/intern/rna_context.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_context.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -40,11 +40,11 @@ static PointerRNA rna_Context_manager_get(PointerRNA *ptr)
 	return rna_pointer_inherit_refine(ptr, &RNA_WindowManager, CTX_wm_manager(C));
 }
 
-/*static PointerRNA rna_Context_window_get(PointerRNA *ptr)
+static PointerRNA rna_Context_window_get(PointerRNA *ptr)
 {
 	bContext *C= (bContext*)ptr->data;
 	return rna_pointer_inherit_refine(ptr, &RNA_Window, CTX_wm_window(C));
-}*/
+}
 
 static PointerRNA rna_Context_screen_get(PointerRNA *ptr)
 {
@@ -96,6 +96,12 @@ static PointerRNA rna_Context_scene_get(PointerRNA *ptr)
 	return rna_pointer_inherit_refine(ptr, &RNA_Scene, CTX_data_scene(C));
 }
 
+static PointerRNA rna_Context_tool_settings_get(PointerRNA *ptr)
+{
+	bContext *C= (bContext*)ptr->data;
+	return rna_pointer_inherit_refine(ptr, &RNA_ToolSettings, CTX_data_tool_settings(C));
+}
+
 #else
 
 void RNA_def_context(BlenderRNA *brna)
@@ -113,10 +119,10 @@ void RNA_def_context(BlenderRNA *brna)
 	RNA_def_property_struct_type(prop, "WindowManager");
 	RNA_def_property_pointer_funcs(prop, "rna_Context_manager_get", NULL, NULL);
 
-	/* prop= RNA_def_property(srna, "window", PROP_POINTER, PROP_NONE);
+	prop= RNA_def_property(srna, "window", PROP_POINTER, PROP_NONE);
 	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 	RNA_def_property_struct_type(prop, "Window");
-	RNA_def_property_pointer_funcs(prop, "rna_Context_window_get", NULL, NULL); */
+	RNA_def_property_pointer_funcs(prop, "rna_Context_window_get", NULL, NULL);
 
 	prop= RNA_def_property(srna, "screen", PROP_POINTER, PROP_NONE);
 	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -153,6 +159,12 @@ void RNA_def_context(BlenderRNA *brna)
 	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 	RNA_def_property_struct_type(prop, "Scene");
 	RNA_def_property_pointer_funcs(prop, "rna_Context_scene_get", NULL, NULL);
+
+	prop= RNA_def_property(srna, "tool_settings", PROP_POINTER, PROP_NONE);
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_struct_type(prop, "ToolSettings");
+	RNA_def_property_pointer_funcs(prop, "rna_Context_tool_settings_get", NULL, NULL);
+
 }
 
 #endif
diff --git a/source/blender/makesrna/intern/rna_controller.c b/source/blender/makesrna/intern/rna_controller.c
index 47399090b4e..4d5ef7aa123 100644
--- a/source/blender/makesrna/intern/rna_controller.c
+++ b/source/blender/makesrna/intern/rna_controller.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_controller.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index c592625c7dc..41a47e279e9 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_curve.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index 98a2ae8b32d..715f03bb3f1 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_define.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -112,7 +112,7 @@ StructDefRNA *rna_find_struct_def(StructRNA *srna)
 	return NULL;
 }
 
-PropertyDefRNA *rna_find_struct_property_def(PropertyRNA *prop)
+PropertyDefRNA *rna_find_struct_property_def(StructRNA *srna, PropertyRNA *prop)
 {
 	StructDefRNA *dsrna;
 	PropertyDefRNA *dprop;
@@ -123,7 +123,7 @@ PropertyDefRNA *rna_find_struct_property_def(PropertyRNA *prop)
 		return NULL;
 	}
 
-	dsrna= rna_find_struct_def(DefRNA.laststruct);
+	dsrna= rna_find_struct_def(srna);
 	dprop= dsrna->cont.properties.last;
 	for (; dprop; dprop= dprop->prev)
 		if (dprop->prop==prop)
@@ -150,7 +150,7 @@ PropertyDefRNA *rna_find_property_def(PropertyRNA *prop)
 		return NULL;
 	}
 
-	dprop= rna_find_struct_property_def(prop);
+	dprop= rna_find_struct_property_def(DefRNA.laststruct, prop);
 	if (dprop)
 		return dprop;
 
@@ -1311,7 +1311,7 @@ static PropertyDefRNA *rna_def_property_sdna(PropertyRNA *prop, const char *stru
 	StructDefRNA *ds;
 	PropertyDefRNA *dp;
 
-	dp= rna_find_struct_property_def(prop);
+	dp= rna_find_struct_property_def(DefRNA.laststruct, prop);
 	if (dp==NULL) return NULL;
 
 	ds= rna_find_struct_def((StructRNA*)dp->cont);
@@ -1371,7 +1371,7 @@ void RNA_def_property_boolean_negative_sdna(PropertyRNA *prop, const char *struc
 
 	RNA_def_property_boolean_sdna(prop, structname, propname, booleanbit);
 
-	dp= rna_find_struct_property_def(prop);
+	dp= rna_find_struct_property_def(DefRNA.laststruct, prop);
 
 	if(dp)
 		dp->booleannegative= 1;
@@ -1468,7 +1468,7 @@ void RNA_def_property_enum_bitflag_sdna(PropertyRNA *prop, const char *structnam
 
 	RNA_def_property_enum_sdna(prop, structname, propname);
 
-	dp= rna_find_struct_property_def(prop);
+	dp= rna_find_struct_property_def(DefRNA.laststruct, prop);
 
 	if(dp)
 		dp->enumbitflags= 1;
@@ -1946,7 +1946,7 @@ PropertyRNA *RNA_def_string_dir_path(StructOrFunctionRNA *cont_, const char *ide
 	return prop;
 }
 
-PropertyRNA *RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, EnumPropertyItem *items, int default_value, 
+PropertyRNA *RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, 
 	const char *ui_name, const char *ui_description)
 {
 	ContainerRNA *cont= cont_;
@@ -2249,7 +2249,6 @@ int rna_parameter_size(PropertyRNA *parm)
 #endif
 			}
 			case PROP_COLLECTION:
-				/* XXX does not work yet */
 				return sizeof(ListBase);
 		}
 	}
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index 70e511de323..806219ec6bf 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_fcurve.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c
index ac51aa6d0d7..4e047ff7772 100644
--- a/source/blender/makesrna/intern/rna_fluidsim.c
+++ b/source/blender/makesrna/intern/rna_fluidsim.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_fluidsim.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c
index 82bdd66802a..1406ad1ae60 100644
--- a/source/blender/makesrna/intern/rna_group.c
+++ b/source/blender/makesrna/intern/rna_group.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_group.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index 7c8b0c3bf8e..c74e46c17da 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_image.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -35,8 +35,12 @@
 #include "BKE_context.h"
 #include "BKE_image.h"
 
+#include "WM_types.h"
+
 #ifdef RNA_RUNTIME
 
+#include "IMB_imbuf_types.h"
+
 static void rna_Image_animated_update(bContext *C, PointerRNA *ptr)
 {
 	Image *ima= (Image*)ptr->data;
@@ -50,6 +54,18 @@ static void rna_Image_animated_update(bContext *C, PointerRNA *ptr)
 	}
 }
 
+static int rna_Image_dirty_get(PointerRNA *ptr)
+{
+	Image *ima= (Image*)ptr->data;
+	ImBuf *ibuf;
+
+	for(ibuf=ima->ibufs.first; ibuf; ibuf=ibuf->next)
+		if(ibuf->userflags & IB_BITMAPDIRTY)
+			return 1;
+	
+	return 0;
+}
+
 #else
 
 static void rna_def_imageuser(BlenderRNA *brna)
@@ -133,16 +149,19 @@ static void rna_def_image(BlenderRNA *brna)
 	RNA_def_property_string_sdna(prop, NULL, "name");
 	RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* imagechanged */
 	RNA_def_property_ui_text(prop, "Filename", "Image/Movie file name.");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
 	prop= RNA_def_property(srna, "source", PROP_ENUM, PROP_NONE);
 	RNA_def_property_enum_items(prop, prop_source_items);
 	RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* imagechanged */
 	RNA_def_property_ui_text(prop, "Source", "Where the image comes from.");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
 	prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
 	RNA_def_property_enum_items(prop, prop_type_items);
 	RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* imagechanged */
 	RNA_def_property_ui_text(prop, "Type", "How to generate the image.");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
 	prop= RNA_def_property(srna, "packed_file", PROP_POINTER, PROP_NONE);
 	RNA_def_property_pointer_sdna(prop, NULL, "packedfile");
@@ -152,90 +171,110 @@ static void rna_def_image(BlenderRNA *brna)
 	prop= RNA_def_property(srna, "fields", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_FIELDS);
 	RNA_def_property_ui_text(prop, "Fields", "Use fields of the image.");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
 	prop= RNA_def_property(srna, "odd_fields", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_STD_FIELD);
 	RNA_def_property_ui_text(prop, "Odd Fields", "Standard field toggle.");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
 	prop= RNA_def_property(srna, "antialias", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_ANTIALI);
 	RNA_def_property_ui_text(prop, "Anti-alias", "Toggles image anti-aliasing, only works with solid colors");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
 	prop= RNA_def_property(srna, "premultiply", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_DO_PREMUL);
 	RNA_def_property_ui_text(prop, "Premultiply", "Convert RGB from key alpha to premultiplied alpha.");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
+
+	prop= RNA_def_property(srna, "dirty", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_funcs(prop, "rna_Image_dirty_get", NULL);
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_ui_text(prop, "Dirty", "Image has changed and is not saved.");
 
 	/* generated image (image_generated_change_cb) */
 	prop= RNA_def_property(srna, "generated_type", PROP_ENUM, PROP_NONE);
 	RNA_def_property_enum_sdna(prop, NULL, "gen_type");
 	RNA_def_property_enum_items(prop, prop_generated_type_items);
 	RNA_def_property_ui_text(prop, "Generated Type", "Generated image type.");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
 	prop= RNA_def_property(srna, "generated_width", PROP_INT, PROP_NONE);
 	RNA_def_property_int_sdna(prop, NULL, "gen_x");
 	RNA_def_property_range(prop, 1, 16384);
 	RNA_def_property_ui_text(prop, "Generated Width", "Generated image width.");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
 	prop= RNA_def_property(srna, "generated_height", PROP_INT, PROP_NONE);
 	RNA_def_property_int_sdna(prop, NULL, "gen_y");
 	RNA_def_property_range(prop, 1, 16384);
 	RNA_def_property_ui_text(prop, "Generated Height", "Generated image height.");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
 	/* realtime properties */
 	prop= RNA_def_property(srna, "mapping", PROP_ENUM, PROP_NONE);
 	RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
 	RNA_def_property_enum_items(prop, prop_mapping_items);
 	RNA_def_property_ui_text(prop, "Mapping", "Mapping type to use for this image in the game engine.");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
 	prop= RNA_def_property(srna, "display_aspect", PROP_FLOAT, PROP_VECTOR);
 	RNA_def_property_float_sdna(prop, NULL, "aspx");
 	RNA_def_property_array(prop, 2);
 	RNA_def_property_range(prop, 0.1f, 5000.0f);
 	RNA_def_property_ui_text(prop, "Display Aspect", "Display Aspect for this image, does not affect rendering.");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
 	prop= RNA_def_property(srna, "animated", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "tpageflag", IMA_TWINANIM);
 	RNA_def_property_ui_text(prop, "Animated", "Use as animated texture in the game engine.");
-	RNA_def_property_update(prop, 0, "rna_Image_animated_update");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, "rna_Image_animated_update");
 
 	prop= RNA_def_property(srna, "animation_start", PROP_INT, PROP_NONE);
 	RNA_def_property_int_sdna(prop, NULL, "twsta");
 	RNA_def_property_range(prop, 0, 128);
 	RNA_def_property_ui_text(prop, "Animation Start", "Start frame of an animated texture.");
-	RNA_def_property_update(prop, 0, "rna_Image_animated_update");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, "rna_Image_animated_update");
 
 	prop= RNA_def_property(srna, "animation_end", PROP_INT, PROP_NONE);
 	RNA_def_property_int_sdna(prop, NULL, "twend");
 	RNA_def_property_range(prop, 0, 128);
 	RNA_def_property_ui_text(prop, "Animation End", "End frame of an animated texture.");
-	RNA_def_property_update(prop, 0, "rna_Image_animated_update");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, "rna_Image_animated_update");
 
 	prop= RNA_def_property(srna, "animation_speed", PROP_INT, PROP_NONE);
 	RNA_def_property_int_sdna(prop, NULL, "animspeed");
 	RNA_def_property_range(prop, 1, 100);
 	RNA_def_property_ui_text(prop, "Animation Speed", "Speed of the animation in frames per second.");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
 	prop= RNA_def_property(srna, "tiles", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "tpageflag", IMA_TILES);
 	RNA_def_property_ui_text(prop, "Tiles", "Use of tilemode for faces (default shift-LMB to pick the tile for selected faces).");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
 	prop= RNA_def_property(srna, "tiles_x", PROP_INT, PROP_NONE);
 	RNA_def_property_int_sdna(prop, NULL, "xrep");
 	RNA_def_property_range(prop, 1, 16);
 	RNA_def_property_ui_text(prop, "Tiles X", "Degree of repetition in the X direction.");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
 	prop= RNA_def_property(srna, "tiles_y", PROP_INT, PROP_NONE);
 	RNA_def_property_int_sdna(prop, NULL, "yrep");
 	RNA_def_property_range(prop, 1, 16);
 	RNA_def_property_ui_text(prop, "Tiles Y", "Degree of repetition in the Y direction.");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
 	prop= RNA_def_property(srna, "clamp_x", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "tpageflag", IMA_CLAMP_U);
 	RNA_def_property_ui_text(prop, "Clamp X", "Disable texture repeating horizontally.");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
 	prop= RNA_def_property(srna, "clamp_y", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "tpageflag", IMA_CLAMP_V);
 	RNA_def_property_ui_text(prop, "Clamp Y", "Disable texture repeating vertically.");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 }
 
 void RNA_def_image(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index a41f522bb0f..3d66682771d 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_internal.h 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -145,7 +145,6 @@ void RNA_def_object_force(struct BlenderRNA *brna);
 void RNA_def_packedfile(struct BlenderRNA *brna);
 void RNA_def_particle(struct BlenderRNA *brna);
 void RNA_def_pose(struct BlenderRNA *brna);
-void RNA_def_radio(struct BlenderRNA *brna);
 void RNA_def_rna(struct BlenderRNA *brna);
 void RNA_def_scene(struct BlenderRNA *brna);
 void RNA_def_screen(struct BlenderRNA *brna);
@@ -256,6 +255,7 @@ void rna_freelistN(struct ListBase *listbase);
 StructDefRNA *rna_find_struct_def(StructRNA *srna);
 FunctionDefRNA *rna_find_function_def(FunctionRNA *func);
 PropertyDefRNA *rna_find_parameter_def(PropertyRNA *parm);
+PropertyDefRNA *rna_find_struct_property_def(StructRNA *srna, PropertyRNA *prop);
 
 /* Pointer Handling */
 
diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h
index 3cf250151c7..401b430ebc9 100644
--- a/source/blender/makesrna/intern/rna_internal_types.h
+++ b/source/blender/makesrna/intern/rna_internal_types.h
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_internal_types.h 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -146,6 +146,10 @@ struct PropertyRNA {
 
 	/* callback for testing if editable/evaluated */
 	EditableFunc editable;
+
+	/* raw access */
+	int rawoffset;
+	RawPropertyType rawtype;
 };
 
 /* Property Types */
diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c
index b97dd95c4d4..71e424bbd69 100644
--- a/source/blender/makesrna/intern/rna_key.c
+++ b/source/blender/makesrna/intern/rna_key.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_key.c 19382 2009-03-23 13:24:48Z blendix $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c
index c6cf2b0a410..a49b4377d9d 100644
--- a/source/blender/makesrna/intern/rna_lamp.c
+++ b/source/blender/makesrna/intern/rna_lamp.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_lamp.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -253,11 +253,11 @@ static void rna_def_lamp(BlenderRNA *brna)
 	PropertyRNA *prop;
 
 	static EnumPropertyItem prop_type_items[] = {
-		{LA_LOCAL, "POINT", 0, "Point", "Omnidirectional point light source."},
-		{LA_SUN, "SUN", 0, "Sun", "Constant direction parallel ray light source."},
-		{LA_SPOT, "SPOT", 0, "Spot", "Directional cone light source."},
-		{LA_HEMI, "HEMI", 0, "Hemi", "180 degree constant light source."},
-		{LA_AREA, "AREA", 0, "Area", "Directional area light source."},
+		{LA_LOCAL, "POINT", ICON_LAMP_POINT, "Point", "Omnidirectional point light source."},
+		{LA_SUN, "SUN", ICON_LAMP_SUN, "Sun", "Constant direction parallel ray light source."},
+		{LA_SPOT, "SPOT", ICON_LAMP_SPOT, "Spot", "Directional cone light source."},
+		{LA_HEMI, "HEMI", ICON_LAMP_HEMI, "Hemi", "180 degree constant light source."},
+		{LA_AREA, "AREA", ICON_LAMP_AREA, "Area", "Directional area light source."},
 		{0, NULL, 0, NULL, NULL}};
 
 	srna= RNA_def_struct(brna, "Lamp", "ID");
diff --git a/source/blender/makesrna/intern/rna_lattice.c b/source/blender/makesrna/intern/rna_lattice.c
index 3af448b0233..f67267ce0d0 100644
--- a/source/blender/makesrna/intern/rna_lattice.c
+++ b/source/blender/makesrna/intern/rna_lattice.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_lattice.c 19382 2009-03-23 13:24:48Z blendix $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c
index 6b1ce8c02ae..26fc3c2941e 100644
--- a/source/blender/makesrna/intern/rna_main.c
+++ b/source/blender/makesrna/intern/rna_main.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_main.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -264,7 +264,7 @@ void RNA_def_main(BlenderRNA *brna)
 	{
 		prop= RNA_def_property(srna, lists[i][0], PROP_COLLECTION, PROP_NONE);
 		RNA_def_property_struct_type(prop, lists[i][1]);
-		RNA_def_property_collection_funcs(prop, lists[i][2], "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, "add_mesh", "remove_mesh");
+		RNA_def_property_collection_funcs(prop, lists[i][2], "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", 0, 0, 0, 0, 0);
 		RNA_def_property_ui_text(prop, lists[i][3], lists[i][4]);
 	}
 
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index 2d699b6b229..6d56b2b00f9 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_main_api.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index 66e30f7ee50..41f31594f6e 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_material.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 25b8739e074..39fa6f36f23 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_mesh.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -34,10 +34,37 @@
 #include "DNA_meshdata_types.h"
 #include "DNA_object_types.h"
 
-#include "BKE_customdata.h"
-
 #ifdef RNA_RUNTIME
 
+#include "DNA_scene_types.h"
+
+#include "BLI_editVert.h"
+
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_utildefines.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+static void rna_Mesh_update_data(bContext *C, PointerRNA *ptr)
+{
+	Main *bmain= CTX_data_main(C);
+	Scene *scene= CTX_data_scene(C);
+	ID *id= ptr->id.data;
+	Object *ob;
+
+	for(ob=bmain->object.first; ob; ob= ob->id.next) {
+		if(ob->data == id) {
+			/* XXX this will loop over all objects again (slow) */
+			DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+			WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
+		}
+	}
+}
+
 static void rna_MeshVertex_normal_get(PointerRNA *ptr, float *value)
 {
 	MVert *mvert= (MVert*)ptr->data;
@@ -183,13 +210,19 @@ static void rna_MeshFace_material_index_range(PointerRNA *ptr, int *min, int *ma
 	*max= me->totcol-1;
 }
 
+static CustomData *rna_mesh_fdata(Mesh *me)
+{
+	return (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
+}
+
 static int rna_CustomDataLayer_length(PointerRNA *ptr, int type)
 {
 	Mesh *me= (Mesh*)ptr->id.data;
+	CustomData *fdata= rna_mesh_fdata(me);
 	CustomDataLayer *layer;
 	int i, length= 0;
 
-	for(layer=me->fdata.layers, i=0; ifdata.totlayer; layer++, i++)
+	for(layer=fdata->layers, i=0; itotlayer; layer++, i++)
 		if(layer->type == type)
 			length++;
 
@@ -199,41 +232,96 @@ static int rna_CustomDataLayer_length(PointerRNA *ptr, int type)
 static int rna_CustomDataLayer_active_get(PointerRNA *ptr, int type, int render)
 {
 	Mesh *me= (Mesh*)ptr->id.data;
-	int n= ((CustomDataLayer*)ptr->data) - me->fdata.layers;
+	CustomData *fdata= rna_mesh_fdata(me);
+	int n= ((CustomDataLayer*)ptr->data) - fdata->layers;
 
-	if(render) return (n == CustomData_get_render_layer_index(&me->fdata, type));
-	else return (n == CustomData_get_active_layer_index(&me->fdata, type));
+	if(render) return (n == CustomData_get_render_layer_index(fdata, type));
+	else return (n == CustomData_get_active_layer_index(fdata, type));
 }
 
 static void rna_CustomDataLayer_active_set(PointerRNA *ptr, int value, int type, int render)
 {
 	Mesh *me= (Mesh*)ptr->id.data;
-	int n= ((CustomDataLayer*)ptr->data) - me->fdata.layers;
+	CustomData *fdata= rna_mesh_fdata(me);
+	int n= ((CustomDataLayer*)ptr->data) - fdata->layers;
 
 	if(value == 0)
 		return;
 
-	if(render) CustomData_set_layer_render_index(&me->fdata, type, n);
-	else CustomData_set_layer_active_index(&me->fdata, type, n);
+	if(render) CustomData_set_layer_render_index(fdata, type, n);
+	else CustomData_set_layer_active_index(fdata, type, n);
 }
 
-static int rna_uv_layer_check(CollectionPropertyIterator *iter, void *data)
+static int rna_uv_texture_check(CollectionPropertyIterator *iter, void *data)
 {
 	CustomDataLayer *layer= (CustomDataLayer*)data;
 	return (layer->type != CD_MTFACE);
 }
 
-static void rna_Mesh_uv_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+static void rna_Mesh_uv_textures_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
 {
 	Mesh *me= (Mesh*)ptr->data;
-	rna_iterator_array_begin(iter, (void*)me->fdata.layers, sizeof(CustomDataLayer), me->fdata.totlayer, rna_uv_layer_check);
+	CustomData *fdata= rna_mesh_fdata(me);
+	rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, rna_uv_texture_check);
 }
 
-static int rna_Mesh_uv_layers_length(PointerRNA *ptr)
+static int rna_Mesh_uv_textures_length(PointerRNA *ptr)
 {
 	return rna_CustomDataLayer_length(ptr, CD_MTFACE);
 }
 
+static PointerRNA rna_Mesh_active_uv_texture_get(PointerRNA *ptr)
+{
+	Mesh *me= (Mesh*)ptr->data;
+	CustomData *fdata= rna_mesh_fdata(me);
+	int index= CustomData_get_active_layer_index(fdata, CD_MTFACE);
+	CustomDataLayer *cdl= (index == -1)? NULL: &fdata->layers[index];
+
+	return rna_pointer_inherit_refine(ptr, &RNA_MeshTextureFaceLayer, cdl);
+}
+
+static void rna_Mesh_active_uv_texture_set(PointerRNA *ptr, PointerRNA value)
+{
+	Mesh *me= (Mesh*)ptr->data;
+	CustomData *fdata= rna_mesh_fdata(me);
+	CustomDataLayer *cdl;
+	int a;
+
+	for(cdl=fdata->layers, a=0; atotlayer; cdl++, a++) {
+		if(value.data == cdl) {
+			CustomData_set_layer_active_index(fdata, CD_MTFACE, a);
+			mesh_update_customdata_pointers(me);
+			return;
+		}
+	}
+}
+
+static int rna_Mesh_active_uv_texture_index_get(PointerRNA *ptr)
+{
+	Mesh *me= (Mesh*)ptr->data;
+	CustomData *fdata= rna_mesh_fdata(me);
+	return CustomData_get_active_layer(fdata, CD_MTFACE);
+}
+
+static void rna_Mesh_active_uv_texture_index_set(PointerRNA *ptr, int value)
+{
+	Mesh *me= (Mesh*)ptr->data;
+	CustomData *fdata= rna_mesh_fdata(me);
+
+	CustomData_set_layer_active(fdata, CD_MTFACE, value);
+	mesh_update_customdata_pointers(me);
+}
+
+static void rna_Mesh_active_uv_texture_index_range(PointerRNA *ptr, int *min, int *max)
+{
+	Mesh *me= (Mesh*)ptr->data;
+	CustomData *fdata= rna_mesh_fdata(me);
+
+	*min= 0;
+	*max= CustomData_number_of_layers(fdata, CD_MTFACE)-1;
+	*max= MAX2(0, *max);
+}
+
 static void rna_MeshTextureFace_uv1_get(PointerRNA *ptr, float *values)
 {
 	MTFace *mtface= (MTFace*)ptr->data;
@@ -331,23 +419,84 @@ static void rna_MeshTextureFaceLayer_active_set(PointerRNA *ptr, int value)
 	rna_CustomDataLayer_active_set(ptr, value, CD_MTFACE, 0);
 }
 
-static int rna_vcol_layer_check(CollectionPropertyIterator *iter, void *data)
+static void rna_MeshTextureFaceLayer_name_set(PointerRNA *ptr, const char *value)
+{
+	Mesh *me= (Mesh*)ptr->id.data;
+	CustomDataLayer *cdl= (CustomDataLayer*)ptr->data;
+	BLI_strncpy(cdl->name, value, sizeof(cdl->name));
+	CustomData_set_layer_unique_name(&me->fdata, cdl - me->fdata.layers);
+}
+
+static int rna_vertex_color_check(CollectionPropertyIterator *iter, void *data)
 {
 	CustomDataLayer *layer= (CustomDataLayer*)data;
 	return (layer->type != CD_MCOL);
 }
 
-static void rna_Mesh_vcol_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+static void rna_Mesh_vertex_colors_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
 {
 	Mesh *me= (Mesh*)ptr->data;
-	rna_iterator_array_begin(iter, (void*)me->fdata.layers, sizeof(CustomDataLayer), me->fdata.totlayer, rna_vcol_layer_check);
+	CustomData *fdata= rna_mesh_fdata(me);
+	rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, rna_vertex_color_check);
 }
 
-static int rna_Mesh_vcol_layers_length(PointerRNA *ptr)
+static int rna_Mesh_vertex_colors_length(PointerRNA *ptr)
 {
 	return rna_CustomDataLayer_length(ptr, CD_MCOL);
 }
 
+static PointerRNA rna_Mesh_active_vertex_color_get(PointerRNA *ptr)
+{
+	Mesh *me= (Mesh*)ptr->data;
+	CustomData *fdata= rna_mesh_fdata(me);
+	int index= CustomData_get_active_layer_index(fdata, CD_MCOL);
+	CustomDataLayer *cdl= (index == -1)? NULL: &fdata->layers[index];
+
+	return rna_pointer_inherit_refine(ptr, &RNA_MeshColorLayer, cdl);
+}
+
+static void rna_Mesh_active_vertex_color_set(PointerRNA *ptr, PointerRNA value)
+{
+	Mesh *me= (Mesh*)ptr->data;
+	CustomData *fdata= rna_mesh_fdata(me);
+	CustomDataLayer *cdl;
+	int a;
+
+	for(cdl=fdata->layers, a=0; atotlayer; cdl++, a++) {
+		if(value.data == cdl) {
+			CustomData_set_layer_active_index(fdata, CD_MCOL, a);
+			mesh_update_customdata_pointers(me);
+			return;
+		}
+	}
+}
+
+static int rna_Mesh_active_vertex_color_index_get(PointerRNA *ptr)
+{
+	Mesh *me= (Mesh*)ptr->data;
+	CustomData *fdata= rna_mesh_fdata(me);
+	return CustomData_get_active_layer(fdata, CD_MCOL);
+}
+
+static void rna_Mesh_active_vertex_color_index_set(PointerRNA *ptr, int value)
+{
+	Mesh *me= (Mesh*)ptr->data;
+	CustomData *fdata= rna_mesh_fdata(me);
+
+	CustomData_set_layer_active(fdata, CD_MCOL, value);
+	mesh_update_customdata_pointers(me);
+}
+
+static void rna_Mesh_active_vertex_color_index_range(PointerRNA *ptr, int *min, int *max)
+{
+	Mesh *me= (Mesh*)ptr->data;
+	CustomData *fdata= rna_mesh_fdata(me);
+
+	*min= 0;
+	*max= CustomData_number_of_layers(fdata, CD_MCOL)-1;
+	*max= MAX2(0, *max);
+}
+
 static void rna_MeshColorLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
 {
 	Mesh *me= (Mesh*)ptr->id.data;
@@ -381,6 +530,14 @@ static void rna_MeshColorLayer_active_set(PointerRNA *ptr, int value)
 	rna_CustomDataLayer_active_set(ptr, value, CD_MCOL, 0);
 }
 
+static void rna_MeshColorLayer_name_set(PointerRNA *ptr, const char *value)
+{
+	Mesh *me= (Mesh*)ptr->id.data;
+	CustomDataLayer *cdl= (CustomDataLayer*)ptr->data;
+	BLI_strncpy(cdl->name, value, sizeof(cdl->name));
+	CustomData_set_layer_unique_name(&me->fdata, cdl - me->fdata.layers);
+}
+
 static void rna_MeshFloatPropertyLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
 {
 	Mesh *me= (Mesh*)ptr->id.data;
@@ -403,7 +560,8 @@ static int rna_float_layer_check(CollectionPropertyIterator *iter, void *data)
 static void rna_Mesh_float_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
 {
 	Mesh *me= (Mesh*)ptr->data;
-	rna_iterator_array_begin(iter, (void*)me->fdata.layers, sizeof(CustomDataLayer), me->fdata.totlayer, rna_float_layer_check);
+	CustomData *fdata= rna_mesh_fdata(me);
+	rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, rna_float_layer_check);
 }
 
 static int rna_Mesh_float_layers_length(PointerRNA *ptr)
@@ -433,7 +591,8 @@ static int rna_MeshIntPropertyLayer_data_length(PointerRNA *ptr)
 static void rna_Mesh_int_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
 {
 	Mesh *me= (Mesh*)ptr->data;
-	rna_iterator_array_begin(iter, (void*)me->fdata.layers, sizeof(CustomDataLayer), me->fdata.totlayer, rna_int_layer_check);
+	CustomData *fdata= rna_mesh_fdata(me);
+	rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, rna_int_layer_check);
 }
 
 static int rna_Mesh_int_layers_length(PointerRNA *ptr)
@@ -463,7 +622,8 @@ static int rna_MeshStringPropertyLayer_data_length(PointerRNA *ptr)
 static void rna_Mesh_string_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
 {
 	Mesh *me= (Mesh*)ptr->data;
-	rna_iterator_array_begin(iter, (void*)me->fdata.layers, sizeof(CustomDataLayer), me->fdata.totlayer, rna_string_layer_check);
+	CustomData *fdata= rna_mesh_fdata(me);
+	rna_iterator_array_begin(iter, (void*)fdata->layers, sizeof(CustomDataLayer), fdata->totlayer, rna_string_layer_check);
 }
 
 static int rna_Mesh_string_layers_length(PointerRNA *ptr)
@@ -522,17 +682,18 @@ static char *rna_MeshVertex_path(PointerRNA *ptr)
 
 static char *rna_MeshTextureFaceLayer_path(PointerRNA *ptr)
 {
-	return BLI_sprintfN("uv_layers[%s]", ((CustomDataLayer*)ptr->data)->name);
+	return BLI_sprintfN("uv_textures[%s]", ((CustomDataLayer*)ptr->data)->name);
 }
 
 static char *rna_CustomDataData_path(PointerRNA *ptr, char *collection, int type)
 {
 	Mesh *me= (Mesh*)ptr->id.data;
+	CustomData *fdata= rna_mesh_fdata(me);
 	CustomDataLayer *cdl;
 	int a;
 	size_t b;
 
-	for(cdl=me->fdata.layers, a=0; afdata.totlayer; cdl++, a++) {
+	for(cdl=fdata->layers, a=0; atotlayer; cdl++, a++) {
 		if(cdl->type == type) {
 			b= ((char*)ptr->data - ((char*)cdl->data))/CustomData_sizeof(type);
 			if(b >= 0 && b < me->totface)
@@ -545,17 +706,17 @@ static char *rna_CustomDataData_path(PointerRNA *ptr, char *collection, int type
 
 static char *rna_MeshTextureFace_path(PointerRNA *ptr)
 {
-	return rna_CustomDataData_path(ptr, "uv_layers", CD_MTFACE);
+	return rna_CustomDataData_path(ptr, "uv_textures", CD_MTFACE);
 }
 
 static char *rna_MeshColorLayer_path(PointerRNA *ptr)
 {
-	return BLI_sprintfN("vcol_layers[%s]", ((CustomDataLayer*)ptr->data)->name);
+	return BLI_sprintfN("vertex_colors[%s]", ((CustomDataLayer*)ptr->data)->name);
 }
 
 static char *rna_MeshColor_path(PointerRNA *ptr)
 {
-	return rna_CustomDataData_path(ptr, "vcol_layers", CD_MCOL);
+	return rna_CustomDataData_path(ptr, "vertex_colors", CD_MCOL);
 }
 
 static char *rna_MeshSticky_path(PointerRNA *ptr)
@@ -670,8 +831,8 @@ static void rna_def_medge(BlenderRNA *brna)
 	prop= RNA_def_property(srna, "verts", PROP_INT, PROP_UNSIGNED);
 	RNA_def_property_int_sdna(prop, NULL, "v1");
 	RNA_def_property_array(prop, 2);
-	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 	RNA_def_property_ui_text(prop, "Vertices", "Vertex indices");
+	// XXX allows creating invalid meshes
 
 	prop= RNA_def_property(srna, "crease", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_float_funcs(prop, "rna_MEdge_crease_get", "rna_MEdge_crease_set", NULL);
@@ -712,8 +873,8 @@ static void rna_def_mface(BlenderRNA *brna)
 	prop= RNA_def_property(srna, "verts", PROP_INT, PROP_UNSIGNED);
 	RNA_def_property_int_sdna(prop, NULL, "v1");
 	RNA_def_property_array(prop, 4);
-	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 	RNA_def_property_ui_text(prop, "Vertices", "Vertex indices");
+	// XXX allows creating invalid meshes
 
 	prop= RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED);
 	RNA_def_property_int_sdna(prop, NULL, "mat_nr");
@@ -752,6 +913,7 @@ static void rna_def_mtface(BlenderRNA *brna)
 
 	prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
 	RNA_def_struct_name_property(srna, prop);
+	RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshTextureFaceLayer_name_set");
 	RNA_def_property_ui_text(prop, "Name", "");
 
 	prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
@@ -889,6 +1051,7 @@ static void rna_def_mcol(BlenderRNA *brna)
 
 	prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
 	RNA_def_struct_name_property(srna, prop);
+	RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshColorLayer_name_set");
 	RNA_def_property_ui_text(prop, "Name", "");
 
 	prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
@@ -1058,7 +1221,6 @@ static void rna_def_mesh(BlenderRNA *brna)
 	RNA_def_property_collection_sdna(prop, NULL, "mvert", "totvert");
 	RNA_def_property_struct_type(prop, "MeshVertex");
 	RNA_def_property_ui_text(prop, "Vertices", "Vertices of the mesh.");
-	// XXX RNA_def_property_collection_funcs(prop, "rna_Mesh_verts_begin", 0, 0, 0, 0, 0, 0, "add_verts", "remove_verts");
 
 	prop= RNA_def_property(srna, "edges", PROP_COLLECTION, PROP_NONE);
 	RNA_def_property_collection_sdna(prop, NULL, "medge", "totedge");
@@ -1075,17 +1237,45 @@ static void rna_def_mesh(BlenderRNA *brna)
 	RNA_def_property_struct_type(prop, "MeshSticky");
 	RNA_def_property_ui_text(prop, "Sticky", "Sticky texture coordinates.");
 
-	prop= RNA_def_property(srna, "uv_layers", PROP_COLLECTION, PROP_NONE);
-	RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
-	RNA_def_property_collection_funcs(prop, "rna_Mesh_uv_layers_begin", 0, 0, 0, "rna_Mesh_uv_layers_length", 0, 0, 0, 0);
-	RNA_def_property_struct_type(prop, "MeshTextureFaceLayer");
-	RNA_def_property_ui_text(prop, "UV Layers", "");
+	/* UV textures */
 
-	prop= RNA_def_property(srna, "vcol_layers", PROP_COLLECTION, PROP_NONE);
+	prop= RNA_def_property(srna, "uv_textures", PROP_COLLECTION, PROP_NONE);
 	RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
-	RNA_def_property_collection_funcs(prop, "rna_Mesh_vcol_layers_begin", 0, 0, 0, "rna_Mesh_vcol_layers_length", 0, 0, 0, 0);
+	RNA_def_property_collection_funcs(prop, "rna_Mesh_uv_textures_begin", 0, 0, 0, "rna_Mesh_uv_textures_length", 0, 0, 0, 0);
+	RNA_def_property_struct_type(prop, "MeshTextureFaceLayer");
+	RNA_def_property_ui_text(prop, "UV Textures", "");
+
+	prop= RNA_def_property(srna, "active_uv_texture", PROP_POINTER, PROP_UNSIGNED);
+	RNA_def_property_struct_type(prop, "MeshTextureFaceLayer");
+	RNA_def_property_pointer_funcs(prop, "rna_Mesh_active_uv_texture_get", "rna_Mesh_active_uv_texture_set", NULL);
+	RNA_def_property_flag(prop, PROP_EDITABLE);
+	RNA_def_property_ui_text(prop, "Active UV Texture", "Active UV texture.");
+	RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+
+	prop= RNA_def_property(srna, "active_uv_texture_index", PROP_INT, PROP_UNSIGNED);
+	RNA_def_property_int_funcs(prop, "rna_Mesh_active_uv_texture_index_get", "rna_Mesh_active_uv_texture_index_set", "rna_Mesh_active_uv_texture_index_range");
+	RNA_def_property_ui_text(prop, "Active UV Texture Index", "Active UV texture index.");
+	RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+
+	/* Vertex colors */
+
+	prop= RNA_def_property(srna, "vertex_colors", PROP_COLLECTION, PROP_NONE);
+	RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
+	RNA_def_property_collection_funcs(prop, "rna_Mesh_vertex_colors_begin", 0, 0, 0, "rna_Mesh_vertex_colors_length", 0, 0, 0, 0);
 	RNA_def_property_struct_type(prop, "MeshColorLayer");
-	RNA_def_property_ui_text(prop, "Vertex Color Layers", "");
+	RNA_def_property_ui_text(prop, "Vertex Colors", "");
+
+	prop= RNA_def_property(srna, "active_vertex_color", PROP_POINTER, PROP_UNSIGNED);
+	RNA_def_property_struct_type(prop, "MeshColorLayer");
+	RNA_def_property_pointer_funcs(prop, "rna_Mesh_active_vertex_color_get", "rna_Mesh_active_vertex_color_set", NULL);
+	RNA_def_property_flag(prop, PROP_EDITABLE);
+	RNA_def_property_ui_text(prop, "Active Vertex Color Layer", "Active vertex color layer.");
+	RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
+
+	prop= RNA_def_property(srna, "active_vertex_color_index", PROP_INT, PROP_UNSIGNED);
+	RNA_def_property_int_funcs(prop, "rna_Mesh_active_vertex_color_index_get", "rna_Mesh_active_vertex_color_index_set", "rna_Mesh_active_vertex_color_index_range");
+	RNA_def_property_ui_text(prop, "Active Vertex Color Index", "Active vertex color index.");
+	RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
 
 	prop= RNA_def_property(srna, "float_layers", PROP_COLLECTION, PROP_NONE);
 	RNA_def_property_collection_sdna(prop, NULL, "fdata.layers", "fdata.totlayer");
@@ -1121,6 +1311,7 @@ static void rna_def_mesh(BlenderRNA *brna)
 	prop= RNA_def_property(srna, "double_sided", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_TWOSIDED);
 	RNA_def_property_ui_text(prop, "Double Sided", "Render/display the mesh with double or single sided lighting");
+	RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
 
 	prop= RNA_def_property(srna, "texco_mesh", PROP_POINTER, PROP_NONE);
 	RNA_def_property_pointer_sdna(prop, NULL, "texcomesh");
diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c
index 02c079920ea..c98b3fb7b09 100644
--- a/source/blender/makesrna/intern/rna_mesh_api.c
+++ b/source/blender/makesrna/intern/rna_mesh_api.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_mesh_api.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -34,74 +34,207 @@
 
 #ifdef RNA_RUNTIME
 
-#include "BKE_customdata.h"
-#include "BKE_DerivedMesh.h"
-
 #include "DNA_mesh_types.h"
 #include "DNA_scene_types.h"
 
-/*
-void rna_Mesh_copy(Mesh *me, Mesh *from)
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+
+#include "BLI_edgehash.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+static void rna_Mesh_calc_edges(Mesh *mesh)
 {
-	copy_mesh_data(me, from);
+	CustomData edata;
+	EdgeHashIterator *ehi;
+	MFace *mf = mesh->mface;
+	MEdge *med;
+	EdgeHash *eh = BLI_edgehash_new();
+	int i, *index, totedge, totface = mesh->totface;
+
+	for (i = 0; i < totface; i++, mf++) {
+		if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
+			BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
+		if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
+			BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
+		
+		if (mf->v4) {
+			if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
+				BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
+			if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
+				BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
+		} else {
+			if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
+				BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
+		}
+	}
+
+	totedge = BLI_edgehash_size(eh);
+
+	/* write new edges into a temporary CustomData */
+	memset(&edata, 0, sizeof(edata));
+	CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
+
+	ehi = BLI_edgehashIterator_new(eh);
+	med = CustomData_get_layer(&edata, CD_MEDGE);
+	for(i = 0; !BLI_edgehashIterator_isDone(ehi);
+	    BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
+		BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
+
+		med->flag = ME_EDGEDRAW|ME_EDGERENDER;
+	}
+	BLI_edgehashIterator_free(ehi);
+
+	/* free old CustomData and assign new one */
+	CustomData_free(&mesh->edata, mesh->totedge);
+	mesh->edata = edata;
+	mesh->totedge = totedge;
+
+	mesh->medge = CustomData_get_layer(&mesh->edata, CD_MEDGE);
+
+	BLI_edgehash_free(eh, NULL);
 }
 
-void rna_Mesh_copy_applied(Mesh *me, Scene *sce, Object *ob)
+static void rna_Mesh_update(Mesh *mesh, bContext *C)
 {
-	DerivedMesh *dm= mesh_create_derived_view(sce, ob, CD_MASK_MESH);
-	DM_to_mesh(dm, me);
-	dm->release(dm);
-}
-*/
+	Main *bmain= CTX_data_main(C);
+	Object *ob;
 
-void rna_Mesh_transform(Mesh *me, float **mat)
-{
+	if(mesh->totface && mesh->totedge == 0)
+		rna_Mesh_calc_edges(mesh);
+
+	mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mface, mesh->totface, NULL);
+
+	for(ob=bmain->object.first; ob; ob=ob->id.next) {
+		if(ob->data == mesh) {
+			ob->recalc |= OB_RECALC_DATA;
+			WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
+		}
+	}
 }
 
-#if 0
-/* extern struct EditVert *addvertlist(EditMesh *em, float *vec, struct EditVert *example); */
-
-static void rna_Mesh_verts_add(PointerRNA *ptr, PointerRNA *ptr_item)
+static void rna_Mesh_add_verts(Mesh *mesh, int len)
 {
-	//Mesh *me= (Mesh*)ptr->data;
+	CustomData vdata;
+	MVert *mvert;
+	int i, totvert;
 
-	/*
-	// XXX if item is not MVert we fail silently
-	if (item->type == RNA_MeshVertex)
+	if(len == 0)
 		return;
 
-	// XXX this must be slow...
-	EditMesh *em= BKE_mesh_get_editmesh(me);
+	totvert= mesh->totvert + len;
+	CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
+	CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert);
 
-	MVert *v = (MVert*)ptr_item->ptr->data;
-	addvertlist(em, v->co, NULL);
+	if(!CustomData_has_layer(&vdata, CD_MVERT))
+		CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
 
-	BKE_mesh_end_editmesh(me, em);
-	*/
+	CustomData_free(&mesh->vdata, mesh->totvert);
+	mesh->vdata= vdata;
+	mesh_update_customdata_pointers(mesh);
+
+	/* scan the input list and insert the new vertices */
+
+	mvert= &mesh->mvert[mesh->totvert];
+	for(i=0; iflag |= SELECT;
+
+	/* set final vertex list size */
+	mesh->totvert= totvert;
+}
+
+static void rna_Mesh_add_edges(Mesh *mesh, int len)
+{
+	CustomData edata;
+	MEdge *medge;
+	int i, totedge;
+
+	if(len == 0)
+		return;
+
+	totedge= mesh->totedge+len;
+
+	/* update customdata  */
+	CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge);
+	CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge);
+
+	if(!CustomData_has_layer(&edata, CD_MEDGE))
+		CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
+
+	CustomData_free(&mesh->edata, mesh->totedge);
+	mesh->edata= edata;
+	mesh_update_customdata_pointers(mesh);
+
+	/* set default flags */
+	medge= &mesh->medge[mesh->totedge];
+	for(i=0; iflag= ME_EDGEDRAW|ME_EDGERENDER|SELECT;
+
+	mesh->totedge= totedge;
+}
+
+static void rna_Mesh_add_faces(Mesh *mesh, int len)
+{
+	CustomData fdata;
+	MFace *mface;
+	int i, totface;
+
+	if(len == 0)
+		return;
+
+	totface= mesh->totface + len;	/* new face count */
+
+	/* update customdata */
+	CustomData_copy(&mesh->fdata, &fdata, CD_MASK_MESH, CD_DEFAULT, totface);
+	CustomData_copy_data(&mesh->fdata, &fdata, 0, 0, mesh->totface);
+
+	if(!CustomData_has_layer(&fdata, CD_MFACE))
+		CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface);
+
+	CustomData_free(&mesh->fdata, mesh->totface);
+	mesh->fdata= fdata;
+	mesh_update_customdata_pointers(mesh);
+
+	/* set default flags */
+	mface= &mesh->mface[mesh->totface];
+	for(i=0; iflag= SELECT;
+
+	mesh->totface= totface;
+}
+
+static void rna_Mesh_add_geometry(Mesh *mesh, int verts, int edges, int faces)
+{
+	if(verts)
+		rna_Mesh_add_verts(mesh, verts);
+	if(edges)
+		rna_Mesh_add_edges(mesh, edges);
+	if(faces)
+		rna_Mesh_add_faces(mesh, faces);
 }
-#endif
 
 #else
 
 void RNA_api_mesh(StructRNA *srna)
 {
-	/*FunctionRNA *func;
-	PropertyRNA *prop;*/
+	FunctionRNA *func;
+	PropertyRNA *parm;
 
-	/*
-	func= RNA_def_function(srna, "copy", "rna_Mesh_copy");
-	RNA_def_function_ui_description(func, "Copy mesh data.");
-	prop= RNA_def_pointer(func, "src", "Mesh", "", "A mesh to copy data from.");
-	RNA_def_property_flag(prop, PROP_REQUIRED);*/
+	func= RNA_def_function(srna, "add_geometry", "rna_Mesh_add_geometry");
+	parm= RNA_def_int(func, "verts", 0, 0, INT_MAX, "Number", "Number of vertices to add.", 0, INT_MAX);
+	RNA_def_property_flag(parm, PROP_REQUIRED);
+	parm= RNA_def_int(func, "edges", 0, 0, INT_MAX, "Number", "Number of edges to add.", 0, INT_MAX);
+	RNA_def_property_flag(parm, PROP_REQUIRED);
+	parm= RNA_def_int(func, "faces", 0, 0, INT_MAX, "Number", "Number of faces to add.", 0, INT_MAX);
+	RNA_def_property_flag(parm, PROP_REQUIRED);
 
-	/*
-	func= RNA_def_function(srna, "add_geom", "rna_Mesh_add_geom");
-	RNA_def_function_ui_description(func, "Add geometry data to mesh.");
-	prop= RNA_def_collection(func, "verts", "?", "", "Vertices.");
-	RNA_def_property_flag(prop, PROP_REQUIRED);
-	prop= RNA_def_collection(func, "faces", "?", "", "Faces.");
-	RNA_def_property_flag(prop, PROP_REQUIRED);
-	*/
+	func= RNA_def_function(srna, "update", "rna_Mesh_update");
+	RNA_def_function_flag(func, FUNC_USE_CONTEXT);
 }
 
 #endif
diff --git a/source/blender/makesrna/intern/rna_meta.c b/source/blender/makesrna/intern/rna_meta.c
index ce5b883f0a9..5f95336af2d 100644
--- a/source/blender/makesrna/intern/rna_meta.c
+++ b/source/blender/makesrna/intern/rna_meta.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_meta.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 4c7bb3f52da..9b3ff6e74a0 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_modifier.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -41,35 +41,35 @@
 #include "WM_types.h"
 
 EnumPropertyItem modifier_type_items[] ={
-	{eModifierType_Armature, "ARMATURE", 0, "Armature", ""},
-	{eModifierType_Array, "ARRAY", 0, "Array", ""},
-	{eModifierType_Bevel, "BEVEL", 0, "Bevel", ""},
-	{eModifierType_Boolean, "BOOLEAN", 0, "Boolean", ""},
-	{eModifierType_Build, "BUILD", 0, "Build", ""},
-	{eModifierType_Cast, "CAST", 0, "Cast", ""},
-	{eModifierType_Cloth, "CLOTH", 0, "Cloth", ""},
-	{eModifierType_Collision, "COLLISION", 0, "Collision", ""},
-	{eModifierType_Curve, "CURVE", 0, "Curve", ""},
-	{eModifierType_Decimate, "DECIMATE", 0, "Decimate", ""},
-	{eModifierType_Displace, "DISPLACE", 0, "Displace", ""},
-	{eModifierType_EdgeSplit, "EDGE_SPLIT", 0, "Edge Split", ""},
-	{eModifierType_Explode, "EXPLODE", 0, "Explode", ""},
-	{eModifierType_Fluidsim, "FLUID_SIMULATION", 0, "Fluid Simulation", ""},
-	{eModifierType_Hook, "HOOK", 0, "Hook", ""},
-	{eModifierType_Lattice, "LATTICE", 0, "Lattice", ""},
-	{eModifierType_Mask, "MASK", 0, "Mask", ""},
-	{eModifierType_MeshDeform, "MESH_DEFORM", 0, "Mesh Deform", ""},
-	{eModifierType_Mirror, "MIRROR", 0, "Mirror", ""},
-	{eModifierType_Multires, "MULTIRES", 0, "Multires", ""},
-	{eModifierType_ParticleInstance, "PARTICLE_INSTANCE", 0, "Particle Instance", ""},
-	{eModifierType_ParticleSystem, "PARTICLE_SYSTEM", 0, "Particle System", ""},
-	{eModifierType_Shrinkwrap, "SHRINKWRAP", 0, "Shrinkwrap", ""},
-	{eModifierType_SimpleDeform, "SIMPLE_DEFORM", 0, "Simple Deform", ""},
-	{eModifierType_Smooth, "SMOOTH", 0, "Smooth", ""},
-	{eModifierType_Softbody, "SOFTBODY", 0, "Softbody", ""},
-	{eModifierType_Subsurf, "SUBSURF", 0, "Subsurf", ""},
-	{eModifierType_UVProject, "UV_PROJECT", 0, "UV Project", ""},
-	{eModifierType_Wave, "WAVE", 0, "Wave", ""},
+	{eModifierType_Armature, "ARMATURE", ICON_MOD_ARMATURE, "Armature", ""},
+	{eModifierType_Array, "ARRAY", ICON_MOD_ARRAY, "Array", ""},
+	{eModifierType_Bevel, "BEVEL", ICON_MOD_BEVEL, "Bevel", ""},
+	{eModifierType_Boolean, "BOOLEAN", ICON_MOD_BOOLEAN, "Boolean", ""},
+	{eModifierType_Build, "BUILD", ICON_MOD_BUILD, "Build", ""},
+	{eModifierType_Cast, "CAST", ICON_MOD_CAST, "Cast", ""},
+	{eModifierType_Cloth, "CLOTH", ICON_MOD_CLOTH, "Cloth", ""},
+	{eModifierType_Collision, "COLLISION", ICON_MOD_PHYSICS, "Collision", ""},
+	{eModifierType_Curve, "CURVE", ICON_MOD_CURVE, "Curve", ""},
+	{eModifierType_Decimate, "DECIMATE", ICON_MOD_DECIM, "Decimate", ""},
+	{eModifierType_Displace, "DISPLACE", ICON_MOD_DISPLACE, "Displace", ""},
+	{eModifierType_EdgeSplit, "EDGE_SPLIT", ICON_MOD_EDGESPLIT, "Edge Split", ""},
+	{eModifierType_Explode, "EXPLODE", ICON_MOD_EXPLODE, "Explode", ""},
+	{eModifierType_Fluidsim, "FLUID_SIMULATION", ICON_MOD_FLUIDSIM, "Fluid Simulation", ""},
+	{eModifierType_Hook, "HOOK", ICON_HOOK, "Hook", ""},
+	{eModifierType_Lattice, "LATTICE", ICON_MOD_LATTICE, "Lattice", ""},
+	{eModifierType_Mask, "MASK", ICON_MOD_MASK, "Mask", ""},
+	{eModifierType_MeshDeform, "MESH_DEFORM", ICON_MOD_MESHDEFORM, "Mesh Deform", ""},
+	{eModifierType_Mirror, "MIRROR", ICON_MOD_MIRROR, "Mirror", ""},
+	{eModifierType_Multires, "MULTIRES", ICON_MOD_MULTIRES, "Multires", ""},
+	{eModifierType_ParticleInstance, "PARTICLE_INSTANCE", ICON_MOD_PARTICLES, "Particle Instance", ""},
+	{eModifierType_ParticleSystem, "PARTICLE_SYSTEM", ICON_MOD_PARTICLES, "Particle System", ""},
+	{eModifierType_Shrinkwrap, "SHRINKWRAP", ICON_MOD_SHRINKWRAP, "Shrinkwrap", ""},
+	{eModifierType_SimpleDeform, "SIMPLE_DEFORM", ICON_MOD_SIMPLEDEFORM, "Simple Deform", ""},
+	{eModifierType_Smooth, "SMOOTH", ICON_MOD_SMOOTH, "Smooth", ""},
+	{eModifierType_Softbody, "SOFTBODY", ICON_MOD_SOFT, "Softbody", ""},
+	{eModifierType_Subsurf, "SUBSURF", ICON_MOD_SUBSURF, "Subsurf", ""},
+	{eModifierType_UVProject, "UV_PROJECT", ICON_MOD_UVPROJECT, "UV Project", ""},
+	{eModifierType_Wave, "WAVE", ICON_MOD_WAVE, "Wave", ""},
 	{0, NULL, 0, NULL, NULL}};
 
 
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index bad3d36bfc2..b35b02b2063 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_nodetree.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h
index cff3984a56a..47a7be163b1 100644
--- a/source/blender/makesrna/intern/rna_nodetree_types.h
+++ b/source/blender/makesrna/intern/rna_nodetree_types.h
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_nodetree_types.h 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 8fa07ecf813..947846f8d8d 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_object.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -33,6 +33,7 @@
 #include "DNA_customdata_types.h"
 #include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
+#include "DNA_object_force.h"
 #include "DNA_object_types.h"
 #include "DNA_property_types.h"
 #include "DNA_scene_types.h"
@@ -41,10 +42,13 @@
 
 #ifdef RNA_RUNTIME
 
+#include "DNA_key_types.h"
+
 #include "BKE_armature.h"
 #include "BKE_context.h"
 #include "BKE_curve.h"
 #include "BKE_depsgraph.h"
+#include "BKE_key.h"
 #include "BKE_material.h"
 #include "BKE_mesh.h"
 #include "BKE_particle.h"
@@ -130,6 +134,27 @@ static PointerRNA rna_Object_active_vertex_group_get(PointerRNA *ptr)
 	return rna_pointer_inherit_refine(ptr, &RNA_VertexGroup, BLI_findlink(&ob->defbase, ob->actdef));
 }
 
+static int rna_Object_active_vertex_group_index_get(PointerRNA *ptr)
+{
+	Object *ob= (Object*)ptr->id.data;
+	return MAX2(ob->actdef-1, 0);
+}
+
+static void rna_Object_active_vertex_group_index_set(PointerRNA *ptr, int value)
+{
+	Object *ob= (Object*)ptr->id.data;
+	ob->actdef= value+1;
+}
+
+static void rna_Object_active_vertex_group_index_range(PointerRNA *ptr, int *min, int *max)
+{
+	Object *ob= (Object*)ptr->id.data;
+
+	*min= 0;
+	*max= BLI_countlist(&ob->defbase)-1;
+	*max= MAX2(0, *max);
+}
+
 void rna_object_vgroup_name_index_get(PointerRNA *ptr, char *value, int index)
 {
 	Object *ob= (Object*)ptr->id.data;
@@ -227,11 +252,23 @@ void rna_object_vcollayer_name_set(PointerRNA *ptr, const char *value, char *res
 	BLI_strncpy(result, "", maxlen);
 }
 
+static int rna_Object_active_material_index_get(PointerRNA *ptr)
+{
+	Object *ob= (Object*)ptr->id.data;
+	return MAX2(ob->actcol-1, 0);
+}
+
+static void rna_Object_active_material_index_set(PointerRNA *ptr, int value)
+{
+	Object *ob= (Object*)ptr->id.data;
+	ob->actcol= value+1;
+}
+
 static void rna_Object_active_material_index_range(PointerRNA *ptr, int *min, int *max)
 {
 	Object *ob= (Object*)ptr->id.data;
-	*min= 1;
-	*max= ob->totcol;
+	*min= 0;
+	*max= MAX2(ob->totcol-1, 0);
 }
 
 static PointerRNA rna_Object_active_material_get(PointerRNA *ptr)
@@ -240,6 +277,26 @@ static PointerRNA rna_Object_active_material_get(PointerRNA *ptr)
 	return rna_pointer_inherit_refine(ptr, &RNA_MaterialSlot, ob->mat+ob->actcol);
 }
 
+static void rna_Object_active_particle_system_index_range(PointerRNA *ptr, int *min, int *max)
+{
+	Object *ob= (Object*)ptr->id.data;
+	*min= 0;
+	*max= BLI_countlist(&ob->particlesystem)-1;
+	*max= MAX2(0, *max);
+}
+
+static int rna_Object_active_particle_system_index_get(PointerRNA *ptr)
+{
+	Object *ob= (Object*)ptr->id.data;
+	return psys_get_current_num(ob);
+}
+
+static void rna_Object_active_particle_system_index_set(struct PointerRNA *ptr, int value)
+{
+	Object *ob= (Object*)ptr->id.data;
+	psys_set_current_num(ob, value);
+}
+
 #if 0
 static void rna_Object_active_material_set(PointerRNA *ptr, PointerRNA value)
 {
@@ -364,6 +421,41 @@ static void rna_GameObjectSettings_state_set(PointerRNA *ptr, const int *values)
 	}
 }
 
+static void rna_Object_active_shape_key_index_range(PointerRNA *ptr, int *min, int *max)
+{
+	Object *ob= (Object*)ptr->id.data;
+	Key *key= ob_get_key(ob);
+
+	*min= 0;
+	*max= (key)? BLI_countlist(&key->block)-1: 0;
+	*max= MAX2(0, *max);
+}
+
+static int rna_Object_active_shape_key_index_get(PointerRNA *ptr)
+{
+	Object *ob= (Object*)ptr->id.data;
+
+	return MAX2(ob->shapenr-1, 0);
+}
+
+static void rna_Object_active_shape_key_index_set(PointerRNA *ptr, int value)
+{
+	Object *ob= (Object*)ptr->id.data;
+
+	ob->shapenr= value+1;
+	ob->shapeflag |= OB_SHAPE_TEMPLOCK;
+}
+
+static void rna_Object_shape_key_lock_set(PointerRNA *ptr, int value)
+{
+	Object *ob= (Object*)ptr->id.data;
+
+	if(value) ob->shapeflag |= OB_SHAPE_LOCK;
+	else ob->shapeflag &= ~OB_SHAPE_LOCK;
+
+	ob->shapeflag &= ~OB_SHAPE_TEMPLOCK;
+}
+
 #else
 
 static void rna_def_vertex_group(BlenderRNA *brna)
@@ -409,11 +501,13 @@ static void rna_def_material_slot(BlenderRNA *brna)
 	RNA_def_property_flag(prop, PROP_EDITABLE);
 	RNA_def_property_pointer_funcs(prop, "rna_MaterialSlot_material_get", "rna_MaterialSlot_material_set", NULL);
 	RNA_def_property_ui_text(prop, "Material", "Material datablock used by this material slot.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_SHADING, "rna_Object_update");
 
 	prop= RNA_def_property(srna, "link", PROP_ENUM, PROP_NONE);
 	RNA_def_property_enum_items(prop, link_items);
 	RNA_def_property_enum_funcs(prop, "rna_MaterialSlot_link_get", "rna_MaterialSlot_link_set", NULL);
 	RNA_def_property_ui_text(prop, "Link", "Link material to object or the object's data.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_SHADING, "rna_Object_update");
 
 	prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
 	RNA_def_property_string_funcs(prop, "rna_MaterialSlot_name_get", "rna_MaterialSlot_name_length", NULL);
@@ -792,7 +886,7 @@ static void rna_def_object(BlenderRNA *brna)
 
 	prop= RNA_def_property(srna, "active_material_index", PROP_INT, PROP_UNSIGNED);
 	RNA_def_property_int_sdna(prop, NULL, "actcol");
-	RNA_def_property_int_funcs(prop, NULL, NULL, "rna_Object_active_material_index_range");
+	RNA_def_property_int_funcs(prop, "rna_Object_active_material_index_get", "rna_Object_active_material_index_set", "rna_Object_active_material_index_range");
 	RNA_def_property_ui_text(prop, "Active Material Index", "Index of active material slot.");
 
 	/* transform */
@@ -873,8 +967,15 @@ static void rna_def_object(BlenderRNA *brna)
 
 	prop= RNA_def_property(srna, "active_vertex_group", PROP_POINTER, PROP_NONE);
 	RNA_def_property_struct_type(prop, "VertexGroup");
-	RNA_def_property_pointer_funcs(prop, "rna_Object_active_vertex_group_get", NULL, NULL);
+	RNA_def_property_pointer_funcs(prop, "rna_Object_active_vertex_group_get", "rna_Object_active_vertex_group_set", NULL);
 	RNA_def_property_ui_text(prop, "Active Vertex Group", "Vertex groups of the object.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_Object_update_data");
+
+	prop= RNA_def_property(srna, "active_vertex_group_index", PROP_INT, PROP_NONE);
+	RNA_def_property_int_sdna(prop, NULL, "actdef");
+	RNA_def_property_int_funcs(prop, "rna_Object_active_vertex_group_index_get", "rna_Object_active_vertex_group_index_set", "rna_Object_active_vertex_group_index_range");
+	RNA_def_property_ui_text(prop, "Active Vertex Group Index", "Active index in vertex group array.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_Object_update_data");
 
 	/* empty */
 
@@ -926,6 +1027,10 @@ static void rna_def_object(BlenderRNA *brna)
 	RNA_def_property_pointer_funcs(prop, "rna_Object_active_particle_system_get", NULL, NULL);
 	RNA_def_property_ui_text(prop, "Active Particle System", "Active particle system being displayed");
 
+	prop= RNA_def_property(srna, "active_particle_system_index", PROP_INT, PROP_UNSIGNED);
+	RNA_def_property_int_funcs(prop, "rna_Object_active_particle_system_index_get", "rna_Object_active_particle_system_index_set", "rna_Object_active_particle_system_index_range");
+	RNA_def_property_ui_text(prop, "Active Particle System Index", "Index of active particle system slot.");
+
 	/* restrict */
 
 	prop= RNA_def_property(srna, "restrict_view", PROP_BOOLEAN, PROP_NONE);
@@ -1145,13 +1250,15 @@ static void rna_def_object(BlenderRNA *brna)
 
 	prop= RNA_def_property(srna, "shape_key_lock", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "shapeflag", OB_SHAPE_LOCK);
-	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_boolean_funcs(prop, NULL, "rna_Object_shape_key_lock_set");
 	RNA_def_property_ui_text(prop, "Shape Key Lock", "Always show the current Shape for this Object.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_Object_update_data");
 
-	prop= RNA_def_property(srna, "active_shape_key", PROP_INT, PROP_NONE);
+	prop= RNA_def_property(srna, "active_shape_key_index", PROP_INT, PROP_NONE);
 	RNA_def_property_int_sdna(prop, NULL, "shapenr");
-	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-	RNA_def_property_ui_text(prop, "Active Shape Key", "Current shape key index.");
+	RNA_def_property_int_funcs(prop, "rna_Object_active_shape_key_index_get", "rna_Object_active_shape_key_index_set", "rna_Object_active_shape_key_index_range");
+	RNA_def_property_ui_text(prop, "Active Shape Key Index", "Current shape key index.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_Object_update_data");
 
 	RNA_api_object(srna);
 }
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 4ed97164988..053ab115b3b 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_object_api.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 41ff8c98f73..4d8c728db12 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_object_force.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -31,9 +31,225 @@
 
 #include "DNA_object_types.h"
 #include "DNA_object_force.h"
+#include "DNA_scene_types.h"
+
+#include "WM_types.h"
 
 #ifdef RNA_RUNTIME
 
+#include "MEM_guardedalloc.h"
+
+#include "BKE_context.h"
+#include "BKE_pointcache.h"
+#include "BKE_depsgraph.h"
+
+#include "BLI_blenlib.h"
+
+static void rna_Cache_change(bContext *C, PointerRNA *ptr)
+{
+	Scene *scene = CTX_data_scene(C);
+	Object *ob = CTX_data_active_object(C);
+	PointCache *cache = (PointCache*)ptr->data;
+	PTCacheID *pid = NULL;
+	ListBase pidlist;
+
+	if(!ob)
+		return;
+
+	cache->flag |= PTCACHE_OUTDATED;
+
+	BKE_ptcache_ids_from_object(&pidlist, ob);
+
+	DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+
+	for(pid=pidlist.first; pid; pid=pid->next) {
+		if(pid->cache==cache)
+			break;
+	}
+
+	if(pid)
+		BKE_ptcache_update_info(pid);
+
+	BLI_freelistN(&pidlist);
+}
+
+static void rna_Cache_toggle_disk_cache(bContext *C, PointerRNA *ptr)
+{
+	Object *ob = CTX_data_active_object(C);
+	PointCache *cache = (PointCache*)ptr->data;
+	PTCacheID *pid = NULL;
+	ListBase pidlist;
+
+	if(!ob)
+		return;
+
+	BKE_ptcache_ids_from_object(&pidlist, ob);
+
+	for(pid=pidlist.first; pid; pid=pid->next) {
+		if(pid->cache==cache)
+			break;
+	}
+
+	if(pid)
+		BKE_ptcache_toggle_disk_cache(pid);
+
+	BLI_freelistN(&pidlist);
+}
+
+static void rna_Cache_idname_change(bContext *C, PointerRNA *ptr)
+{
+	Object *ob = CTX_data_active_object(C);
+	PointCache *cache = (PointCache*)ptr->data;
+	PTCacheID *pid = NULL, *pid2;
+	ListBase pidlist;
+	int new_name = 1;
+	char name[80];
+
+	if(!ob)
+		return;
+
+	/* TODO: check for proper characters */
+
+	BKE_ptcache_ids_from_object(&pidlist, ob);
+
+	for(pid=pidlist.first; pid; pid=pid->next) {
+		if(pid->cache==cache)
+			pid2 = pid;
+		else if(strcmp(cache->name, "") && strcmp(cache->name,pid->cache->name)==0) {
+			/*TODO: report "name exists" to user */
+			strcpy(cache->name, cache->prev_name);
+			new_name = 0;
+		}
+	}
+
+	if(new_name) {
+		if(pid2 && cache->flag & PTCACHE_DISK_CACHE) {
+			strcpy(name, cache->name);
+			strcpy(cache->name, cache->prev_name);
+
+			cache->flag &= ~PTCACHE_DISK_CACHE;
+
+			BKE_ptcache_toggle_disk_cache(pid2);
+
+			strcpy(cache->name, name);
+
+			cache->flag |= PTCACHE_DISK_CACHE;
+
+			BKE_ptcache_toggle_disk_cache(pid2);
+		}
+
+		strcpy(cache->prev_name, cache->name);
+	}
+
+	BLI_freelistN(&pidlist);
+}
+
+static int rna_SoftBodySettings_use_edges_get(PointerRNA *ptr)
+{
+	Object *data= (Object*)(ptr->data);
+	return (((data->softflag) & OB_SB_EDGES) != 0);
+}
+
+static void rna_SoftBodySettings_use_edges_set(PointerRNA *ptr, int value)
+{
+	Object *data= (Object*)(ptr->data);
+	if(value) data->softflag |= OB_SB_EDGES;
+	else data->softflag &= ~OB_SB_EDGES;
+}
+
+static int rna_SoftBodySettings_use_goal_get(PointerRNA *ptr)
+{
+	Object *data= (Object*)(ptr->data);
+	return (((data->softflag) & OB_SB_GOAL) != 0);
+}
+
+static void rna_SoftBodySettings_use_goal_set(PointerRNA *ptr, int value)
+{
+	Object *data= (Object*)(ptr->data);
+	if(value) data->softflag |= OB_SB_GOAL;
+	else data->softflag &= ~OB_SB_GOAL;
+}
+
+static int rna_SoftBodySettings_stiff_quads_get(PointerRNA *ptr)
+{
+	Object *data= (Object*)(ptr->data);
+	return (((data->softflag) & OB_SB_QUADS) != 0);
+}
+
+static void rna_SoftBodySettings_stiff_quads_set(PointerRNA *ptr, int value)
+{
+	Object *data= (Object*)(ptr->data);
+	if(value) data->softflag |= OB_SB_QUADS;
+	else data->softflag &= ~OB_SB_QUADS;
+}
+
+static int rna_SoftBodySettings_self_collision_get(PointerRNA *ptr)
+{
+	Object *data= (Object*)(ptr->data);
+	return (((data->softflag) & OB_SB_SELF) != 0);
+}
+
+static void rna_SoftBodySettings_self_collision_set(PointerRNA *ptr, int value)
+{
+	Object *data= (Object*)(ptr->data);
+	if(value) data->softflag |= OB_SB_SELF;
+	else data->softflag &= ~OB_SB_SELF;
+}
+
+static int rna_SoftBodySettings_new_aero_get(PointerRNA *ptr)
+{
+	Object *data= (Object*)(ptr->data);
+	return (((data->softflag) & OB_SB_AERO_ANGLE) != 0);
+}
+
+static void rna_SoftBodySettings_new_aero_set(PointerRNA *ptr, int value)
+{
+	Object *data= (Object*)(ptr->data);
+	if(value) data->softflag |= OB_SB_AERO_ANGLE;
+	else data->softflag &= ~OB_SB_AERO_ANGLE;
+}
+
+static int rna_SoftBodySettings_enabled_get(PointerRNA *ptr)
+{
+	Object *data= (Object*)(ptr->data);
+	return (((data->softflag) & OB_SB_ENABLE) != 0);
+}
+
+#if 0
+static void rna_SoftBodySettings_enabled_set(PointerRNA *ptr, int value)
+{
+	Object *data= (Object*)(ptr->data);
+	if(value) data->softflag |= OB_SB_ENABLE;
+	else data->softflag &= ~OB_SB_ENABLE;
+}
+#endif
+
+static int rna_SoftBodySettings_face_collision_get(PointerRNA *ptr)
+{
+	Object *data= (Object*)(ptr->data);
+	return (((data->softflag) & OB_SB_FACECOLL) != 0);
+}
+
+static void rna_SoftBodySettings_face_collision_set(PointerRNA *ptr, int value)
+{
+	Object *data= (Object*)(ptr->data);
+	if(value) data->softflag |= OB_SB_FACECOLL;
+	else data->softflag &= ~OB_SB_FACECOLL;
+}
+
+static int rna_SoftBodySettings_edge_collision_get(PointerRNA *ptr)
+{
+	Object *data= (Object*)(ptr->data);
+	return (((data->softflag) & OB_SB_EDGECOLL) != 0);
+}
+
+static void rna_SoftBodySettings_edge_collision_set(PointerRNA *ptr, int value)
+{
+	Object *data= (Object*)(ptr->data);
+	if(value) data->softflag |= OB_SB_EDGECOLL;
+	else data->softflag &= ~OB_SB_EDGECOLL;
+}
+
 #else
 
 static void rna_def_pointcache(BlenderRNA *brna)
@@ -54,12 +270,47 @@ static void rna_def_pointcache(BlenderRNA *brna)
 	RNA_def_property_range(prop, 1, 300000);
 	RNA_def_property_ui_text(prop, "End", "Frame on which the simulation stops.");
 
+	prop= RNA_def_property(srna, "step", PROP_INT, PROP_NONE);
+	RNA_def_property_int_sdna(prop, NULL, "step");
+	RNA_def_property_range(prop, 1, 20);
+	RNA_def_property_ui_text(prop, "Cache Step", "Number of frames between cached frames.");
+	RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change");
+
 	/* flags */
 	prop= RNA_def_property(srna, "baked", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_BAKED);
 
 	prop= RNA_def_property(srna, "baking", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_BAKING);
+
+	prop= RNA_def_property(srna, "disk_cache", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_DISK_CACHE);
+	RNA_def_property_ui_text(prop, "Disk Cache", "Save cache files to disk");
+	RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_toggle_disk_cache");
+
+	prop= RNA_def_property(srna, "outdated", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_OUTDATED);
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_ui_text(prop, "Cache is outdated", "");
+
+	prop= RNA_def_property(srna, "frames_skipped", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_FRAMES_SKIPPED);
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+	prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+	RNA_def_property_string_sdna(prop, NULL, "name");
+	RNA_def_property_ui_text(prop, "Name", "Cache name");
+	RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change");
+
+	prop= RNA_def_property(srna, "quick_cache", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_QUICK_CACHE);
+	RNA_def_property_ui_text(prop, "Quick Cache", "Update simulation with cache steps");
+	RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change");
+
+	prop= RNA_def_property(srna, "info", PROP_STRING, PROP_NONE);
+	RNA_def_property_string_sdna(prop, NULL, "info");
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_ui_text(prop, "Cache Info", "Info on current cache status.");
 }
 
 static void rna_def_collision(BlenderRNA *brna)
@@ -163,6 +414,7 @@ static void rna_def_field(BlenderRNA *brna)
 	srna= RNA_def_struct(brna, "FieldSettings", NULL);
 	RNA_def_struct_sdna(srna, "PartDeflect");
 	RNA_def_struct_ui_text(srna, "Field Settings", "Field settings for an object in physics simulation.");
+	RNA_def_struct_ui_icon(srna, ICON_PHYSICS);
 	
 	/* Enums */
 	
@@ -305,10 +557,206 @@ static void rna_def_game_softbody(BlenderRNA *brna)
 static void rna_def_softbody(BlenderRNA *brna)
 {
 	StructRNA *srna;
+	PropertyRNA *prop;
+	
+	static EnumPropertyItem collision_type_items[] = {
+		{SBC_MODE_MANUAL, "MANUAL", 0, "Manual", "Manual adjust"},
+		{SBC_MODE_AVG, "AVERAGE", 0, "Average", "Average Spring lenght * Ball Size"},
+		{SBC_MODE_MIN, "MINIMAL", 0, "Minimal", "Minimal Spring lenght * Ball Size"},
+		{SBC_MODE_MAX, "MAXIMAL", 0, "Maximal", "Maximal Spring lenght * Ball Size"},
+		{SBC_MODE_AVGMINMAX, "MINMAX", 0, "AvMinMax", "(Min+Max)/2 * Ball Size"},
+		{0, NULL, 0, NULL, NULL}};
 
 	srna= RNA_def_struct(brna, "SoftBodySettings", NULL);
 	RNA_def_struct_sdna(srna, "SoftBody");
 	RNA_def_struct_ui_text(srna, "Soft Body Settings", "Soft body simulation settings for an object.");
+	
+	/* General Settings */
+	
+	prop= RNA_def_property(srna, "friction", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "mediafrict");
+	RNA_def_property_range(prop, 0.0f, 50.0f);
+	RNA_def_property_ui_text(prop, "Friction", "General media friction for point movements");
+	
+	prop= RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "nodemass");
+	RNA_def_property_range(prop, 0.0f, 50000.0f);
+	RNA_def_property_ui_text(prop, "Mass", "");
+	
+	prop= RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "grav");
+	RNA_def_property_range(prop, -10.0f, 10.0f);
+	RNA_def_property_ui_text(prop, "Gravitation", "Apply gravitation to point movement");
+	
+	prop= RNA_def_property(srna, "speed", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "physics_speed");
+	RNA_def_property_range(prop, 0.01f, 100.0f);
+	RNA_def_property_ui_text(prop, "Speed", "Tweak timing for physics to control frequency and speed");
+	
+	/* Goal */
+	
+	/*prop= RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
+	RNA_def_property_string_sdna(prop, NULL, "vertgroup");
+	RNA_def_property_ui_text(prop, "Vertex Group", "Use control point weight values");*/
+	
+	prop= RNA_def_property(srna, "goal_min", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "mingoal");
+	RNA_def_property_range(prop, 0.0f, 1.0f);
+	RNA_def_property_ui_text(prop, "Goal Minimum", "Goal minimum, vertex group weights are scaled to match this range.");
+
+	prop= RNA_def_property(srna, "goal_max", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "maxgoal");
+	RNA_def_property_range(prop, 0.0f, 1.0f);
+	RNA_def_property_ui_text(prop, "Goal Maximum", "Goal maximum, vertex group weights are scaled to match this range.");
+
+	prop= RNA_def_property(srna, "goal_default", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "defgoal");
+	RNA_def_property_range(prop, 0.0f, 1.0f);
+	RNA_def_property_ui_text(prop, "Goal Default", "Default Goal (vertex target position) value, when no Vertex Group used.");
+	
+	prop= RNA_def_property(srna, "goal_spring", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "goalspring");
+	RNA_def_property_range(prop, 0.0f, 0.999f);
+	RNA_def_property_ui_text(prop, "Goal Stiffness", "Goal (vertex target position) spring stiffness.");
+	
+	prop= RNA_def_property(srna, "goal_friction", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "goalfrict");
+	RNA_def_property_range(prop, 0.0f, 50.0f);
+	RNA_def_property_ui_text(prop, "Goal Damping", "Goal (vertex target position) friction.");
+	
+	/* Edge Spring Settings */
+	
+	prop= RNA_def_property(srna, "pull", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "inspring");
+	RNA_def_property_range(prop, 0.0f, 0.999f);
+	RNA_def_property_ui_text(prop, "Pull", "Edge spring stiffness when longer than rest length");
+	
+	prop= RNA_def_property(srna, "push", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "inpush");
+	RNA_def_property_range(prop, 0.0f, 0.999f);
+	RNA_def_property_ui_text(prop, "Push", "Edge spring stiffness when shorter than rest length");
+	
+	prop= RNA_def_property(srna, "damp", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "infrict");
+	RNA_def_property_range(prop, 0.0f, 50.0f);
+	RNA_def_property_ui_text(prop, "Damp", "Edge spring friction");
+	
+	prop= RNA_def_property(srna, "spring_lenght", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "springpreload");
+	RNA_def_property_range(prop, 0.0f, 200.0f);
+	RNA_def_property_ui_text(prop, "SL", "Alter spring lenght to shrink/blow up (unit %) 0 to disable");
+	
+	prop= RNA_def_property(srna, "aero", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "aeroedge");
+	RNA_def_property_range(prop, 0.0f, 30000.0f);
+	RNA_def_property_ui_text(prop, "Aero", "Make edges 'sail'");
+	
+	prop= RNA_def_property(srna, "plastic", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "plastic");
+	RNA_def_property_range(prop, 0.0f, 100.0f);
+	RNA_def_property_ui_text(prop, "Plastic", "Permanent deform");
+	
+	prop= RNA_def_property(srna, "bending", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "secondspring");
+	RNA_def_property_range(prop, 0.0f, 10.0f);
+	RNA_def_property_ui_text(prop, "Bending", "Bending Stiffness");
+	
+	prop= RNA_def_property(srna, "shear", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "shearstiff");
+	RNA_def_property_range(prop, 0.0f, 1.0f);
+	RNA_def_property_ui_text(prop, "Shear", "Shear Stiffness");
+	
+	/* Collision */
+	
+	prop= RNA_def_property(srna, "collision_type", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_sdna(prop, NULL, "sbc_mode");
+	RNA_def_property_enum_items(prop, collision_type_items);
+	RNA_def_property_ui_text(prop, "Collision Type", "Choose Collision Type");
+	
+	prop= RNA_def_property(srna, "ball_size", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "colball");
+	RNA_def_property_range(prop, -10.0f, 10.0f);
+	RNA_def_property_ui_text(prop, "Ball Size", "Absolute ball size or factor if not manual adjusted");
+	
+	prop= RNA_def_property(srna, "ball_stiff", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "ballstiff");
+	RNA_def_property_range(prop, 0.001f, 100.0f);
+	RNA_def_property_ui_text(prop, "Ball Size", "Ball inflating presure");
+	
+	prop= RNA_def_property(srna, "ball_damp", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "balldamp");
+	RNA_def_property_range(prop, 0.001f, 1.0f);
+	RNA_def_property_ui_text(prop, "Ball Size", "Blending to inelastic collision");
+	
+	/* Solver */
+	
+	prop= RNA_def_property(srna, "error_limit", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "rklimit");
+	RNA_def_property_range(prop, 0.001f, 10.0f);
+	RNA_def_property_ui_text(prop, "Error Limit", "The Runge-Kutta ODE solver error limit, low value gives more precision, high values speed");
+	
+	prop= RNA_def_property(srna, "minstep", PROP_INT, PROP_NONE);
+	RNA_def_property_int_sdna(prop, NULL, "minloops");
+	RNA_def_property_range(prop, 0, 30000);
+	RNA_def_property_ui_text(prop, "Min Step", "Minimal # solver steps/frame");
+	
+	prop= RNA_def_property(srna, "maxstep", PROP_INT, PROP_NONE);
+	RNA_def_property_int_sdna(prop, NULL, "maxloops");
+	RNA_def_property_range(prop, 0, 30000);
+	RNA_def_property_ui_text(prop, "Max Step", "Maximal # solver steps/frame");
+	
+	prop= RNA_def_property(srna, "choke", PROP_INT, PROP_NONE);
+	RNA_def_property_int_sdna(prop, NULL, "choke");
+	RNA_def_property_range(prop, 0, 100);
+	RNA_def_property_ui_text(prop, "Choke", "'Viscosity' inside collision target");
+	
+	prop= RNA_def_property(srna, "fuzzy", PROP_INT, PROP_NONE);
+	RNA_def_property_int_sdna(prop, NULL, "fuzzyness");
+	RNA_def_property_range(prop, 1, 100);
+	RNA_def_property_ui_text(prop, "Fuzzy", "Fuzzyness while on collision, high values make collsion handling faster but less stable");
+	
+	prop= RNA_def_property(srna, "auto_step", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "solverflags", SBSO_OLDERR);
+	RNA_def_property_ui_text(prop, "V", "Use velocities for automagic step sizes");
+	
+	prop= RNA_def_property(srna, "diagnose", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "solverflags", SBSO_MONITOR);
+	RNA_def_property_ui_text(prop, "Print Performance to Console", "Turn on SB diagnose console prints");
+	
+	/* Flags */
+	
+	prop= RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_enabled_get", "rna_SoftBodySettings_enabled_set");
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_ui_text(prop, "Enable", "Sets object to become soft body.");
+	
+	prop= RNA_def_property(srna, "use_goal", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_use_goal_get", "rna_SoftBodySettings_use_goal_set");
+	RNA_def_property_ui_text(prop, "Use Goal", "Define forces for vertices to stick to animated position.");
+	
+	prop= RNA_def_property(srna, "use_edges", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_use_edges_get", "rna_SoftBodySettings_use_edges_set");
+	RNA_def_property_ui_text(prop, "Use Edges", "Use Edges as springs");
+	
+	prop= RNA_def_property(srna, "stiff_quads", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_stiff_quads_get", "rna_SoftBodySettings_stiff_quads_set");
+	RNA_def_property_ui_text(prop, "Stiff Quads", "Adds diagonal springs on 4-gons.");
+	
+	prop= RNA_def_property(srna, "edge_collision", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_edge_collision_get", "rna_SoftBodySettings_edge_collision_set");
+	RNA_def_property_ui_text(prop, "Edge Collision", "Edges collide too.");
+	
+	prop= RNA_def_property(srna, "face_collision", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_face_collision_get", "rna_SoftBodySettings_face_collision_set");
+	RNA_def_property_ui_text(prop, "Face Collision", "Faces collide too, SLOOOOOW warning.");
+	
+	prop= RNA_def_property(srna, "new_aero", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_new_aero_get", "rna_SoftBodySettings_new_aero_set");
+	RNA_def_property_ui_text(prop, "N", "New aero(uses angle and length).");
+	
+	prop= RNA_def_property(srna, "self_collision", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_funcs(prop, "rna_SoftBodySettings_self_collision_get", "rna_SoftBodySettings_self_collision_set");
+	RNA_def_property_ui_text(prop, "Self Collision", "Enable naive vertex ball self collision.");
 }
 
 void RNA_def_object_force(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_packedfile.c b/source/blender/makesrna/intern/rna_packedfile.c
index 6b6db71ef87..6b9a708f555 100644
--- a/source/blender/makesrna/intern/rna_packedfile.c
+++ b/source/blender/makesrna/intern/rna_packedfile.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_packedfile.c 19382 2009-03-23 13:24:48Z blendix $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index efcd9dbd434..d60a215b498 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_particle.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -38,6 +38,7 @@
 #include "DNA_scene_types.h"
 
 #include "WM_types.h"
+#include "WM_api.h"
 
 #ifdef RNA_RUNTIME
 
@@ -45,48 +46,110 @@
 #include "BKE_depsgraph.h"
 #include "BKE_particle.h"
 
+#include "BLI_arithb.h"
+
+/* property update functions */
 static void rna_Particle_redo(bContext *C, PointerRNA *ptr)
 {
+	Scene *scene = CTX_data_scene(C);
 	ParticleSettings *part;
-	if(ptr->type==&RNA_ParticleSystem)
-		part = ((ParticleSystem*)ptr->data)->part;
-	else
-		part = ptr->id.data;
+	if(ptr->type==&RNA_ParticleSystem) {
+		ParticleSystem *psys = (ParticleSystem*)ptr->data;
+		Object *ob = psys_find_object(scene, psys);
+		
+		psys->recalc = PSYS_RECALC_REDO;
 
-	psys_flush_particle_settings(CTX_data_scene(C), part, PSYS_RECALC_REDO);
+		if(ob)
+			DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+	}
+	else {
+		part = ptr->id.data;
+		psys_flush_particle_settings(scene, part, PSYS_RECALC_REDO);
+	}
 }
 
 static void rna_Particle_reset(bContext *C, PointerRNA *ptr)
 {
+	Scene *scene = CTX_data_scene(C);
 	ParticleSettings *part;
-	if(ptr->type==&RNA_ParticleSystem)
-		part = ((ParticleSystem*)ptr->data)->part;
-	else
-		part = ptr->id.data;
 
-	psys_flush_particle_settings(CTX_data_scene(C), part, PSYS_RECALC_RESET|PSYS_RECALC_REDO);
+	if(ptr->type==&RNA_ParticleSystem) {
+		ParticleSystem *psys = (ParticleSystem*)ptr->data;
+		Object *ob = psys_find_object(scene, psys);
+		
+		psys->recalc = PSYS_RECALC_RESET;
+
+		if(ob) {
+			DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+		}
+	}
+	else {
+		part = ptr->id.data;
+		psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET);
+	}
 }
 
 static void rna_Particle_change_type(bContext *C, PointerRNA *ptr)
 {
+	Scene *scene = CTX_data_scene(C);
 	ParticleSettings *part;
-	if(ptr->type==&RNA_ParticleSystem)
-		part = ((ParticleSystem*)ptr->data)->part;
-	else
-		part = ptr->id.data;
 
-	psys_flush_particle_settings(CTX_data_scene(C), part, PSYS_RECALC_RESET|PSYS_RECALC_TYPE|PSYS_RECALC_REDO);
+	if(ptr->type==&RNA_ParticleSystem) {
+		ParticleSystem *psys = (ParticleSystem*)ptr->data;
+		Object *ob = psys_find_object(scene, psys);
+		
+		psys->recalc = PSYS_RECALC_RESET|PSYS_RECALC_TYPE;
+
+		if(ob) {
+			DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+		}
+	}
+	else {
+		part = ptr->id.data;
+		psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET|PSYS_RECALC_TYPE);
+	}
 }
 
 static void rna_Particle_redo_child(bContext *C, PointerRNA *ptr)
 {
+	Scene *scene = CTX_data_scene(C);
 	ParticleSettings *part;
-	if(ptr->type==&RNA_ParticleSystem)
-		part = ((ParticleSystem*)ptr->data)->part;
-	else
+
+	if(ptr->type==&RNA_ParticleSystem) {
+		ParticleSystem *psys = (ParticleSystem*)ptr->data;
+		Object *ob = psys_find_object(scene, psys);
+		
+		psys->recalc = PSYS_RECALC_CHILD;
+
+		if(ob)
+			DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+	}
+	else {
 		part = ptr->id.data;
 
-	psys_flush_particle_settings(CTX_data_scene(C), part, PSYS_RECALC_CHILD);
+		psys_flush_particle_settings(scene, part, PSYS_RECALC_CHILD);
+	}
+}
+static PointerRNA rna_particle_settings_get(PointerRNA *ptr)
+{
+	Object *ob= (Object*)ptr->id.data;
+	ParticleSettings *part = psys_get_current(ob)->part;
+
+	return rna_pointer_inherit_refine(ptr, &RNA_ParticleSettings, part);
+}
+
+static void rna_particle_settings_set(PointerRNA *ptr, PointerRNA value)
+{
+	Object *ob= (Object*)ptr->id.data;
+	ParticleSystem *psys = psys_get_current(ob);
+
+	if(psys->part)
+		psys->part->id.us--;
+
+	psys->part = (ParticleSettings *)value.data;
+
+	if(psys->part)
+		psys->part->id.us++;
 }
 static void rna_PartSettings_start_set(struct PointerRNA *ptr, float value)
 {
@@ -887,7 +950,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
 	RNA_def_property_int_sdna(prop, NULL, "disp");
 	RNA_def_property_range(prop, 0, 100);
 	RNA_def_property_ui_text(prop, "Display", "Percentage of particles to display in 3d view");
-	RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
+	RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
 
 	prop= RNA_def_property(srna, "material", PROP_INT, PROP_NONE);
 	RNA_def_property_int_sdna(prop, NULL, "omat");
@@ -1424,14 +1487,9 @@ static void rna_def_particle_settings(BlenderRNA *brna)
 	RNA_def_property_flag(prop, PROP_EDITABLE);
 	RNA_def_property_ui_text(prop, "Billboard Object", "Billboards face this object (default is active camera)");
 	RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
-
-#if 0
-	prop= RNA_def_property(srna, "ipo", PROP_POINTER, PROP_NONE);
-	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-	RNA_def_property_pointer_sdna(prop, NULL, "ipo");
-	RNA_def_property_struct_type(prop, "Ipo");
-	RNA_def_property_ui_text(prop, "Ipo", "");
-#endif
+	
+	/* animation here? */
+	rna_def_animdata_common(srna);
 
 //	struct PartDeflect *pd;
 //	struct PartDeflect *pd2;
@@ -1452,9 +1510,15 @@ static void rna_def_particle_system(BlenderRNA *brna)
 	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
 	RNA_def_struct_name_property(srna, prop);
 
+	/* access to particle settings is redirected through functions */
+	/* to allow proper id-buttons functionality */
 	prop= RNA_def_property(srna, "settings", PROP_POINTER, PROP_NEVER_NULL);
-	RNA_def_property_pointer_sdna(prop, NULL, "part");
+	//RNA_def_property_pointer_sdna(prop, NULL, "part");
+	RNA_def_property_struct_type(prop, "ParticleSettings");
+	RNA_def_property_flag(prop, PROP_EDITABLE);
+	RNA_def_property_pointer_funcs(prop, "rna_particle_settings_get", "rna_particle_settings_set", NULL);
 	RNA_def_property_ui_text(prop, "Settings", "Particle system settings.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
 
 	prop= RNA_def_property(srna, "particles", PROP_COLLECTION, PROP_NONE);
 	RNA_def_property_collection_sdna(prop, NULL, "particles", "totpart");
@@ -1669,6 +1733,14 @@ static void rna_def_particle_system(BlenderRNA *brna)
 	RNA_def_property_pointer_sdna(prop, NULL, "pointcache");
 	RNA_def_property_struct_type(prop, "PointCache");
 	RNA_def_property_ui_text(prop, "Point Cache", "");
+
+	/* offset ob */
+	prop= RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE);
+	RNA_def_property_pointer_sdna(prop, NULL, "parent");
+	RNA_def_property_flag(prop, PROP_EDITABLE);
+	RNA_def_property_ui_text(prop, "Parent", "Use this object's coordinate system instead of global coordinate system.");
+	RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
+
 }
 
 void RNA_def_particle(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index 54cf1dea0ac..b8863540bdf 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_pose.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_property.c b/source/blender/makesrna/intern/rna_property.c
index a0a5c41b19c..a840552b86f 100644
--- a/source/blender/makesrna/intern/rna_property.c
+++ b/source/blender/makesrna/intern/rna_property.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_property.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_radio.c b/source/blender/makesrna/intern/rna_radio.c
deleted file mode 100644
index 8b862b4c535..00000000000
--- a/source/blender/makesrna/intern/rna_radio.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/**
- * $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.
- *
- * Contributor(s): Blender Foundation (2008).
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include 
-
-#include "RNA_define.h"
-#include "RNA_types.h"
-
-#include "rna_internal.h"
-
-#include "DNA_radio_types.h"
-
-#ifdef RNA_RUNTIME
-
-#else
-
-void RNA_def_radio(BlenderRNA *brna)
-{
-	StructRNA *srna;
-	PropertyRNA *prop;
-	static EnumPropertyItem prop_drawtype_items[] = { 
-		{RAD_WIREFRAME, "WIREFRAME", 0, "Wireframe", "Enables Wireframe draw mode"},
-		{RAD_SOLID, "SOLID", 0, "Solid", "Enables Solid draw mode"},
-		{RAD_GOURAUD, "GOURAUD", 0, "Gouraud", "Enables Gouraud draw mode"},
-		{0, NULL, 0, NULL, NULL}};
-
-	srna= RNA_def_struct(brna, "Radiosity", NULL);
-	RNA_def_struct_ui_text(srna, "Radiosity", "Settings for radiosity simulation of indirect diffuse lighting.");
-	RNA_def_struct_sdna(srna, "Radio");
-
-	/* Enums */
-	prop= RNA_def_property(srna, "draw_mode", PROP_ENUM, PROP_NONE);
-	RNA_def_property_enum_sdna(prop, NULL, "drawtype");
-	RNA_def_property_enum_items(prop, prop_drawtype_items);
-	RNA_def_property_ui_text(prop, "Draw Mode", "Radiosity draw modes.");
-
-	/* Number values */
-	prop= RNA_def_property(srna, "hemi_resolution", PROP_INT, PROP_NONE);
-	RNA_def_property_int_sdna(prop, NULL, "hemires");
-	RNA_def_property_range(prop, 100, 1000);
-	RNA_def_property_ui_text(prop, "Hemi Resolution", "Sets the size of a hemicube.");
-
-	prop= RNA_def_property(srna, "max_iterations", PROP_INT, PROP_NONE);
-	RNA_def_property_int_sdna(prop, NULL, "maxiter");
-	RNA_def_property_range(prop, 0, 10000);
-	RNA_def_property_ui_text(prop, "Max Iterations", "Limits the maximum number of radiosity rounds.");
-
-	prop= RNA_def_property(srna, "multiplier", PROP_FLOAT, PROP_NONE);
-	RNA_def_property_float_sdna(prop, NULL, "radfac");
-	RNA_def_property_range(prop, 0.001f, 250.0f);
-	RNA_def_property_ui_text(prop, "Multiplier", "Multiplies the energy values.");
-
-	prop= RNA_def_property(srna, "gamma", PROP_FLOAT, PROP_NONE);
-	RNA_def_property_float_sdna(prop, NULL, "gamma");
-	RNA_def_property_range(prop, 0.2f, 10.0f);
-	RNA_def_property_ui_text(prop, "Gamma", "Changes the contrast of the energy values.");
-
-	prop= RNA_def_property(srna, "convergence", PROP_FLOAT, PROP_NONE);
-	RNA_def_property_float_sdna(prop, NULL, "convergence");
-	RNA_def_property_range(prop, 0.0f, 1.0f);
-	RNA_def_property_ui_text(prop, "Convergence", "Sets the lower threshold of unshot energy.");
-
-	prop= RNA_def_property(srna, "element_max", PROP_INT, PROP_NONE);
-	RNA_def_property_int_sdna(prop, NULL, "elma");
-	RNA_def_property_range(prop, 1, 500);
-	RNA_def_property_ui_text(prop, "Element Max", "Sets maximum size of an element");
-
-	prop= RNA_def_property(srna, "element_min", PROP_INT, PROP_NONE);
-	RNA_def_property_int_sdna(prop, NULL, "elmi");
-	RNA_def_property_range(prop, 1, 100);
-	RNA_def_property_ui_text(prop, "Element Min", "Sets minimum size of an element");
-
-	prop= RNA_def_property(srna, "patch_max", PROP_INT, PROP_NONE);
-	RNA_def_property_int_sdna(prop, NULL, "pama");
-	RNA_def_property_range(prop, 10, 1000);
-	RNA_def_property_ui_text(prop, "Patch Max", "Sets maximum size of a patch.");
-
-	prop= RNA_def_property(srna, "patch_min", PROP_INT, PROP_NONE);
-	RNA_def_property_int_sdna(prop, NULL, "pami");
-	RNA_def_property_range(prop, 10, 1000);
-	RNA_def_property_ui_text(prop, "Patch Min", "Sets minimum size of a patch.");
-
-	prop= RNA_def_property(srna, "subshoot_patch", PROP_INT, PROP_NONE);
-	RNA_def_property_int_sdna(prop, NULL, "subshootp");
-	RNA_def_property_range(prop, 0, 10);
-	RNA_def_property_ui_text(prop, "SubShoot Patch", "Sets the number of times the environment is tested to detect paths.");
-
-	prop= RNA_def_property(srna, "subshoot_element", PROP_INT, PROP_NONE);
-	RNA_def_property_int_sdna(prop, NULL, "subshoote");
-	RNA_def_property_range(prop, 0, 10);
-	RNA_def_property_ui_text(prop, "SubShoot Element", "Sets the number of times the environment is tested to detect elements.");
-
-	prop= RNA_def_property(srna, "max_elements", PROP_INT, PROP_NONE);
-	RNA_def_property_int_sdna(prop, NULL, "maxnode");
-	RNA_def_property_range(prop, 1, 250000);
-	RNA_def_property_ui_text(prop, "Max Elements", "Sets the maximum allowed number of elements.");
-
-	prop= RNA_def_property(srna, "max_subdiv_shoot", PROP_INT, PROP_NONE);
-	RNA_def_property_int_sdna(prop, NULL, "maxsublamp");
-	RNA_def_property_range(prop, 1, 250);
-	RNA_def_property_ui_text(prop, "Max Subdiv Shoot", "Sets the maximum number of initial shoot patches that are evaluated");
-
-	prop= RNA_def_property(srna, "remove_doubles_limit", PROP_INT, PROP_NONE);
-	RNA_def_property_int_sdna(prop, NULL, "nodelim");
-	RNA_def_property_range(prop, 0, 50);
-	RNA_def_property_ui_text(prop, "Remove Doubles Limit", "Sets the range for removing doubles");
-
-	/* flag */
-	prop= RNA_def_property(srna, "show_limits", PROP_BOOLEAN, PROP_NONE);
-	RNA_def_property_boolean_sdna(prop, NULL, "flag", RAD_SHOWLIMITS);
-	RNA_def_property_ui_text(prop, "Show Limits", "Draws patch and element limits");
-
-	prop= RNA_def_property(srna, "show_z", PROP_BOOLEAN, PROP_NONE);
-	RNA_def_property_boolean_sdna(prop, NULL, "flag", RAD_SHOWZ);
-	RNA_def_property_ui_text(prop, "Show Z", "Draws limits differently");
-}
-
-#endif
-
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index 5066654434e..14db8ea3377 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_rna.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -309,14 +309,16 @@ PointerRNA rna_builtin_properties_lookup_string(PointerRNA *ptr, const char *key
 		}
 	} while((srna=srna->base));
 
-	group= RNA_struct_idproperties(ptr, 0);
+	if(ptr->data) {
+		group= RNA_struct_idproperties(ptr, 0);
 
-	if(group) {
-		for(idp=group->data.group.first; idp; idp=idp->next) {
-			if(strcmp(idp->name, key) == 0) {
-				propptr.type= &RNA_Property;
-				propptr.data= idp;
-				return propptr;
+		if(group) {
+			for(idp=group->data.group.first; idp; idp=idp->next) {
+				if(strcmp(idp->name, key) == 0) {
+					propptr.type= &RNA_Property;
+					propptr.data= idp;
+					return propptr;
+				}
 			}
 		}
 	}
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 875d657dee4..59d036a84dc 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_scene.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -151,8 +151,34 @@ void rna_def_tool_settings(BlenderRNA  *brna)
 	StructRNA *srna;
 	PropertyRNA *prop;
 
+	static EnumPropertyItem uv_select_mode_items[] = {
+		{UV_SELECT_VERTEX, "VERTEX", ICON_VERTEXSEL, "Vertex", "Vertex selection mode."},
+		{UV_SELECT_EDGE, "EDGE", ICON_EDGESEL, "Edge", "Edge selection mode."},
+		{UV_SELECT_FACE, "FACE", ICON_FACESEL, "Face", "Face selection mode."},
+		{UV_SELECT_ISLAND, "ISLAND", ICON_LINKEDSEL, "Island", "Island selection mode."},
+		{0, NULL, 0, NULL, NULL}};
+
+	static EnumPropertyItem mesh_select_mode_items[] = {
+		{SCE_SELECT_VERTEX, "VERTEX", ICON_VERTEXSEL, "Vertex", "Vertex selection mode."},
+		{SCE_SELECT_EDGE, "EDGE", ICON_EDGESEL, "Edge", "Edge selection mode."},
+		{SCE_SELECT_FACE, "FACE", ICON_FACESEL, "Face", "Face selection mode."},
+		{0, NULL, 0, NULL, NULL}};
+
+	static EnumPropertyItem snap_element_items[] = {
+		{SCE_SNAP_MODE_VERTEX, "VERTEX", ICON_SNAP_VERTEX, "Vertex", "Snap to vertices."},
+		{SCE_SNAP_MODE_EDGE, "EDGE", ICON_SNAP_EDGE, "Edge", "Snap to edges."},
+		{SCE_SNAP_MODE_FACE, "FACE", ICON_SNAP_FACE, "Face", "Snap to faces."},
+		{SCE_SNAP_MODE_VOLUME, "VOLUME", ICON_SNAP_VOLUME, "Volume", "Snap to volume."},
+		{0, NULL, 0, NULL, NULL}};
+
+	static EnumPropertyItem snap_mode_items[] = {
+		{SCE_SNAP_TARGET_CLOSEST, "CLOSEST", 0, "Closest", "Snap closest point onto target."},
+		{SCE_SNAP_TARGET_CENTER, "CENTER", 0, "Center", "Snap center onto target."},
+		{SCE_SNAP_TARGET_MEDIAN, "MEDIAN", 0, "Median", "Snap median onto target."},
+		{SCE_SNAP_TARGET_ACTIVE, "ACTIVE", 0, "Active", "Snap active onto target."},
+		{0, NULL, 0, NULL, NULL}};
+
 	srna= RNA_def_struct(brna, "ToolSettings", NULL);
-	RNA_def_struct_nested(brna, srna, "Scene");
 	RNA_def_struct_ui_text(srna, "Tool Settings", "");
 	
 	prop= RNA_def_property(srna, "sculpt", PROP_POINTER, PROP_NONE);
@@ -163,6 +189,67 @@ void rna_def_tool_settings(BlenderRNA  *brna)
 	RNA_def_property_struct_type(prop, "VPaint");
 	RNA_def_property_ui_text(prop, "Vertex Paint", "");
 
+	/* Transform */
+	prop= RNA_def_property(srna, "proportional_editing", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "proportional", 0);
+	RNA_def_property_ui_text(prop, "Proportional Editing", "Proportional editing mode.");
+
+	prop= RNA_def_property(srna, "proportional_editing_falloff", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_sdna(prop, NULL, "prop_mode");
+	RNA_def_property_enum_items(prop, prop_mode_items);
+	RNA_def_property_ui_text(prop, "Proportional Editing Falloff", "Falloff type for proportional editing mode.");
+
+	prop= RNA_def_property(srna, "snap", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP);
+	RNA_def_property_ui_text(prop, "Snap", "Snap while Ctrl is held during transform.");
+	RNA_def_property_ui_icon(prop, ICON_SNAP_GEAR, 1);
+
+	prop= RNA_def_property(srna, "snap_align_rotation", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_ROTATE);
+	RNA_def_property_ui_text(prop, "Snap Align Rotation", "Align rotation with the snapping target.");
+	RNA_def_property_ui_icon(prop, ICON_SNAP_NORMAL, 0);
+
+	prop= RNA_def_property(srna, "snap_element", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_sdna(prop, NULL, "snap_mode");
+	RNA_def_property_enum_items(prop, snap_element_items);
+	RNA_def_property_ui_text(prop, "Snap Element", "Type of element to snap to.");
+
+	prop= RNA_def_property(srna, "snap_mode", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_sdna(prop, NULL, "snap_target");
+	RNA_def_property_enum_items(prop, snap_mode_items);
+	RNA_def_property_ui_text(prop, "Snap Mode", "Which part to snap onto the target.");
+
+	prop= RNA_def_property(srna, "snap_peel_object", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_PEEL_OBJECT);
+	RNA_def_property_ui_text(prop, "Snap Peel Object", "Consider objects as whole when finding volume center.");
+	RNA_def_property_ui_icon(prop, ICON_SNAP_PEEL_OBJECT, 0);
+
+	/* UV */
+	prop= RNA_def_property(srna, "uv_selection_mode", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_sdna(prop, NULL, "uv_selectmode");
+	RNA_def_property_enum_items(prop, uv_select_mode_items);
+	RNA_def_property_ui_text(prop, "UV Selection Mode", "UV selection and display mode.");
+
+	prop= RNA_def_property(srna, "uv_sync_selection", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "uv_flag", UV_SYNC_SELECTION);
+	RNA_def_property_ui_text(prop, "UV Sync Selection", "Keep UV and edit mode mesh selection in sync.");
+	RNA_def_property_ui_icon(prop, ICON_EDIT, 0);
+
+	prop= RNA_def_property(srna, "uv_local_view", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "uv_flag", UV_SHOW_SAME_IMAGE);
+	RNA_def_property_ui_text(prop, "UV Local View", "Draw only faces with the currently displayed image assigned.");
+
+	/* Mesh */
+	prop= RNA_def_property(srna, "mesh_selection_mode", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_bitflag_sdna(prop, NULL, "selectmode");
+	RNA_def_property_enum_items(prop, mesh_select_mode_items);
+	RNA_def_property_ui_text(prop, "Mesh Selection Mode", "Mesh selection and display mode.");
+
+	prop= RNA_def_property(srna, "vertex_group_weight", PROP_FLOAT, PROP_PERCENTAGE);
+	RNA_def_property_float_sdna(prop, NULL, "vgroup_weight");
+	RNA_def_property_ui_text(prop, "Vertex Group Weight", "Weight to assign in vertex groups.");
+
+	/* Sculpt */
 	rna_def_sculpt(brna);
 }
 
@@ -852,10 +939,6 @@ void RNA_def_scene(BlenderRNA *brna)
 {
 	StructRNA *srna;
 	PropertyRNA *prop;
-	static EnumPropertyItem unwrapper_items[] = {
-		{0, "CONFORMAL", 0, "Conformal", ""},
-		{1, "ANGLEBASED", 0, "Angle Based", ""}, 
-		{0, NULL, 0, NULL, NULL}};
 
 	srna= RNA_def_struct(brna, "Scene", "ID");
 	RNA_def_struct_ui_text(srna, "Scene", "Scene consisting objects and defining time and render related settings.");
@@ -887,11 +970,6 @@ void RNA_def_scene(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Visible Layers", "Layers visible when rendering the scene.");
 	RNA_def_property_boolean_funcs(prop, NULL, "rna_Scene_layer_set");
 
-	prop= RNA_def_property(srna, "proportional_editing_falloff", PROP_ENUM, PROP_NONE);
-	RNA_def_property_enum_sdna(prop, NULL, "prop_mode");
-	RNA_def_property_enum_items(prop, prop_mode_items);
-	RNA_def_property_ui_text(prop, "Proportional Editing Falloff", "Falloff type for proportional editing mode.");
-
 	prop= RNA_def_property(srna, "current_frame", PROP_INT, PROP_NONE);
 	RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
 	RNA_def_property_int_sdna(prop, NULL, "r.cfra");
@@ -924,11 +1002,6 @@ void RNA_def_scene(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Stamp Note", "User define note for the render stamping.");
 	RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
 
-	prop= RNA_def_property(srna, "unwrapper", PROP_ENUM, PROP_NONE);
-	RNA_def_property_enum_sdna(prop, NULL, "toolsettings->unwrapper");
-	RNA_def_property_enum_items(prop, unwrapper_items);
-	RNA_def_property_ui_text(prop, "Unwrapper", "Unwrap algorithm used by the Unwrap tool.");
-	
 	prop= RNA_def_property(srna, "nodetree", PROP_POINTER, PROP_NONE);
 	RNA_def_property_ui_text(prop, "Node Tree", "Compositing node tree.");
 	
@@ -936,10 +1009,6 @@ void RNA_def_scene(BlenderRNA *brna)
 	RNA_def_property_pointer_sdna(prop, NULL, "ed");
 	RNA_def_property_struct_type(prop, "SequenceEditor");
 	RNA_def_property_ui_text(prop, "Sequence Editor", "");
-
-	prop= RNA_def_property(srna, "radiosity", PROP_POINTER, PROP_NONE);
-	RNA_def_property_pointer_sdna(prop, NULL, "radio");
-	RNA_def_property_ui_text(prop, "Radiosity", "");
 	
 	prop= RNA_def_property(srna, "keyingsets", PROP_COLLECTION, PROP_NONE);
 	RNA_def_property_collection_sdna(prop, NULL, "keyingsets", NULL);
diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c
index 35191744f22..a4ba6ec172b 100644
--- a/source/blender/makesrna/intern/rna_screen.c
+++ b/source/blender/makesrna/intern/rna_screen.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_screen.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -42,6 +42,31 @@ EnumPropertyItem region_type_items[] = {
 
 #ifdef RNA_RUNTIME
 
+#include "WM_api.h"
+#include "WM_types.h"
+
+static void rna_Screen_scene_set(PointerRNA *ptr, PointerRNA value)
+{
+	bScreen *sc= (bScreen*)ptr->data;
+
+	if(value.data == NULL)
+		return;
+
+	/* exception: can't set screens inside of area/region handers */
+	sc->newscene= value.data;
+}
+
+static void rna_Screen_scene_update(bContext *C, PointerRNA *ptr)
+{
+	bScreen *sc= (bScreen*)ptr->data;
+
+	/* exception: can't set screens inside of area/region handers */
+	if(sc->newscene) {
+		WM_event_add_notifier(C, NC_SCENE|ND_SCENEBROWSE, sc->newscene);
+		sc->newscene= NULL;
+	}
+}
+
 #else
 
 static void rna_def_scrarea(BlenderRNA *brna)
@@ -94,6 +119,9 @@ static void rna_def_bscreen(BlenderRNA *brna)
 	
 	prop= RNA_def_property(srna, "scene", PROP_POINTER, PROP_NEVER_NULL);
 	RNA_def_property_ui_text(prop, "Scene", "Active scene to be edited in the screen.");
+	RNA_def_property_flag(prop, PROP_EDITABLE);
+	RNA_def_property_pointer_funcs(prop, NULL, "rna_Screen_scene_set", NULL);
+	RNA_def_property_update(prop, 0, "rna_Screen_scene_update");
 	
 	prop= RNA_def_property(srna, "areas", PROP_COLLECTION, PROP_NONE);
 	RNA_def_property_collection_sdna(prop, NULL, "areabase", NULL);
diff --git a/source/blender/makesrna/intern/rna_scriptlink.c b/source/blender/makesrna/intern/rna_scriptlink.c
index db33e7a8543..b486cd4a874 100644
--- a/source/blender/makesrna/intern/rna_scriptlink.c
+++ b/source/blender/makesrna/intern/rna_scriptlink.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_scriptlink.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c
index d31ec7b9b83..53bd230870f 100644
--- a/source/blender/makesrna/intern/rna_sensor.c
+++ b/source/blender/makesrna/intern/rna_sensor.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_sensor.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_sequence.c b/source/blender/makesrna/intern/rna_sequence.c
index 5b76db4ff43..055e67fb135 100644
--- a/source/blender/makesrna/intern/rna_sequence.c
+++ b/source/blender/makesrna/intern/rna_sequence.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_sequence.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_sound.c b/source/blender/makesrna/intern/rna_sound.c
index f26024f7a9e..363a5595b43 100644
--- a/source/blender/makesrna/intern/rna_sound.c
+++ b/source/blender/makesrna/intern/rna_sound.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_sound.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 12f0c110ea2..ae3b249e51f 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_space.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -96,8 +96,8 @@ static StructRNA* rna_Space_refine(struct PointerRNA *ptr)
 			return &RNA_SpaceOutliner;
 		case SPACE_BUTS:
 			return &RNA_SpaceButtonsWindow;
-		/* case SPACE_FILE:
-			return &RNA_SpaceFileBrowser;*/
+		case SPACE_FILE:
+			return &RNA_SpaceFileBrowser;
 		case SPACE_IMAGE:
 			return &RNA_SpaceImageEditor;
 		/*case SPACE_INFO:
@@ -210,6 +210,13 @@ void rna_SpaceTextEditor_text_set(PointerRNA *ptr, PointerRNA value)
 	st->top= 0;
 }
 
+void rna_SpaceFileBrowser_params_set(PointerRNA *ptr, PointerRNA value)
+{
+	SpaceFile *sfile= (SpaceFile*)(ptr->data);
+
+	sfile->params= value.data;
+}
+
 /* Space Buttons */
 
 StructRNA *rna_SpaceButtonsWindow_pin_id_typef(PointerRNA *ptr)
@@ -246,19 +253,10 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
 	StructRNA *srna;
 	PropertyRNA *prop;
 
-#if 0
-	static EnumPropertyItem select_mode_items[] = {
-		{SI_SELECT_VERTEX, "VERTEX", 0, "Vertex", "Vertex selection mode."},
-		//{SI_SELECT_EDGE, "Edge", 0, "Edge", "Edge selection mode."},
-		{SI_SELECT_FACE, "FACE", 0, "Face", "Face selection mode."},
-		{SI_SELECT_ISLAND, "ISLAND", 0, "Island", "Island selection mode."},
-		{0, NULL, 0, NULL, NULL}};
-#endif
-
 	static EnumPropertyItem sticky_mode_items[] = {
-		{SI_STICKY_DISABLE, "DISABLED", 0, "Disabled", "Sticky vertex selection disabled."},
-		{SI_STICKY_LOC, "SHARED_LOCATION", 0, "SHARED_LOCATION", "Select UVs that are at the same location and share a mesh vertex."},
-		{SI_STICKY_VERTEX, "SHARED_VERTEX", 0, "SHARED_VERTEX", "Select UVs that share mesh vertex, irrespective if they are in the same location."},
+		{SI_STICKY_DISABLE, "DISABLED", ICON_STICKY_UVS_DISABLE, "Disabled", "Sticky vertex selection disabled."},
+		{SI_STICKY_LOC, "SHARED_LOCATION", ICON_STICKY_UVS_LOC, "SHARED_LOCATION", "Select UVs that are at the same location and share a mesh vertex."},
+		{SI_STICKY_VERTEX, "SHARED_VERTEX", ICON_STICKY_UVS_VERT, "SHARED_VERTEX", "Select UVs that share mesh vertex, irrespective if they are in the same location."},
 		{0, NULL, 0, NULL, NULL}};
 
 	static EnumPropertyItem dt_uv_items[] = {
@@ -273,17 +271,18 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
 		{SI_UVDT_STRETCH_AREA, "AREA", 0, "Area", "Area distortion between UV and 3D faces."},
 		{0, NULL, 0, NULL, NULL}};
 
+	static EnumPropertyItem pivot_items[] = {
+		{V3D_CENTER, "CENTER", ICON_ROTATE, "Bounding Box Center", ""},
+		{V3D_CENTROID, "MEDIAN", ICON_ROTATECENTER, "Median Point", ""},
+		{V3D_CURSOR, "CURSOR", ICON_CURSOR, "2D Cursor", ""},
+		{0, NULL, 0, NULL, NULL}};
+
 	srna= RNA_def_struct(brna, "SpaceUVEditor", NULL);
 	RNA_def_struct_sdna(srna, "SpaceImage");
 	RNA_def_struct_nested(brna, srna, "SpaceImageEditor");
 	RNA_def_struct_ui_text(srna, "Space UV Editor", "UV editor data for the image editor space.");
 
 	/* selection */
-	/*prop= RNA_def_property(srna, "selection_mode", PROP_ENUM, PROP_NONE);
-	RNA_def_property_enum_sdna(prop, NULL, "selectmode");
-	RNA_def_property_enum_items(prop, select_mode_items);
-	RNA_def_property_ui_text(prop, "Selection Mode", "UV selection and display mode.");*/
-
 	prop= RNA_def_property(srna, "sticky_selection_mode", PROP_ENUM, PROP_NONE);
 	RNA_def_property_enum_sdna(prop, NULL, "sticky");
 	RNA_def_property_enum_items(prop, sticky_mode_items);
@@ -313,16 +312,15 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Draw Stretch Type", "Type of stretch to draw.");
 	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
-	prop= RNA_def_property(srna, "draw_modified_edges", PROP_ENUM, PROP_NONE);
-	RNA_def_property_enum_sdna(prop, NULL, "dt_uvstretch");
-	RNA_def_property_enum_items(prop, dt_uvstretch_items);
-	RNA_def_property_ui_text(prop, "Draw Modified Edges", "Draw edges from the final mesh after object modifier evaluation.");
+	prop= RNA_def_property(srna, "draw_modified_edges", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_DRAWSHADOW);
+	RNA_def_property_ui_text(prop, "Draw Modified Edges", "Draw edges after modifiers are applied.");
 	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
-	/*prop= RNA_def_property(srna, "local_view", PROP_BOOLEAN, PROP_NONE);
-	RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_LOCAL_UV);
-	RNA_def_property_ui_text(prop, "Local View", "Draw only faces with the currently displayed image assigned.");
-	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);*/
+	prop= RNA_def_property(srna, "draw_other_objects", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_DRAW_OTHER);
+	RNA_def_property_ui_text(prop, "Draw Other Objects", "Draw other selected objects that share the same image.");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 
 	prop= RNA_def_property(srna, "normalized_coordinates", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_COORDFLOATS);
@@ -331,12 +329,6 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
 
 	/* todo: move edge and face drawing options here from G.f */
 
-	/* editing */
-	/*prop= RNA_def_property(srna, "sync_selection", PROP_BOOLEAN, PROP_NONE);
-	RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_SYNC_UVSEL);
-	RNA_def_property_ui_text(prop, "Sync Selection", "Keep UV and edit mode mesh selection in sync.");
-	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);*/
-
 	prop= RNA_def_property(srna, "snap_to_pixels", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_PIXELSNAP);
 	RNA_def_property_ui_text(prop, "Snap to Pixels", "Snap UVs to pixel locations while editing.");
@@ -348,6 +340,12 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
 	prop= RNA_def_property(srna, "live_unwrap", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_LIVE_UNWRAP);
 	RNA_def_property_ui_text(prop, "Live Unwrap", "Continuously unwrap the selected UV island while transforming pinned vertices.");
+
+	prop= RNA_def_property(srna, "pivot", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_sdna(prop, NULL, "around");
+	RNA_def_property_enum_items(prop, pivot_items);
+	RNA_def_property_ui_text(prop, "Pivot", "Rotation/Scaling Pivot.");
+	RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
 }
 
 static void rna_def_space_outliner(BlenderRNA *brna)
@@ -575,18 +573,17 @@ static void rna_def_space_buttons(BlenderRNA *brna)
 	PropertyRNA *prop;
 
 	static EnumPropertyItem buttons_context_items[] = {
-		{BCONTEXT_SCENE, "SCENE", 0, "Scene", ""},
-		{BCONTEXT_WORLD, "WORLD", 0, "World", ""},
-		{BCONTEXT_OBJECT, "OBJECT", 0, "Object", ""},
-		{BCONTEXT_DATA, "DATA", 0, "Data", ""},
-		{BCONTEXT_MATERIAL, "MATERIAL", 0, "Material", ""},
-		{BCONTEXT_TEXTURE, "TEXTURE", 0, "Texture", ""},
-		{BCONTEXT_PARTICLE, "PARTICLE", 0, "Particle", ""},
-		{BCONTEXT_PHYSICS, "PHYSICS", 0, "Physics", ""},
-		{BCONTEXT_GAME, "GAME", 0, "Game", ""},
-		{BCONTEXT_BONE, "BONE", 0, "Bone", ""},
-		{BCONTEXT_MODIFIER, "MODIFIER", 0, "Modifier", ""},
-		{BCONTEXT_CONSTRAINT, "CONSTRAINT", 0, "Constraint", ""},
+		{BCONTEXT_SCENE, "SCENE", ICON_SCENE, "Scene", "Scene"},
+		{BCONTEXT_WORLD, "WORLD", ICON_WORLD, "World", "World"},
+		{BCONTEXT_OBJECT, "OBJECT", ICON_OBJECT_DATA, "Object", "Object"},
+		{BCONTEXT_CONSTRAINT, "CONSTRAINT", ICON_CONSTRAINT, "Constraint", "Constraint"},
+		{BCONTEXT_MODIFIER, "MODIFIER", ICON_MODIFIER, "Modifier", "Modifier"},
+		{BCONTEXT_DATA, "DATA", 0, "Data", "Data"},
+		{BCONTEXT_BONE, "BONE", ICON_BONE_DATA, "Bone", "Bone"},
+		{BCONTEXT_MATERIAL, "MATERIAL", ICON_MATERIAL, "Material", "Material"},
+		{BCONTEXT_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture"},
+		{BCONTEXT_PARTICLE, "PARTICLE", ICON_PARTICLES, "Particle", "Particle"},
+		{BCONTEXT_PHYSICS, "PHYSICS", ICON_PHYSICS, "Physics", "Physics"},
 		{0, NULL, 0, NULL, NULL}};
 		
 	static EnumPropertyItem panel_alignment_items[] = {
@@ -602,11 +599,13 @@ static void rna_def_space_buttons(BlenderRNA *brna)
 	RNA_def_property_enum_sdna(prop, NULL, "mainb");
 	RNA_def_property_enum_items(prop, buttons_context_items);
 	RNA_def_property_ui_text(prop, "Buttons Context", "The type of active data to display and edit in the buttons window");
+	RNA_def_property_update(prop, NC_WINDOW, NULL);
 	
 	prop= RNA_def_property(srna, "panel_alignment", PROP_ENUM, PROP_NONE);
 	RNA_def_property_enum_sdna(prop, NULL, "align");
 	RNA_def_property_enum_items(prop, panel_alignment_items);
 	RNA_def_property_ui_text(prop, "Panel Alignment", "Arrangement of the panels within the buttons window");
+	RNA_def_property_update(prop, NC_WINDOW, NULL);
 
 	/* pinned data */
 	prop= RNA_def_property(srna, "pin_id", PROP_POINTER, PROP_NONE);
@@ -868,12 +867,124 @@ static void rna_def_space_text(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Replace Text", "Text to replace selected text with using the replace tool.");
 }
 
+static void rna_def_fileselect_params(BlenderRNA *brna)
+{
+	StructRNA *srna;
+	PropertyRNA *prop;
+	
+	static EnumPropertyItem file_display_items[] = {
+		{FILE_SHORTDISPLAY, "FILE_SHORTDISPLAY", ICON_SHORTDISPLAY, "Short List", "Display files as short list"},
+		{FILE_LONGDISPLAY, "FILE_LONGDISPLAY", ICON_LONGDISPLAY, "Long List", "Display files as a detailed list"},
+		{FILE_IMGDISPLAY, "FILE_IMGDISPLAY", ICON_IMGDISPLAY, "Thumbnails", "Display files as thumbnails"},
+		{0, NULL, 0, NULL, NULL}};
+
+	static EnumPropertyItem file_sort_items[] = {
+		{FILE_SORT_ALPHA, "FILE_SORT_ALPHA", ICON_SORTALPHA, "Sort alphabetically", "Sort the file list alphabetically."},
+		{FILE_SORT_EXTENSION, "FILE_SORT_EXTENSION", ICON_SORTBYEXT, "Sort by extension", "Sort the file list by extension."},
+		{FILE_SORT_TIME, "FILE_SORT_TIME", ICON_SORTTIME, "Sort by time", "Sort files by modification time."},
+		{FILE_SORT_SIZE, "FILE_SORT_SIZE", ICON_SORTSIZE, "Sort by size", "Sort files by size."},
+		{0, NULL, 0, NULL, NULL}};
+
+	srna= RNA_def_struct(brna, "FileSelectParams", NULL);
+	RNA_def_struct_ui_text(srna, "File Select Parameters", "File Select Parameters.");
+
+	prop= RNA_def_property(srna, "display", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_sdna(prop, NULL, "display");
+	RNA_def_property_enum_items(prop, file_display_items);
+	RNA_def_property_ui_text(prop, "Display Mode", "Display mode for the file list");
+	RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL);
+
+	prop= RNA_def_property(srna, "do_filter", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "flag", FILE_FILTER);
+	RNA_def_property_ui_text(prop, "Filter Files", "Enable filtering of files.");
+	RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL);
+
+	prop= RNA_def_property(srna, "hide_dot", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "flag", FILE_HIDE_DOT);
+	RNA_def_property_ui_text(prop, "Hide Dot Files", "Hide hidden dot files.");
+	RNA_def_property_update(prop, NC_FILE | ND_FILELIST , NULL);
+
+	prop= RNA_def_property(srna, "sort", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_sdna(prop, NULL, "sort");
+	RNA_def_property_enum_items(prop, file_sort_items);
+	RNA_def_property_ui_text(prop, "Sort", "");
+	RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL);
+
+	prop= RNA_def_property(srna, "filter_image", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "filter", IMAGEFILE);
+	RNA_def_property_ui_text(prop, "Filter Images", "Show image files.");
+	RNA_def_property_ui_icon(prop, ICON_FILE_IMAGE, 0);
+	RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL);
+
+	prop= RNA_def_property(srna, "filter_blender", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "filter", BLENDERFILE);
+	RNA_def_property_ui_text(prop, "Filter Blender", "Show .blend files.");
+	RNA_def_property_ui_icon(prop, ICON_FILE_BLEND, 0);
+	RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL);
+
+	prop= RNA_def_property(srna, "filter_movie", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "filter", MOVIEFILE);
+	RNA_def_property_ui_text(prop, "Filter Movies", "Show movie files.");
+	RNA_def_property_ui_icon(prop, ICON_FILE_MOVIE, 0);
+	RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL);
+
+	prop= RNA_def_property(srna, "filter_script", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "filter", PYSCRIPTFILE);
+	RNA_def_property_ui_text(prop, "Filter Script", "Show script files.");
+	RNA_def_property_ui_icon(prop, ICON_FILE_SCRIPT, 0);
+	RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL);
+
+	prop= RNA_def_property(srna, "filter_font", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "filter", FTFONTFILE);
+	RNA_def_property_ui_text(prop, "Filter Fonts", "Show font files.");
+	RNA_def_property_ui_icon(prop, ICON_FILE_FONT, 0);
+	RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL);
+
+	prop= RNA_def_property(srna, "filter_sound", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "filter", SOUNDFILE);
+	RNA_def_property_ui_text(prop, "Filter Sound", "Show sound files.");
+	RNA_def_property_ui_icon(prop, ICON_FILE_SOUND, 0);
+	RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL);
+
+	prop= RNA_def_property(srna, "filter_text", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "filter", TEXTFILE);
+	RNA_def_property_ui_text(prop, "Filter Text", "Show text files.");
+	RNA_def_property_ui_icon(prop, ICON_FILE_BLANK, 0);
+	RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL);
+
+	prop= RNA_def_property(srna, "filter_folder", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "filter", FOLDERFILE);
+	RNA_def_property_ui_text(prop, "Filter Folder", "Show folders.");
+	RNA_def_property_ui_icon(prop, ICON_FILE_FOLDER, 0);
+	RNA_def_property_update(prop, NC_FILE | ND_PARAMS, NULL);
+
+	
+}
+
+static void rna_def_space_filebrowser(BlenderRNA *brna)
+{
+	StructRNA *srna;
+	PropertyRNA *prop;
+
+	srna= RNA_def_struct(brna, "SpaceFileBrowser", "Space");
+	RNA_def_struct_sdna(srna, "SpaceFile");
+	RNA_def_struct_ui_text(srna, "Space File Browser", "File browser space data.");
+
+	prop= RNA_def_property(srna, "params", PROP_POINTER, PROP_NONE);
+	RNA_def_property_pointer_sdna(prop, NULL, "params");
+	RNA_def_property_pointer_funcs(prop, NULL, "rna_SpaceFileBrowser_params_set", NULL);
+	RNA_def_property_ui_text(prop, "Filebrowser Parameter", "Parameters and Settings for the Filebrowser.");
+
+}
+
 void RNA_def_space(BlenderRNA *brna)
 {
 	rna_def_space(brna);
 	rna_def_space_image(brna);
 	rna_def_space_sequencer(brna);
 	rna_def_space_text(brna);
+	rna_def_fileselect_params(brna);
+	rna_def_space_filebrowser(brna);
 	rna_def_space_outliner(brna);
 	rna_def_background_image(brna);
 	rna_def_space_3dview(brna);
diff --git a/source/blender/makesrna/intern/rna_text.c b/source/blender/makesrna/intern/rna_text.c
index b44c392d741..cd39c317bc5 100644
--- a/source/blender/makesrna/intern/rna_text.c
+++ b/source/blender/makesrna/intern/rna_text.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_text.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c
index 33d7c8fd6c0..2a7f65e2d90 100644
--- a/source/blender/makesrna/intern/rna_texture.c
+++ b/source/blender/makesrna/intern/rna_texture.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_texture.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_timeline.c b/source/blender/makesrna/intern/rna_timeline.c
index deb40f85986..d42603e1952 100644
--- a/source/blender/makesrna/intern/rna_timeline.c
+++ b/source/blender/makesrna/intern/rna_timeline.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_timeline.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index 976ccc670bb..eef221e45a4 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_ui.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -416,12 +416,12 @@ static int rna_UILayout_active_get(struct PointerRNA *ptr)
 
 static void rna_UILayout_active_set(struct PointerRNA *ptr, int value)
 {
-	return uiLayoutSetActive(ptr->data, value);
+	uiLayoutSetActive(ptr->data, value);
 }
 
 static void rna_UILayout_op_context_set(struct PointerRNA *ptr, int value)
 {
-	return uiLayoutSetOperatorContext(ptr->data, value);
+	uiLayoutSetOperatorContext(ptr->data, value);
 }
 
 static int rna_UILayout_op_context_get(struct PointerRNA *ptr)
@@ -436,7 +436,7 @@ static int rna_UILayout_enabled_get(struct PointerRNA *ptr)
 
 static void rna_UILayout_enabled_set(struct PointerRNA *ptr, int value)
 {
-	return uiLayoutSetEnabled(ptr->data, value);
+	uiLayoutSetEnabled(ptr->data, value);
 }
 
 static int rna_UILayout_red_alert_get(struct PointerRNA *ptr)
@@ -446,7 +446,7 @@ static int rna_UILayout_red_alert_get(struct PointerRNA *ptr)
 
 static void rna_UILayout_red_alert_set(struct PointerRNA *ptr, int value)
 {
-	return uiLayoutSetRedAlert(ptr->data, value);
+	uiLayoutSetRedAlert(ptr->data, value);
 }
 
 static int rna_UILayout_keep_aspect_get(struct PointerRNA *ptr)
@@ -456,7 +456,7 @@ static int rna_UILayout_keep_aspect_get(struct PointerRNA *ptr)
 
 static void rna_UILayout_keep_aspect_set(struct PointerRNA *ptr, int value)
 {
-	return uiLayoutSetKeepAspect(ptr->data, value);
+	uiLayoutSetKeepAspect(ptr->data, value);
 }
 
 static int rna_UILayout_alignment_get(struct PointerRNA *ptr)
@@ -466,7 +466,7 @@ static int rna_UILayout_alignment_get(struct PointerRNA *ptr)
 
 static void rna_UILayout_alignment_set(struct PointerRNA *ptr, int value)
 {
-	return uiLayoutSetAlignment(ptr->data, value);
+	uiLayoutSetAlignment(ptr->data, value);
 }
 
 static float rna_UILayout_scale_x_get(struct PointerRNA *ptr)
@@ -476,7 +476,7 @@ static float rna_UILayout_scale_x_get(struct PointerRNA *ptr)
 
 static void rna_UILayout_scale_x_set(struct PointerRNA *ptr, float value)
 {
-	return uiLayoutSetScaleX(ptr->data, value);
+	uiLayoutSetScaleX(ptr->data, value);
 }
 
 static float rna_UILayout_scale_y_get(struct PointerRNA *ptr)
@@ -486,7 +486,7 @@ static float rna_UILayout_scale_y_get(struct PointerRNA *ptr)
 
 static void rna_UILayout_scale_y_set(struct PointerRNA *ptr, float value)
 {
-	return uiLayoutSetScaleY(ptr->data, value);
+	uiLayoutSetScaleY(ptr->data, value);
 }
 
 #else // RNA_RUNTIME
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index d06d4d4406d..3df3fad3f15 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -136,6 +136,14 @@ void RNA_api_ui_layout(StructRNA *srna)
 	parm= RNA_def_string(func, "value", "", 0, "", "Enum property value.");
 	RNA_def_property_flag(parm, PROP_REQUIRED);*/
 
+	func= RNA_def_function(srna, "item_pointerR", "uiItemPointerR");
+	api_ui_item_common(func);
+	api_ui_item_rna_common(func);
+	parm= RNA_def_pointer(func, "search_data", "AnyType", "", "Data from which to take collection to search in.");
+	RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR);
+	parm= RNA_def_string(func, "search_property", "", 0, "", "Identifier of search collection property.");
+	RNA_def_property_flag(parm, PROP_REQUIRED);
+
 	func= RNA_def_function(srna, "itemO", "uiItemO");
 	api_ui_item_op_common(func);
 
@@ -189,8 +197,7 @@ void RNA_api_ui_layout(StructRNA *srna)
 	api_ui_item_common(func);
 
 	func= RNA_def_function(srna, "itemM", "uiItemM");
-	parm= RNA_def_pointer(func, "context", "Context", "", "Current context.");
-	RNA_def_property_flag(parm, PROP_REQUIRED);
+	RNA_def_function_flag(func, FUNC_USE_CONTEXT);
 	api_ui_item_common(func);
 	parm= RNA_def_string(func, "menu", "", 0, "", "Identifier of the menu.");
 	RNA_def_property_flag(parm, PROP_REQUIRED);
@@ -206,15 +213,12 @@ void RNA_api_ui_layout(StructRNA *srna)
 
 	/* templates */
 	func= RNA_def_function(srna, "template_header", "uiTemplateHeader");
-	parm= RNA_def_pointer(func, "context", "Context", "", "Current context.");
-	RNA_def_property_flag(parm, PROP_REQUIRED);
+	RNA_def_function_flag(func, FUNC_USE_CONTEXT);
 
 	func= RNA_def_function(srna, "template_ID", "uiTemplateID");
-	parm= RNA_def_pointer(func, "context", "Context", "", "Current context.");
-	RNA_def_property_flag(parm, PROP_REQUIRED);
+	RNA_def_function_flag(func, FUNC_USE_CONTEXT);
 	api_ui_item_rna_common(func);
 	RNA_def_string(func, "new", "", 0, "", "Operator identifier to create a new ID block.");
-	RNA_def_string(func, "open", "", 0, "", "Operator identifier to open a new ID block.");
 	RNA_def_string(func, "unlink", "", 0, "", "Operator identifier to unlink the ID block.");
 
 	func= RNA_def_function(srna, "template_modifier", "uiTemplateModifier");
@@ -245,6 +249,30 @@ void RNA_api_ui_layout(StructRNA *srna)
 	
 	func= RNA_def_function(srna, "template_layers", "uiTemplateLayers");
 	api_ui_item_rna_common(func);
+
+	func= RNA_def_function(srna, "template_image_layers", "uiTemplateImageLayers");
+	RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+	parm= RNA_def_pointer(func, "image", "Image", "", "");
+	RNA_def_property_flag(parm, PROP_REQUIRED);
+	parm= RNA_def_pointer(func, "image_user", "ImageUser", "", "");
+	RNA_def_property_flag(parm, PROP_REQUIRED);
+
+	func= RNA_def_function(srna, "template_list", "uiTemplateList");
+	api_ui_item_rna_common(func);
+	parm= RNA_def_pointer(func, "active_data", "AnyType", "", "Data from which to take property for the active element.");
+	RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR);
+	parm= RNA_def_string(func, "active_property", "", 0, "", "Identifier of property in data, for the active element.");
+	RNA_def_property_flag(parm, PROP_REQUIRED);
+	parm= RNA_def_int(func, "rows", 5, 0, INT_MAX, "", "Number of rows to display.", 0, INT_MAX);
+	parm= RNA_def_int(func, "columns", 5, 0, INT_MAX, "", "Number of columns to display.", 0, INT_MAX);
+	parm= RNA_def_boolean(func, "compact", 0, "", "Use compact, single row list template.");
+	parm= RNA_def_collection(func, "items", 0, "", "Items visible in the list.");
+	RNA_def_function_return(func, parm);
+
+	func= RNA_def_function(srna, "template_running_jobs", "uiTemplateRunningJobs");
+	RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+
+	func= RNA_def_function(srna, "template_operator_search", "uiTemplateOperatorSearch");
 }
 
 #endif
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index ad3875280fb..609082144e1 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_userdef.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -139,7 +139,12 @@ static void rna_def_userdef_theme_ui_font_style(BlenderRNA *brna)
 
 	prop= RNA_def_property(srna, "kerning", PROP_FLOAT, PROP_NONE);
 	RNA_def_property_range(prop, -5.0, 5.0);
-	RNA_def_property_ui_text(prop, "Kerning", "");
+	RNA_def_property_ui_text(prop, "Kerning", "User kerning value in pixels");
+	RNA_def_property_update(prop, NC_WINDOW, NULL);
+
+	prop= RNA_def_property(srna, "overlap", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "overlap", 1);
+	RNA_def_property_ui_text(prop, "Overlap", "Check for overlap characters");
 	RNA_def_property_update(prop, NC_WINDOW, NULL);
 
 	prop= RNA_def_property(srna, "shadow", PROP_INT, PROP_NONE);
@@ -301,6 +306,12 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna)
 	RNA_def_property_struct_type(prop, "ThemeWidgetColors");
 	RNA_def_property_ui_text(prop, "Option Widget Colors", "");
 	RNA_def_property_update(prop, NC_WINDOW, NULL);
+
+	prop= RNA_def_property(srna, "wcol_toggle", PROP_POINTER, PROP_NEVER_NULL);
+	RNA_def_property_pointer_sdna(prop, NULL, "wcol_toggle");
+	RNA_def_property_struct_type(prop, "ThemeWidgetColors");
+	RNA_def_property_ui_text(prop, "Toggle Widget Colors", "");
+	RNA_def_property_update(prop, NC_WINDOW, NULL);
 	
 	prop= RNA_def_property(srna, "wcol_num", PROP_POINTER, PROP_NEVER_NULL);
 	RNA_def_property_pointer_sdna(prop, NULL, "wcol_num");
@@ -343,7 +354,12 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna)
 	RNA_def_property_struct_type(prop, "ThemeWidgetColors");
 	RNA_def_property_ui_text(prop, "Menu Item Colors", "");
 	RNA_def_property_update(prop, NC_WINDOW, NULL);
-	
+
+	prop= RNA_def_property(srna, "wcol_scroll", PROP_POINTER, PROP_NEVER_NULL);
+	RNA_def_property_pointer_sdna(prop, NULL, "wcol_scroll");
+	RNA_def_property_struct_type(prop, "ThemeWidgetColors");
+	RNA_def_property_ui_text(prop, "Scroll Widget Colors", "");
+	RNA_def_property_update(prop, NC_WINDOW, NULL);
 	
 	prop= RNA_def_property(srna, "icon_file", PROP_STRING, PROP_FILEPATH);
 	RNA_def_property_string_sdna(prop, NULL, "iconfile");
@@ -1505,7 +1521,7 @@ static void rna_def_userdef_view(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Toolbox Column Layout", "Use a column layout for toolbox.");
 
 	prop= RNA_def_property(srna, "directional_menus", PROP_BOOLEAN, PROP_NONE);
-	RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_DIRECTIONALORDER);
+	RNA_def_property_boolean_negative_sdna(prop, NULL, "uiflag", USER_MENUFIXEDORDER);
 	RNA_def_property_ui_text(prop, "Contents Follow Opening Direction", "Otherwise menus, etc will always be top to bottom, left to right, no matter opening direction.");
 
 	/* snap to grid */
diff --git a/source/blender/makesrna/intern/rna_vfont.c b/source/blender/makesrna/intern/rna_vfont.c
index 7837a0b5657..aa2aaaf6342 100644
--- a/source/blender/makesrna/intern/rna_vfont.c
+++ b/source/blender/makesrna/intern/rna_vfont.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_vfont.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_vpaint.c b/source/blender/makesrna/intern/rna_vpaint.c
index 6a831467487..a34099dffb7 100644
--- a/source/blender/makesrna/intern/rna_vpaint.c
+++ b/source/blender/makesrna/intern/rna_vpaint.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_vpaint.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 3cb3f4ee4cb..f8ab3a86744 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_wm.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -30,9 +30,125 @@
 #include "rna_internal.h"
 
 #include "DNA_windowmanager_types.h"
+#include "WM_types.h" /* wmEvent */
+
+
+EnumPropertyItem event_value_items[] = {
+	{KM_ANY, "ANY", 0, "Any", ""},
+	{KM_NOTHING, "NOTHING", 0, "Nothing", ""},
+	{KM_PRESS, "PRESS", 0, "Press", ""},
+	{KM_RELEASE, "RELEASE", 0, "Release", ""},
+	{0, NULL, 0, NULL, NULL}};
+
+/* not returned: CAPSLOCKKEY, UNKNOWNKEY, COMMANDKEY, GRLESSKEY */
+EnumPropertyItem event_type_items[] = {
+	{AKEY, "A", 0, "A", ""},
+	{BKEY, "B", 0, "B", ""},
+	{CKEY, "C", 0, "C", ""},
+	{DKEY, "D", 0, "D", ""},
+	{EKEY, "E", 0, "E", ""},
+	{FKEY, "F", 0, "F", ""},
+	{GKEY, "G", 0, "G", ""},
+	{HKEY, "H", 0, "H", ""},
+	{IKEY, "I", 0, "I", ""},
+	{JKEY, "J", 0, "J", ""},
+	{KKEY, "K", 0, "K", ""},
+	{LKEY, "L", 0, "L", ""},
+	{MKEY, "M", 0, "M", ""},
+	{NKEY, "N", 0, "N", ""},
+	{OKEY, "O", 0, "O", ""},
+	{PKEY, "P", 0, "P", ""},
+	{QKEY, "Q", 0, "Q", ""},
+	{RKEY, "R", 0, "R", ""},
+	{SKEY, "S", 0, "S", ""},
+	{TKEY, "T", 0, "T", ""},
+	{UKEY, "U", 0, "U", ""},
+	{VKEY, "V", 0, "V", ""},
+	{WKEY, "W", 0, "W", ""},
+	{XKEY, "X", 0, "X", ""},
+	{YKEY, "Y", 0, "Y", ""},
+	{ZKEY, "Z", 0, "Z", ""},
+	
+	{ZEROKEY, "ZERO",	0, "Zero Key", ""},
+	{ONEKEY, "ONE",		0, "One Key", ""},
+	{TWOKEY, "TWO",		0, "Two Key", ""},
+	{THREEKEY, "THREE",	0, "Three Key", ""},
+	{FOURKEY, "FOUR",	0, "Four Key", ""},
+	{FIVEKEY, "FIVE",	0, "Five Key", ""},
+	{SIXKEY, "SIX",		0, "Six Key", ""},
+	{SEVENKEY, "SEVEN",	0, "Seven Key", ""},
+	{EIGHTKEY, "EIGHT",	0, "Eight Key", ""},
+	{NINEKEY, "NINE",	0, "Nine Key", ""},
+	
+	{LEFTCTRLKEY,	"LEFT_CTRL",	0, "Left Ctrl", ""},
+	{LEFTALTKEY,	"LEFT_ALT",		0, "Left Alt", ""},
+	{RIGHTALTKEY,	"RIGHT_ALT",	0, "Right Alt", ""},
+	{RIGHTCTRLKEY,	"RIGHT_CTRL",	0, "Rightctrl", ""},
+	{RIGHTSHIFTKEY,	"RIGHT_SHIFT",	0, "Rightshift", ""},
+	{LEFTSHIFTKEY,	"LEFT_SHIFT",	0, "Leftshift", ""},
+	
+	{ESCKEY, "ESC", 0, "Esc", ""},
+	{TABKEY, "TAB", 0, "Tab", ""},
+	{RETKEY, "RET", 0, "Return", ""},
+	{SPACEKEY, "SPACE", 0, "Spacebar", ""},
+	{LINEFEEDKEY, "LINE_FEED", 0, "Line Feed", ""},
+	{BACKSPACEKEY, "BACK_SPACE", 0, "Back Space", ""},
+	{DELKEY, "DEL", 0, "Delete", ""},
+	{SEMICOLONKEY, "SEMI_COLON", 0, "Semicolon", ""},
+	{PERIODKEY, "PERIOD", 0, "Period", ""},
+	{COMMAKEY, "COMMA", 0, "Comma", ""},
+	{QUOTEKEY, "QUOTE", 0, "Quote", ""},
+	{ACCENTGRAVEKEY, "ACCENT_GRAVE", 0, "Accentgrave", ""},
+	{MINUSKEY, "MINUS", 0, "Minus", ""},
+	{SLASHKEY, "SLASH", 0, "Slash", ""},
+	{BACKSLASHKEY, "BACK_SLASH", 0, "Backslash", ""},
+	{EQUALKEY, "EQUAL", 0, "Equal", ""},
+	{LEFTBRACKETKEY, "LEFT_BRACKET", 0, "Leftbracket", ""},
+	{RIGHTBRACKETKEY, "RIGHT_BRACKET", 0, "Rightbracket", ""},
+	{LEFTARROWKEY, "LEFT_ARROW", 0, "Left Arrow", ""},
+	{DOWNARROWKEY, "DOWN_ARROW", 0, "Down Arrow", ""},
+	{RIGHTARROWKEY, "RIGHT_ARROW", 0, "Right Arrow", ""},
+	{UPARROWKEY, "UP_ARROW", 0, "Up Arrow", ""},
+	{PAD2, "NUMPAD_2", 0, "Numpad 2", ""},
+	{PAD4, "NUMPAD_4", 0, "Numpad 4", ""},
+	{PAD6, "NUMPAD_6", 0, "Numpad 6", ""},
+	{PAD8, "NUMPAD_8", 0, "Numpad 8", ""},
+	{PAD1, "NUMPAD_1", 0, "Numpad 1", ""},
+	{PAD3, "NUMPAD_3", 0, "Numpad 3", ""},
+	{PAD5, "NUMPAD_5", 0, "Numpad 5", ""},
+	{PAD7, "NUMPAD_7", 0, "Numpad 7", ""},
+	{PAD9, "NUMPAD_9", 0, "Numpad 9", ""},
+	{PADPERIOD, "NUMPAD_PERIOD", 0, "Numpad .", ""},
+	{PADSLASHKEY, "NUMPAD_SLASH", 0, "Numpad /", ""},
+	{PADASTERKEY, "NUMPAD_ASTERIX", 0, "Numpad *", ""},
+	{PAD0, "NUMPAD_0", 0, "Numpad 0", ""},
+	{PADMINUS, "NUMPAD_MINUS", 0, "Numpad -", ""},
+	{PADENTER, "NUMPAD_ENTER", 0, "Numpad Enter", ""},
+	{PADPLUSKEY, "NUMPAD_PLUS", 0, "Numpad +", ""},
+	{F1KEY, "F1", 0, "F1", ""},
+	{F2KEY, "F2", 0, "F2", ""},
+	{F3KEY, "F3", 0, "F3", ""},
+	{F4KEY, "F4", 0, "F4", ""},
+	{F5KEY, "F5", 0, "F5", ""},
+	{F6KEY, "F6", 0, "F6", ""},
+	{F7KEY, "F7", 0, "F7", ""},
+	{F8KEY, "F8", 0, "F8", ""},
+	{F9KEY, "F9", 0, "F9", ""},
+	{F10KEY, "F10", 0, "F10", ""},
+	{F11KEY, "F11", 0, "F11", ""},
+	{F12KEY, "F12", 0, "F12", ""},
+	{PAUSEKEY, "PAUSE", 0, "Pause", ""},
+	{INSERTKEY, "INSERT", 0, "Insert", ""},
+	{HOMEKEY, "HOME", 0, "Home", ""},
+	{PAGEUPKEY, "PAGE_UP", 0, "Page Up", ""},
+	{PAGEDOWNKEY, "PAGE_DOWN", 0, "Page Down", ""},
+	{ENDKEY, "END", 0, "End", ""},
+	{0, NULL, 0, NULL, NULL}};	
 
 #ifdef RNA_RUNTIME
 
+#include "WM_api.h"
+
 #include "BKE_idprop.h"
 
 static wmOperator *rna_OperatorProperties_find_operator(PointerRNA *ptr)
@@ -87,6 +203,42 @@ static PointerRNA rna_Operator_properties_get(PointerRNA *ptr)
 	return rna_pointer_inherit_refine(ptr, &RNA_OperatorProperties, op->properties);
 }
 
+
+static void rna_Event_ascii_get(PointerRNA *ptr, char *value)
+{
+	wmEvent *event= (wmEvent*)ptr->id.data;
+	value[0]= event->ascii;
+	value[1]= '\0';
+}
+
+static int rna_Event_ascii_length(PointerRNA *ptr)
+{
+	wmEvent *event= (wmEvent*)ptr->id.data;
+	return (event->ascii)? 1 : 0;
+}
+
+static void rna_Window_screen_set(PointerRNA *ptr, PointerRNA value)
+{
+	wmWindow *win= (wmWindow*)ptr->data;
+
+	if(value.data == NULL)
+		return;
+
+	/* exception: can't set screens inside of area/region handers */
+	win->newscreen= value.data;
+}
+
+static void rna_Window_screen_update(bContext *C, PointerRNA *ptr)
+{
+	wmWindow *win= (wmWindow*)ptr->data;
+
+	/* exception: can't set screens inside of area/region handers */
+	if(win->newscreen) {
+		WM_event_add_notifier(C, NC_SCREEN|ND_SCREENBROWSE, win->newscreen);
+		win->newscreen= NULL;
+	}
+}
+
 #else
 
 static void rna_def_operator(BlenderRNA *brna)
@@ -146,7 +298,97 @@ static void rna_def_operator_filelist_element(BlenderRNA *brna)
 	RNA_def_property_flag(prop, PROP_IDPROPERTY);
 	RNA_def_property_ui_text(prop, "Name", "the name of a file or directory within a file list");
 }
+	
+static void rna_def_event(BlenderRNA *brna)
+{
+	StructRNA *srna;
+	PropertyRNA *prop;
+	
+	srna= RNA_def_struct(brna, "Event", NULL);
+	RNA_def_struct_ui_text(srna, "Event", "Window Manager Event");
+	RNA_def_struct_sdna(srna, "wmEvent");
 
+	/* strings */
+	prop= RNA_def_property(srna, "ascii", PROP_STRING, PROP_NONE);
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_string_funcs(prop, "rna_Event_ascii_get", "rna_Event_ascii_length", NULL);
+	RNA_def_property_ui_text(prop, "ASCII", "Single ASCII character for this event.");
+
+
+	/* enums */
+	prop= RNA_def_property(srna, "value", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_sdna(prop, NULL, "val");
+	RNA_def_property_enum_items(prop, event_value_items);
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_ui_text(prop, "Value",  "The type of event, only applies to some.");
+	
+	prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_sdna(prop, NULL, "type");
+	RNA_def_property_enum_items(prop, event_type_items);
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_ui_text(prop, "Type",  "");
+
+
+	/* mouse */
+	prop= RNA_def_property(srna, "mouse_x", PROP_INT, PROP_NONE);
+	RNA_def_property_int_sdna(prop, NULL, "x");
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_ui_text(prop, "Mouse X Position", "The window relative vertical location of the mouse.");
+	
+	prop= RNA_def_property(srna, "mouse_y", PROP_INT, PROP_NONE);
+	RNA_def_property_int_sdna(prop, NULL, "y");
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_ui_text(prop, "Mouse Y Position", "The window relative horizontal location of the mouse.");
+	
+	prop= RNA_def_property(srna, "mouse_prev_x", PROP_INT, PROP_NONE);
+	RNA_def_property_int_sdna(prop, NULL, "prevx");
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_ui_text(prop, "Mouse Previous X Position", "The window relative vertical location of the mouse.");
+	
+	prop= RNA_def_property(srna, "mouse_prev_y", PROP_INT, PROP_NONE);
+	RNA_def_property_int_sdna(prop, NULL, "prevy");
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_ui_text(prop, "Mouse Previous Y Position", "The window relative horizontal location of the mouse.");	
+
+
+	/* modifiers */
+	prop= RNA_def_property(srna, "shift", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "shift", 1);
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_ui_text(prop, "Shift", "True when the shift key is held.");
+	
+	prop= RNA_def_property(srna, "ctrl", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "ctrl", 1);
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_ui_text(prop, "Ctrl", "True when the shift key is held.");
+	
+	prop= RNA_def_property(srna, "alt", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "alt", 1);
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_ui_text(prop, "Alt", "True when the shift key is held.");
+	
+	prop= RNA_def_property(srna, "oskey", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "oskey", 1);
+	RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+	RNA_def_property_ui_text(prop, "OS Key", "True when the shift key is held.");
+}
+
+static void rna_def_window(BlenderRNA *brna)
+{
+	StructRNA *srna;
+	PropertyRNA *prop;
+
+	srna= RNA_def_struct(brna, "Window", NULL);
+	RNA_def_struct_ui_text(srna, "Window", "Open window.");
+	RNA_def_struct_sdna(srna, "wmWindow");
+
+	prop= RNA_def_property(srna, "screen", PROP_POINTER, PROP_NEVER_NULL);
+	RNA_def_property_struct_type(prop, "Screen");
+	RNA_def_property_ui_text(prop, "Screen", "Active screen showing in the window.");
+	RNA_def_property_flag(prop, PROP_EDITABLE);
+	RNA_def_property_pointer_funcs(prop, NULL, "rna_Window_screen_set", NULL);
+	RNA_def_property_update(prop, 0, "rna_Window_screen_update");
+}
 
 static void rna_def_windowmanager(BlenderRNA *brna)
 {
@@ -161,6 +403,10 @@ static void rna_def_windowmanager(BlenderRNA *brna)
 	RNA_def_property_struct_type(prop, "Operator");
 	RNA_def_property_ui_text(prop, "Operators", "Operator registry.");
 
+	prop= RNA_def_property(srna, "windows", PROP_COLLECTION, PROP_NONE);
+	RNA_def_property_struct_type(prop, "Window");
+	RNA_def_property_ui_text(prop, "Windows", "Open windows.");
+
 	RNA_api_wm(srna);
 }
 
@@ -169,6 +415,8 @@ void RNA_def_wm(BlenderRNA *brna)
 	rna_def_operator(brna);
 	rna_def_operator_utils(brna);
 	rna_def_operator_filelist_element(brna);
+	rna_def_event(brna);
+	rna_def_window(brna);
 	rna_def_windowmanager(brna);
 }
 
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index 87a94993a42..fd34d7c4d70 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_wm_api.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c
index e313f01c194..f5eb81e3cea 100644
--- a/source/blender/makesrna/intern/rna_world.c
+++ b/source/blender/makesrna/intern/rna_world.c
@@ -1,5 +1,5 @@
 /**
- * $Id: rna_world.c 21247 2009-06-29 21:50:53Z jaguarandi $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -337,7 +337,7 @@ void RNA_def_world(BlenderRNA *brna)
 	static EnumPropertyItem physics_engine_items[] = {
 		{WOPHY_NONE, "NONE", 0, "None", ""},
 		//{WOPHY_ENJI, "ENJI", 0, "Enji", ""},
-		{WOPHY_SUMO, "SUMO", 0, "Sumo (Deprecated)", ""},
+		//{WOPHY_SUMO, "SUMO", 0, "Sumo (Deprecated)", ""},
 		//{WOPHY_DYNAMO, "DYNAMO", 0, "Dynamo", ""},
 		//{WOPHY_ODE, "ODE", 0, "ODE", ""},
 		{WOPHY_BULLET, "BULLET", 0, "Bullet", ""},
diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h
index 855fdde50c5..d141a585378 100644
--- a/source/blender/python/BPY_extern.h
+++ b/source/blender/python/BPY_extern.h
@@ -1,5 +1,5 @@
 /*
- * $Id: BPY_extern.h 12334 2007-10-21 23:00:29Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -50,6 +50,8 @@ struct bConstraintTarget; /* DNA_constraint_types.h*/
 struct Script;				/* DNA_screen_types.h */
 struct BPyMenu;
 struct bContext;
+struct ReportList;
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/source/blender/python/BPY_menus.c b/source/blender/python/BPY_menus.c
deleted file mode 100644
index b67f1e717da..00000000000
--- a/source/blender/python/BPY_menus.c
+++ /dev/null
@@ -1,1118 +0,0 @@
-/* 
- * $Id: BPY_menus.c 12932 2007-12-17 20:21:06Z theeth $
- *
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * This is a new part of Blender.
- *
- * Contributor(s): Willian P. Germano, Michael Reimpell
- *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
-*/
-
-/* 
- *This is the main file responsible for having bpython scripts accessible
- * from Blender menus.  To know more, please start with its header file.
- */
-
-#include "BPY_menus.h"
-
-#include 
-#ifndef WIN32
-  #include 
-#else
-  #include "BLI_winstuff.h"
-#endif
-#include "BKE_global.h"
-#include "BKE_utildefines.h"
-#include "BLI_blenlib.h"
-#include "MEM_guardedalloc.h"
-#include "DNA_userdef_types.h"	/* for U.pythondir */
-#include "api2_2x/EXPP_interface.h" /* for bpy_gethome() */
-
-#define BPYMENU_DATAFILE "Bpymenus"
-#define MAX_DIR_DEPTH 4 /* max depth for traversing scripts dirs */
-#define MAX_DIR_NUMBER 30 /* max number of dirs in scripts dirs trees */
-
-static int DEBUG;
-static int Dir_Depth;
-static int Dirs_Number;
-
-/* BPyMenuTable holds all registered pymenus, as linked lists for each menu
- * where they can appear (see PYMENUHOOKS enum in BPY_menus.h).
-*/
-BPyMenu *BPyMenuTable[PYMENU_TOTAL];
-
-static int bpymenu_group_atoi( char *str )
-{
-	if( !strcmp( str, "Export" ) )
-		return PYMENU_EXPORT;
-	else if( !strcmp( str, "Import" ) )
-		return PYMENU_IMPORT;
-	else if( !strcmp( str, "Help" ) )
-		return PYMENU_HELP;
-	else if( !strcmp( str, "HelpWebsites" ) )
-		return PYMENU_HELPWEBSITES;
-	else if( !strcmp( str, "HelpSystem" ) )
-		return PYMENU_HELPSYSTEM;
-	else if( !strcmp( str, "Render" ) )
-		return PYMENU_RENDER;
-	else if( !strcmp( str, "System" ) )
-		return PYMENU_SYSTEM;
-	else if( !strcmp( str, "Object" ) )
-		return PYMENU_OBJECT;
-	else if( !strcmp( str, "Mesh" ) )
-		return PYMENU_MESH;
-	else if( !strncmp( str, "Theme", 5 ) )
-		return PYMENU_THEMES;
-	else if( !strcmp( str, "Add" ) )
-		return PYMENU_ADD;
-	else if( !strcmp( str, "Wizards" ) )
-		return PYMENU_WIZARDS;
-	else if( !strcmp( str, "Animation" ) )
-		return PYMENU_ANIMATION;
-	else if( !strcmp( str, "Materials" ) )
-		return PYMENU_MATERIALS;
-	else if( !strcmp( str, "UV" ) )
-		return PYMENU_UV;
-	else if( !strcmp( str, "Image" ) )
-		return PYMENU_IMAGE;
-	else if( !strcmp( str, "FaceSelect" ) )
-		return PYMENU_FACESELECT;
-	else if( !strcmp( str, "WeightPaint" ) )
-		return PYMENU_WEIGHTPAINT;
-	else if( !strcmp( str, "VertexPaint" ) )
-		return PYMENU_VERTEXPAINT;
-	else if( !strcmp( str, "UVCalculation" ) )
-		return PYMENU_UVCALCULATION;
-	else if( !strcmp( str, "Armature" ) )
-		return PYMENU_ARMATURE;
-	else if( !strcmp( str, "ScriptTemplate" ) )
-		return PYMENU_SCRIPTTEMPLATE;
-	else if( !strcmp( str, "MeshFaceKey" ) )
-		return PYMENU_MESHFACEKEY;
-	else if( !strcmp( str, "AddMesh" ) )
-		return PYMENU_ADDMESH;
-	/* "Misc" or an inexistent group name: use misc */
-	else
-		return PYMENU_MISC;
-}
-
-char *BPyMenu_group_itoa( short menugroup )
-{
-	switch ( menugroup ) {
-	case PYMENU_EXPORT:
-		return "Export";
-		break;
-	case PYMENU_IMPORT:
-		return "Import";
-		break;
-	case PYMENU_ADD:
-		return "Add";
-		break;
-	case PYMENU_HELP:
-		return "Help";
-		break;
-	case PYMENU_HELPWEBSITES:
-		return "HelpWebsites";
-		break;
-	case PYMENU_HELPSYSTEM:
-		return "HelpSystem";
-		break;
-	case PYMENU_RENDER:
-		return "Render";
-		break;
-	case PYMENU_SYSTEM:
-		return "System";
-		break;
-	case PYMENU_OBJECT:
-		return "Object";
-		break;
-	case PYMENU_MESH:
-		return "Mesh";
-		break;
-	case PYMENU_THEMES:
-		return "Themes";
-		break;
-	case PYMENU_WIZARDS:
-		return "Wizards";
-		break;
-	case PYMENU_ANIMATION:
-		return "Animation";
-		break;
-	case PYMENU_MATERIALS:
-		return "Materials";
-		break;
-	case PYMENU_UV:
-		return "UV";
-		break;
-	case PYMENU_IMAGE:
-		return "Image";
-		break;
-	case PYMENU_FACESELECT:
-		return "FaceSelect";
-		break;
-	case PYMENU_WEIGHTPAINT:
-		return "WeightPaint";
-		break;
-	case PYMENU_VERTEXPAINT:
-		return "VertexPaint";
-		break;
-	case PYMENU_UVCALCULATION:
-		return "UVCalculation";
-		break;
-	case PYMENU_ARMATURE:
-		return "Armature";
-		break;
-	case PYMENU_SCRIPTTEMPLATE:
-		return "ScriptTemplate";
-		break;
-	case PYMENU_MESHFACEKEY:
-		return "MeshFaceKey";
-		break;
-	case PYMENU_ADDMESH:
-		return "AddMesh";
-		break;
-	case PYMENU_MISC:
-		return "Misc";
-		break;
-	}
-	return NULL;
-}
-
-/* BPyMenu_CreatePupmenuStr:
- * build and return a meaninful string to be used by pupmenu().  The
- * string is made of a bpymenu name as title and its submenus as possible
- * choices for the user.
-*/
-char *BPyMenu_CreatePupmenuStr( BPyMenu * pym, short menugroup )
-{
-	BPySubMenu *pysm = pym->submenus;
-	char str[1024], str2[100];
-	int i = 0, rlen;
-
-	if( !pym || !pysm )
-		return NULL;
-
-	str[0] = '\0';
-
-	PyOS_snprintf( str2, sizeof( str2 ), "%s: %s%%t",
-		       BPyMenu_group_itoa( menugroup ), pym->name );
-	strcat( str, str2 );
-
-	while( pysm ) {
-		PyOS_snprintf( str2, sizeof( str2 ), "|%s%%x%d", pysm->name,
-			       i );
-		rlen = sizeof( str ) - strlen( str );
-		strncat( str, str2, rlen );
-		i++;
-		pysm = pysm->next;
-	}
-
-	return BLI_strdup( str );
-}
-
-static void bpymenu_RemoveAllSubEntries( BPySubMenu * smenu )
-{
-	BPySubMenu *tmp;
-
-	while( smenu ) {
-		tmp = smenu->next;
-		if( smenu->name )
-			MEM_freeN( smenu->name );
-		if( smenu->arg )
-			MEM_freeN( smenu->arg );
-		MEM_freeN( smenu );
-		smenu = tmp;
-	}
-	return;
-}
-
-void BPyMenu_RemoveAllEntries( void )
-{
-	BPyMenu *tmp, *pymenu;
-	int i;
-
-	for( i = 0; i < PYMENU_TOTAL; i++ ) {
-		pymenu = BPyMenuTable[i];
-		while( pymenu ) {
-			tmp = pymenu->next;
-			if( pymenu->name )
-				MEM_freeN( pymenu->name );
-			if( pymenu->filename )
-				MEM_freeN( pymenu->filename );
-			if( pymenu->tooltip )
-				MEM_freeN( pymenu->tooltip );
-			if( pymenu->submenus )
-				bpymenu_RemoveAllSubEntries( pymenu->
-							     submenus );
-			MEM_freeN( pymenu );
-			pymenu = tmp;
-		}
-		BPyMenuTable[i] = NULL;
-	}
-
-	Dirs_Number = 0;
-	Dir_Depth = 0;
-
-	return;
-}
-
-static BPyMenu *bpymenu_FindEntry( short group, char *name )
-{
-	BPyMenu *pymenu;
-
-	if( ( group < 0 ) || ( group >= PYMENU_TOTAL ) )
-		return NULL;
-
-	pymenu = BPyMenuTable[group];
-
-	while( pymenu ) {
-		if( !strcmp( pymenu->name, name ) )
-			return pymenu;
-		pymenu = pymenu->next;
-	}
-
-	return NULL;
-}
-
-/* BPyMenu_GetEntry:
- * given a group and a position, return the entry in that position from
- * that group.
-*/
-BPyMenu *BPyMenu_GetEntry( short group, short pos )
-{
-	BPyMenu *pym = NULL;
-
-	if( ( group < 0 ) || ( group >= PYMENU_TOTAL ) )
-		return NULL;
-
-	pym = BPyMenuTable[group];
-
-	while( pos-- ) {
-		if( pym )
-			pym = pym->next;
-		else
-			break;
-	}
-
-	return pym;		/* found entry or NULL */
-}
-
-static void bpymenu_set_tooltip( BPyMenu * pymenu, char *tip )
-{
-	if( !pymenu )
-		return;
-
-	if( pymenu->tooltip )
-		MEM_freeN( pymenu->tooltip );
-	pymenu->tooltip = BLI_strdup( tip );
-
-	return;
-}
-
-/* bpymenu_AddEntry:
- * try to find an existing pymenu entry with the given type and name;
- * if found, update it with new info, otherwise create a new one and fill it.
- */
-static BPyMenu *bpymenu_AddEntry( short group, short version, char *name,
-	char *fname, int is_userdir, char *tooltip )
-{
-	BPyMenu *menu, *next = NULL, **iter;
-	int nameclash = 0;
-
-	if( ( group < 0 ) || ( group >= PYMENU_TOTAL ) )
-		return NULL;
-	if( !name || !fname )
-		return NULL;
-
-	menu = bpymenu_FindEntry( group, name );	/* already exists? */
-
-	/* if a menu with this name already exists in the same group:
-	 * - if one script is in the default dir and the other in U.pythondir,
-	 *   accept and let the new one override the other.
-	 * - otherwise, report the error and return NULL. */
-	if( menu ) {
-		if( menu->dir < is_userdir ) {	/* new one is in U.pythondir */
-			nameclash = 1;
-			if( menu->name )
-				MEM_freeN( menu->name );
-			if( menu->filename )
-				MEM_freeN( menu->filename );
-			if( menu->tooltip )
-				MEM_freeN( menu->tooltip );
-			if( menu->submenus )
-				bpymenu_RemoveAllSubEntries( menu->submenus );
-			next = menu->next;
-		} else {	/* they are in the same dir */
-			if (DEBUG) {
-				fprintf(stderr, "\n\
-Warning: script %s's menu name is already in use.\n\
-Edit the script and change its \n\
-Name: '%s'\n\
-field, please.\n\
-Note: if you really want to have two scripts for the same menu with\n\
-the same name, keep one in the default dir and the other in\n\
-the user defined dir (only the later will be registered).\n", fname, name);
-			}
-			return NULL;
-		}
-	} else
-		menu = MEM_mallocN( sizeof( BPyMenu ), "pymenu" );
-
-	if( !menu )
-		return NULL;
-
-	menu->name = BLI_strdup( name );
-	menu->version = version;
-	menu->filename = BLI_strdup( fname );
-	menu->tooltip = NULL;
-	if( tooltip )
-		menu->tooltip = BLI_strdup( tooltip );
-	menu->dir = is_userdir;
-	menu->submenus = NULL;
-	menu->next = next;	/* non-NULL if menu already existed */
-
-	if( nameclash )
-		return menu;	/* no need to place it, it's already at the list */
-	else {	/* insert the new entry in its correct position at the table */
-		BPyMenu *prev = NULL;
-		char *s = NULL;
-
-		iter = &BPyMenuTable[group];
-		while( *iter ) {
-			s = ( *iter )->name;
-			if( s )
-				if( strcmp( menu->name, s ) < 0 )
-					break;	/* sort by names */
-			prev = *iter;
-			iter = &( ( *iter )->next );
-		}
-
-		if( *iter ) {	/* prepend */
-			menu->next = *iter;
-			if( prev )
-				prev->next = menu;
-			else
-				BPyMenuTable[group] = menu;	/* is first entry */
-		} else
-			*iter = menu;	/* append */
-	}
-
-	return menu;
-}
-
-/* bpymenu_AddSubEntry:
- * add a submenu to an existing python menu.
- */
-static int bpymenu_AddSubEntry( BPyMenu * mentry, char *name, char *arg )
-{
-	BPySubMenu *smenu, **iter;
-
-	smenu = MEM_mallocN( sizeof( BPySubMenu ), "pysubmenu" );
-	if( !smenu )
-		return -1;
-
-	smenu->name = BLI_strdup( name );
-	smenu->arg = BLI_strdup( arg );
-	smenu->next = NULL;
-
-	if( !smenu->name || !smenu->arg )
-		return -1;
-
-	iter = &( mentry->submenus );
-	while( *iter )
-		iter = &( ( *iter )->next );
-
-	*iter = smenu;
-
-	return 0;
-}
-
-/* bpymenu_CreateFromFile:
- * parse the bpymenus data file where Python menu data is stored;
- * based on this data, create and fill the pymenu structs.
- */
-static int bpymenu_CreateFromFile( void )
-{
-	FILE *fp;
-	char line[255], w1[255], w2[255], tooltip[255], *tip;
-	char *homedir = NULL;
-	int parsing, version, is_userdir;
-	short group;
-	BPyMenu *pymenu = NULL;
-
-	/* init global bpymenu table (it is a list of pointers to struct BPyMenus
-	 * for each available cathegory: import, export, etc.) */
-	for( group = 0; group < PYMENU_TOTAL; group++ )
-		BPyMenuTable[group] = NULL;
-
-	/* let's try to open the file with bpymenu data */
-	homedir = bpy_gethome(0);
-	if (!homedir) {
-		if( DEBUG )
-			fprintf(stderr,
-				"BPyMenus error: couldn't open config file Bpymenus: no home dir.\n");
-		return -1;
-	}
-
-	BLI_make_file_string( "/", line, homedir, BPYMENU_DATAFILE );
-
-	fp = fopen( line, "rb" );
-
-	if( !fp ) {
-		if( DEBUG )
-			fprintf(stderr, "BPyMenus error: couldn't open config file %s.\n", line );
-		return -1;
-	}
-
-	fgets( line, 255, fp );	/* header */
-
-	/* check if the U.pythondir we saved at the file is different from the
-	 * current one.  If so, return to force updating from dirs */
-	w1[0] = '\0';
-	fscanf( fp, "# User defined scripts dir: %[^\n]\n", w1 );
-	if( w1 ) {
-		char upythondir[FILE_MAXDIR];
-
-		BLI_strncpy(upythondir, U.pythondir, FILE_MAXDIR);
-		BLI_convertstringcode(upythondir, G.sce, 0);
-		if( strcmp( w1, upythondir ) != 0 )
-			return -1;
-		w1[0] = '\0';
-	}
-
-	while( fgets( line, 255, fp ) ) {	/* parsing file lines */
-
-		switch ( line[0] ) {	/* check first char */
-		case '#':	/* comment */
-			continue;
-			break;
-		case '\n':
-			continue;
-			break;
-		default:
-			parsing = sscanf( line, "%s {\n", w1 );	/* menu group */
-			break;
-		}
-
-		if( parsing == 1 ) {	/* got menu group string */
-			group = (short)bpymenu_group_atoi( w1 );
-			if( group < 0 && DEBUG ) {	/* invalid type */
-				fprintf(stderr,
-					"BPyMenus error parsing config file: wrong group: %s,\n\
-will use 'Misc'.\n", w1 );
-			}
-		} else
-			continue;
-
-		for(;;) {
-			tip = NULL;	/* optional tooltip */
-			fgets( line, 255, fp );
-			if( line[0] == '}' )
-				break;
-			else if( line[0] == '\n' )
-				continue;
-			else if( line[0] == '\'' ) {	/* menu entry */
-				parsing =
-					sscanf( line,
-						"'%[^']' %d %s %d '%[^']'\n",
-						w1, &version, w2, &is_userdir,
-						tooltip );
-
-				if( parsing <= 0 ) {	/* invalid line, get rid of it */
-					fgets( line, 255, fp );
-				} else if( parsing == 5 )
-					tip = tooltip;	/* has tooltip */
-
-				pymenu = bpymenu_AddEntry( group,
-							   ( short ) version,
-							   w1, w2, is_userdir,
-							   tip );
-				if( !pymenu ) {
-					puts( "BPyMenus error: couldn't create bpymenu entry.\n" );
-					fclose( fp );
-					return -1;
-				}
-			} else if( line[0] == '|' && line[1] == '_' ) {	/* menu sub-entry */
-				if( !pymenu )
-					continue;	/* no menu yet, skip this line */
-				sscanf( line, "|_%[^:]: %s\n", w1, w2 );
-				bpymenu_AddSubEntry( pymenu, w1, w2 );
-			}
-		}
-	}
-
-	fclose( fp );
-	return 0;
-}
-
-/* bpymenu_WriteDataFile:
- * writes the registered scripts info to the user's home dir, for faster
- * access when the scripts dir hasn't changed.
-*/
-static void bpymenu_WriteDataFile( void )
-{
-	BPyMenu *pymenu;
-	BPySubMenu *smenu;
-	FILE *fp;
-	char fname[FILE_MAXDIR], *homedir;
-	int i;
-
-	homedir = bpy_gethome(0);
-
-	if (!homedir) {
-		if( DEBUG )
-			fprintf(stderr,
-				"BPyMenus error: couldn't write Bpymenus file: no home dir.\n\n");
-		return;
-	}
-
-	BLI_make_file_string( "/", fname, homedir, BPYMENU_DATAFILE );
-
-	fp = fopen( fname, "w" );
-	if( !fp ) {
-		if( DEBUG )
-			fprintf(stderr, "BPyMenus error: couldn't write %s file.\n\n",
-				fname );
-		return;
-	}
-
-	fprintf( fp,
-		 "# Blender: registered menu entries for bpython scripts\n" );
-
-	if (U.pythondir[0] != '\0' &&
-			strcmp(U.pythondir, "/") != 0 && strcmp(U.pythondir, "//") != 0)
-	{
-		char upythondir[FILE_MAXDIR];
-
-		BLI_strncpy(upythondir, U.pythondir, FILE_MAXDIR);
-		BLI_convertstringcode(upythondir, G.sce, 0);
-		fprintf( fp, "# User defined scripts dir: %s\n", upythondir );
-	}
-
-	for( i = 0; i < PYMENU_TOTAL; i++ ) {
-		pymenu = BPyMenuTable[i];
-		if( !pymenu )
-			continue;
-		fprintf( fp, "\n%s {\n", BPyMenu_group_itoa( (short)i ) );
-		while( pymenu ) {
-			fprintf( fp, "'%s' %d %s %d", pymenu->name,
-				 pymenu->version, pymenu->filename,
-				 pymenu->dir );
-			if( pymenu->tooltip )
-				fprintf( fp, " '%s'\n", pymenu->tooltip );
-			else
-				fprintf( fp, "\n" );
-			smenu = pymenu->submenus;
-			while( smenu ) {
-				fprintf( fp, "|_%s: %s\n", smenu->name,
-					 smenu->arg );
-				smenu = smenu->next;
-			}
-			pymenu = pymenu->next;
-		}
-		fprintf( fp, "}\n" );
-	}
-
-	fclose( fp );
-	return;
-}
-
-/* BPyMenu_PrintAllEntries:
- * useful for debugging.
- */
-void BPyMenu_PrintAllEntries( void )
-{
-	BPyMenu *pymenu;
-	BPySubMenu *smenu;
-	int i;
-
-	printf( "# Blender: registered menu entries for bpython scripts\n" );
-
-	for( i = 0; i < PYMENU_TOTAL; i++ ) {
-		pymenu = BPyMenuTable[i];
-		printf( "\n%s {\n", BPyMenu_group_itoa( (short)i ) );
-		while( pymenu ) {
-			printf( "'%s' %d %s %d", pymenu->name, pymenu->version,
-				pymenu->filename, pymenu->dir );
-			if( pymenu->tooltip )
-				printf( " '%s'\n", pymenu->tooltip );
-			else
-				printf( "\n" );
-			smenu = pymenu->submenus;
-			while( smenu ) {
-				printf( "|_%s: %s\n", smenu->name,
-					smenu->arg );
-				smenu = smenu->next;
-			}
-			pymenu = pymenu->next;
-		}
-		printf( "}\n" );
-	}
-}
-
-/* bpymenu_ParseFile:
- * recursively scans folders looking for scripts to register.
- *
- * This function scans the scripts directory looking for .py files with the
- * right header and menu info, using that to fill the bpymenu structs.
- * is_userdir defines if the script is in the default scripts dir or the
- * user defined one (U.pythondir: is_userdir == 1).
- * Speed is important.
- *
- * The first line of the script must be '#!BPY'.
- * The header registration lines must appear between the first pair of
- * '\"\"\"' and follow this order (the single-quotes are part of
- * the format):
- *
- * # \"\"\"
- * # Name: 'script name for the menu' - * # Blender: short int (minimal Blender version) - * # Group: 'group name' (defines menu) - * # Submenu: 'submenu name' related_1word_arg - * # Tooltip: 'tooltip for the menu' - * # \"\"\" - * - * Notes: - * - * - Commenting out header lines with "#" is optional, but recommended. - * - There may be more than one submenu line, or none: - * submenus and the tooltip are optional; - * - The Blender version is the same number reported by - * Blender.Get('version') in BPython or G.version in C; - * - Line length must be less than 99. - */ -static int bpymenu_ParseFile(FILE *file, char *fname, int is_userdir) -{ - char line[100]; - char head[100]; - char middle[100]; - char tail[100]; - int matches; - int parser_state; - - char script_name[100]; - int script_version = 1; - int script_group; - - BPyMenu *scriptMenu = NULL; - - if (file != NULL) { - parser_state = 1; /* state of parser, 0 to terminate */ - - while ((parser_state != 0) && (fgets(line, 100, file) != NULL)) { - - switch (parser_state) { - - case 1: /* !BPY */ - if (strncmp(line, "#!BPY", 5) == 0) { - parser_state++; - } else { - parser_state = 0; - } - break; - - case 2: /* \"\"\" */ - if ((strstr(line, "\"\"\""))) { - parser_state++; - } - break; - - case 3: /* Name: 'script name for the menu' */ - matches = sscanf(line, "%[^']'%[^']'%c", head, script_name, tail); - if ((matches == 3) && (strstr(head, "Name:") != NULL)) { - parser_state++; - } else { - if (DEBUG) - fprintf(stderr, "BPyMenus error: Wrong 'Name' line: %s\n", fname); - parser_state = 0; - } - break; - - case 4: /* Blender: */ - matches = sscanf(line, "%[^1234567890]%i%c", head, &script_version, - tail); - if (matches == 3) { - parser_state++; - } else { - if (DEBUG) - fprintf(stderr,"BPyMenus error: Wrong 'Blender' line: %s\n",fname); - parser_state = 0; - } - break; - - case 5: /* Group: 'group name' */ - matches = sscanf(line, "%[^']'%[^']'%c", head, middle, tail); - if ((matches == 3) && (strstr(head, "Group:") != NULL)) { - script_group = bpymenu_group_atoi(middle); - if (script_group < 0) { - if (DEBUG) - fprintf(stderr, "BPyMenus error: Unknown group \"%s\": %s\n", - middle, fname); - parser_state = 0; - } - - else { /* register script */ - scriptMenu = bpymenu_AddEntry((short)script_group, - (short int)script_version, script_name, fname, is_userdir,NULL); - if (scriptMenu == NULL) { - if (DEBUG) - fprintf(stderr, - "BPyMenus error: Couldn't create entry for: %s\n", fname); - parser_state = 0; - } else { - parser_state++; - } - } - - } else { - if (DEBUG) - fprintf(stderr, "BPyMenus error: Wrong 'Group' line: %s\n",fname); - parser_state = 0; - } - break; - - case 6: /* optional elements */ - /* Submenu: 'submenu name' related_1word_arg */ - matches = sscanf(line, "%[^']'%[^']'%s\n", head, middle, tail); - if ((matches == 3) && (strstr(head, "Submenu:") != NULL)) { - bpymenu_AddSubEntry(scriptMenu, middle, tail); - } else { - /* Tooltip: 'tooltip for the menu */ - matches = sscanf(line, "%[^']'%[^']'%c", head, middle, tail); - if ((matches == 3) && ((strstr(head, "Tooltip:") != NULL) || - (strstr(head, "Tip:") != NULL))) { - bpymenu_set_tooltip(scriptMenu, middle); - } - parser_state = 0; - } - break; - - default: - parser_state = 0; - break; - } - } - } - - else { /* shouldn't happen, it's checked in bpymenus_ParseDir */ - if (DEBUG) - fprintf(stderr, "BPyMenus error: Couldn't open %s.\n", fname); - return -1; - } - - return 0; -} - -/* bpymenu_ParseDir: - * recursively scans folders looking for scripts to register. - * - * This function scans the scripts directory looking for .py files with the - * right header and menu info. - * - is_userdir defines if the script is in the default scripts dir or the - * user defined one (U.pythondir: is_userdir == 1); - * - parentdir is the parent dir name to store as part of the script filename, - * if we're down a subdir. - * Speed is important. - */ -static int bpymenu_ParseDir(char *dirname, char *parentdir, int is_userdir ) -{ - DIR *dir; - FILE *file = NULL; - struct dirent *de; - struct stat status; - char *file_extension; - char path[FILE_MAX]; - char subdir[FILE_MAX]; - char *s = NULL; - - dir = opendir(dirname); - - if (dir != NULL) { - while ((de = readdir(dir)) != NULL) { - - /* skip files and dirs starting with '.' or 'bpy' */ - if ((de->d_name[0] == '.') || !strncmp(de->d_name, "bpy", 3)) { - continue; - } - - BLI_make_file_string("/", path, dirname, de->d_name); - - if (stat(path, &status) != 0) { - if (DEBUG) - fprintf(stderr, "stat %s failed: %s\n", path, strerror(errno)); - } - - if (S_ISREG(status.st_mode)) { /* is file */ - - file_extension = strstr(de->d_name, ".py"); - - if (file_extension && *(file_extension + 3) == '\0') { - file = fopen(path, "rb"); - - if (file) { - s = de->d_name; - if (parentdir) { - /* Join parentdir and de->d_name */ - BLI_join_dirfile(subdir, parentdir, de->d_name); - - s = subdir; - } - bpymenu_ParseFile(file, s, is_userdir); - fclose(file); - } - - else { - if (DEBUG) - fprintf(stderr, "BPyMenus error: Couldn't open %s.\n", path); - } - } - } - - else if (S_ISDIR(status.st_mode)) { /* is subdir */ - Dirs_Number++; - Dir_Depth++; - if (Dirs_Number > MAX_DIR_NUMBER) { - if (DEBUG) { - fprintf(stderr, "BPyMenus error: too many subdirs.\n"); - } - closedir(dir); - return -1; - } - else if (Dir_Depth > MAX_DIR_DEPTH) { - if (DEBUG) - fprintf(stderr, - "BPyMenus error: max depth reached traversing dir tree.\n"); - closedir(dir); - return -1; - } - s = de->d_name; - if (parentdir) { - /* Join parentdir and de->d_name */ - BLI_join_dirfile(subdir, parentdir, de->d_name); - s = subdir; - } - if (bpymenu_ParseDir(path, s, is_userdir) == -1) { - closedir(dir); - return -1; - } - Dir_Depth--; - } - - } - closedir(dir); - } - - else { /* open directory stream failed */ - if (DEBUG) - fprintf(stderr, "opendir %s failed: %s\n", dirname, strerror(errno)); - return -1; - } - - return 0; -} - -static int bpymenu_GetStatMTime( char *name, int is_file, time_t * mtime ) -{ - struct stat st; - int result; - - result = stat( name, &st ); - - if( result == -1 ) - return -1; - - if( is_file ) { - if( !S_ISREG( st.st_mode ) ) - return -2; - } else if( !S_ISDIR( st.st_mode ) ) - return -2; - - *mtime = st.st_mtime; - - return 0; -} - -/* BPyMenu_Init: - * import the bpython menus data to Blender, either from: - * - the BPYMENU_DATAFILE file (?/.blender/Bpymenus) or - * - the scripts dir(s), case newer than the datafile (then update the file). - * then fill the bpymenu table with this data. - * if param usedir != 0, then the data is recreated from the dir(s) anyway. -*/ -int BPyMenu_Init( int usedir ) -{ - char fname[FILE_MAXDIR]; - char dirname[FILE_MAXDIR]; - char upythondir[FILE_MAXDIR]; - char *upydir = U.pythondir, *sdir = NULL; - time_t time_dir1 = 0, time_dir2 = 0, time_file = 0; - int stat_dir1 = 0, stat_dir2 = 0, stat_file = 0; - int i; - - DEBUG = G.f & G_DEBUG; /* is Blender in debug mode (started with -d) ? */ - - /* init global bpymenu table (it is a list of pointers to struct BPyMenus - * for each available group: import, export, etc.) */ - for( i = 0; i < PYMENU_TOTAL; i++ ) - BPyMenuTable[i] = NULL; - - if( DEBUG ) - fprintf(stdout, "\nRegistering scripts in Blender menus ...\n\n" ); - - if( U.pythondir[0] == '\0') { - upydir = NULL; - } - else if (strcmp(U.pythondir, "/") == 0 || strcmp(U.pythondir, "//") == 0) { - /* these are not accepted to prevent possible slight slowdowns on startup; - * they should not be used as user defined scripts dir, anyway, also from - * speed considerations, since they'd not be dedicated scripts dirs */ - if (DEBUG) fprintf(stderr, - "BPyMenus: invalid user defined Python scripts dir: \"/\" or \"//\".\n"); - upydir = NULL; - } - else { - BLI_strncpy(upythondir, upydir, FILE_MAXDIR); - BLI_convertstringcode(upythondir, G.sce, 0); - } - - sdir = bpy_gethome(1); - - if (sdir) { - BLI_strncpy(dirname, sdir, FILE_MAXDIR); - stat_dir1 = bpymenu_GetStatMTime( dirname, 0, &time_dir1 ); - - if( stat_dir1 < 0 ) { - time_dir1 = 0; - if( DEBUG ) { - fprintf(stderr, - "\nDefault scripts dir: %s:\n%s\n", dirname, strerror(errno)); - if( upydir ) - fprintf(stdout, - "Getting scripts menu data from user defined dir: %s.\n", - upythondir ); - } - } - } - else stat_dir1 = -1; - - if( upydir ) { - stat_dir2 = bpymenu_GetStatMTime( upythondir, 0, &time_dir2 ); - - if( stat_dir2 < 0 ) { - time_dir2 = 0; - upydir = NULL; - if( DEBUG ) - fprintf(stderr, "\nUser defined scripts dir: %s:\n%s.\n", - upythondir, strerror( errno ) ); - if( stat_dir1 < 0 ) { - if( DEBUG ) - fprintf(stderr, "\ -To have scripts in menus, please add them to the default scripts dir:\n\ -%s\n\ -and / or go to 'Info window -> File Paths tab' and set a valid path for\n\ -the user defined Python scripts dir.\n", dirname ); - return -1; - } - } - } - else stat_dir2 = -1; - - if( ( stat_dir1 < 0 ) && ( stat_dir2 < 0 ) ) { - if( DEBUG ) { - fprintf(stderr, "\nCannot register scripts in menus, no scripts dir" - " available.\nExpected default dir at: %s \n", dirname ); - } - return -1; - } - - if (usedir) stat_file = -1; - else { /* if we're not forced to use the dir */ - char *homedir = bpy_gethome(0); - - if (homedir) { - BLI_make_file_string( "/", fname, homedir, BPYMENU_DATAFILE ); - stat_file = bpymenu_GetStatMTime( fname, 1, &time_file ); - if( stat_file < 0 ) - time_file = 0; - - /* comparing dates */ - - if((stat_file == 0) - && (time_file > time_dir1) && (time_file > time_dir2)) - { /* file is newer */ - stat_file = bpymenu_CreateFromFile( ); /* -1 if an error occurred */ - if( !stat_file && DEBUG ) - fprintf(stdout, - "Getting menu data for scripts from file:\n%s\n\n", fname ); - } - else stat_file = -1; - } - else stat_file = -1; /* -1 to use dirs: didn't use file or it was corrupted */ - } - - if( stat_file == -1 ) { /* use dirs */ - if( DEBUG ) { - fprintf(stdout, - "Getting menu data for scripts from dir(s):\ndefault: %s\n", dirname ); - if( upydir ) - fprintf(stdout, "user defined: %s\n", upythondir ); - fprintf(stdout, "\n"); - } - if( stat_dir1 == 0 ) { - i = bpymenu_ParseDir( dirname, NULL, 0 ); - if (i == -1 && DEBUG) - fprintf(stderr, "Default scripts dir does not seem valid.\n\n"); - } - if( stat_dir2 == 0 ) { - BLI_strncpy(dirname, U.pythondir, FILE_MAXDIR); - BLI_convertstringcode(dirname, G.sce, 0); - i = bpymenu_ParseDir( dirname, NULL, 1 ); - if (i == -1 && DEBUG) - fprintf(stderr, "User defined scripts dir does not seem valid.\n\n"); - } - - /* check if we got any data */ - for( i = 0; i < PYMENU_TOTAL; i++ ) - if( BPyMenuTable[i] ) - break; - - /* if we got, recreate the file */ - if( i < PYMENU_TOTAL ) - bpymenu_WriteDataFile( ); - else if( DEBUG ) { - fprintf(stderr, "\n\ -Warning: Registering scripts in menus -- no info found.\n\ -Either your scripts dirs have no .py scripts or the scripts\n\ -don't have a header with registration data.\n\ -Default scripts dir is:\n\ -%s\n", dirname ); - if( upydir ) - fprintf(stderr, "User defined scripts dir is: %s\n", - upythondir ); - } - } - - return 0; -} diff --git a/source/blender/python/BPY_menus.h b/source/blender/python/BPY_menus.h deleted file mode 100644 index 6cdea608b10..00000000000 --- a/source/blender/python/BPY_menus.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * $Id: BPY_menus.h 12931 2007-12-17 18:20:48Z theeth $ - * - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * This is a new part of Blender. - * - * Contributor(s): Willian P. Germano, Matt Ebb - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** -*/ - -#ifndef BPY_MENUS_H -#define BPY_MENUS_H - -/* This header exposes BPyMenu related public declarations. The implementation - * adds 'dynamic' menus to Blender, letting scripts register themselves in any - * of a few pre-defined (trivial to upgrade) places in menus. These places or - * slots are called groups here (Import, Export, etc). This is how it works: - * - scripts at dirs user pref U.pythondir and .blender/scripts/ are scanned - * for registration info. - * - this data is also saved to a Bpymenus file at the user's .blender/ dir and - * only re-created when the scripts folder gets modified. - * - on start-up Blender uses this info to fill a table, which is used to - * create the menu entries when they are needed (see header_info.c or - * header_script.c, under source/blender/src/, for examples). -*/ - -/* These two structs hold py menu/submenu info. - * BPyMenu holds a script's name (as should appear in the menu) and filename, - * plus an optional list of submenus. Each submenu is related to a string - * (arg) that the script can get from the __script__ pydict, to know which - * submenu was chosen. */ - -typedef struct BPySubMenu { - char *name; - char *arg; - struct BPySubMenu *next; -} BPySubMenu; - -typedef struct BPyMenu { - char *name; - char *filename; - char *tooltip; - short version; /* Blender version */ - int dir; /* 0: default, 1: U.pythondir */ - struct BPySubMenu *submenus; - struct BPyMenu *next; -} BPyMenu; - -/* Scripts can be added to only a few pre-defined places in menus, like - * File->Import, File->Export, etc. (for speed and better control). - * To make a new menu 'slot' available for scripts: - * - add an entry to the enum below, before PYMENU_TOTAL, of course; - * - update the bpymenu_group_atoi() and BPyMenu_group_itoa() functions in - * BPY_menus.c; - * - add the necessary code to the header_***.c file in - * source/blender/src/, like done in header_info.c for import/export; -*/ -typedef enum { - PYMENU_ADD,/* creates new objects */ - PYMENU_ANIMATION, - PYMENU_EXPORT, - PYMENU_IMPORT, - PYMENU_MATERIALS, - PYMENU_MESH, - PYMENU_MISC, - PYMENU_OBJECT, - PYMENU_RENDER,/* exporters to external renderers */ - PYMENU_SYSTEM, - PYMENU_THEMES, - PYMENU_UV,/* UV editing tools, to go in UV/Image editor space, 'UV' menu */ - PYMENU_IMAGE,/* Image editing tools, to go in UV/Image editor space, 'Image' menu */ - PYMENU_WIZARDS,/* complex 'app' scripts */ - - /* entries put after Wizards don't appear at the Scripts win->Scripts menu; - * see define right below */ - - PYMENU_FACESELECT, - PYMENU_WEIGHTPAINT, - PYMENU_VERTEXPAINT, - PYMENU_UVCALCULATION, - PYMENU_ARMATURE, - PYMENU_SCRIPTTEMPLATE, - PYMENU_HELP,/*Main Help menu items - prob best to leave for 'official' ones*/ - PYMENU_HELPSYSTEM,/* Resources, troubleshooting, system tools */ - PYMENU_HELPWEBSITES,/* Help -> Websites submenu */ - PYMENU_MESHFACEKEY, /* face key in mesh editmode */ - PYMENU_ADDMESH, /* adds mesh */ - PYMENU_TOTAL -} PYMENUHOOKS; - -#define PYMENU_SCRIPTS_MENU_TOTAL (PYMENU_WIZARDS + 1) - -/* BPyMenuTable holds all registered pymenus, as linked lists for each menu - * where they can appear (see PYMENUHOOKS enum above). -*/ -extern BPyMenu *BPyMenuTable[]; /* defined in BPY_menus.c */ - -/* public functions: */ -int BPyMenu_Init( int usedir ); -void BPyMenu_RemoveAllEntries( void ); -void BPyMenu_PrintAllEntries( void ); -char *BPyMenu_CreatePupmenuStr( BPyMenu * pym, short group ); -char *BPyMenu_group_itoa( short group ); -struct BPyMenu *BPyMenu_GetEntry( short group, short pos ); - -#endif /* BPY_MENUS_H */ diff --git a/source/blender/python/Makefile b/source/blender/python/Makefile index 0c4b9ab6578..8e2a04b8449 100644 --- a/source/blender/python/Makefile +++ b/source/blender/python/Makefile @@ -1,5 +1,5 @@ # -# $Id: Makefile 14444 2008-04-16 22:40:48Z hos $ +# $Id$ # # ***** BEGIN GPL LICENSE BLOCK ***** # diff --git a/source/blender/python/generic/BGL.c b/source/blender/python/generic/BGL.c index f1a72270ea1..de82781cf3a 100644 --- a/source/blender/python/generic/BGL.c +++ b/source/blender/python/generic/BGL.c @@ -1,5 +1,5 @@ /* - * $Id: BGL.c 20922 2009-06-16 07:16:51Z campbellbarton $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -83,8 +83,13 @@ static PyObject *Buffer_getattr( PyObject * self, char *name ); static PyObject *Buffer_repr( PyObject * self ); PyTypeObject buffer_Type = { - PyObject_HEAD_INIT( NULL ) /* required python macro */ - 0, /*ob_size */ +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "buffer", /*tp_name */ sizeof( Buffer ), /*tp_basicsize */ 0, /*tp_itemsize */ @@ -1087,7 +1092,7 @@ static struct PyMethodDef BGL_methods[] = { #if (PY_VERSION_HEX >= 0x03000000) static struct PyModuleDef BGL_module_def = { - {}, /* m_base */ + PyModuleDef_HEAD_INIT, "BGL", /* m_name */ 0, /* m_doc */ 0, /* m_size */ diff --git a/source/blender/python/generic/BGL.h b/source/blender/python/generic/BGL.h index e2d1b0bb495..938c916bcea 100755 --- a/source/blender/python/generic/BGL.h +++ b/source/blender/python/generic/BGL.h @@ -1,5 +1,5 @@ /* - * $Id: BGL.h 19717 2009-04-14 17:19:09Z campbellbarton $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/python/generic/Geometry.c b/source/blender/python/generic/Geometry.c index d1e8b471f75..b4a34d30051 100644 --- a/source/blender/python/generic/Geometry.c +++ b/source/blender/python/generic/Geometry.c @@ -1,5 +1,5 @@ /* - * $Id: Geometry.c 20922 2009-06-16 07:16:51Z campbellbarton $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -80,7 +80,7 @@ struct PyMethodDef M_Geometry_methods[] = { #if (PY_VERSION_HEX >= 0x03000000) static struct PyModuleDef M_Geometry_module_def = { - {}, /* m_base */ + PyModuleDef_HEAD_INIT, "Geometry", /* m_name */ M_Geometry_doc, /* m_doc */ 0, /* m_size */ @@ -164,6 +164,10 @@ static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq ) for( index = 0; indexvec[0]; fp[1] = ((VectorObject *)polyVec)->vec[1]; if( ((VectorObject *)polyVec)->size > 2 ) @@ -234,6 +238,9 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args ) return NULL; } + if(!BaseMath_ReadCallback(line_a1) || !BaseMath_ReadCallback(line_a2) || !BaseMath_ReadCallback(line_b1) || !BaseMath_ReadCallback(line_b2)) + return NULL; + a1x= line_a1->vec[0]; a1y= line_a1->vec[1]; a2x= line_a2->vec[0]; @@ -266,7 +273,7 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args ) /*X of vert, Y of hoz. no calculation needed */ newvec[0]= a1x; newvec[1]= b1y; - return newVectorObject(newvec, 2, Py_NEW); + return newVectorObject(newvec, 2, Py_NEW, NULL); } yi = (float)(((b1y / fabs(b1x - b2x)) * fabs(b2x - a1x)) + ((b2y / fabs(b1x - b2x)) * fabs(b1x - a1x))); @@ -278,7 +285,7 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args ) } newvec[0]= a1x; newvec[1]= yi; - return newVectorObject(newvec, 2, Py_NEW); + return newVectorObject(newvec, 2, Py_NEW, NULL); } else if (fabs(a2y-a1y) < eul) { /* hoz line1 */ if (fabs(b2y-b1y) < eul) { /*hoz line2*/ Py_RETURN_NONE; /*2 hoz lines dont intersect*/ @@ -293,7 +300,7 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args ) } newvec[0]= xi; newvec[1]= a1y; - return newVectorObject(newvec, 2, Py_NEW); + return newVectorObject(newvec, 2, Py_NEW, NULL); } b1 = (a2y-a1y)/(a2x-a1x); @@ -310,7 +317,7 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args ) if ((a1x-xi)*(xi-a2x) >= 0 && (b1x-xi)*(xi-b2x) >= 0 && (a1y-yi)*(yi-a2y) >= 0 && (b1y-yi)*(yi-b2y)>=0) { newvec[0]= xi; newvec[1]= yi; - return newVectorObject(newvec, 2, Py_NEW); + return newVectorObject(newvec, 2, Py_NEW, NULL); } Py_RETURN_NONE; } @@ -330,6 +337,10 @@ static PyObject *M_Geometry_ClosestPointOnLine( PyObject * self, PyObject * args PyErr_SetString( PyExc_TypeError, "expected 3 vector types\n" ); return NULL; } + + if(!BaseMath_ReadCallback(pt) || !BaseMath_ReadCallback(line_1) || !BaseMath_ReadCallback(line_2)) + return NULL; + /* accept 2d verts */ if (pt->size==3) { VECCOPY(pt_in, pt->vec);} else { pt_in[2]=0.0; VECCOPY2D(pt_in, pt->vec) } @@ -344,7 +355,7 @@ static PyObject *M_Geometry_ClosestPointOnLine( PyObject * self, PyObject * args lambda = lambda_cp_line_ex(pt_in, l1, l2, pt_out); ret = PyTuple_New(2); - PyTuple_SET_ITEM( ret, 0, newVectorObject(pt_out, 3, Py_NEW) ); + PyTuple_SET_ITEM( ret, 0, newVectorObject(pt_out, 3, Py_NEW, NULL) ); PyTuple_SET_ITEM( ret, 1, PyFloat_FromDouble(lambda) ); return ret; } @@ -363,6 +374,9 @@ static PyObject *M_Geometry_PointInTriangle2D( PyObject * self, PyObject * args return NULL; } + if(!BaseMath_ReadCallback(pt_vec) || !BaseMath_ReadCallback(tri_p1) || !BaseMath_ReadCallback(tri_p2) || !BaseMath_ReadCallback(tri_p3)) + return NULL; + return PyLong_FromLong(IsectPT2Df(pt_vec->vec, tri_p1->vec, tri_p2->vec, tri_p3->vec)); } @@ -381,6 +395,9 @@ static PyObject *M_Geometry_PointInQuad2D( PyObject * self, PyObject * args ) return NULL; } + if(!BaseMath_ReadCallback(pt_vec) || !BaseMath_ReadCallback(quad_p1) || !BaseMath_ReadCallback(quad_p2) || !BaseMath_ReadCallback(quad_p3) || !BaseMath_ReadCallback(quad_p4)) + return NULL; + return PyLong_FromLong(IsectPQ2Df(pt_vec->vec, quad_p1->vec, quad_p2->vec, quad_p3->vec, quad_p4->vec)); } @@ -500,6 +517,9 @@ static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args ) return NULL; } + if(!BaseMath_ReadCallback(vec_k1) || !BaseMath_ReadCallback(vec_h1) || !BaseMath_ReadCallback(vec_k2) || !BaseMath_ReadCallback(vec_h2)) + return NULL; + dims= MAX4(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size); for(i=0; i < vec_k1->size; i++) k1[i]= vec_k1->vec[i]; @@ -515,7 +535,7 @@ static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args ) list= PyList_New(resolu); fp= coord_array; for(i=0; i= 0x03000000) static struct PyModuleDef M_Mathutils_module_def = { - {}, /* m_base */ + PyModuleDef_HEAD_INIT, "Mathutils", /* m_name */ M_Mathutils_doc, /* m_doc */ 0, /* m_size */ @@ -137,81 +137,12 @@ PyObject *Mathutils_Init(const char *from) PyModule_AddObject( submodule, "Euler", (PyObject *)&euler_Type ); PyModule_AddObject( submodule, "Quaternion", (PyObject *)&quaternion_Type ); + mathutils_matrix_vector_cb_index= Mathutils_RegisterCallback(&mathutils_matrix_vector_cb); + return (submodule); } //-----------------------------METHODS---------------------------- -//----------------column_vector_multiplication (internal)--------- -//COLUMN VECTOR Multiplication (Matrix X Vector) -// [1][2][3] [a] -// [4][5][6] * [b] -// [7][8][9] [c] -//vector/matrix multiplication IS NOT COMMUTATIVE!!!! -PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec) -{ - float vecNew[4], vecCopy[4]; - double dot = 0.0f; - int x, y, z = 0; - - if(mat->rowSize != vec->size){ - if(mat->rowSize == 4 && vec->size != 3){ - PyErr_SetString(PyExc_AttributeError, "matrix * vector: matrix row size and vector size must be the same"); - return NULL; - }else{ - vecCopy[3] = 1.0f; - } - } - - for(x = 0; x < vec->size; x++){ - vecCopy[x] = vec->vec[x]; - } - - for(x = 0; x < mat->rowSize; x++) { - for(y = 0; y < mat->colSize; y++) { - dot += mat->matrix[x][y] * vecCopy[y]; - } - vecNew[z++] = (float)dot; - dot = 0.0f; - } - return newVectorObject(vecNew, vec->size, Py_NEW); -} - -//-----------------row_vector_multiplication (internal)----------- -//ROW VECTOR Multiplication - Vector X Matrix -//[x][y][z] * [1][2][3] -// [4][5][6] -// [7][8][9] -//vector/matrix multiplication IS NOT COMMUTATIVE!!!! -PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat) -{ - float vecNew[4], vecCopy[4]; - double dot = 0.0f; - int x, y, z = 0, vec_size = vec->size; - - if(mat->colSize != vec_size){ - if(mat->rowSize == 4 && vec_size != 3){ - PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same"); - return NULL; - }else{ - vecCopy[3] = 1.0f; - } - } - - for(x = 0; x < vec_size; x++){ - vecCopy[x] = vec->vec[x]; - } - - //muliplication - for(x = 0; x < mat->colSize; x++) { - for(y = 0; y < mat->rowSize; y++) { - dot += mat->matrix[y][x] * vecCopy[y]; - } - vecNew[z++] = (float)dot; - dot = 0.0f; - } - return newVectorObject(vecNew, vec_size, Py_NEW); -} - //-----------------quat_rotation (internal)----------- //This function multiplies a vector/point * quat or vice versa //to rotate the point/vector by the quaternion @@ -224,8 +155,15 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2) if(QuaternionObject_Check(arg1)){ quat = (QuaternionObject*)arg1; + if(!BaseMath_ReadCallback(quat)) + return NULL; + if(VectorObject_Check(arg2)){ vec = (VectorObject*)arg2; + + if(!BaseMath_ReadCallback(vec)) + return NULL; + rot[0] = quat->quat[0]*quat->quat[0]*vec->vec[0] + 2*quat->quat[2]*quat->quat[0]*vec->vec[2] - 2*quat->quat[3]*quat->quat[0]*vec->vec[1] + quat->quat[1]*quat->quat[1]*vec->vec[0] + 2*quat->quat[2]*quat->quat[1]*vec->vec[1] + 2*quat->quat[3]*quat->quat[1]*vec->vec[2] - @@ -238,12 +176,19 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2) quat->quat[3]*quat->quat[3]*vec->vec[2] - 2*quat->quat[0]*quat->quat[2]*vec->vec[0] - quat->quat[2]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[1]*vec->vec[1] - quat->quat[1]*quat->quat[1]*vec->vec[2] + quat->quat[0]*quat->quat[0]*vec->vec[2]; - return newVectorObject(rot, 3, Py_NEW); + return newVectorObject(rot, 3, Py_NEW, NULL); } }else if(VectorObject_Check(arg1)){ vec = (VectorObject*)arg1; + + if(!BaseMath_ReadCallback(vec)) + return NULL; + if(QuaternionObject_Check(arg2)){ quat = (QuaternionObject*)arg2; + if(!BaseMath_ReadCallback(quat)) + return NULL; + rot[0] = quat->quat[0]*quat->quat[0]*vec->vec[0] + 2*quat->quat[2]*quat->quat[0]*vec->vec[2] - 2*quat->quat[3]*quat->quat[0]*vec->vec[1] + quat->quat[1]*quat->quat[1]*vec->vec[0] + 2*quat->quat[2]*quat->quat[1]*vec->vec[1] + 2*quat->quat[3]*quat->quat[1]*vec->vec[2] - @@ -256,7 +201,7 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2) quat->quat[3]*quat->quat[3]*vec->vec[2] - 2*quat->quat[0]*quat->quat[2]*vec->vec[0] - quat->quat[2]*quat->quat[2]*vec->vec[2] + 2*quat->quat[0]*quat->quat[1]*vec->vec[1] - quat->quat[1]*quat->quat[1]*vec->vec[2] + quat->quat[0]*quat->quat[0]*vec->vec[2]; - return newVectorObject(rot, 3, Py_NEW); + return newVectorObject(rot, 3, Py_NEW, NULL); } } @@ -308,6 +253,9 @@ static PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args) if(vec1->size != vec2->size) goto AttributeError1; //bad sizes + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2)) + return NULL; + //since size is the same.... size = vec1->size; @@ -327,8 +275,11 @@ static PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args) angleRads = (double)saacos(dot); +#ifdef USE_MATHUTILS_DEG return PyFloat_FromDouble(angleRads * (180/ Py_PI)); - +#else + return PyFloat_FromDouble(angleRads); +#endif AttributeError1: PyErr_SetString(PyExc_AttributeError, "Mathutils.AngleBetweenVecs(): expects (2) VECTOR objects of the same size\n"); return NULL; @@ -353,11 +304,14 @@ static PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args) PyErr_SetString(PyExc_AttributeError, "Mathutils.MidpointVecs(): expects (2) vector objects of the same size\n"); return NULL; } + + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2)) + return NULL; for(x = 0; x < vec1->size; x++) { vec[x] = 0.5f * (vec1->vec[x] + vec2->vec[x]); } - return newVectorObject(vec, vec1->size, Py_NEW); + return newVectorObject(vec, vec1->size, Py_NEW, NULL); } //----------------------------------Mathutils.ProjectVecs() ------------- //projects vector 1 onto vector 2 @@ -377,6 +331,10 @@ static PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args) return NULL; } + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2)) + return NULL; + + //since they are the same size... size = vec1->size; @@ -390,7 +348,7 @@ static PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args) for(x = 0; x < size; x++) { vec[x] = (float)(dot * vec2->vec[x]); } - return newVectorObject(vec, size, Py_NEW); + return newVectorObject(vec, size, Py_NEW, NULL); } //----------------------------------MATRIX FUNCTIONS-------------------- //----------------------------------Mathutils.RotationMatrix() ---------- @@ -409,12 +367,19 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args) PyErr_SetString(PyExc_TypeError, "Mathutils.RotationMatrix(): expected float int and optional string and vector\n"); return NULL; } - + +#ifdef USE_MATHUTILS_DEG /* Clamp to -360:360 */ while (angle<-360.0f) angle+=360.0; while (angle>360.0f) angle-=360.0; +#else + while (angle<-(Py_PI*2)) + angle+=(Py_PI*2); + while (angle>(Py_PI*2)) + angle-=(Py_PI*2); +#endif if(matSize != 2 && matSize != 3 && matSize != 4) { PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n"); @@ -439,9 +404,16 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args) PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): the arbitrary axis must be a 3D vector\n"); return NULL; } + + if(!BaseMath_ReadCallback(vec)) + return NULL; + } +#ifdef USE_MATHUTILS_DEG //convert to radians angle = angle * (float) (Py_PI / 180); +#endif + if(axis == NULL && matSize == 2) { //2D rotation matrix mat[0] = (float) cos (angle); @@ -521,7 +493,7 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args) mat[3] = 0.0f; } //pass to matrix creation - return newMatrixObject(mat, matSize, matSize, Py_NEW); + return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL); } //----------------------------------Mathutils.TranslationMatrix() ------- //creates a translation matrix @@ -538,13 +510,17 @@ static PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * v PyErr_SetString(PyExc_TypeError, "Mathutils.TranslationMatrix(): vector must be 3D or 4D\n"); return NULL; } + + if(!BaseMath_ReadCallback(vec)) + return NULL; + //create a identity matrix and add translation Mat4One((float(*)[4]) mat); mat[12] = vec->vec[0]; mat[13] = vec->vec[1]; mat[14] = vec->vec[2]; - return newMatrixObject(mat, 4, 4, Py_NEW); + return newMatrixObject(mat, 4, 4, Py_NEW, NULL); } //----------------------------------Mathutils.ScaleMatrix() ------------- //mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc. @@ -570,6 +546,10 @@ static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args) PyErr_SetString(PyExc_AttributeError, "Mathutils.ScaleMatrix(): please use 2D vectors when scaling in 2D\n"); return NULL; } + + if(!BaseMath_ReadCallback(vec)) + return NULL; + } if(vec == NULL) { //scaling along axis if(matSize == 2) { @@ -618,7 +598,7 @@ static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args) mat[3] = 0.0f; } //pass to matrix creation - return newMatrixObject(mat, matSize, matSize, Py_NEW); + return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL); } //----------------------------------Mathutils.OrthoProjectionMatrix() --- //mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc. @@ -645,6 +625,10 @@ static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * a PyErr_SetString(PyExc_AttributeError, "Mathutils.OrthoProjectionMatrix(): please use 2D vectors when scaling in 2D\n"); return NULL; } + + if(!BaseMath_ReadCallback(vec)) + return NULL; + } if(vec == NULL) { //ortho projection onto cardinal plane if(((strcmp(plane, "x") == 0) @@ -717,7 +701,7 @@ static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * a mat[3] = 0.0f; } //pass to matrix creation - return newMatrixObject(mat, matSize, matSize, Py_NEW); + return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL); } //----------------------------------Mathutils.ShearMatrix() ------------- //creates a shear matrix @@ -784,7 +768,7 @@ static PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args) mat[3] = 0.0f; } //pass to matrix creation - return newMatrixObject(mat, matSize, matSize, Py_NEW); + return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL); } //----------------------------------QUATERNION FUNCTIONS----------------- @@ -801,6 +785,10 @@ static PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args) PyErr_SetString(PyExc_TypeError, "Mathutils.DifferenceQuats(): expected Quaternion types"); return NULL; } + + if(!BaseMath_ReadCallback(quatU) || !BaseMath_ReadCallback(quatV)) + return NULL; + tempQuat[0] = quatU->quat[0]; tempQuat[1] = -quatU->quat[1]; tempQuat[2] = -quatU->quat[2]; @@ -813,7 +801,7 @@ static PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args) tempQuat[x] /= (float)(dot * dot); } QuatMul(quat, tempQuat, quatV->quat); - return newQuaternionObject(quat, Py_NEW); + return newQuaternionObject(quat, Py_NEW, NULL); } //----------------------------------Mathutils.Slerp() ------------------ //attemps to interpolate 2 quaternions and return the result @@ -828,6 +816,10 @@ static PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args) PyErr_SetString(PyExc_TypeError, "Mathutils.Slerp(): expected Quaternion types and float"); return NULL; } + + if(!BaseMath_ReadCallback(quatU) || !BaseMath_ReadCallback(quatV)) + return NULL; + if(param > 1.0f || param < 0.0f) { PyErr_SetString(PyExc_AttributeError, "Mathutils.Slerp(): interpolation factor must be between 0.0 and 1.0"); return NULL; @@ -870,7 +862,7 @@ static PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args) quat[2] = (float)(quat_u[2] * x + quat_v[2] * y); quat[3] = (float)(quat_u[3] * x + quat_v[3] * y); - return newQuaternionObject(quat, Py_NEW); + return newQuaternionObject(quat, Py_NEW, NULL); } //----------------------------------EULER FUNCTIONS---------------------- //---------------------------------INTERSECTION FUNCTIONS-------------------- @@ -891,6 +883,9 @@ static PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args ) return NULL; } + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(ray) || !BaseMath_ReadCallback(ray_off)) + return NULL; + VECCOPY(v1, vec1->vec); VECCOPY(v2, vec2->vec); VECCOPY(v3, vec3->vec); @@ -941,7 +936,7 @@ static PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args ) VecMulf(dir, t); VecAddf(pvec, orig, dir); - return newVectorObject(pvec, 3, Py_NEW); + return newVectorObject(pvec, 3, Py_NEW, NULL); } //----------------------------------Mathutils.LineIntersect() ------------------- /* Line-Line intersection using algorithm from mathworld.wolfram.com */ @@ -959,6 +954,10 @@ static PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args ) PyErr_SetString( PyExc_TypeError,"vectors must be of the same size\n" ); return NULL; } + + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(vec4)) + return NULL; + if( vec1->size == 3 || vec1->size == 2) { int result; @@ -994,8 +993,8 @@ static PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args ) } else { tuple = PyTuple_New( 2 ); - PyTuple_SetItem( tuple, 0, newVectorObject(i1, vec1->size, Py_NEW) ); - PyTuple_SetItem( tuple, 1, newVectorObject(i2, vec1->size, Py_NEW) ); + PyTuple_SetItem( tuple, 0, newVectorObject(i1, vec1->size, Py_NEW, NULL) ); + PyTuple_SetItem( tuple, 1, newVectorObject(i2, vec1->size, Py_NEW, NULL) ); return tuple; } } @@ -1029,6 +1028,10 @@ static PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args ) PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" ); return NULL; } + + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(vec4)) + return NULL; + VECCOPY(v1, vec1->vec); VECCOPY(v2, vec2->vec); VECCOPY(v3, vec3->vec); @@ -1052,7 +1055,7 @@ static PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args ) VecAddf(n1, n2, n1); Normalize(n1); - return newVectorObject(n1, 3, Py_NEW); + return newVectorObject(n1, 3, Py_NEW, NULL); } //----------------------------Mathutils.TriangleNormal() ------------------- @@ -1073,6 +1076,9 @@ static PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args ) PyErr_SetString( PyExc_TypeError, "only 3D vectors\n" ); return NULL; } + + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3)) + return NULL; VECCOPY(v1, vec1->vec); VECCOPY(v2, vec2->vec); @@ -1085,7 +1091,7 @@ static PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args ) Crossf(n, e2, e1); Normalize(n); - return newVectorObject(n, 3, Py_NEW); + return newVectorObject(n, 3, Py_NEW, NULL); } //--------------------------------- AREA FUNCTIONS-------------------- @@ -1105,6 +1111,9 @@ static PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args ) PyErr_SetString( PyExc_TypeError, "vectors must be of the same size\n" ); return NULL; } + + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3)) + return NULL; if (vec1->size == 3) { VECCOPY(v1, vec1->vec); @@ -1154,8 +1163,8 @@ int EXPP_FloatsAreEqual(float A, float B, int floatSteps) } /*---------------------- EXPP_VectorsAreEqual ------------------------- Builds on EXPP_FloatsAreEqual to test vectors */ -int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps){ - +int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps) +{ int x; for (x=0; x< size; x++){ if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0) @@ -1165,6 +1174,86 @@ int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps){ } +/* Mathutils Callbacks */ + +/* for mathutils internal use only, eventually should re-alloc but to start with we only have a few users */ +Mathutils_Callback *mathutils_callbacks[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; + +int Mathutils_RegisterCallback(Mathutils_Callback *cb) +{ + int i; + + /* find the first free slot */ + for(i= 0; mathutils_callbacks[i]; i++) { + if(mathutils_callbacks[i]==cb) /* alredy registered? */ + return i; + } + + mathutils_callbacks[i] = cb; + return i; +} + +/* use macros to check for NULL */ +int _BaseMathObject_ReadCallback(BaseMathObject *self) +{ + Mathutils_Callback *cb= mathutils_callbacks[self->cb_type]; + if(cb->get(self->cb_user, self->cb_subtype, self->data)) + return 1; + + PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name); + return 0; +} + +int _BaseMathObject_WriteCallback(BaseMathObject *self) +{ + Mathutils_Callback *cb= mathutils_callbacks[self->cb_type]; + if(cb->set(self->cb_user, self->cb_subtype, self->data)) + return 1; + + PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name); + return 0; +} + +int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index) +{ + Mathutils_Callback *cb= mathutils_callbacks[self->cb_type]; + if(cb->get_index(self->cb_user, self->cb_subtype, self->data, index)) + return 1; + + PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name); + return 0; +} + +int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index) +{ + Mathutils_Callback *cb= mathutils_callbacks[self->cb_type]; + if(cb->set_index(self->cb_user, self->cb_subtype, self->data, index)) + return 1; + + PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name); + return 0; +} + +/* BaseMathObject generic functions for all mathutils types */ +PyObject *BaseMathObject_getOwner( BaseMathObject * self, void *type ) +{ + PyObject *ret= self->cb_user ? self->cb_user : Py_None; + Py_INCREF(ret); + return ret; +} + +PyObject *BaseMathObject_getWrapped( BaseMathObject *self, void *type ) +{ + return PyBool_FromLong((self->wrapped == Py_WRAP) ? 1:0); +} + +void BaseMathObject_dealloc(BaseMathObject * self) +{ + /* only free non wrapped */ + if(self->wrapped != Py_WRAP) + PyMem_Free(self->data); + + Py_XDECREF(self->cb_user); + Py_TYPE(self)->tp_free(self); // PyObject_DEL(self); // breaks subtypes +} -//####################################################################### -//#############################DEPRECATED################################ diff --git a/source/blender/python/generic/Mathutils.h b/source/blender/python/generic/Mathutils.h index e8882c3dac2..6a4e28d6068 100644 --- a/source/blender/python/generic/Mathutils.h +++ b/source/blender/python/generic/Mathutils.h @@ -1,5 +1,5 @@ /* - * $Id: Mathutils.h 20332 2009-05-22 03:22:56Z campbellbarton $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -38,10 +38,28 @@ #include "quat.h" #include "euler.h" +/* #define USE_MATHUTILS_DEG - for backwards compat */ + +/* Can cast different mathutils types to this, use for generic funcs */ + +typedef struct { + PyObject_VAR_HEAD + float *data; /*array of data (alias), wrapped status depends on wrapped status */ + PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */ + unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */ + unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */ + unsigned char wrapped; /* wrapped data type? */ +} BaseMathObject; + +PyObject *BaseMathObject_getOwner( BaseMathObject * self, void * ); +PyObject *BaseMathObject_getWrapped( BaseMathObject *self, void * ); +void BaseMathObject_dealloc(BaseMathObject * self); + + + + PyObject *Mathutils_Init( const char * from ); -PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat); -PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec); PyObject *quat_rotation(PyObject *arg1, PyObject *arg2); int EXPP_FloatsAreEqual(float A, float B, int floatSteps); @@ -49,8 +67,9 @@ int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps); #define Py_PI 3.14159265358979323846 -#define Py_WRAP 1024 -#define Py_NEW 2048 + +#define Py_NEW 1 +#define Py_WRAP 2 /* Mathutils is used by the BGE and Blender so have to define @@ -65,4 +84,26 @@ int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps); #define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True #endif +typedef struct Mathutils_Callback Mathutils_Callback; +struct Mathutils_Callback { + int (*check)(PyObject *user); /* checks the user is still valid */ + int (*get)(PyObject *user, int subtype, float *from); /* gets the vector from the user */ + int (*set)(PyObject *user, int subtype, float *to); /* sets the users vector values once the vector is modified */ + int (*get_index)(PyObject *user, int subtype, float *from,int index); /* same as above but only for an index */ + int (*set_index)(PyObject *user, int subtype, float *to, int index); /* same as above but only for an index */ +}; + +int Mathutils_RegisterCallback(Mathutils_Callback *cb); + +int _BaseMathObject_ReadCallback(BaseMathObject *self); +int _BaseMathObject_WriteCallback(BaseMathObject *self); +int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index); +int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index); + +/* since this is called so often avoid where possible */ +#define BaseMath_ReadCallback(_self) (((_self)->cb_user ? _BaseMathObject_ReadCallback((BaseMathObject *)_self):1)) +#define BaseMath_WriteCallback(_self) (((_self)->cb_user ?_BaseMathObject_WriteCallback((BaseMathObject *)_self):1)) +#define BaseMath_ReadIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_ReadIndexCallback((BaseMathObject *)_self, _index):1)) +#define BaseMath_WriteIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_WriteIndexCallback((BaseMathObject *)_self, _index):1)) + #endif /* EXPP_Mathutils_H */ diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c index 6789aea9c10..c41ea386c0e 100644 --- a/source/blender/python/generic/bpy_internal_import.c +++ b/source/blender/python/generic/bpy_internal_import.c @@ -1,5 +1,5 @@ /* - * $Id: bpy_internal_import.c 20434 2009-05-26 18:06:09Z campbellbarton $ + * $Id$ * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or diff --git a/source/blender/python/generic/bpy_internal_import.h b/source/blender/python/generic/bpy_internal_import.h index 475ec8dd118..aeeafb7c1c4 100644 --- a/source/blender/python/generic/bpy_internal_import.h +++ b/source/blender/python/generic/bpy_internal_import.h @@ -1,5 +1,5 @@ /* - * $Id: bpy_internal_import.h 20434 2009-05-26 18:06:09Z campbellbarton $ + * $Id$ * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or diff --git a/source/blender/python/generic/euler.c b/source/blender/python/generic/euler.c index a65feb7e949..1e0632f4040 100644 --- a/source/blender/python/generic/euler.c +++ b/source/blender/python/generic/euler.c @@ -1,5 +1,5 @@ /* - * $Id: euler.c 20248 2009-05-18 04:11:54Z campbellbarton $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -34,13 +34,6 @@ //-------------------------DOC STRINGS --------------------------- -static char Euler_Zero_doc[] = "() - set all values in the euler to 0"; -static char Euler_Unique_doc[] ="() - sets the euler rotation a unique shortest arc rotation - tests for gimbal lock"; -static char Euler_ToMatrix_doc[] = "() - returns a rotation matrix representing the euler rotation"; -static char Euler_ToQuat_doc[] = "() - returns a quaternion representing the euler rotation"; -static char Euler_Rotate_doc[] = "() - rotate a euler by certain amount around an axis of rotation"; -static char Euler_copy_doc[] = "() - returns a copy of the euler."; -static char Euler_MakeCompatible_doc[] = "(euler) - Make this user compatible with another (no axis flipping)."; static PyObject *Euler_Zero( EulerObject * self ); static PyObject *Euler_Unique( EulerObject * self ); @@ -52,25 +45,24 @@ static PyObject *Euler_copy( EulerObject * self, PyObject *args ); //-----------------------METHOD DEFINITIONS ---------------------- static struct PyMethodDef Euler_methods[] = { - {"zero", (PyCFunction) Euler_Zero, METH_NOARGS, Euler_Zero_doc}, - {"unique", (PyCFunction) Euler_Unique, METH_NOARGS, Euler_Unique_doc}, - {"toMatrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, Euler_ToMatrix_doc}, - {"toQuat", (PyCFunction) Euler_ToQuat, METH_NOARGS, Euler_ToQuat_doc}, - {"rotate", (PyCFunction) Euler_Rotate, METH_VARARGS, Euler_Rotate_doc}, - {"makeCompatible", (PyCFunction) Euler_MakeCompatible, METH_O, Euler_MakeCompatible_doc}, - {"__copy__", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc}, - {"copy", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc}, + {"zero", (PyCFunction) Euler_Zero, METH_NOARGS, NULL}, + {"unique", (PyCFunction) Euler_Unique, METH_NOARGS, NULL}, + {"toMatrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, NULL}, + {"toQuat", (PyCFunction) Euler_ToQuat, METH_NOARGS, NULL}, + {"rotate", (PyCFunction) Euler_Rotate, METH_VARARGS, NULL}, + {"makeCompatible", (PyCFunction) Euler_MakeCompatible, METH_O, NULL}, + {"__copy__", (PyCFunction) Euler_copy, METH_VARARGS, NULL}, + {"copy", (PyCFunction) Euler_copy, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} }; //----------------------------------Mathutils.Euler() ------------------- //makes a new euler for you to play with -static PyObject *Euler_new(PyObject * self, PyObject * args) +static PyObject *Euler_new(PyTypeObject * type, PyObject * args, PyObject * kwargs) { - PyObject *listObject = NULL; int size, i; - float eul[3], scalar; + float eul[3]; PyObject *e; size = PyTuple_GET_SIZE(args); @@ -84,7 +76,7 @@ static PyObject *Euler_new(PyObject * self, PyObject * args) } } else if (size == 0) { //returns a new empty 3d euler - return newEulerObject(NULL, Py_NEW); + return newEulerObject(NULL, Py_NEW, NULL); } else { listObject = args; } @@ -102,17 +94,15 @@ static PyObject *Euler_new(PyObject * self, PyObject * args) return NULL; } - scalar= (float)PyFloat_AsDouble(e); + eul[i]= (float)PyFloat_AsDouble(e); Py_DECREF(e); - if(scalar==-1 && PyErr_Occurred()) { // parsed item is not a number + if(eul[i]==-1 && PyErr_Occurred()) { // parsed item is not a number PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n"); return NULL; } - - eul[i]= scalar; } - return newEulerObject(eul, Py_NEW); + return newEulerObject(eul, Py_NEW, NULL); } //-----------------------------METHODS---------------------------- @@ -120,14 +110,25 @@ static PyObject *Euler_new(PyObject * self, PyObject * args) //return a quaternion representation of the euler static PyObject *Euler_ToQuat(EulerObject * self) { - float eul[3], quat[4]; + float quat[4]; +#ifdef USE_MATHUTILS_DEG + float eul[3]; int x; +#endif + if(!BaseMath_ReadCallback(self)) + return NULL; + +#ifdef USE_MATHUTILS_DEG for(x = 0; x < 3; x++) { eul[x] = self->eul[x] * ((float)Py_PI / 180); } EulToQuat(eul, quat); - return newQuaternionObject(quat, Py_NEW); +#else + EulToQuat(self->eul, quat); +#endif + + return newQuaternionObject(quat, Py_NEW, NULL); } //----------------------------Euler.toMatrix()--------------------- //return a matrix representation of the euler @@ -137,60 +138,80 @@ static PyObject *Euler_ToMatrix(EulerObject * self) float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; int x; + if(!BaseMath_ReadCallback(self)) + return NULL; + +#ifdef USE_MATHUTILS_DEG for(x = 0; x < 3; x++) { eul[x] = self->eul[x] * ((float)Py_PI / 180); } EulToMat3(eul, (float (*)[3]) mat); - return newMatrixObject(mat, 3, 3 , Py_NEW); +#else + EulToMat3(self->eul, (float (*)[3]) mat); +#endif + return newMatrixObject(mat, 3, 3 , Py_NEW, NULL); } //----------------------------Euler.unique()----------------------- //sets the x,y,z values to a unique euler rotation static PyObject *Euler_Unique(EulerObject * self) { - double heading, pitch, bank; - double pi2 = Py_PI * 2.0f; - double piO2 = Py_PI / 2.0f; - double Opi2 = 1.0f / pi2; +#define PI_2 (Py_PI * 2.0) +#define PI_HALF (Py_PI / 2.0) +#define PI_INV (1.0 / Py_PI) + double heading, pitch, bank; + + if(!BaseMath_ReadCallback(self)) + return NULL; + +#ifdef USE_MATHUTILS_DEG //radians heading = self->eul[0] * (float)Py_PI / 180; pitch = self->eul[1] * (float)Py_PI / 180; bank = self->eul[2] * (float)Py_PI / 180; +#else + heading = self->eul[0]; + pitch = self->eul[1]; + bank = self->eul[2]; +#endif //wrap heading in +180 / -180 pitch += Py_PI; - pitch -= floor(pitch * Opi2) * pi2; + pitch -= floor(pitch * PI_INV) * PI_2; pitch -= Py_PI; - if(pitch < -piO2) { + if(pitch < -PI_HALF) { pitch = -Py_PI - pitch; heading += Py_PI; bank += Py_PI; - } else if(pitch > piO2) { + } else if(pitch > PI_HALF) { pitch = Py_PI - pitch; heading += Py_PI; bank += Py_PI; } //gimbal lock test - if(fabs(pitch) > piO2 - 1e-4) { + if(fabs(pitch) > PI_HALF - 1e-4) { heading += bank; bank = 0.0f; } else { bank += Py_PI; - bank -= (floor(bank * Opi2)) * pi2; + bank -= (floor(bank * PI_INV)) * PI_2; bank -= Py_PI; } heading += Py_PI; - heading -= (floor(heading * Opi2)) * pi2; + heading -= (floor(heading * PI_INV)) * PI_2; heading -= Py_PI; +#ifdef USE_MATHUTILS_DEG //back to degrees self->eul[0] = (float)(heading * 180 / (float)Py_PI); self->eul[1] = (float)(pitch * 180 / (float)Py_PI); self->eul[2] = (float)(bank * 180 / (float)Py_PI); +#endif + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject *)self; } @@ -202,6 +223,7 @@ static PyObject *Euler_Zero(EulerObject * self) self->eul[1] = 0.0; self->eul[2] = 0.0; + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject *)self; } @@ -223,42 +245,63 @@ static PyObject *Euler_Rotate(EulerObject * self, PyObject *args) return NULL; } + if(!BaseMath_ReadCallback(self)) + return NULL; + +#ifdef USE_MATHUTILS_DEG //covert to radians angle *= ((float)Py_PI / 180); for(x = 0; x < 3; x++) { self->eul[x] *= ((float)Py_PI / 180); } +#endif euler_rot(self->eul, angle, *axis); + +#ifdef USE_MATHUTILS_DEG //convert back from radians for(x = 0; x < 3; x++) { self->eul[x] *= (180 / (float)Py_PI); } +#endif + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject *)self; } static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value) { +#ifdef USE_MATHUTILS_DEG float eul_from_rad[3]; int x; +#endif if(!EulerObject_Check(value)) { PyErr_SetString(PyExc_TypeError, "euler.makeCompatible(euler):expected a single euler argument."); return NULL; } + if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value)) + return NULL; + +#ifdef USE_MATHUTILS_DEG //covert to radians for(x = 0; x < 3; x++) { self->eul[x] = self->eul[x] * ((float)Py_PI / 180); eul_from_rad[x] = value->eul[x] * ((float)Py_PI / 180); } compatible_eul(self->eul, eul_from_rad); +#else + compatible_eul(self->eul, value->eul); +#endif + +#ifdef USE_MATHUTILS_DEG //convert back from radians for(x = 0; x < 3; x++) { self->eul[x] *= (180 / (float)Py_PI); } - +#endif + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject *)self; } @@ -267,19 +310,10 @@ static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value) // return a copy of the euler static PyObject *Euler_copy(EulerObject * self, PyObject *args) { - return newEulerObject(self->eul, Py_NEW); -} + if(!BaseMath_ReadCallback(self)) + return NULL; - -//----------------------------dealloc()(internal) ------------------ -//free the py_object -static void Euler_dealloc(EulerObject * self) -{ - //only free py_data - if(self->data.py_data){ - PyMem_Free(self->data.py_data); - } - PyObject_DEL(self); + return newEulerObject(self->eul, Py_NEW, Py_TYPE(self)); } //----------------------------print object (internal)-------------- @@ -287,6 +321,10 @@ static void Euler_dealloc(EulerObject * self) static PyObject *Euler_repr(EulerObject * self) { char str[64]; + + if(!BaseMath_ReadCallback(self)) + return NULL; + sprintf(str, "[%.6f, %.6f, %.6f](euler)", self->eul[0], self->eul[1], self->eul[2]); return PyUnicode_FromString(str); } @@ -297,7 +335,18 @@ static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int compar EulerObject *eulA = NULL, *eulB = NULL; int result = 0; - if (!EulerObject_Check(objectA) || !EulerObject_Check(objectB)){ + if(EulerObject_Check(objectA)) { + eulA = (EulerObject*)objectA; + if(!BaseMath_ReadCallback(eulA)) + return NULL; + } + if(EulerObject_Check(objectB)) { + eulB = (EulerObject*)objectB; + if(!BaseMath_ReadCallback(eulB)) + return NULL; + } + + if (!eulA || !eulB){ if (comparison_type == Py_NE){ Py_RETURN_TRUE; }else{ @@ -329,8 +378,7 @@ static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int compar Py_RETURN_FALSE; } } -//------------------------tp_doc -static char EulerObject_doc[] = "This is a wrapper for euler objects."; + //---------------------SEQUENCE PROTOCOLS------------------------ //----------------------------len(object)------------------------ //sequence length @@ -342,13 +390,16 @@ static int Euler_len(EulerObject * self) //sequence accessor (get) static PyObject *Euler_item(EulerObject * self, int i) { - if(i<0) - i= 3-i; + if(i<0) i= 3-i; if(i < 0 || i >= 3) { PyErr_SetString(PyExc_IndexError, "euler[attribute]: array index out of range"); return NULL; } + + if(!BaseMath_ReadIndexCallback(self, i)) + return NULL; + return PyFloat_FromDouble(self->eul[i]); } @@ -363,8 +414,7 @@ static int Euler_ass_item(EulerObject * self, int i, PyObject * value) return -1; } - if(i<0) - i= 3-i; + if(i<0) i= 3-i; if(i < 0 || i >= 3){ PyErr_SetString(PyExc_IndexError, "euler[attribute] = x: array assignment index out of range\n"); @@ -372,6 +422,10 @@ static int Euler_ass_item(EulerObject * self, int i, PyObject * value) } self->eul[i] = f; + + if(!BaseMath_WriteIndexCallback(self, i)) + return -1; + return 0; } //----------------------------object[z:y]------------------------ @@ -381,6 +435,9 @@ static PyObject *Euler_slice(EulerObject * self, int begin, int end) PyObject *list = NULL; int count; + if(!BaseMath_ReadCallback(self)) + return NULL; + CLAMP(begin, 0, 3); if (end<0) end= 4+end; CLAMP(end, 0, 3); @@ -401,7 +458,10 @@ static int Euler_ass_slice(EulerObject * self, int begin, int end, { int i, y, size = 0; float eul[3]; - PyObject *e, *f; + PyObject *e; + + if(!BaseMath_ReadCallback(self)) + return -1; CLAMP(begin, 0, 3); if (end<0) end= 4+end; @@ -421,21 +481,20 @@ static int Euler_ass_slice(EulerObject * self, int begin, int end, return -1; } - f = PyNumber_Float(e); - if(f == NULL) { // parsed item not a number - Py_DECREF(e); + eul[i] = (float)PyFloat_AsDouble(e); + Py_DECREF(e); + + if(eul[i]==-1 && PyErr_Occurred()) { // parsed item not a number PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: sequence argument not a number"); return -1; } - - eul[i] = (float)PyFloat_AS_DOUBLE(f); - Py_DECREF(f); - Py_DECREF(e); } //parsed well - now set in vector for(y = 0; y < 3; y++){ self->eul[begin + y] = eul[y]; } + + BaseMath_WriteCallback(self); return 0; } //-----------------PROTCOL DECLARATIONS-------------------------- @@ -450,79 +509,30 @@ static PySequenceMethods Euler_SeqMethods = { }; - /* * vector axis, vector.x/y/z/w */ static PyObject *Euler_getAxis( EulerObject * self, void *type ) { - switch( (long)type ) { - case 'X': /* these are backwards, but that how it works */ - return PyFloat_FromDouble(self->eul[0]); - case 'Y': - return PyFloat_FromDouble(self->eul[1]); - case 'Z': - return PyFloat_FromDouble(self->eul[2]); - } - - PyErr_SetString(PyExc_SystemError, "corrupt euler, cannot get axis"); - return NULL; + return Euler_item(self, GET_INT_FROM_POINTER(type)); } static int Euler_setAxis( EulerObject * self, PyObject * value, void * type ) { - float param= (float)PyFloat_AsDouble( value ); - - if (param==-1 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "expected a number for the vector axis"); - return -1; - } - - switch( (long)type ) { - case 'X': /* these are backwards, but that how it works */ - self->eul[0]= param; - break; - case 'Y': - self->eul[1]= param; - break; - case 'Z': - self->eul[2]= param; - break; - } - - return 0; + return Euler_ass_item(self, GET_INT_FROM_POINTER(type), value); } -static PyObject *Euler_getWrapped( VectorObject * self, void *type ) -{ - if (self->wrapped == Py_WRAP) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - - /*****************************************************************************/ /* Python attributes get/set structure: */ /*****************************************************************************/ static PyGetSetDef Euler_getseters[] = { - {"x", - (getter)Euler_getAxis, (setter)Euler_setAxis, - "Euler X axis", - (void *)'X'}, - {"y", - (getter)Euler_getAxis, (setter)Euler_setAxis, - "Euler Y axis", - (void *)'Y'}, - {"z", - (getter)Euler_getAxis, (setter)Euler_setAxis, - "Euler Z axis", - (void *)'Z'}, - {"wrapped", - (getter)Euler_getWrapped, (setter)NULL, - "True when this wraps blenders internal data", - NULL}, + {"x", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler X axis", (void *)0}, + {"y", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Y axis", (void *)1}, + {"z", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Z axis", (void *)2}, + + {"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "True when this wraps blenders internal data", NULL}, + {"__owner__", (getter)BaseMathObject_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; @@ -538,7 +548,7 @@ PyTypeObject euler_Type = { "euler", //tp_name sizeof(EulerObject), //tp_basicsize 0, //tp_itemsize - (destructor)Euler_dealloc, //tp_dealloc + (destructor)BaseMathObject_dealloc, //tp_dealloc 0, //tp_print 0, //tp_getattr 0, //tp_setattr @@ -553,8 +563,8 @@ PyTypeObject euler_Type = { 0, //tp_getattro 0, //tp_setattro 0, //tp_as_buffer - Py_TPFLAGS_DEFAULT, //tp_flags - EulerObject_doc, //tp_doc + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags + 0, //tp_doc 0, //tp_traverse 0, //tp_clear (richcmpfunc)Euler_richcmpr, //tp_richcompare @@ -587,30 +597,29 @@ PyTypeObject euler_Type = { (i.e. it was allocated elsewhere by MEM_mallocN()) pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON (i.e. it must be created here with PyMEM_malloc())*/ -PyObject *newEulerObject(float *eul, int type) +PyObject *newEulerObject(float *eul, int type, PyTypeObject *base_type) { EulerObject *self; int x; - self = PyObject_NEW(EulerObject, &euler_Type); - self->data.blend_data = NULL; - self->data.py_data = NULL; + if(base_type) self = base_type->tp_alloc(base_type, 0); + else self = PyObject_NEW(EulerObject, &euler_Type); + + /* init callbacks as NULL */ + self->cb_user= NULL; + self->cb_type= self->cb_subtype= 0; if(type == Py_WRAP){ - self->data.blend_data = eul; - self->eul = self->data.blend_data; + self->eul = eul; self->wrapped = Py_WRAP; }else if (type == Py_NEW){ - self->data.py_data = PyMem_Malloc(3 * sizeof(float)); - self->eul = self->data.py_data; + self->eul = PyMem_Malloc(3 * sizeof(float)); if(!eul) { //new empty for(x = 0; x < 3; x++) { self->eul[x] = 0.0f; } }else{ - for(x = 0; x < 3; x++){ - self->eul[x] = eul[x]; - } + VECCOPY(self->eul, eul); } self->wrapped = Py_NEW; }else{ //bad type @@ -618,3 +627,16 @@ PyObject *newEulerObject(float *eul, int type) } return (PyObject *)self; } + +PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype) +{ + EulerObject *self= (EulerObject *)newEulerObject(NULL, Py_NEW, NULL); + if(self) { + Py_INCREF(cb_user); + self->cb_user= cb_user; + self->cb_type= (unsigned char)cb_type; + self->cb_subtype= (unsigned char)cb_subtype; + } + + return (PyObject *)self; +} diff --git a/source/blender/python/generic/euler.h b/source/blender/python/generic/euler.h index 3206668ffa0..a3706d53756 100644 --- a/source/blender/python/generic/euler.h +++ b/source/blender/python/generic/euler.h @@ -1,5 +1,5 @@ /* - * $Id: euler.h 20248 2009-05-18 04:11:54Z campbellbarton $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -35,17 +35,17 @@ #include "../intern/bpy_compat.h" extern PyTypeObject euler_Type; - -#define EulerObject_Check(v) (Py_TYPE(v) == &euler_Type) +#define EulerObject_Check(_v) PyObject_TypeCheck((_v), &euler_Type) typedef struct { PyObject_VAR_HEAD - struct{ - float *py_data; //python managed - float *blend_data; //blender managed - }data; - float *eul; //1D array of data (alias) - int wrapped; //is wrapped data? + float *eul; /*1D array of data */ + PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */ + unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */ + unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */ + unsigned char wrapped; /* wrapped data type? */ + /* end BaseMathObject */ + } EulerObject; /*struct data contains a pointer to the actual data that the @@ -54,6 +54,7 @@ be stored in py_data) or be a wrapper for data allocated through blender (stored in blend_data). This is an either/or struct not both*/ //prototypes -PyObject *newEulerObject( float *eul, int type ); +PyObject *newEulerObject( float *eul, int type, PyTypeObject *base_type); +PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype); #endif /* EXPP_euler_h */ diff --git a/source/blender/python/generic/matrix.c b/source/blender/python/generic/matrix.c index e2ab1c3c653..5bdbf804618 100644 --- a/source/blender/python/generic/matrix.c +++ b/source/blender/python/generic/matrix.c @@ -1,5 +1,5 @@ /* - * $Id: matrix.c 20249 2009-05-18 04:27:48Z campbellbarton $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -31,19 +31,72 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" +static PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec); /* utility func */ + + +/* matrix vector callbacks */ +int mathutils_matrix_vector_cb_index= -1; + +static int mathutils_matrix_vector_check(MatrixObject *self) +{ + return BaseMath_ReadCallback(self); +} + +static int mathutils_matrix_vector_get(MatrixObject *self, int subtype, float *vec_from) +{ + int i; + if(!BaseMath_ReadCallback(self)) + return 0; + + for(i=0; icolSize; i++) + vec_from[i]= self->matrix[subtype][i]; + + return 1; +} + +static int mathutils_matrix_vector_set(MatrixObject *self, int subtype, float *vec_to) +{ + int i; + if(!BaseMath_ReadCallback(self)) + return 0; + + for(i=0; icolSize; i++) + self->matrix[subtype][i]= vec_to[i]; + + BaseMath_WriteCallback(self); + return 1; +} + +static int mathutils_matrix_vector_get_index(MatrixObject *self, int subtype, float *vec_from, int index) +{ + if(!BaseMath_ReadCallback(self)) + return 0; + + vec_from[index]= self->matrix[subtype][index]; + return 1; +} + +static int mathutils_matrix_vector_set_index(MatrixObject *self, int subtype, float *vec_to, int index) +{ + if(!BaseMath_ReadCallback(self)) + return 0; + + self->matrix[subtype][index]= vec_to[index]; + + BaseMath_WriteCallback(self); + return 1; +} + +Mathutils_Callback mathutils_matrix_vector_cb = { + mathutils_matrix_vector_check, + mathutils_matrix_vector_get, + mathutils_matrix_vector_set, + mathutils_matrix_vector_get_index, + mathutils_matrix_vector_set_index +}; +/* matrix vector callbacks, this is so you can do matrix[i][j] = val */ + /*-------------------------DOC STRINGS ---------------------------*/ -static char Matrix_Zero_doc[] = "() - set all values in the matrix to 0"; -static char Matrix_Identity_doc[] = "() - set the square matrix to it's identity matrix"; -static char Matrix_Transpose_doc[] = "() - set the matrix to it's transpose"; -static char Matrix_Determinant_doc[] = "() - return the determinant of the matrix"; -static char Matrix_Invert_doc[] = "() - set the matrix to it's inverse if an inverse is possible"; -static char Matrix_TranslationPart_doc[] = "() - return a vector encompassing the translation of the matrix"; -static char Matrix_RotationPart_doc[] = "() - return a vector encompassing the rotation of the matrix"; -static char Matrix_scalePart_doc[] = "() - convert matrix to a 3D vector"; -static char Matrix_Resize4x4_doc[] = "() - resize the matrix to a 4x4 square matrix"; -static char Matrix_toEuler_doc[] = "(eul_compat) - convert matrix to a euler angle rotation, optional euler argument that the new euler will be made compatible with."; -static char Matrix_toQuat_doc[] = "() - convert matrix to a quaternion rotation"; -static char Matrix_copy_doc[] = "() - return a copy of the matrix"; static PyObject *Matrix_Zero( MatrixObject * self ); static PyObject *Matrix_Identity( MatrixObject * self ); @@ -60,19 +113,19 @@ static PyObject *Matrix_copy( MatrixObject * self ); /*-----------------------METHOD DEFINITIONS ----------------------*/ static struct PyMethodDef Matrix_methods[] = { - {"zero", (PyCFunction) Matrix_Zero, METH_NOARGS, Matrix_Zero_doc}, - {"identity", (PyCFunction) Matrix_Identity, METH_NOARGS, Matrix_Identity_doc}, - {"transpose", (PyCFunction) Matrix_Transpose, METH_NOARGS, Matrix_Transpose_doc}, - {"determinant", (PyCFunction) Matrix_Determinant, METH_NOARGS, Matrix_Determinant_doc}, - {"invert", (PyCFunction) Matrix_Invert, METH_NOARGS, Matrix_Invert_doc}, - {"translationPart", (PyCFunction) Matrix_TranslationPart, METH_NOARGS, Matrix_TranslationPart_doc}, - {"rotationPart", (PyCFunction) Matrix_RotationPart, METH_NOARGS, Matrix_RotationPart_doc}, - {"scalePart", (PyCFunction) Matrix_scalePart, METH_NOARGS, Matrix_scalePart_doc}, - {"resize4x4", (PyCFunction) Matrix_Resize4x4, METH_NOARGS, Matrix_Resize4x4_doc}, - {"toEuler", (PyCFunction) Matrix_toEuler, METH_VARARGS, Matrix_toEuler_doc}, - {"toQuat", (PyCFunction) Matrix_toQuat, METH_NOARGS, Matrix_toQuat_doc}, - {"copy", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc}, - {"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc}, + {"zero", (PyCFunction) Matrix_Zero, METH_NOARGS, NULL}, + {"identity", (PyCFunction) Matrix_Identity, METH_NOARGS, NULL}, + {"transpose", (PyCFunction) Matrix_Transpose, METH_NOARGS, NULL}, + {"determinant", (PyCFunction) Matrix_Determinant, METH_NOARGS, NULL}, + {"invert", (PyCFunction) Matrix_Invert, METH_NOARGS, NULL}, + {"translationPart", (PyCFunction) Matrix_TranslationPart, METH_NOARGS, NULL}, + {"rotationPart", (PyCFunction) Matrix_RotationPart, METH_NOARGS, NULL}, + {"scalePart", (PyCFunction) Matrix_scalePart, METH_NOARGS, NULL}, + {"resize4x4", (PyCFunction) Matrix_Resize4x4, METH_NOARGS, NULL}, + {"toEuler", (PyCFunction) Matrix_toEuler, METH_VARARGS, NULL}, + {"toQuat", (PyCFunction) Matrix_toQuat, METH_NOARGS, NULL}, + {"copy", (PyCFunction) Matrix_copy, METH_NOARGS, NULL}, + {"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, NULL}, {NULL, NULL, 0, NULL} }; @@ -93,18 +146,16 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyErr_SetString(PyExc_AttributeError, "Mathutils.Matrix(): expects 0-4 numeric sequences of the same size\n"); return NULL; } else if (argSize == 0) { //return empty 4D matrix - return (PyObject *) newMatrixObject(NULL, 4, 4, Py_NEW); + return (PyObject *) newMatrixObject(NULL, 4, 4, Py_NEW, NULL); }else if (argSize == 1){ //copy constructor for matrix objects argObject = PyTuple_GET_ITEM(args, 0); if(MatrixObject_Check(argObject)){ mat = (MatrixObject*)argObject; + if(!BaseMath_ReadCallback(mat)) + return NULL; - argSize = mat->rowSize; //rows - seqSize = mat->colSize; //col - for(i = 0; i < (seqSize * argSize); i++){ - matrix[i] = mat->contigPtr[i]; - } + memcpy(matrix, mat->contigPtr, sizeof(float) * mat->rowSize * mat->colSize); } }else{ //2-4 arguments (all seqs? all same size?) for(i =0; i < argSize; i++){ @@ -149,7 +200,7 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } } } - return newMatrixObject(matrix, argSize, seqSize, Py_NEW); + return newMatrixObject(matrix, argSize, seqSize, Py_NEW, NULL); } /*-----------------------------METHODS----------------------------*/ @@ -158,6 +209,9 @@ static PyObject *Matrix_toQuat(MatrixObject * self) { float quat[4]; + if(!BaseMath_ReadCallback(self)) + return NULL; + /*must be 3-4 cols, 3-4 rows, square matrix*/ if(self->colSize < 3 || self->rowSize < 3 || (self->colSize != self->rowSize)) { PyErr_SetString(PyExc_AttributeError, "Matrix.toQuat(): inappropriate matrix size - expects 3x3 or 4x4 matrix"); @@ -169,22 +223,34 @@ static PyObject *Matrix_toQuat(MatrixObject * self) Mat4ToQuat((float (*)[4])*self->matrix, quat); } - return newQuaternionObject(quat, Py_NEW); + return newQuaternionObject(quat, Py_NEW, NULL); } /*---------------------------Matrix.toEuler() --------------------*/ PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args) { float eul[3], eul_compatf[3]; EulerObject *eul_compat = NULL; +#ifdef USE_MATHUTILS_DEG int x; +#endif + + if(!BaseMath_ReadCallback(self)) + return NULL; if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat)) return NULL; if(eul_compat) { + if(!BaseMath_ReadCallback(eul_compat)) + return NULL; + +#ifdef USE_MATHUTILS_DEG for(x = 0; x < 3; x++) { eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180); } +#else + VECCOPY(eul_compatf, eul_compat->eul); +#endif } /*must be 3-4 cols, 3-4 rows, square matrix*/ @@ -202,28 +268,33 @@ PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args) PyErr_SetString(PyExc_AttributeError, "Matrix.toEuler(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n"); return NULL; } +#ifdef USE_MATHUTILS_DEG /*have to convert to degrees*/ for(x = 0; x < 3; x++) { eul[x] *= (float) (180 / Py_PI); } - return newEulerObject(eul, Py_NEW); +#endif + return newEulerObject(eul, Py_NEW, NULL); } /*---------------------------Matrix.resize4x4() ------------------*/ PyObject *Matrix_Resize4x4(MatrixObject * self) { int x, first_row_elem, curr_pos, new_pos, blank_columns, blank_rows, index; - if(self->data.blend_data){ - PyErr_SetString(PyExc_TypeError, "cannot resize wrapped data - only python matrices"); + if(self->wrapped==Py_WRAP){ + PyErr_SetString(PyExc_TypeError, "cannot resize wrapped data - make a copy and resize that"); return NULL; } - - self->data.py_data = PyMem_Realloc(self->data.py_data, (sizeof(float) * 16)); - if(self->data.py_data == NULL) { + if(self->cb_user){ + PyErr_SetString(PyExc_TypeError, "cannot resize owned data - make a copy and resize that"); + return NULL; + } + + self->contigPtr = PyMem_Realloc(self->contigPtr, (sizeof(float) * 16)); + if(self->contigPtr == NULL) { PyErr_SetString(PyExc_MemoryError, "matrix.resize4x4(): problem allocating pointer space"); return NULL; } - self->contigPtr = self->data.py_data; /*force*/ self->matrix = PyMem_Realloc(self->matrix, (sizeof(float *) * 4)); if(self->matrix == NULL) { PyErr_SetString(PyExc_MemoryError, "matrix.resize4x4(): problem allocating pointer space"); @@ -266,7 +337,10 @@ PyObject *Matrix_Resize4x4(MatrixObject * self) PyObject *Matrix_TranslationPart(MatrixObject * self) { float vec[4]; - + + if(!BaseMath_ReadCallback(self)) + return NULL; + if(self->colSize < 3 || self->rowSize < 4){ PyErr_SetString(PyExc_AttributeError, "Matrix.translationPart: inappropriate matrix size"); return NULL; @@ -276,7 +350,7 @@ PyObject *Matrix_TranslationPart(MatrixObject * self) vec[1] = self->matrix[3][1]; vec[2] = self->matrix[3][2]; - return newVectorObject(vec, 3, Py_NEW); + return newVectorObject(vec, 3, Py_NEW, NULL); } /*---------------------------Matrix.rotationPart() ---------------*/ PyObject *Matrix_RotationPart(MatrixObject * self) @@ -284,6 +358,9 @@ PyObject *Matrix_RotationPart(MatrixObject * self) float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + if(!BaseMath_ReadCallback(self)) + return NULL; + if(self->colSize < 3 || self->rowSize < 3){ PyErr_SetString(PyExc_AttributeError, "Matrix.rotationPart: inappropriate matrix size\n"); return NULL; @@ -299,7 +376,7 @@ PyObject *Matrix_RotationPart(MatrixObject * self) mat[7] = self->matrix[2][1]; mat[8] = self->matrix[2][2]; - return newMatrixObject(mat, 3, 3, Py_NEW); + return newMatrixObject(mat, 3, 3, Py_NEW, Py_TYPE(self)); } /*---------------------------Matrix.scalePart() --------------------*/ PyObject *Matrix_scalePart(MatrixObject * self) @@ -307,6 +384,9 @@ PyObject *Matrix_scalePart(MatrixObject * self) float scale[3], rot[3]; float mat[3][3], imat[3][3], tmat[3][3]; + if(!BaseMath_ReadCallback(self)) + return NULL; + /*must be 3-4 cols, 3-4 rows, square matrix*/ if(self->colSize == 4 && self->rowSize == 4) Mat3CpyMat4(mat, (float (*)[4])*self->matrix); @@ -325,7 +405,7 @@ PyObject *Matrix_scalePart(MatrixObject * self) scale[0]= tmat[0][0]; scale[1]= tmat[1][1]; scale[2]= tmat[2][2]; - return newVectorObject(scale, 3, Py_NEW); + return newVectorObject(scale, 3, Py_NEW, NULL); } /*---------------------------Matrix.invert() ---------------------*/ PyObject *Matrix_Invert(MatrixObject * self) @@ -337,6 +417,9 @@ PyObject *Matrix_Invert(MatrixObject * self) float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + if(!BaseMath_ReadCallback(self)) + return NULL; + if(self->rowSize != self->colSize){ PyErr_SetString(PyExc_AttributeError, "Matrix.invert(ed): only square matrices are supported"); return NULL; @@ -377,6 +460,7 @@ PyObject *Matrix_Invert(MatrixObject * self) return NULL; } + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject *)self; } @@ -387,6 +471,9 @@ PyObject *Matrix_Determinant(MatrixObject * self) { float det = 0.0f; + if(!BaseMath_ReadCallback(self)) + return NULL; + if(self->rowSize != self->colSize){ PyErr_SetString(PyExc_AttributeError, "Matrix.determinant: only square matrices are supported"); return NULL; @@ -412,6 +499,9 @@ PyObject *Matrix_Transpose(MatrixObject * self) { float t = 0.0f; + if(!BaseMath_ReadCallback(self)) + return NULL; + if(self->rowSize != self->colSize){ PyErr_SetString(PyExc_AttributeError, "Matrix.transpose(d): only square matrices are supported"); return NULL; @@ -427,6 +517,7 @@ PyObject *Matrix_Transpose(MatrixObject * self) Mat4Transp((float (*)[4])*self->matrix); } + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject *)self; } @@ -436,18 +527,25 @@ PyObject *Matrix_Transpose(MatrixObject * self) PyObject *Matrix_Zero(MatrixObject * self) { int row, col; - + for(row = 0; row < self->rowSize; row++) { for(col = 0; col < self->colSize; col++) { self->matrix[row][col] = 0.0f; } } + + if(!BaseMath_WriteCallback(self)) + return NULL; + Py_INCREF(self); return (PyObject *)self; } /*---------------------------Matrix.identity(() ------------------*/ PyObject *Matrix_Identity(MatrixObject * self) { + if(!BaseMath_ReadCallback(self)) + return NULL; + if(self->rowSize != self->colSize){ PyErr_SetString(PyExc_AttributeError, "Matrix.identity: only square matrices are supported\n"); return NULL; @@ -464,6 +562,9 @@ PyObject *Matrix_Identity(MatrixObject * self) Mat4One((float (*)[4]) *self->matrix); } + if(!BaseMath_WriteCallback(self)) + return NULL; + Py_INCREF(self); return (PyObject *)self; } @@ -471,19 +572,10 @@ PyObject *Matrix_Identity(MatrixObject * self) /*---------------------------Matrix.inverted() ------------------*/ PyObject *Matrix_copy(MatrixObject * self) { - return (PyObject*)(MatrixObject*)newMatrixObject((float (*))*self->matrix, self->rowSize, self->colSize, Py_NEW); -} - -/*----------------------------dealloc()(internal) ----------------*/ -/*free the py_object*/ -static void Matrix_dealloc(MatrixObject * self) -{ - PyMem_Free(self->matrix); - /*only free py_data*/ - if(self->data.py_data){ - PyMem_Free(self->data.py_data); - } - PyObject_DEL(self); + if(!BaseMath_ReadCallback(self)) + return NULL; + + return (PyObject*)newMatrixObject((float (*))*self->matrix, self->rowSize, self->colSize, Py_NEW, Py_TYPE(self)); } /*----------------------------print object (internal)-------------*/ @@ -493,6 +585,9 @@ static PyObject *Matrix_repr(MatrixObject * self) int x, y; char buffer[48], str[1024]; + if(!BaseMath_ReadCallback(self)) + return NULL; + BLI_strncpy(str,"",1024); for(x = 0; x < self->rowSize; x++){ sprintf(buffer, "["); @@ -529,6 +624,9 @@ static PyObject* Matrix_richcmpr(PyObject *objectA, PyObject *objectB, int compa matA = (MatrixObject*)objectA; matB = (MatrixObject*)objectB; + if(!BaseMath_ReadCallback(matA) || !BaseMath_ReadCallback(matB)) + return NULL; + if (matA->colSize != matB->colSize || matA->rowSize != matB->rowSize){ if (comparison_type == Py_NE){ Py_RETURN_TRUE; @@ -562,8 +660,7 @@ static PyObject* Matrix_richcmpr(PyObject *objectA, PyObject *objectB, int compa Py_RETURN_FALSE; } } -/*------------------------tp_doc*/ -static char MatrixObject_doc[] = "This is a wrapper for matrix objects."; + /*---------------------SEQUENCE PROTOCOLS------------------------ ----------------------------len(object)------------------------ sequence length*/ @@ -576,11 +673,14 @@ static int Matrix_len(MatrixObject * self) the wrapped vector gives direct access to the matrix data*/ static PyObject *Matrix_item(MatrixObject * self, int i) { + if(!BaseMath_ReadCallback(self)) + return NULL; + if(i < 0 || i >= self->rowSize) { PyErr_SetString(PyExc_IndexError, "matrix[attribute]: array index out of range"); return NULL; } - return newVectorObject(self->matrix[i], self->colSize, Py_WRAP); + return newVectorObject_cb((PyObject *)self, self->colSize, mathutils_matrix_vector_cb_index, i); } /*----------------------------object[]------------------------- sequence accessor (set)*/ @@ -590,6 +690,9 @@ static int Matrix_ass_item(MatrixObject * self, int i, PyObject * ob) float vec[4]; PyObject *m, *f; + if(!BaseMath_ReadCallback(self)) + return -1; + if(i >= self->rowSize || i < 0){ PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: bad row\n"); return -1; @@ -623,6 +726,8 @@ static int Matrix_ass_item(MatrixObject * self, int i, PyObject * ob) for(y = 0; y < size; y++){ self->matrix[i][y] = vec[y]; } + + BaseMath_WriteCallback(self); return 0; }else{ PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: expects a sequence of column size\n"); @@ -636,6 +741,9 @@ static PyObject *Matrix_slice(MatrixObject * self, int begin, int end) PyObject *list = NULL; int count; + + if(!BaseMath_ReadCallback(self)) + return NULL; CLAMP(begin, 0, self->rowSize); CLAMP(end, 0, self->rowSize); @@ -644,21 +752,24 @@ static PyObject *Matrix_slice(MatrixObject * self, int begin, int end) list = PyList_New(end - begin); for(count = begin; count < end; count++) { PyList_SetItem(list, count - begin, - newVectorObject(self->matrix[count], self->colSize, Py_WRAP)); + newVectorObject_cb((PyObject *)self, self->colSize, mathutils_matrix_vector_cb_index, count)); + } return list; } /*----------------------------object[z:y]------------------------ sequence slice (set)*/ -static int Matrix_ass_slice(MatrixObject * self, int begin, int end, - PyObject * seq) +static int Matrix_ass_slice(MatrixObject * self, int begin, int end, PyObject * seq) { int i, x, y, size, sub_size = 0; float mat[16], f; PyObject *subseq; PyObject *m; + if(!BaseMath_ReadCallback(self)) + return -1; + CLAMP(begin, 0, self->rowSize); CLAMP(end, 0, self->rowSize); begin = MIN2(begin,end); @@ -716,6 +827,8 @@ static int Matrix_ass_slice(MatrixObject * self, int begin, int end, for(x = 0; x < (size * sub_size); x++){ self->matrix[begin + (int)floor(x / self->colSize)][x % self->colSize] = mat[x]; } + + BaseMath_WriteCallback(self); return 0; }else{ PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: illegal argument type for built-in operation\n"); @@ -738,6 +851,10 @@ static PyObject *Matrix_add(PyObject * m1, PyObject * m2) PyErr_SetString(PyExc_AttributeError, "Matrix addition: arguments not valid for this operation...."); return NULL; } + + if(!BaseMath_ReadCallback(mat1) || !BaseMath_ReadCallback(mat2)) + return NULL; + if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){ PyErr_SetString(PyExc_AttributeError, "Matrix addition: matrices must have the same dimensions for this operation"); return NULL; @@ -749,7 +866,7 @@ static PyObject *Matrix_add(PyObject * m1, PyObject * m2) } } - return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW); + return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW, NULL); } /*------------------------obj - obj------------------------------ subtraction*/ @@ -767,6 +884,10 @@ static PyObject *Matrix_sub(PyObject * m1, PyObject * m2) PyErr_SetString(PyExc_AttributeError, "Matrix addition: arguments not valid for this operation...."); return NULL; } + + if(!BaseMath_ReadCallback(mat1) || !BaseMath_ReadCallback(mat2)) + return NULL; + if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){ PyErr_SetString(PyExc_AttributeError, "Matrix addition: matrices must have the same dimensions for this operation"); return NULL; @@ -778,7 +899,7 @@ static PyObject *Matrix_sub(PyObject * m1, PyObject * m2) } } - return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW); + return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW, NULL); } /*------------------------obj * obj------------------------------ mulplication*/ @@ -791,8 +912,16 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2) double dot = 0.0f; MatrixObject *mat1 = NULL, *mat2 = NULL; - if(MatrixObject_Check(m1)) mat1 = (MatrixObject*)m1; - if(MatrixObject_Check(m2)) mat2 = (MatrixObject*)m2; + if(MatrixObject_Check(m1)) { + mat1 = (MatrixObject*)m1; + if(!BaseMath_ReadCallback(mat1)) + return NULL; + } + if(MatrixObject_Check(m2)) { + mat2 = (MatrixObject*)m2; + if(!BaseMath_ReadCallback(mat2)) + return NULL; + } if(mat1 && mat2) { /*MATRIX * MATRIX*/ if(mat1->colSize != mat2->rowSize){ @@ -809,7 +938,7 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2) } } - return newMatrixObject(mat, mat1->rowSize, mat2->colSize, Py_NEW); + return newMatrixObject(mat, mat1->rowSize, mat2->colSize, Py_NEW, NULL); } if(mat1==NULL){ @@ -820,7 +949,7 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2) mat[((x * mat2->colSize) + y)] = scalar * mat2->matrix[x][y]; } } - return newMatrixObject(mat, mat2->rowSize, mat2->colSize, Py_NEW); + return newMatrixObject(mat, mat2->rowSize, mat2->colSize, Py_NEW, NULL); } PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation"); @@ -829,7 +958,7 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2) else /* if(mat1) { */ { if(VectorObject_Check(m2)) { /* MATRIX*VECTOR */ - return column_vector_multiplication(mat1, (VectorObject *)m2); + return column_vector_multiplication(mat1, (VectorObject *)m2); /* vector update done inside the function */ } else { scalar= PyFloat_AsDouble(m2); @@ -839,7 +968,7 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2) mat[((x * mat1->colSize) + y)] = scalar * mat1->matrix[x][y]; } } - return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW); + return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW, NULL); } } PyErr_SetString(PyExc_TypeError, "Matrix multiplication: arguments not acceptable for this operation"); @@ -851,6 +980,9 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2) } static PyObject* Matrix_inv(MatrixObject *self) { + if(!BaseMath_ReadCallback(self)) + return NULL; + return Matrix_Invert(self); } @@ -864,6 +996,123 @@ static PySequenceMethods Matrix_SeqMethods = { (ssizeobjargproc) Matrix_ass_item, /* sq_ass_item */ (ssizessizeobjargproc) Matrix_ass_slice, /* sq_ass_slice */ }; + + + +#if (PY_VERSION_HEX >= 0x03000000) +static PyObject *Matrix_subscript(MatrixObject* self, PyObject* item) +{ + if (PyIndex_Check(item)) { + Py_ssize_t i; + i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) + return NULL; + if (i < 0) + i += self->rowSize; + return Matrix_item(self, i); + } else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx((PySliceObject*)item, self->rowSize, &start, &stop, &step, &slicelength) < 0) + return NULL; + + if (slicelength <= 0) { + return PyList_New(0); + } + else if (step == 1) { + return Matrix_slice(self, start, stop); + } + else { + PyErr_SetString(PyExc_TypeError, "slice steps not supported with matricies"); + return NULL; + } + } + else { + PyErr_Format(PyExc_TypeError, + "vector indices must be integers, not %.200s", + item->ob_type->tp_name); + return NULL; + } +} + +static int Matrix_ass_subscript(MatrixObject* self, PyObject* item, PyObject* value) +{ + if (PyIndex_Check(item)) { + Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) + return -1; + if (i < 0) + i += self->rowSize; + return Matrix_ass_item(self, i, value); + } + else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx((PySliceObject*)item, self->rowSize, &start, &stop, &step, &slicelength) < 0) + return -1; + + if (step == 1) + return Matrix_ass_slice(self, start, stop, value); + else { + PyErr_SetString(PyExc_TypeError, "slice steps not supported with matricies"); + return -1; + } + } + else { + PyErr_Format(PyExc_TypeError, + "matrix indices must be integers, not %.200s", + item->ob_type->tp_name); + return -1; + } +} + +static PyMappingMethods Matrix_AsMapping = { + (lenfunc)Matrix_len, + (binaryfunc)Matrix_subscript, + (objobjargproc)Matrix_ass_subscript +}; +#endif /* (PY_VERSION_HEX >= 0x03000000) */ + + + +#if (PY_VERSION_HEX >= 0x03000000) +static PyNumberMethods Matrix_NumMethods = { + (binaryfunc) Matrix_add, /*nb_add*/ + (binaryfunc) Matrix_sub, /*nb_subtract*/ + (binaryfunc) Matrix_mul, /*nb_multiply*/ + 0, /*nb_remainder*/ + 0, /*nb_divmod*/ + 0, /*nb_power*/ + (unaryfunc) 0, /*nb_negative*/ + (unaryfunc) 0, /*tp_positive*/ + (unaryfunc) 0, /*tp_absolute*/ + (inquiry) 0, /*tp_bool*/ + (unaryfunc) Matrix_inv, /*nb_invert*/ + 0, /*nb_lshift*/ + (binaryfunc)0, /*nb_rshift*/ + 0, /*nb_and*/ + 0, /*nb_xor*/ + 0, /*nb_or*/ + 0, /*nb_int*/ + 0, /*nb_reserved*/ + 0, /*nb_float*/ + 0, /* nb_inplace_add */ + 0, /* nb_inplace_subtract */ + 0, /* nb_inplace_multiply */ + 0, /* nb_inplace_remainder */ + 0, /* nb_inplace_power */ + 0, /* nb_inplace_lshift */ + 0, /* nb_inplace_rshift */ + 0, /* nb_inplace_and */ + 0, /* nb_inplace_xor */ + 0, /* nb_inplace_or */ + 0, /* nb_floor_divide */ + 0, /* nb_true_divide */ + 0, /* nb_inplace_floor_divide */ + 0, /* nb_inplace_true_divide */ + 0, /* nb_index */ +}; +#else static PyNumberMethods Matrix_NumMethods = { (binaryfunc) Matrix_add, /* __add__ */ (binaryfunc) Matrix_sub, /* __sub__ */ @@ -889,6 +1138,7 @@ static PyNumberMethods Matrix_NumMethods = { (unaryfunc) 0, /* __oct__ */ (unaryfunc) 0, /* __hex__ */ }; +#endif static PyObject *Matrix_getRowSize( MatrixObject * self, void *type ) { @@ -900,21 +1150,15 @@ static PyObject *Matrix_getColSize( MatrixObject * self, void *type ) return PyLong_FromLong((long) self->colSize); } -static PyObject *Matrix_getWrapped( MatrixObject * self, void *type ) -{ - if (self->wrapped == Py_WRAP) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - /*****************************************************************************/ /* Python attributes get/set structure: */ /*****************************************************************************/ static PyGetSetDef Matrix_getseters[] = { {"rowSize", (getter)Matrix_getRowSize, (setter)NULL, "", NULL}, {"colSize", (getter)Matrix_getColSize, (setter)NULL, "", NULL}, - {"wrapped", (getter)Matrix_getWrapped, (setter)NULL, "", NULL}, + {"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "", NULL}, + {"__owner__",(getter)BaseMathObject_getOwner, (setter)NULL, "", + NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; @@ -930,7 +1174,7 @@ PyTypeObject matrix_Type = { "matrix", /*tp_name*/ sizeof(MatrixObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ - (destructor)Matrix_dealloc, /*tp_dealloc*/ + (destructor)BaseMathObject_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ @@ -938,15 +1182,19 @@ PyTypeObject matrix_Type = { (reprfunc) Matrix_repr, /*tp_repr*/ &Matrix_NumMethods, /*tp_as_number*/ &Matrix_SeqMethods, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ +#if (PY_VERSION_HEX >= 0x03000000) + &Matrix_AsMapping, /*tp_as_mapping*/ +#else + 0, +#endif 0, /*tp_hash*/ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - MatrixObject_doc, /*tp_doc*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + 0, /*tp_doc*/ 0, /*tp_traverse*/ 0, /*tp_clear*/ (richcmpfunc)Matrix_richcmpr, /*tp_richcompare*/ @@ -984,13 +1232,13 @@ self->matrix self->contiguous_ptr (reference to data.xxx) [4] [5] .... -self->matrix[1][1] = self->contiguous_ptr[4] = self->data.xxx_data[4]*/ +self->matrix[1][1] = self->contigPtr[4] */ /*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER (i.e. it was allocated elsewhere by MEM_mallocN()) pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON (i.e. it must be created here with PyMEM_malloc())*/ -PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type) +PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type, PyTypeObject *base_type) { MatrixObject *self; int x, row, col; @@ -1001,15 +1249,18 @@ PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type) return NULL; } - self = PyObject_NEW(MatrixObject, &matrix_Type); - self->data.blend_data = NULL; - self->data.py_data = NULL; + if(base_type) self = (MatrixObject *)base_type->tp_alloc(base_type, 0); + else self = PyObject_NEW(MatrixObject, &matrix_Type); + self->rowSize = rowSize; self->colSize = colSize; + + /* init callbacks as NULL */ + self->cb_user= NULL; + self->cb_type= self->cb_subtype= 0; if(type == Py_WRAP){ - self->data.blend_data = mat; - self->contigPtr = self->data.blend_data; + self->contigPtr = mat; /*create pointer array*/ self->matrix = PyMem_Malloc(rowSize * sizeof(float *)); if(self->matrix == NULL) { /*allocation failure*/ @@ -1022,16 +1273,15 @@ PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type) } self->wrapped = Py_WRAP; }else if (type == Py_NEW){ - self->data.py_data = PyMem_Malloc(rowSize * colSize * sizeof(float)); - if(self->data.py_data == NULL) { /*allocation failure*/ + self->contigPtr = PyMem_Malloc(rowSize * colSize * sizeof(float)); + if(self->contigPtr == NULL) { /*allocation failure*/ PyErr_SetString( PyExc_MemoryError, "matrix(): problem allocating pointer space\n"); return NULL; } - self->contigPtr = self->data.py_data; /*create pointer array*/ self->matrix = PyMem_Malloc(rowSize * sizeof(float *)); if(self->matrix == NULL) { /*allocation failure*/ - PyMem_Free(self->data.py_data); + PyMem_Free(self->contigPtr); PyErr_SetString( PyExc_MemoryError, "matrix(): problem allocating pointer space"); return NULL; } @@ -1056,3 +1306,53 @@ PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type) } return (PyObject *) self; } + +PyObject *newMatrixObject_cb(PyObject *cb_user, int rowSize, int colSize, int cb_type, int cb_subtype) +{ + MatrixObject *self= (MatrixObject *)newMatrixObject(NULL, rowSize, colSize, Py_NEW, NULL); + if(self) { + Py_INCREF(cb_user); + self->cb_user= cb_user; + self->cb_type= (unsigned char)cb_type; + self->cb_subtype= (unsigned char)cb_subtype; + } + return (PyObject *) self; +} + +//----------------column_vector_multiplication (internal)--------- +//COLUMN VECTOR Multiplication (Matrix X Vector) +// [1][2][3] [a] +// [4][5][6] * [b] +// [7][8][9] [c] +//vector/matrix multiplication IS NOT COMMUTATIVE!!!! +static PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec) +{ + float vecNew[4], vecCopy[4]; + double dot = 0.0f; + int x, y, z = 0; + + if(!BaseMath_ReadCallback(mat) || !BaseMath_ReadCallback(vec)) + return NULL; + + if(mat->rowSize != vec->size){ + if(mat->rowSize == 4 && vec->size != 3){ + PyErr_SetString(PyExc_AttributeError, "matrix * vector: matrix row size and vector size must be the same"); + return NULL; + }else{ + vecCopy[3] = 1.0f; + } + } + + for(x = 0; x < vec->size; x++){ + vecCopy[x] = vec->vec[x]; + } + + for(x = 0; x < mat->rowSize; x++) { + for(y = 0; y < mat->colSize; y++) { + dot += mat->matrix[x][y] * vecCopy[y]; + } + vecNew[z++] = (float)dot; + dot = 0.0f; + } + return newVectorObject(vecNew, vec->size, Py_NEW, NULL); +} diff --git a/source/blender/python/generic/matrix.h b/source/blender/python/generic/matrix.h index ef82263fe00..856c711c4ef 100644 --- a/source/blender/python/generic/matrix.h +++ b/source/blender/python/generic/matrix.h @@ -1,5 +1,5 @@ /* - * $Id: matrix.h 20248 2009-05-18 04:11:54Z campbellbarton $ + * $Id$ * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -33,21 +33,22 @@ #include extern PyTypeObject matrix_Type; - -#define MatrixObject_Check(v) ((v)->ob_type == &matrix_Type) +#define MatrixObject_Check(_v) PyObject_TypeCheck((_v), &matrix_Type) typedef float **ptRow; -typedef struct _Matrix { - PyObject_VAR_HEAD - struct{ - float *py_data; /*python managed*/ - float *blend_data; /*blender managed*/ - }data; - ptRow matrix; /*ptr to the contigPtr (accessor)*/ - float *contigPtr; /*1D array of data (alias)*/ - int rowSize; - int colSize; - int wrapped; /*is wrapped data?*/ +typedef struct _Matrix { /* keep aligned with BaseMathObject in Mathutils.h */ + PyObject_VAR_HEAD + float *contigPtr; /*1D array of data (alias)*/ + PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */ + unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */ + unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */ + unsigned char wrapped; /*is wrapped data?*/ + /* end BaseMathObject */ + + unsigned char rowSize; + unsigned int colSize; + ptRow matrix; /*ptr to the contigPtr (accessor)*/ + } MatrixObject; /*struct data contains a pointer to the actual data that the @@ -56,6 +57,10 @@ be stored in py_data) or be a wrapper for data allocated through blender (stored in blend_data). This is an either/or struct not both*/ /*prototypes*/ -PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type); +PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type, PyTypeObject *base_type); +PyObject *newMatrixObject_cb(PyObject *user, int rowSize, int colSize, int cb_type, int cb_subtype); + +extern int mathutils_matrix_vector_cb_index; +extern struct Mathutils_Callback mathutils_matrix_vector_cb; #endif /* EXPP_matrix_H */ diff --git a/source/blender/python/generic/quat.c b/source/blender/python/generic/quat.c index 4ad5d07b3b8..81d69834469 100644 --- a/source/blender/python/generic/quat.c +++ b/source/blender/python/generic/quat.c @@ -1,5 +1,5 @@ /* - * $Id: quat.c 20332 2009-05-22 03:22:56Z campbellbarton $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -34,16 +34,6 @@ //-------------------------DOC STRINGS --------------------------- -static char Quaternion_Identity_doc[] = "() - set the quaternion to it's identity (1, vector)"; -static char Quaternion_Negate_doc[] = "() - set all values in the quaternion to their negative"; -static char Quaternion_Conjugate_doc[] = "() - set the quaternion to it's conjugate"; -static char Quaternion_Inverse_doc[] = "() - set the quaternion to it's inverse"; -static char Quaternion_Normalize_doc[] = "() - normalize the vector portion of the quaternion"; -static char Quaternion_ToEuler_doc[] = "(eul_compat) - return a euler rotation representing the quaternion, optional euler argument that the new euler will be made compatible with."; -static char Quaternion_ToMatrix_doc[] = "() - return a rotation matrix representing the quaternion"; -static char Quaternion_Cross_doc[] = "(other) - return the cross product between this quaternion and another"; -static char Quaternion_Dot_doc[] = "(other) - return the dot product between this quaternion and another"; -static char Quaternion_copy_doc[] = "() - return a copy of the quat"; static PyObject *Quaternion_Identity( QuaternionObject * self ); static PyObject *Quaternion_Negate( QuaternionObject * self ); @@ -58,27 +48,27 @@ static PyObject *Quaternion_copy( QuaternionObject * self ); //-----------------------METHOD DEFINITIONS ---------------------- static struct PyMethodDef Quaternion_methods[] = { - {"identity", (PyCFunction) Quaternion_Identity, METH_NOARGS, Quaternion_Identity_doc}, - {"negate", (PyCFunction) Quaternion_Negate, METH_NOARGS, Quaternion_Negate_doc}, - {"conjugate", (PyCFunction) Quaternion_Conjugate, METH_NOARGS, Quaternion_Conjugate_doc}, - {"inverse", (PyCFunction) Quaternion_Inverse, METH_NOARGS, Quaternion_Inverse_doc}, - {"normalize", (PyCFunction) Quaternion_Normalize, METH_NOARGS, Quaternion_Normalize_doc}, - {"toEuler", (PyCFunction) Quaternion_ToEuler, METH_VARARGS, Quaternion_ToEuler_doc}, - {"toMatrix", (PyCFunction) Quaternion_ToMatrix, METH_NOARGS, Quaternion_ToMatrix_doc}, - {"cross", (PyCFunction) Quaternion_Cross, METH_O, Quaternion_Cross_doc}, - {"dot", (PyCFunction) Quaternion_Dot, METH_O, Quaternion_Dot_doc}, - {"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc}, - {"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc}, + {"identity", (PyCFunction) Quaternion_Identity, METH_NOARGS, NULL}, + {"negate", (PyCFunction) Quaternion_Negate, METH_NOARGS, NULL}, + {"conjugate", (PyCFunction) Quaternion_Conjugate, METH_NOARGS, NULL}, + {"inverse", (PyCFunction) Quaternion_Inverse, METH_NOARGS, NULL}, + {"normalize", (PyCFunction) Quaternion_Normalize, METH_NOARGS, NULL}, + {"toEuler", (PyCFunction) Quaternion_ToEuler, METH_VARARGS, NULL}, + {"toMatrix", (PyCFunction) Quaternion_ToMatrix, METH_NOARGS, NULL}, + {"cross", (PyCFunction) Quaternion_Cross, METH_O, NULL}, + {"dot", (PyCFunction) Quaternion_Dot, METH_O, NULL}, + {"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, NULL}, + {"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, NULL}, {NULL, NULL, 0, NULL} }; //----------------------------------Mathutils.Quaternion() -------------- static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyObject *listObject = NULL, *n, *q, *f; + PyObject *listObject = NULL, *n, *q; int size, i; - float quat[4], scalar; - double norm = 0.0f, angle = 0.0f; + float quat[4]; + double angle = 0.0f; size = PyTuple_GET_SIZE(args); if (size == 1 || size == 2) { //seq? @@ -127,7 +117,7 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw } } } else if (size == 0) { //returns a new empty quat - return newQuaternionObject(NULL, Py_NEW); + return newQuaternionObject(NULL, Py_NEW, NULL); } else { listObject = args; } @@ -151,31 +141,23 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw return NULL; } - scalar = PyFloat_AsDouble(q); - if (scalar==-1 && PyErr_Occurred()) { - Py_DECREF(q); + quat[i] = PyFloat_AsDouble(q); + Py_DECREF(q); + + if (quat[i]==-1 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n"); return NULL; } - - quat[i] = scalar; - Py_DECREF(f); - Py_DECREF(q); - } - if(size == 3){ //calculate the quat based on axis/angle - norm = sqrt(quat[0] * quat[0] + quat[1] * quat[1] + quat[2] * quat[2]); - quat[0] /= (float)norm; - quat[1] /= (float)norm; - quat[2] /= (float)norm; - - angle = angle * (Py_PI / 180); - quat[3] =(float) (sin(angle/ 2.0f)) * quat[2]; - quat[2] =(float) (sin(angle/ 2.0f)) * quat[1]; - quat[1] =(float) (sin(angle/ 2.0f)) * quat[0]; - quat[0] =(float) (cos(angle/ 2.0f)); } - return newQuaternionObject(quat, Py_NEW); + if(size == 3) //calculate the quat based on axis/angle +#ifdef USE_MATHUTILS_DEG + AxisAngleToQuat(quat, quat, angle * (Py_PI / 180)); +#else + AxisAngleToQuat(quat, quat, angle); +#endif + + return newQuaternionObject(quat, Py_NEW, NULL); } //-----------------------------METHODS------------------------------ @@ -190,34 +172,48 @@ static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args) if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat)) return NULL; + if(!BaseMath_ReadCallback(self)) + return NULL; + if(eul_compat) { float mat[3][3], eul_compatf[3]; + if(!BaseMath_ReadCallback(eul_compat)) + return NULL; + + QuatToMat3(self->quat, mat); + +#ifdef USE_MATHUTILS_DEG for(x = 0; x < 3; x++) { eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180); } - - QuatToMat3(self->quat, mat); Mat3ToCompatibleEul(mat, eul, eul_compatf); +#else + Mat3ToCompatibleEul(mat, eul, eul_compat->eul); +#endif } else { QuatToEul(self->quat, eul); } - +#ifdef USE_MATHUTILS_DEG for(x = 0; x < 3; x++) { eul[x] *= (180 / (float)Py_PI); } - return newEulerObject(eul, Py_NEW); +#endif + return newEulerObject(eul, Py_NEW, NULL); } //----------------------------Quaternion.toMatrix()------------------ //return the quat as a matrix static PyObject *Quaternion_ToMatrix(QuaternionObject * self) { - float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; - QuatToMat3(self->quat, (float (*)[3]) mat); + float mat[9]; /* all values are set */ - return newMatrixObject(mat, 3, 3, Py_NEW); + if(!BaseMath_ReadCallback(self)) + return NULL; + + QuatToMat3(self->quat, (float (*)[3]) mat); + return newMatrixObject(mat, 3, 3, Py_NEW, NULL); } //----------------------------Quaternion.cross(other)------------------ @@ -231,33 +227,38 @@ static PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * va return NULL; } + if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value)) + return NULL; + QuatMul(quat, self->quat, value->quat); - return newQuaternionObject(quat, Py_NEW); + return newQuaternionObject(quat, Py_NEW, NULL); } //----------------------------Quaternion.dot(other)------------------ //return the dot quat static PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * value) { - int x; - double dot = 0.0; - if (!QuaternionObject_Check(value)) { PyErr_SetString( PyExc_TypeError, "quat.dot(value): expected a quaternion argument" ); return NULL; } - - for(x = 0; x < 4; x++) { - dot += self->quat[x] * value->quat[x]; - } - return PyFloat_FromDouble(dot); + + if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value)) + return NULL; + + return PyFloat_FromDouble(QuatDot(self->quat, value->quat)); } //----------------------------Quaternion.normalize()---------------- //normalize the axis of rotation of [theta,vector] static PyObject *Quaternion_Normalize(QuaternionObject * self) { + if(!BaseMath_ReadCallback(self)) + return NULL; + NormalQuat(self->quat); + + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject*)self; } @@ -265,20 +266,12 @@ static PyObject *Quaternion_Normalize(QuaternionObject * self) //invert the quat static PyObject *Quaternion_Inverse(QuaternionObject * self) { - double mag = 0.0f; - int x; + if(!BaseMath_ReadCallback(self)) + return NULL; - for(x = 1; x < 4; x++) { - self->quat[x] = -self->quat[x]; - } - for(x = 0; x < 4; x++) { - mag += (self->quat[x] * self->quat[x]); - } - mag = sqrt(mag); - for(x = 0; x < 4; x++) { - self->quat[x] /= (float)(mag * mag); - } + QuatInv(self->quat); + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject*)self; } @@ -286,11 +279,12 @@ static PyObject *Quaternion_Inverse(QuaternionObject * self) //generate the identity quaternion static PyObject *Quaternion_Identity(QuaternionObject * self) { - self->quat[0] = 1.0; - self->quat[1] = 0.0; - self->quat[2] = 0.0; - self->quat[3] = 0.0; + if(!BaseMath_ReadCallback(self)) + return NULL; + QuatOne(self->quat); + + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject*)self; } @@ -298,10 +292,12 @@ static PyObject *Quaternion_Identity(QuaternionObject * self) //negate the quat static PyObject *Quaternion_Negate(QuaternionObject * self) { - int x; - for(x = 0; x < 4; x++) { - self->quat[x] = -self->quat[x]; - } + if(!BaseMath_ReadCallback(self)) + return NULL; + + QuatMulf(self->quat, -1.0f); + + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject*)self; } @@ -309,10 +305,12 @@ static PyObject *Quaternion_Negate(QuaternionObject * self) //negate the vector part static PyObject *Quaternion_Conjugate(QuaternionObject * self) { - int x; - for(x = 1; x < 4; x++) { - self->quat[x] = -self->quat[x]; - } + if(!BaseMath_ReadCallback(self)) + return NULL; + + QuatConj(self->quat); + + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject*)self; } @@ -320,18 +318,10 @@ static PyObject *Quaternion_Conjugate(QuaternionObject * self) //return a copy of the quat static PyObject *Quaternion_copy(QuaternionObject * self) { - return newQuaternionObject(self->quat, Py_NEW); -} + if(!BaseMath_ReadCallback(self)) + return NULL; -//----------------------------dealloc()(internal) ------------------ -//free the py_object -static void Quaternion_dealloc(QuaternionObject * self) -{ - //only free py_data - if(self->data.py_data){ - PyMem_Free(self->data.py_data); - } - PyObject_DEL(self); + return newQuaternionObject(self->quat, Py_NEW, Py_TYPE(self)); } //----------------------------print object (internal)-------------- @@ -339,6 +329,10 @@ static void Quaternion_dealloc(QuaternionObject * self) static PyObject *Quaternion_repr(QuaternionObject * self) { char str[64]; + + if(!BaseMath_ReadCallback(self)) + return NULL; + sprintf(str, "[%.6f, %.6f, %.6f, %.6f](quaternion)", self->quat[0], self->quat[1], self->quat[2], self->quat[3]); return PyUnicode_FromString(str); } @@ -349,15 +343,24 @@ static PyObject* Quaternion_richcmpr(PyObject *objectA, PyObject *objectB, int c QuaternionObject *quatA = NULL, *quatB = NULL; int result = 0; - if (!QuaternionObject_Check(objectA) || !QuaternionObject_Check(objectB)){ + if(QuaternionObject_Check(objectA)) { + quatA = (QuaternionObject*)objectA; + if(!BaseMath_ReadCallback(quatA)) + return NULL; + } + if(QuaternionObject_Check(objectB)) { + quatB = (QuaternionObject*)objectB; + if(!BaseMath_ReadCallback(quatB)) + return NULL; + } + + if (!quatA || !quatB){ if (comparison_type == Py_NE){ Py_RETURN_TRUE; }else{ Py_RETURN_FALSE; } } - quatA = (QuaternionObject*)objectA; - quatB = (QuaternionObject*)objectB; switch (comparison_type){ case Py_EQ: @@ -381,8 +384,7 @@ static PyObject* Quaternion_richcmpr(PyObject *objectA, PyObject *objectB, int c Py_RETURN_FALSE; } } -//------------------------tp_doc -static char QuaternionObject_doc[] = "This is a wrapper for quaternion objects."; + //---------------------SEQUENCE PROTOCOLS------------------------ //----------------------------len(object)------------------------ //sequence length @@ -394,10 +396,16 @@ static int Quaternion_len(QuaternionObject * self) //sequence accessor (get) static PyObject *Quaternion_item(QuaternionObject * self, int i) { + if(i<0) i= 4-i; + if(i < 0 || i >= 4) { PyErr_SetString(PyExc_IndexError, "quaternion[attribute]: array index out of range\n"); return NULL; } + + if(!BaseMath_ReadIndexCallback(self, i)) + return NULL; + return PyFloat_FromDouble(self->quat[i]); } @@ -405,21 +413,23 @@ static PyObject *Quaternion_item(QuaternionObject * self, int i) //sequence accessor (set) static int Quaternion_ass_item(QuaternionObject * self, int i, PyObject * ob) { - PyObject *f = NULL; - - f = PyNumber_Float(ob); - if(f == NULL) { // parsed item not a number - PyErr_SetString(PyExc_TypeError, "quaternion[attribute] = x: argument not a number\n"); + float scalar= (float)PyFloat_AsDouble(ob); + if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */ + PyErr_SetString(PyExc_TypeError, "quaternion[index] = x: index argument not a number\n"); return -1; } + if(i<0) i= 4-i; + if(i < 0 || i >= 4){ - Py_DECREF(f); PyErr_SetString(PyExc_IndexError, "quaternion[attribute] = x: array assignment index out of range\n"); return -1; } - self->quat[i] = (float)PyFloat_AS_DOUBLE(f); - Py_DECREF(f); + self->quat[i] = scalar; + + if(!BaseMath_WriteIndexCallback(self, i)) + return -1; + return 0; } //----------------------------object[z:y]------------------------ @@ -429,6 +439,9 @@ static PyObject *Quaternion_slice(QuaternionObject * self, int begin, int end) PyObject *list = NULL; int count; + if(!BaseMath_ReadCallback(self)) + return NULL; + CLAMP(begin, 0, 4); if (end<0) end= 5+end; CLAMP(end, 0, 4); @@ -444,12 +457,14 @@ static PyObject *Quaternion_slice(QuaternionObject * self, int begin, int end) } //----------------------------object[z:y]------------------------ //sequence slice (set) -static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, - PyObject * seq) +static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, PyObject * seq) { int i, y, size = 0; float quat[4]; - PyObject *q, *f; + PyObject *q; + + if(!BaseMath_ReadCallback(self)) + return -1; CLAMP(begin, 0, 4); if (end<0) end= 5+end; @@ -469,21 +484,19 @@ static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, return -1; } - f = PyNumber_Float(q); - if(f == NULL) { // parsed item not a number - Py_DECREF(q); + quat[i]= (float)PyFloat_AsDouble(q); + Py_DECREF(q); + + if(quat[i]==-1.0f && PyErr_Occurred()) { /* parsed item not a number */ PyErr_SetString(PyExc_TypeError, "quaternion[begin:end] = []: sequence argument not a number\n"); return -1; } - - quat[i] = (float)PyFloat_AS_DOUBLE(f); - Py_DECREF(f); - Py_DECREF(q); } //parsed well - now set in vector - for(y = 0; y < size; y++){ + for(y = 0; y < size; y++) self->quat[begin + y] = quat[y]; - } + + BaseMath_WriteCallback(self); return 0; } //------------------------NUMERIC PROTOCOLS---------------------- @@ -491,7 +504,6 @@ static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, //addition static PyObject *Quaternion_add(PyObject * q1, PyObject * q2) { - int x; float quat[4]; QuaternionObject *quat1 = NULL, *quat2 = NULL; @@ -499,15 +511,14 @@ static PyObject *Quaternion_add(PyObject * q1, PyObject * q2) PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation....\n"); return NULL; } - quat1 = (QuaternionObject*)q1; quat2 = (QuaternionObject*)q2; - for(x = 0; x < 4; x++) { - quat[x] = quat1->quat[x] + quat2->quat[x]; - } + if(!BaseMath_ReadCallback(quat1) || !BaseMath_ReadCallback(quat2)) + return NULL; - return newQuaternionObject(quat, Py_NEW); + QuatAdd(quat, quat1->quat, quat2->quat, 1.0f); + return newQuaternionObject(quat, Py_NEW, NULL); } //------------------------obj - obj------------------------------ //subtraction @@ -525,40 +536,45 @@ static PyObject *Quaternion_sub(PyObject * q1, PyObject * q2) quat1 = (QuaternionObject*)q1; quat2 = (QuaternionObject*)q2; + if(!BaseMath_ReadCallback(quat1) || !BaseMath_ReadCallback(quat2)) + return NULL; + for(x = 0; x < 4; x++) { quat[x] = quat1->quat[x] - quat2->quat[x]; } - return newQuaternionObject(quat, Py_NEW); + return newQuaternionObject(quat, Py_NEW, NULL); } //------------------------obj * obj------------------------------ //mulplication static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2) { - int x; float quat[4], scalar; - double dot = 0.0f; QuaternionObject *quat1 = NULL, *quat2 = NULL; VectorObject *vec = NULL; - quat1 = (QuaternionObject*)q1; - quat2 = (QuaternionObject*)q2; + if(QuaternionObject_Check(q1)) { + quat1 = (QuaternionObject*)q1; + if(!BaseMath_ReadCallback(quat1)) + return NULL; + } + if(QuaternionObject_Check(q2)) { + quat2 = (QuaternionObject*)q2; + if(!BaseMath_ReadCallback(quat2)) + return NULL; + } - if(QuaternionObject_Check(q1) && QuaternionObject_Check(q2)) { /* QUAT*QUAT (dot product) */ - for(x = 0; x < 4; x++) { - dot += quat1->quat[x] * quat1->quat[x]; - } - return PyFloat_FromDouble(dot); + if(quat1 && quat2) { /* QUAT*QUAT (dot product) */ + return PyFloat_FromDouble(QuatDot(quat1->quat, quat2->quat)); } /* the only case this can happen (for a supported type is "FLOAT*QUAT" ) */ if(!QuaternionObject_Check(q1)) { scalar= PyFloat_AsDouble(q1); if ((scalar == -1.0 && PyErr_Occurred())==0) { /* FLOAT*QUAT */ - for(x = 0; x < 4; x++) { - quat[x] = quat2->quat[x] * scalar; - } - return newQuaternionObject(quat, Py_NEW); + QUATCOPY(quat, quat2->quat); + QuatMulf(quat, scalar); + return newQuaternionObject(quat, Py_NEW, NULL); } PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: val * quat, val is not an acceptable type"); return NULL; @@ -570,15 +586,14 @@ static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2) PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: only 3D vector rotations currently supported\n"); return NULL; } - return quat_rotation((PyObject*)quat1, (PyObject*)vec); + return quat_rotation((PyObject*)quat1, (PyObject*)vec); /* vector updating done inside the func */ } scalar= PyFloat_AsDouble(q2); if ((scalar == -1.0 && PyErr_Occurred())==0) { /* QUAT*FLOAT */ - for(x = 0; x < 4; x++) { - quat[x] = quat1->quat[x] * scalar; - } - return newQuaternionObject(quat, Py_NEW); + QUATCOPY(quat, quat1->quat); + QuatMulf(quat, scalar); + return newQuaternionObject(quat, Py_NEW, NULL); } } @@ -596,6 +611,45 @@ static PySequenceMethods Quaternion_SeqMethods = { (ssizeobjargproc) Quaternion_ass_item, /* sq_ass_item */ (ssizessizeobjargproc) Quaternion_ass_slice, /* sq_ass_slice */ }; + +#if (PY_VERSION_HEX >= 0x03000000) +static PyNumberMethods Quaternion_NumMethods = { + (binaryfunc) Quaternion_add, /*nb_add*/ + (binaryfunc) Quaternion_sub, /*nb_subtract*/ + (binaryfunc) Quaternion_mul, /*nb_multiply*/ + 0, /*nb_remainder*/ + 0, /*nb_divmod*/ + 0, /*nb_power*/ + (unaryfunc) 0, /*nb_negative*/ + (unaryfunc) 0, /*tp_positive*/ + (unaryfunc) 0, /*tp_absolute*/ + (inquiry) 0, /*tp_bool*/ + (unaryfunc) 0, /*nb_invert*/ + 0, /*nb_lshift*/ + (binaryfunc)0, /*nb_rshift*/ + 0, /*nb_and*/ + 0, /*nb_xor*/ + 0, /*nb_or*/ + 0, /*nb_int*/ + 0, /*nb_reserved*/ + 0, /*nb_float*/ + 0, /* nb_inplace_add */ + 0, /* nb_inplace_subtract */ + 0, /* nb_inplace_multiply */ + 0, /* nb_inplace_remainder */ + 0, /* nb_inplace_power */ + 0, /* nb_inplace_lshift */ + 0, /* nb_inplace_rshift */ + 0, /* nb_inplace_and */ + 0, /* nb_inplace_xor */ + 0, /* nb_inplace_or */ + 0, /* nb_floor_divide */ + 0, /* nb_true_divide */ + 0, /* nb_inplace_floor_divide */ + 0, /* nb_inplace_true_divide */ + 0, /* nb_index */ +}; +#else static PyNumberMethods Quaternion_NumMethods = { (binaryfunc) Quaternion_add, /* __add__ */ (binaryfunc) Quaternion_sub, /* __sub__ */ @@ -620,76 +674,31 @@ static PyNumberMethods Quaternion_NumMethods = { (unaryfunc) 0, /* __float__ */ (unaryfunc) 0, /* __oct__ */ (unaryfunc) 0, /* __hex__ */ - }; - +#endif static PyObject *Quaternion_getAxis( QuaternionObject * self, void *type ) { - switch( (long)type ) { - case 'W': - return PyFloat_FromDouble(self->quat[0]); - case 'X': - return PyFloat_FromDouble(self->quat[1]); - case 'Y': - return PyFloat_FromDouble(self->quat[2]); - case 'Z': - return PyFloat_FromDouble(self->quat[3]); - } - - PyErr_SetString(PyExc_SystemError, "corrupt quaternion, cannot get axis"); - return NULL; + return Quaternion_item(self, GET_INT_FROM_POINTER(type)); } static int Quaternion_setAxis( QuaternionObject * self, PyObject * value, void * type ) { - float param= (float)PyFloat_AsDouble( value ); - - if (param==-1 && PyErr_Occurred()) { - PyErr_SetString( PyExc_TypeError, "expected a number for the vector axis" ); - return -1; - } - switch( (long)type ) { - case 'W': - self->quat[0]= param; - break; - case 'X': - self->quat[1]= param; - break; - case 'Y': - self->quat[2]= param; - break; - case 'Z': - self->quat[3]= param; - break; - } - - return 0; -} - -static PyObject *Quaternion_getWrapped( QuaternionObject * self, void *type ) -{ - if (self->wrapped == Py_WRAP) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; + return Quaternion_ass_item(self, GET_INT_FROM_POINTER(type), value); } static PyObject *Quaternion_getMagnitude( QuaternionObject * self, void *type ) { - double mag = 0.0; - int i; - for(i = 0; i < 4; i++) { - mag += self->quat[i] * self->quat[i]; - } - return PyFloat_FromDouble(sqrt(mag)); + return PyFloat_FromDouble(sqrt(QuatDot(self->quat, self->quat))); } static PyObject *Quaternion_getAngle( QuaternionObject * self, void *type ) { double ang = self->quat[0]; ang = 2 * (saacos(ang)); +#ifdef USE_MATHUTILS_DEG ang *= (180 / Py_PI); +#endif return PyFloat_FromDouble(ang); } @@ -710,7 +719,7 @@ static PyObject *Quaternion_getAxisVec( QuaternionObject * self, void *type ) EXPP_FloatsAreEqual(vec[2], 0.0f, 10) ){ vec[0] = 1.0f; } - return (PyObject *) newVectorObject(vec, 3, Py_NEW); + return (PyObject *) newVectorObject(vec, 3, Py_NEW, NULL); } @@ -721,19 +730,19 @@ static PyGetSetDef Quaternion_getseters[] = { {"w", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion W value", - (void *)'W'}, + (void *)0}, {"x", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion X axis", - (void *)'X'}, + (void *)1}, {"y", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion Y axis", - (void *)'Y'}, + (void *)2}, {"z", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion Z axis", - (void *)'Z'}, + (void *)3}, {"magnitude", (getter)Quaternion_getMagnitude, (setter)NULL, "Size of the quaternion", @@ -747,9 +756,14 @@ static PyGetSetDef Quaternion_getseters[] = { "quaternion axis as a vector", NULL}, {"wrapped", - (getter)Quaternion_getWrapped, (setter)NULL, + (getter)BaseMathObject_getWrapped, (setter)NULL, "True when this wraps blenders internal data", NULL}, + {"__owner__", + (getter)BaseMathObject_getOwner, (setter)NULL, + "Read only owner for vectors that depend on another object", + NULL}, + {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; @@ -766,7 +780,7 @@ PyTypeObject quaternion_Type = { "quaternion", //tp_name sizeof(QuaternionObject), //tp_basicsize 0, //tp_itemsize - (destructor)Quaternion_dealloc, //tp_dealloc + (destructor)BaseMathObject_dealloc, //tp_dealloc 0, //tp_print 0, //tp_getattr 0, //tp_setattr @@ -781,8 +795,8 @@ PyTypeObject quaternion_Type = { 0, //tp_getattro 0, //tp_setattro 0, //tp_as_buffer - Py_TPFLAGS_DEFAULT, //tp_flags - QuaternionObject_doc, //tp_doc + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags + 0, //tp_doc 0, //tp_traverse 0, //tp_clear (richcmpfunc)Quaternion_richcmpr, //tp_richcompare @@ -815,29 +829,26 @@ PyTypeObject quaternion_Type = { (i.e. it was allocated elsewhere by MEM_mallocN()) pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON (i.e. it must be created here with PyMEM_malloc())*/ -PyObject *newQuaternionObject(float *quat, int type) +PyObject *newQuaternionObject(float *quat, int type, PyTypeObject *base_type) { QuaternionObject *self; - int x; - self = PyObject_NEW(QuaternionObject, &quaternion_Type); - self->data.blend_data = NULL; - self->data.py_data = NULL; + if(base_type) self = base_type->tp_alloc(base_type, 0); + else self = PyObject_NEW(QuaternionObject, &quaternion_Type); + + /* init callbacks as NULL */ + self->cb_user= NULL; + self->cb_type= self->cb_subtype= 0; if(type == Py_WRAP){ - self->data.blend_data = quat; - self->quat = self->data.blend_data; + self->quat = quat; self->wrapped = Py_WRAP; }else if (type == Py_NEW){ - self->data.py_data = PyMem_Malloc(4 * sizeof(float)); - self->quat = self->data.py_data; + self->quat = PyMem_Malloc(4 * sizeof(float)); if(!quat) { //new empty - Quaternion_Identity(self); - Py_DECREF(self); + QuatOne(self->quat); }else{ - for(x = 0; x < 4; x++){ - self->quat[x] = quat[x]; - } + QUATCOPY(self->quat, quat); } self->wrapped = Py_NEW; }else{ //bad type @@ -845,3 +856,16 @@ PyObject *newQuaternionObject(float *quat, int type) } return (PyObject *) self; } + +PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype) +{ + QuaternionObject *self= (QuaternionObject *)newQuaternionObject(NULL, Py_NEW, NULL); + if(self) { + Py_INCREF(cb_user); + self->cb_user= cb_user; + self->cb_type= (unsigned char)cb_type; + self->cb_subtype= (unsigned char)cb_subtype; + } + + return (PyObject *)self; +} diff --git a/source/blender/python/generic/quat.h b/source/blender/python/generic/quat.h index cfb50e4dbe1..a7cfb7898b1 100644 --- a/source/blender/python/generic/quat.h +++ b/source/blender/python/generic/quat.h @@ -1,5 +1,5 @@ /* - * $Id: quat.h 20332 2009-05-22 03:22:56Z campbellbarton $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -35,17 +35,17 @@ #include "../intern/bpy_compat.h" extern PyTypeObject quaternion_Type; +#define QuaternionObject_Check(_v) PyObject_TypeCheck((_v), &quaternion_Type) -#define QuaternionObject_Check(v) (Py_TYPE(v) == &quaternion_Type) - -typedef struct { +typedef struct { /* keep aligned with BaseMathObject in Mathutils.h */ PyObject_VAR_HEAD - struct{ - float *py_data; //python managed - float *blend_data; //blender managed - }data; - float *quat; //1D array of data (alias) - int wrapped; //is wrapped data? + float *quat; /* 1D array of data (alias) */ + PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */ + unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */ + unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */ + unsigned char wrapped; /* wrapped data type? */ + /* end BaseMathObject */ + } QuaternionObject; /*struct data contains a pointer to the actual data that the @@ -54,6 +54,7 @@ be stored in py_data) or be a wrapper for data allocated through blender (stored in blend_data). This is an either/or struct not both*/ //prototypes -PyObject *newQuaternionObject( float *quat, int type ); +PyObject *newQuaternionObject( float *quat, int type, PyTypeObject *base_type); +PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype); #endif /* EXPP_quat_h */ diff --git a/source/blender/python/generic/vector.c b/source/blender/python/generic/vector.c index 562413c6967..b4c74787e05 100644 --- a/source/blender/python/generic/vector.c +++ b/source/blender/python/generic/vector.c @@ -1,5 +1,5 @@ /* - * $Id: vector.c 20332 2009-05-22 03:22:56Z campbellbarton $ + * $Id$ * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -39,19 +39,8 @@ #define SWIZZLE_VALID_AXIS 0x4 #define SWIZZLE_AXIS 0x3 -/*-------------------------DOC STRINGS ---------------------------*/ -static char Vector_Zero_doc[] = "() - set all values in the vector to 0"; -static char Vector_Normalize_doc[] = "() - normalize the vector"; -static char Vector_Negate_doc[] = "() - changes vector to it's additive inverse"; -static char Vector_Resize2D_doc[] = "() - resize a vector to [x,y]"; -static char Vector_Resize3D_doc[] = "() - resize a vector to [x,y,z]"; -static char Vector_Resize4D_doc[] = "() - resize a vector to [x,y,z,w]"; -static char Vector_ToTrackQuat_doc[] = "(track, up) - extract a quaternion from the vector and the track and up axis"; -static char Vector_Reflect_doc[] = "(mirror) - return a vector reflected on the mirror normal"; -static char Vector_Cross_doc[] = "(other) - return the cross product between this vector and another"; -static char Vector_Dot_doc[] = "(other) - return the dot product between this vector and another"; -static char Vector_copy_doc[] = "() - return a copy of the vector"; -static char Vector_swizzle_doc[] = "Swizzle: Get or set axes in specified order"; +static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat); /* utility func */ + /*-----------------------METHOD DEFINITIONS ----------------------*/ static PyObject *Vector_Zero( VectorObject * self ); static PyObject *Vector_Normalize( VectorObject * self ); @@ -60,24 +49,24 @@ static PyObject *Vector_Resize2D( VectorObject * self ); static PyObject *Vector_Resize3D( VectorObject * self ); static PyObject *Vector_Resize4D( VectorObject * self ); static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args ); -static PyObject *Vector_Reflect( VectorObject * self, PyObject * value ); +static PyObject *Vector_Reflect( VectorObject *self, VectorObject *value ); static PyObject *Vector_Cross( VectorObject * self, VectorObject * value ); static PyObject *Vector_Dot( VectorObject * self, VectorObject * value ); static PyObject *Vector_copy( VectorObject * self ); static struct PyMethodDef Vector_methods[] = { - {"zero", (PyCFunction) Vector_Zero, METH_NOARGS, Vector_Zero_doc}, - {"normalize", (PyCFunction) Vector_Normalize, METH_NOARGS, Vector_Normalize_doc}, - {"negate", (PyCFunction) Vector_Negate, METH_NOARGS, Vector_Negate_doc}, - {"resize2D", (PyCFunction) Vector_Resize2D, METH_NOARGS, Vector_Resize2D_doc}, - {"resize3D", (PyCFunction) Vector_Resize3D, METH_NOARGS, Vector_Resize2D_doc}, - {"resize4D", (PyCFunction) Vector_Resize4D, METH_NOARGS, Vector_Resize2D_doc}, - {"toTrackQuat", ( PyCFunction ) Vector_ToTrackQuat, METH_VARARGS, Vector_ToTrackQuat_doc}, - {"reflect", ( PyCFunction ) Vector_Reflect, METH_O, Vector_Reflect_doc}, - {"cross", ( PyCFunction ) Vector_Cross, METH_O, Vector_Dot_doc}, - {"dot", ( PyCFunction ) Vector_Dot, METH_O, Vector_Cross_doc}, - {"copy", (PyCFunction) Vector_copy, METH_NOARGS, Vector_copy_doc}, - {"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, Vector_copy_doc}, + {"zero", (PyCFunction) Vector_Zero, METH_NOARGS, NULL}, + {"normalize", (PyCFunction) Vector_Normalize, METH_NOARGS, NULL}, + {"negate", (PyCFunction) Vector_Negate, METH_NOARGS, NULL}, + {"resize2D", (PyCFunction) Vector_Resize2D, METH_NOARGS, NULL}, + {"resize3D", (PyCFunction) Vector_Resize3D, METH_NOARGS, NULL}, + {"resize4D", (PyCFunction) Vector_Resize4D, METH_NOARGS, NULL}, + {"toTrackQuat", ( PyCFunction ) Vector_ToTrackQuat, METH_VARARGS, NULL}, + {"reflect", ( PyCFunction ) Vector_Reflect, METH_O, NULL}, + {"cross", ( PyCFunction ) Vector_Cross, METH_O, NULL}, + {"dot", ( PyCFunction ) Vector_Dot, METH_O, NULL}, + {"copy", (PyCFunction) Vector_copy, METH_NOARGS, NULL}, + {"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, NULL}, {NULL, NULL, 0, NULL} }; @@ -102,7 +91,7 @@ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } } else if (size == 0) { //returns a new empty 3d vector - return newVectorObject(NULL, 3, Py_NEW); + return newVectorObject(NULL, 3, Py_NEW, type); } else { listObject = args; } @@ -129,7 +118,7 @@ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds) vec[i]= f; Py_DECREF(v); } - return newVectorObject(vec, size, Py_NEW); + return newVectorObject(vec, size, Py_NEW, type); } /*-----------------------------METHODS---------------------------- */ @@ -141,6 +130,8 @@ static PyObject *Vector_Zero(VectorObject * self) for(i = 0; i < self->size; i++) { self->vec[i] = 0.0f; } + + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject*)self; } @@ -151,6 +142,9 @@ static PyObject *Vector_Normalize(VectorObject * self) int i; float norm = 0.0f; + if(!BaseMath_ReadCallback(self)) + return NULL; + for(i = 0; i < self->size; i++) { norm += self->vec[i] * self->vec[i]; } @@ -158,6 +152,8 @@ static PyObject *Vector_Normalize(VectorObject * self) for(i = 0; i < self->size; i++) { self->vec[i] /= norm; } + + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject*)self; } @@ -171,6 +167,11 @@ static PyObject *Vector_Resize2D(VectorObject * self) PyErr_SetString(PyExc_TypeError, "vector.resize2d(): cannot resize wrapped data - only python vectors\n"); return NULL; } + if(self->cb_user) { + PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize a vector that has an owner"); + return NULL; + } + self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 2)); if(self->vec == NULL) { PyErr_SetString(PyExc_MemoryError, "vector.resize2d(): problem allocating pointer space\n\n"); @@ -189,6 +190,11 @@ static PyObject *Vector_Resize3D(VectorObject * self) PyErr_SetString(PyExc_TypeError, "vector.resize3d(): cannot resize wrapped data - only python vectors\n"); return NULL; } + if(self->cb_user) { + PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize a vector that has an owner"); + return NULL; + } + self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 3)); if(self->vec == NULL) { PyErr_SetString(PyExc_MemoryError, "vector.resize3d(): problem allocating pointer space\n\n"); @@ -210,6 +216,11 @@ static PyObject *Vector_Resize4D(VectorObject * self) PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize wrapped data - only python vectors"); return NULL; } + if(self->cb_user) { + PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize a vector that has an owner"); + return NULL; + } + self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 4)); if(self->vec == NULL) { PyErr_SetString(PyExc_MemoryError, "vector.resize4d(): problem allocating pointer space\n\n"); @@ -241,6 +252,9 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args ) PyErr_SetString( PyExc_TypeError, "only for 3D vectors\n" ); return NULL; } + + if(!BaseMath_ReadCallback(self)) + return NULL; if (strack) { if (strlen(strack) == 2) { @@ -335,16 +349,15 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args ) vectoquat(vec, track, up, quat); - return newQuaternionObject(quat, Py_NEW); + return newQuaternionObject(quat, Py_NEW, NULL); } /*----------------------------Vector.reflect(mirror) ---------------------- return a reflected vector on the mirror normal ((2 * DotVecs(vec, mirror)) * mirror) - vec using arithb.c would be nice here */ -static PyObject *Vector_Reflect( VectorObject * self, PyObject * value ) +static PyObject *Vector_Reflect( VectorObject * self, VectorObject * value ) { - VectorObject *mirrvec; float mirror[3]; float vec[3]; float reflect[4] = {0.0f, 0.0f, 0.0f, 0.0f}; @@ -358,11 +371,13 @@ static PyObject *Vector_Reflect( VectorObject * self, PyObject * value ) PyErr_SetString( PyExc_TypeError, "vec.reflect(value): expected a vector argument" ); return NULL; } - mirrvec = (VectorObject *)value; - mirror[0] = mirrvec->vec[0]; - mirror[1] = mirrvec->vec[1]; - if (mirrvec->size > 2) mirror[2] = mirrvec->vec[2]; + if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value)) + return NULL; + + mirror[0] = value->vec[0]; + mirror[1] = value->vec[1]; + if (value->size > 2) mirror[2] = value->vec[2]; else mirror[2] = 0.0; /* normalize, whos idea was it not to use arithb.c? :-/ */ @@ -386,7 +401,7 @@ static PyObject *Vector_Reflect( VectorObject * self, PyObject * value ) reflect[1] = (dot2 * mirror[1]) - vec[1]; reflect[2] = (dot2 * mirror[2]) - vec[2]; - return newVectorObject(reflect, self->size, Py_NEW); + return newVectorObject(reflect, self->size, Py_NEW, NULL); } static PyObject *Vector_Cross( VectorObject * self, VectorObject * value ) @@ -403,7 +418,10 @@ static PyObject *Vector_Cross( VectorObject * self, VectorObject * value ) return NULL; } - vecCross = (VectorObject *)newVectorObject(NULL, 3, Py_NEW); + if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value)) + return NULL; + + vecCross = (VectorObject *)newVectorObject(NULL, 3, Py_NEW, NULL); Crossf(vecCross->vec, self->vec, value->vec); return (PyObject *)vecCross; } @@ -423,6 +441,9 @@ static PyObject *Vector_Dot( VectorObject * self, VectorObject * value ) return NULL; } + if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value)) + return NULL; + for(x = 0; x < self->size; x++) { dot += self->vec[x] * value->vec[x]; } @@ -433,18 +454,10 @@ static PyObject *Vector_Dot( VectorObject * self, VectorObject * value ) return a copy of the vector */ static PyObject *Vector_copy(VectorObject * self) { - return newVectorObject(self->vec, self->size, Py_NEW); -} - -/*----------------------------dealloc()(internal) ---------------- - free the py_object */ -static void Vector_dealloc(VectorObject * self) -{ - /* only free non wrapped */ - if(self->wrapped != Py_WRAP){ - PyMem_Free(self->vec); - } - PyObject_DEL(self); + if(!BaseMath_ReadCallback(self)) + return NULL; + + return newVectorObject(self->vec, self->size, Py_NEW, Py_TYPE(self)); } /*----------------------------print object (internal)------------- @@ -454,6 +467,9 @@ static PyObject *Vector_repr(VectorObject * self) int i; char buffer[48], str[1024]; + if(!BaseMath_ReadCallback(self)) + return NULL; + BLI_strncpy(str,"[",1024); for(i = 0; i < self->size; i++){ if(i < (self->size - 1)){ @@ -479,11 +495,16 @@ static int Vector_len(VectorObject * self) sequence accessor (get)*/ static PyObject *Vector_item(VectorObject * self, int i) { + if(i<0) i= self->size-i; + if(i < 0 || i >= self->size) { PyErr_SetString(PyExc_IndexError,"vector[index]: out of range\n"); return NULL; } + if(!BaseMath_ReadIndexCallback(self, i)) + return NULL; + return PyFloat_FromDouble(self->vec[i]); } @@ -497,11 +518,16 @@ static int Vector_ass_item(VectorObject * self, int i, PyObject * ob) return -1; } + if(i<0) i= self->size-i; + if(i < 0 || i >= self->size){ PyErr_SetString(PyExc_IndexError, "vector[index] = x: assignment index out of range\n"); return -1; } self->vec[i] = scalar; + + if(!BaseMath_WriteIndexCallback(self, i)) + return -1; return 0; } @@ -512,6 +538,9 @@ static PyObject *Vector_slice(VectorObject * self, int begin, int end) PyObject *list = NULL; int count; + if(!BaseMath_ReadCallback(self)) + return NULL; + CLAMP(begin, 0, self->size); if (end<0) end= self->size+end+1; CLAMP(end, 0, self->size); @@ -534,6 +563,9 @@ static int Vector_ass_slice(VectorObject * self, int begin, int end, float vec[4], scalar; PyObject *v; + if(!BaseMath_ReadCallback(self)) + return -1; + CLAMP(begin, 0, self->size); if (end<0) end= self->size+end+1; CLAMP(end, 0, self->size); @@ -566,6 +598,10 @@ static int Vector_ass_slice(VectorObject * self, int begin, int end, for(y = 0; y < size; y++){ self->vec[begin + y] = vec[y]; } + + if(!BaseMath_WriteCallback(self)) + return -1; + return 0; } /*------------------------NUMERIC PROTOCOLS---------------------- @@ -586,6 +622,10 @@ static PyObject *Vector_add(PyObject * v1, PyObject * v2) /* make sure v1 is always the vector */ if (vec1 && vec2 ) { + + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2)) + return NULL; + /*VECTOR + VECTOR*/ if(vec1->size != vec2->size) { PyErr_SetString(PyExc_AttributeError, "Vector addition: vectors must have the same dimensions for this operation\n"); @@ -594,7 +634,7 @@ static PyObject *Vector_add(PyObject * v1, PyObject * v2) for(i = 0; i < vec1->size; i++) { vec[i] = vec1->vec[i] + vec2->vec[i]; } - return newVectorObject(vec, vec1->size, Py_NEW); + return newVectorObject(vec, vec1->size, Py_NEW, NULL); } PyErr_SetString(PyExc_AttributeError, "Vector addition: arguments not valid for this operation....\n"); @@ -617,6 +657,10 @@ static PyObject *Vector_iadd(PyObject * v1, PyObject * v2) /* make sure v1 is always the vector */ if (vec1 && vec2 ) { + + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2)) + return NULL; + /*VECTOR + VECTOR*/ if(vec1->size != vec2->size) { PyErr_SetString(PyExc_AttributeError, "Vector addition: vectors must have the same dimensions for this operation\n"); @@ -629,6 +673,7 @@ static PyObject *Vector_iadd(PyObject * v1, PyObject * v2) return v1; } + BaseMath_WriteCallback(vec1); PyErr_SetString(PyExc_AttributeError, "Vector addition: arguments not valid for this operation....\n"); return NULL; } @@ -648,6 +693,9 @@ static PyObject *Vector_sub(PyObject * v1, PyObject * v2) vec1 = (VectorObject*)v1; vec2 = (VectorObject*)v2; + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2)) + return NULL; + if(vec1->size != vec2->size) { PyErr_SetString(PyExc_AttributeError, "Vector subtraction: vectors must have the same dimensions for this operation\n"); return NULL; @@ -656,14 +704,14 @@ static PyObject *Vector_sub(PyObject * v1, PyObject * v2) vec[i] = vec1->vec[i] - vec2->vec[i]; } - return newVectorObject(vec, vec1->size, Py_NEW); + return newVectorObject(vec, vec1->size, Py_NEW, NULL); } /*------------------------obj -= obj------------------------------ subtraction*/ static PyObject *Vector_isub(PyObject * v1, PyObject * v2) { - int i, size; + int i; VectorObject *vec1 = NULL, *vec2 = NULL; if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { @@ -677,12 +725,15 @@ static PyObject *Vector_isub(PyObject * v1, PyObject * v2) PyErr_SetString(PyExc_AttributeError, "Vector subtraction: vectors must have the same dimensions for this operation\n"); return NULL; } + + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2)) + return NULL; - size = vec1->size; for(i = 0; i < vec1->size; i++) { vec1->vec[i] = vec1->vec[i] - vec2->vec[i]; } + BaseMath_WriteCallback(vec1); Py_INCREF( v1 ); return v1; } @@ -694,11 +745,17 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2) VectorObject *vec1 = NULL, *vec2 = NULL; float scalar; - if VectorObject_Check(v1) + if VectorObject_Check(v1) { vec1= (VectorObject *)v1; - - if VectorObject_Check(v2) + if(!BaseMath_ReadCallback(vec1)) + return NULL; + } + if VectorObject_Check(v2) { vec2= (VectorObject *)v2; + if(!BaseMath_ReadCallback(vec2)) + return NULL; + } + /* make sure v1 is always the vector */ if (vec1 && vec2 ) { @@ -727,7 +784,8 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2) /* VEC * MATRIX */ return row_vector_multiplication(vec1, (MatrixObject*)v2); } else if (QuaternionObject_Check(v2)) { - QuaternionObject *quat = (QuaternionObject*)v2; + QuaternionObject *quat = (QuaternionObject*)v2; /* quat_rotation validates */ + if(vec1->size != 3) { PyErr_SetString(PyExc_TypeError, "Vector multiplication: only 3D vector rotations (with quats) currently supported\n"); return NULL; @@ -741,7 +799,7 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2) for(i = 0; i < vec1->size; i++) { vec[i] = vec1->vec[i] * scalar; } - return newVectorObject(vec, vec1->size, Py_NEW); + return newVectorObject(vec, vec1->size, Py_NEW, NULL); } @@ -757,6 +815,9 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2) int i; float scalar; + if(!BaseMath_ReadCallback(vec)) + return NULL; + /* only support vec*=float and vec*=mat vec*=vec result is a float so that wont work */ if (MatrixObject_Check(v2)) { @@ -764,6 +825,9 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2) int x,y, size = vec->size; MatrixObject *mat= (MatrixObject*)v2; + if(!BaseMath_ReadCallback(mat)) + return NULL; + if(mat->colSize != size){ if(mat->rowSize == 4 && vec->size != 3){ PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same"); @@ -787,22 +851,21 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2) } vec->vec[i] = (float)dot; } - Py_INCREF( v1 ); - return v1; } else if (((scalar= PyFloat_AsDouble(v2)) == -1.0 && PyErr_Occurred())==0) { /* VEC*=FLOAT */ for(i = 0; i < vec->size; i++) { vec->vec[i] *= scalar; } - - Py_INCREF( v1 ); - return v1; - + } + else { + PyErr_SetString(PyExc_TypeError, "Vector multiplication: arguments not acceptable for this operation\n"); + return NULL; } - PyErr_SetString(PyExc_TypeError, "Vector multiplication: arguments not acceptable for this operation\n"); - return NULL; + BaseMath_WriteCallback(vec); + Py_INCREF( v1 ); + return v1; } /*------------------------obj / obj------------------------------ @@ -819,6 +882,9 @@ static PyObject *Vector_div(PyObject * v1, PyObject * v2) } vec1 = (VectorObject*)v1; /* vector */ + if(!BaseMath_ReadCallback(vec1)) + return NULL; + scalar = (float)PyFloat_AsDouble(v2); if(scalar== -1.0f && PyErr_Occurred()) { /* parsed item not a number */ PyErr_SetString(PyExc_TypeError, "Vector division: Vector must be divided by a float\n"); @@ -833,7 +899,7 @@ static PyObject *Vector_div(PyObject * v1, PyObject * v2) for(i = 0; i < vec1->size; i++) { vec[i] = vec1->vec[i] / scalar; } - return newVectorObject(vec, vec1->size, Py_NEW); + return newVectorObject(vec, vec1->size, Py_NEW, NULL); } /*------------------------obj /= obj------------------------------ @@ -842,14 +908,10 @@ static PyObject *Vector_idiv(PyObject * v1, PyObject * v2) { int i; float scalar; - VectorObject *vec1 = NULL; + VectorObject *vec1 = (VectorObject*)v1; - /*if(!VectorObject_Check(v1)) { - PyErr_SetString(PyExc_TypeError, "Vector division: Vector must be divided by a float\n"); - return -1; - }*/ - - vec1 = (VectorObject*)v1; /* vector */ + if(!BaseMath_ReadCallback(vec1)) + return NULL; scalar = (float)PyFloat_AsDouble(v2); if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */ @@ -864,6 +926,9 @@ static PyObject *Vector_idiv(PyObject * v1, PyObject * v2) for(i = 0; i < vec1->size; i++) { vec1->vec[i] /= scalar; } + + BaseMath_WriteCallback(vec1); + Py_INCREF( v1 ); return v1; } @@ -874,15 +939,17 @@ static PyObject *Vector_neg(VectorObject *self) { int i; float vec[4]; + + if(!BaseMath_ReadCallback(self)) + return NULL; + for(i = 0; i < self->size; i++){ vec[i] = -self->vec[i]; } - return newVectorObject(vec, self->size, Py_NEW); + return newVectorObject(vec, self->size, Py_NEW, Py_TYPE(self)); } -/*------------------------tp_doc*/ -static char VectorObject_doc[] = "This is a wrapper for vector objects."; /*------------------------vec_magnitude_nosqrt (internal) - for comparing only */ static double vec_magnitude_nosqrt(float *data, int size) { @@ -919,6 +986,9 @@ static PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int compa vecA = (VectorObject*)objectA; vecB = (VectorObject*)objectB; + if(!BaseMath_ReadCallback(vecA) || !BaseMath_ReadCallback(vecB)) + return NULL; + if (vecA->size != vecB->size){ if (comparison_type == Py_NE){ Py_RETURN_TRUE; @@ -981,17 +1051,139 @@ static PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int compa Py_RETURN_FALSE; } } + /*-----------------PROTCOL DECLARATIONS--------------------------*/ static PySequenceMethods Vector_SeqMethods = { (inquiry) Vector_len, /* sq_length */ (binaryfunc) 0, /* sq_concat */ - (ssizeargfunc) 0, /* sq_repeat */ + (ssizeargfunc) 0, /* sq_repeat */ (ssizeargfunc) Vector_item, /* sq_item */ - (ssizessizeargfunc) Vector_slice, /* sq_slice */ +#if (PY_VERSION_HEX < 0x03000000) + (ssizessizeargfunc) Vector_slice, /* sq_slice */ /* PY2 ONLY */ +#else + NULL, +#endif (ssizeobjargproc) Vector_ass_item, /* sq_ass_item */ - (ssizessizeobjargproc) Vector_ass_slice, /* sq_ass_slice */ +#if (PY_VERSION_HEX < 0x03000000) + (ssizessizeobjargproc) Vector_ass_slice, /* sq_ass_slice */ /* PY2 ONLY */ +#else + NULL, +#endif }; + + +#if (PY_VERSION_HEX >= 0x03000000) +static PyObject *Vector_subscript(VectorObject* self, PyObject* item) +{ + if (PyIndex_Check(item)) { + Py_ssize_t i; + i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) + return NULL; + if (i < 0) + i += self->size; + return Vector_item(self, i); + } else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx((PySliceObject*)item, self->size, &start, &stop, &step, &slicelength) < 0) + return NULL; + + if (slicelength <= 0) { + return PyList_New(0); + } + else if (step == 1) { + return Vector_slice(self, start, stop); + } + else { + PyErr_SetString(PyExc_TypeError, "slice steps not supported with vectors"); + return NULL; + } + } + else { + PyErr_Format(PyExc_TypeError, + "vector indices must be integers, not %.200s", + item->ob_type->tp_name); + return NULL; + } +} + +static int Vector_ass_subscript(VectorObject* self, PyObject* item, PyObject* value) +{ + if (PyIndex_Check(item)) { + Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) + return -1; + if (i < 0) + i += self->size; + return Vector_ass_item(self, i, value); + } + else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx((PySliceObject*)item, self->size, &start, &stop, &step, &slicelength) < 0) + return -1; + + if (step == 1) + return Vector_ass_slice(self, start, stop, value); + else { + PyErr_SetString(PyExc_TypeError, "slice steps not supported with vectors"); + return -1; + } + } + else { + PyErr_Format(PyExc_TypeError, + "vector indices must be integers, not %.200s", + item->ob_type->tp_name); + return -1; + } +} + +static PyMappingMethods Vector_AsMapping = { + (lenfunc)Vector_len, + (binaryfunc)Vector_subscript, + (objobjargproc)Vector_ass_subscript +}; +#endif /* (PY_VERSION_HEX >= 0x03000000) */ +#if (PY_VERSION_HEX >= 0x03000000) +static PyNumberMethods Vector_NumMethods = { + (binaryfunc) Vector_add, /*nb_add*/ + (binaryfunc) Vector_sub, /*nb_subtract*/ + (binaryfunc) Vector_mul, /*nb_multiply*/ + 0, /*nb_remainder*/ + 0, /*nb_divmod*/ + 0, /*nb_power*/ + (unaryfunc) Vector_neg, /*nb_negative*/ + (unaryfunc) 0, /*tp_positive*/ + (unaryfunc) 0, /*tp_absolute*/ + (inquiry) 0, /*tp_bool*/ + (unaryfunc) 0, /*nb_invert*/ + 0, /*nb_lshift*/ + (binaryfunc)0, /*nb_rshift*/ + 0, /*nb_and*/ + 0, /*nb_xor*/ + 0, /*nb_or*/ + 0, /*nb_int*/ + 0, /*nb_reserved*/ + 0, /*nb_float*/ + Vector_iadd, /* nb_inplace_add */ + Vector_isub, /* nb_inplace_subtract */ + Vector_imul, /* nb_inplace_multiply */ + 0, /* nb_inplace_remainder */ + 0, /* nb_inplace_power */ + 0, /* nb_inplace_lshift */ + 0, /* nb_inplace_rshift */ + 0, /* nb_inplace_and */ + 0, /* nb_inplace_xor */ + 0, /* nb_inplace_or */ + 0, /* nb_floor_divide */ + Vector_div, /* nb_true_divide */ + 0, /* nb_inplace_floor_divide */ + Vector_idiv, /* nb_inplace_true_divide */ + 0, /* nb_index */ +}; +#else static PyNumberMethods Vector_NumMethods = { (binaryfunc) Vector_add, /* __add__ */ (binaryfunc) Vector_sub, /* __sub__ */ @@ -1037,6 +1229,8 @@ static PyNumberMethods Vector_NumMethods = { (binaryfunc) NULL, /*__ifloordiv__*/ (binaryfunc) NULL, /*__itruediv__*/ }; +#endif + /*------------------PY_OBECT DEFINITION--------------------------*/ /* @@ -1045,66 +1239,12 @@ static PyNumberMethods Vector_NumMethods = { static PyObject *Vector_getAxis( VectorObject * self, void *type ) { - switch( (long)type ) { - case 'X': /* these are backwards, but that how it works */ - return PyFloat_FromDouble(self->vec[0]); - case 'Y': - return PyFloat_FromDouble(self->vec[1]); - case 'Z': /* these are backwards, but that how it works */ - if(self->size < 3) { - PyErr_SetString(PyExc_AttributeError, "vector.z: error, cannot get this axis for a 2D vector\n"); - return NULL; - } - else { - return PyFloat_FromDouble(self->vec[2]); - } - case 'W': - if(self->size < 4) { - PyErr_SetString(PyExc_AttributeError, "vector.w: error, cannot get this axis for a 3D vector\n"); - return NULL; - } - - return PyFloat_FromDouble(self->vec[3]); - default: - { - PyErr_SetString( PyExc_RuntimeError, "undefined type in Vector_getAxis" ); - return NULL; - } - } + return Vector_item(self, GET_INT_FROM_POINTER(type)); } static int Vector_setAxis( VectorObject * self, PyObject * value, void * type ) { - float param= (float)PyFloat_AsDouble( value ); - - if (param==-1 && PyErr_Occurred()) { - PyErr_SetString( PyExc_TypeError, "expected a number for the vector axis" ); - return -1; - } - switch( (long)type ) { - case 'X': /* these are backwards, but that how it works */ - self->vec[0]= param; - break; - case 'Y': - self->vec[1]= param; - break; - case 'Z': /* these are backwards, but that how it works */ - if(self->size < 3) { - PyErr_SetString(PyExc_AttributeError, "vector.z: error, cannot get this axis for a 2D vector\n"); - return -1; - } - self->vec[2]= param; - break; - case 'W': - if(self->size < 4) { - PyErr_SetString(PyExc_AttributeError, "vector.w: error, cannot get this axis for a 3D vector\n"); - return -1; - } - self->vec[3]= param; - break; - } - - return 0; + return Vector_ass_item(self, GET_INT_FROM_POINTER(type), value); } /* vector.length */ @@ -1113,6 +1253,9 @@ static PyObject *Vector_getLength( VectorObject * self, void *type ) double dot = 0.0f; int i; + if(!BaseMath_ReadCallback(self)) + return NULL; + for(i = 0; i < self->size; i++){ dot += (self->vec[i] * self->vec[i]); } @@ -1124,6 +1267,9 @@ static int Vector_setLength( VectorObject * self, PyObject * value ) double dot = 0.0f, param; int i; + if(!BaseMath_ReadCallback(self)) + return -1; + param= PyFloat_AsDouble( value ); if(param==-1.0 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "length must be set to a number"); @@ -1159,18 +1305,11 @@ static int Vector_setLength( VectorObject * self, PyObject * value ) self->vec[i]= self->vec[i] / (float)dot; } + BaseMath_WriteCallback(self); /* checked alredy */ + return 0; } -static PyObject *Vector_getWrapped( VectorObject * self, void *type ) -{ - if (self->wrapped == Py_WRAP) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - - /* Get a new Vector according to the provided swizzle. This function has little error checking, as we are in control of the inputs: the closure is set by us in Vector_createSwizzleGetSeter. */ @@ -1181,6 +1320,9 @@ static PyObject *Vector_getSwizzle(VectorObject * self, void *closure) float vec[MAX_DIMENSIONS]; unsigned int swizzleClosure; + if(!BaseMath_ReadCallback(self)) + return NULL; + /* Unpack the axes from the closure into an array. */ axisA = 0; swizzleClosure = (unsigned int) closure; @@ -1192,7 +1334,7 @@ static PyObject *Vector_getSwizzle(VectorObject * self, void *closure) axisA++; } - return newVectorObject(vec, axisA, Py_NEW); + return newVectorObject(vec, axisA, Py_NEW, Py_TYPE(self)); } /* Set the items of this vector using a swizzle. @@ -1218,6 +1360,9 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur float vecTemp[MAX_DIMENSIONS]; + if(!BaseMath_ReadCallback(self)) + return -1; + /* Check that the closure can be used with this vector: even 2D vectors have swizzles defined for axes z and w, but they would be invalid. */ swizzleClosure = (unsigned int) closure; @@ -1247,7 +1392,7 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur axisB++; } memcpy(self->vec, vecTemp, axisB * sizeof(float)); - return 0; + /* continue with BaseMathObject_WriteCallback at the end */ } else if (PyList_Check(value)) { @@ -1273,7 +1418,7 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur axisB++; } memcpy(self->vec, vecTemp, axisB * sizeof(float)); - return 0; + /* continue with BaseMathObject_WriteCallback at the end */ } else if (((scalarVal = (float)PyFloat_AsDouble(value)) == -1.0 && PyErr_Occurred())==0) { @@ -1286,13 +1431,17 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS; } - return 0; + /* continue with BaseMathObject_WriteCallback at the end */ } - else - { + else { PyErr_SetString( PyExc_TypeError, "Expected a Vector, list or scalar value." ); return -1; } + + if(!BaseMath_WriteCallback(vecVal)) + return -1; + else + return 0; } /*****************************************************************************/ @@ -1302,19 +1451,19 @@ static PyGetSetDef Vector_getseters[] = { {"x", (getter)Vector_getAxis, (setter)Vector_setAxis, "Vector X axis", - (void *)'X'}, + (void *)0}, {"y", (getter)Vector_getAxis, (setter)Vector_setAxis, "Vector Y axis", - (void *)'Y'}, + (void *)1}, {"z", (getter)Vector_getAxis, (setter)Vector_setAxis, "Vector Z axis", - (void *)'Z'}, + (void *)2}, {"w", (getter)Vector_getAxis, (setter)Vector_setAxis, "Vector Z axis", - (void *)'W'}, + (void *)3}, {"length", (getter)Vector_getLength, (setter)Vector_setLength, "Vector Length", @@ -1324,347 +1473,351 @@ static PyGetSetDef Vector_getseters[] = { "Vector Length", NULL}, {"wrapped", - (getter)Vector_getWrapped, (setter)NULL, + (getter)BaseMathObject_getWrapped, (setter)NULL, "True when this wraps blenders internal data", NULL}, + {"__owner__", + (getter)BaseMathObject_getOwner, (setter)NULL, + "Read only owner for vectors that depend on another object", + NULL}, /* autogenerated swizzle attrs, see python script below */ - {"xx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<." */ - "Blender Vector", /* char *tp_name; */ + "vector", /* char *tp_name; */ sizeof( VectorObject ), /* int tp_basicsize; */ 0, /* tp_itemsize; For allocation */ /* Methods to implement standard operations */ - ( destructor ) Vector_dealloc,/* destructor tp_dealloc; */ + ( destructor ) BaseMathObject_dealloc,/* destructor tp_dealloc; */ NULL, /* printfunc tp_print; */ NULL, /* getattrfunc tp_getattr; */ NULL, /* setattrfunc tp_setattr; */ @@ -1744,7 +1897,11 @@ PyTypeObject vector_Type = { &Vector_NumMethods, /* PyNumberMethods *tp_as_number; */ &Vector_SeqMethods, /* PySequenceMethods *tp_as_sequence; */ - NULL, /* PyMappingMethods *tp_as_mapping; */ +#if (PY_VERSION_HEX >= 0x03000000) + &Vector_AsMapping, /* PyMappingMethods *tp_as_mapping; */ +#else + NULL, +#endif /* More standard operations (here for binary compatibility) */ @@ -1758,8 +1915,8 @@ PyTypeObject vector_Type = { NULL, /* PyBufferProcs *tp_as_buffer; */ /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT, - VectorObject_doc, /* char *tp_doc; Documentation string */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + NULL, /* char *tp_doc; Documentation string */ /*** Assigned meaning in release 2.0 ***/ /* call function for all accessible objects */ NULL, /* traverseproc tp_traverse; */ @@ -1811,14 +1968,21 @@ PyTypeObject vector_Type = { (i.e. it was allocated elsewhere by MEM_mallocN()) pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON (i.e. it must be created here with PyMEM_malloc())*/ -PyObject *newVectorObject(float *vec, int size, int type) +PyObject *newVectorObject(float *vec, int size, int type, PyTypeObject *base_type) { int i; - VectorObject *self = PyObject_NEW(VectorObject, &vector_Type); + VectorObject *self; + + if(base_type) self = base_type->tp_alloc(base_type, 0); + else self = PyObject_NEW(VectorObject, &vector_Type); if(size > 4 || size < 2) return NULL; self->size = size; + + /* init callbacks as NULL */ + self->cb_user= NULL; + self->cb_type= self->cb_subtype= 0; if(type == Py_WRAP) { self->vec = vec; @@ -1843,20 +2007,72 @@ PyObject *newVectorObject(float *vec, int size, int type) return (PyObject *) self; } -/* - #############################DEPRECATED################################ - ####################################################################### - ----------------------------Vector.negate() -------------------- +PyObject *newVectorObject_cb(PyObject *cb_user, int size, int cb_type, int cb_subtype) +{ + float dummy[4] = {0.0, 0.0, 0.0, 0.0}; /* dummy init vector, callbacks will be used on access */ + VectorObject *self= (VectorObject *)newVectorObject(dummy, size, Py_NEW, NULL); + if(self) { + Py_INCREF(cb_user); + self->cb_user= cb_user; + self->cb_type= (unsigned char)cb_type; + self->cb_subtype= (unsigned char)cb_subtype; + } + + return (PyObject *)self; +} + +//-----------------row_vector_multiplication (internal)----------- +//ROW VECTOR Multiplication - Vector X Matrix +//[x][y][z] * [1][2][3] +// [4][5][6] +// [7][8][9] +//vector/matrix multiplication IS NOT COMMUTATIVE!!!! +static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat) +{ + float vecNew[4], vecCopy[4]; + double dot = 0.0f; + int x, y, z = 0, vec_size = vec->size; + + if(mat->colSize != vec_size){ + if(mat->rowSize == 4 && vec_size != 3){ + PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same"); + return NULL; + }else{ + vecCopy[3] = 1.0f; + } + } + + if(!BaseMath_ReadCallback(vec) || !BaseMath_ReadCallback(mat)) + return NULL; + + for(x = 0; x < vec_size; x++){ + vecCopy[x] = vec->vec[x]; + } + + //muliplication + for(x = 0; x < mat->colSize; x++) { + for(y = 0; y < mat->rowSize; y++) { + dot += mat->matrix[y][x] * vecCopy[y]; + } + vecNew[z++] = (float)dot; + dot = 0.0f; + } + return newVectorObject(vecNew, vec_size, Py_NEW, NULL); +} + +/*----------------------------Vector.negate() -------------------- set the vector to it's negative -x, -y, -z */ static PyObject *Vector_Negate(VectorObject * self) { int i; - for(i = 0; i < self->size; i++) { + if(!BaseMath_ReadCallback(self)) + return NULL; + + for(i = 0; i < self->size; i++) self->vec[i] = -(self->vec[i]); - } - /*printf("Vector.negate(): Deprecated: use -vector instead\n");*/ + + BaseMath_WriteCallback(self); // alredy checked for error + Py_INCREF(self); return (PyObject*)self; } -/*################################################################### - ###########################DEPRECATED##############################*/ diff --git a/source/blender/python/generic/vector.h b/source/blender/python/generic/vector.h index d2eb826ef10..f6babac7ed9 100644 --- a/source/blender/python/generic/vector.h +++ b/source/blender/python/generic/vector.h @@ -1,4 +1,4 @@ -/* $Id: vector.h 20332 2009-05-22 03:22:56Z campbellbarton $ +/* $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -34,17 +34,22 @@ #include "../intern/bpy_compat.h" extern PyTypeObject vector_Type; +#define VectorObject_Check(_v) PyObject_TypeCheck((_v), &vector_Type) -#define VectorObject_Check(v) (((PyObject *)v)->ob_type == &vector_Type) - -typedef struct { +typedef struct { /* keep aligned with BaseMathObject in Mathutils.h */ PyObject_VAR_HEAD - float *vec; /*1D array of data (alias), wrapped status depends on wrapped status */ - short size; /* vec size 2,3 or 4 */ - short wrapped; /* is wrapped data? */ + float *vec; /*1D array of data (alias), wrapped status depends on wrapped status */ + PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */ + unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */ + unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */ + unsigned char wrapped; /* wrapped data type? */ + /* end BaseMathObject */ + + unsigned char size; /* vec size 2,3 or 4 */ } VectorObject; /*prototypes*/ -PyObject *newVectorObject(float *vec, int size, int type); +PyObject *newVectorObject(float *vec, int size, int type, PyTypeObject *base_type); +PyObject *newVectorObject_cb(PyObject *user, int size, int callback_type, int subtype); #endif /* EXPP_vector_h */ diff --git a/source/blender/python/intern/Makefile b/source/blender/python/intern/Makefile index 0c4a540a4bd..d210cfaf973 100644 --- a/source/blender/python/intern/Makefile +++ b/source/blender/python/intern/Makefile @@ -1,5 +1,5 @@ # -# $Id: Makefile 11904 2007-08-31 16:16:33Z sirdude $ +# $Id$ # # ***** BEGIN GPL LICENSE BLOCK ***** # diff --git a/source/blender/python/intern/bpy_compat.h b/source/blender/python/intern/bpy_compat.h index 032b60988d5..1ad9376c13b 100644 --- a/source/blender/python/intern/bpy_compat.h +++ b/source/blender/python/intern/bpy_compat.h @@ -1,5 +1,5 @@ /** - * $Id: bpy_compat.h 21247 2009-06-29 21:50:53Z jaguarandi $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 559ed537757..8b5ad36f349 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -37,6 +37,11 @@ #include "BPY_extern.h" #include "../generic/bpy_internal_import.h" // our own imports +/* external util modukes */ + +#include "../generic/Mathutils.h" +#include "../generic/Geometry.h" +#include "../generic/BGL.h" void BPY_free_compiled_text( struct Text *text ) @@ -61,11 +66,17 @@ static void bpy_init_modules( void ) PyModule_AddObject( mod, "types", BPY_rna_types() ); PyModule_AddObject( mod, "props", BPY_rna_props() ); PyModule_AddObject( mod, "ops", BPY_operator_module() ); - PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experemental, consider this a test, especially PyCObject is not meant to be perminant + PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experimental, consider this a test, especially PyCObject is not meant to be permanent /* add the module so we can import it */ PyDict_SetItemString(PySys_GetObject("modules"), "bpy", mod); Py_DECREF(mod); + + + /* stand alone utility modules not related to blender directly */ + Geometry_Init("Geometry"); + Mathutils_Init("Mathutils"); + BGL_Init("BGL"); } #if (PY_VERSION_HEX < 0x02050000) diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index 3ea330adc85..004cf2fb7c7 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -1,6 +1,6 @@ /** - * $Id: bpy_operator.c 21247 2009-06-29 21:50:53Z jaguarandi $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/python/intern/bpy_operator.h b/source/blender/python/intern/bpy_operator.h index 8a4493b5866..46ea144fd4d 100644 --- a/source/blender/python/intern/bpy_operator.h +++ b/source/blender/python/intern/bpy_operator.h @@ -1,6 +1,6 @@ /** - * $Id: bpy_operator.h 21247 2009-06-29 21:50:53Z jaguarandi $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c index 3d5427ddefd..60a9afda0c4 100644 --- a/source/blender/python/intern/bpy_operator_wrap.c +++ b/source/blender/python/intern/bpy_operator_wrap.c @@ -1,6 +1,6 @@ /** - * $Id: bpy_operator_wrap.c 21247 2009-06-29 21:50:53Z jaguarandi $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -47,98 +47,6 @@ #define PYOP_ATTR_IDNAME "__name__" /* use pythons class name */ #define PYOP_ATTR_DESCRIPTION "__doc__" /* use pythons docstring */ -static PyObject *pyop_dict_from_event(wmEvent *event) -{ - PyObject *dict= PyDict_New(); - PyObject *item; - char *cstring, ascii[2]; - - /* type */ - item= PyUnicode_FromString(WM_key_event_string(event->type)); - PyDict_SetItemString(dict, "type", item); Py_DECREF(item); - - /* val */ - switch(event->val) { - case KM_ANY: - cstring = "ANY"; - break; - case KM_RELEASE: - cstring = "RELEASE"; - break; - case KM_PRESS: - cstring = "PRESS"; - break; - default: - cstring = "UNKNOWN"; - break; - } - - item= PyUnicode_FromString(cstring); - PyDict_SetItemString(dict, "val", item); Py_DECREF(item); - - /* x, y (mouse) */ - item= PyLong_FromLong(event->x); - PyDict_SetItemString(dict, "x", item); Py_DECREF(item); - - item= PyLong_FromLong(event->y); - PyDict_SetItemString(dict, "y", item); Py_DECREF(item); - - item= PyLong_FromLong(event->prevx); - PyDict_SetItemString(dict, "prevx", item); Py_DECREF(item); - - item= PyLong_FromLong(event->prevy); - PyDict_SetItemString(dict, "prevy", item); Py_DECREF(item); - - /* ascii */ - ascii[0]= event->ascii; - ascii[1]= '\0'; - item= PyUnicode_FromString(ascii); - PyDict_SetItemString(dict, "ascii", item); Py_DECREF(item); - - /* modifier keys */ - item= PyLong_FromLong(event->shift); - PyDict_SetItemString(dict, "shift", item); Py_DECREF(item); - - item= PyLong_FromLong(event->ctrl); - PyDict_SetItemString(dict, "ctrl", item); Py_DECREF(item); - - item= PyLong_FromLong(event->alt); - PyDict_SetItemString(dict, "alt", item); Py_DECREF(item); - - item= PyLong_FromLong(event->oskey); - PyDict_SetItemString(dict, "oskey", item); Py_DECREF(item); - - - - /* modifier */ -#if 0 - item= PyTuple_New(0); - if(event->keymodifier & KM_SHIFT) { - _PyTuple_Resize(&item, size+1); - PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("SHIFT")); - size++; - } - if(event->keymodifier & KM_CTRL) { - _PyTuple_Resize(&item, size+1); - PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("CTRL")); - size++; - } - if(event->keymodifier & KM_ALT) { - _PyTuple_Resize(&item, size+1); - PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("ALT")); - size++; - } - if(event->keymodifier & KM_OSKEY) { - _PyTuple_Resize(&item, size+1); - PyTuple_SET_ITEM(item, size, _PyUnicode_AsString("OSKEY")); - size++; - } - PyDict_SetItemString(dict, "keymodifier", item); Py_DECREF(item); -#endif - - return dict; -} - static struct BPY_flag_def pyop_ret_flags[] = { {"RUNNING_MODAL", OPERATOR_RUNNING_MODAL}, {"CANCELLED", OPERATOR_CANCELLED}, @@ -180,6 +88,7 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve int ret_flag= (mode==PYOP_POLL ? 0:OPERATOR_CANCELLED); PointerRNA ptr_context; PointerRNA ptr_operator; + PointerRNA ptr_event; PyObject *py_operator; PyGILState_STATE gilstate = PyGILState_Ensure(); @@ -198,15 +107,9 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve /* Assign instance attributes from operator properties */ { - PropertyRNA *prop, *iterprop; - CollectionPropertyIterator iter; const char *arg_name; - iterprop= RNA_struct_iterator_property(op->ptr->type); - RNA_property_collection_begin(op->ptr, iterprop, &iter); - - for(; iter.valid; RNA_property_collection_next(&iter)) { - prop= iter.ptr.data; + RNA_STRUCT_BEGIN(op->ptr, prop) { arg_name= RNA_property_identifier(prop); if (strcmp(arg_name, "rna_type")==0) continue; @@ -215,8 +118,7 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve PyObject_SetAttrString(py_class_instance, arg_name, item); Py_DECREF(item); } - - RNA_property_collection_end(&iter); + RNA_STRUCT_END; } /* set operator pointer RNA as instance "__operator__" attribute */ @@ -230,11 +132,13 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve if (mode==PYOP_INVOKE) { item= PyObject_GetAttrString(py_class, "invoke"); args = PyTuple_New(3); + + RNA_pointer_create(NULL, &RNA_Event, event, &ptr_event); // PyTuple_SET_ITEM "steals" object reference, it is // an object passed shouldn't be DECREF'ed PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context)); - PyTuple_SET_ITEM(args, 2, pyop_dict_from_event(event)); + PyTuple_SET_ITEM(args, 2, pyrna_struct_CreatePyObject(&ptr_event)); } else if (mode==PYOP_EXEC) { item= PyObject_GetAttrString(py_class, "execute"); @@ -449,7 +353,8 @@ PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class) /* remove if it already exists */ if ((ot=WM_operatortype_find(idname))) { - Py_XDECREF((PyObject*)ot->pyop_data); + if(ot->pyop_data) + Py_XDECREF((PyObject*)ot->pyop_data); WM_operatortype_remove(idname); } diff --git a/source/blender/python/intern/bpy_operator_wrap.h b/source/blender/python/intern/bpy_operator_wrap.h index c9efb1ea22f..2929d57ab82 100644 --- a/source/blender/python/intern/bpy_operator_wrap.h +++ b/source/blender/python/intern/bpy_operator_wrap.h @@ -1,6 +1,6 @@ /** - * $Id: bpy_operator_wrap.h 21247 2009-06-29 21:50:53Z jaguarandi $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index d131361294d..4729620bb8a 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -1,5 +1,5 @@ /** - * $Id: bpy_rna.c 21247 2009-06-29 21:50:53Z jaguarandi $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -35,10 +35,99 @@ #include "RNA_define.h" /* for defining our own rna */ #include "MEM_guardedalloc.h" +#include "BKE_utildefines.h" #include "BKE_context.h" #include "BKE_global.h" /* evil G.* */ #include "BKE_report.h" +#define USE_MATHUTILS + +#ifdef USE_MATHUTILS +#include "../generic/Mathutils.h" /* so we can have mathutils callbacks */ + +/* bpyrna vector/euler/quat callbacks */ +static int mathutils_rna_array_cb_index= -1; /* index for our callbacks */ + +static int mathutils_rna_generic_check(BPy_PropertyRNA *self) +{ + return self->prop?1:0; +} + +static int mathutils_rna_vector_get(BPy_PropertyRNA *self, int subtype, float *vec_from) +{ + if(self->prop==NULL) + return 0; + + RNA_property_float_get_array(&self->ptr, self->prop, vec_from); + return 1; +} + +static int mathutils_rna_vector_set(BPy_PropertyRNA *self, int subtype, float *vec_to) +{ + if(self->prop==NULL) + return 0; + + RNA_property_float_set_array(&self->ptr, self->prop, vec_to); + return 1; +} + +static int mathutils_rna_vector_get_index(BPy_PropertyRNA *self, int subtype, float *vec_from, int index) +{ + if(self->prop==NULL) + return 0; + + vec_from[index]= RNA_property_float_get_index(&self->ptr, self->prop, index); + return 1; +} + +static int mathutils_rna_vector_set_index(BPy_PropertyRNA *self, int subtype, float *vec_to, int index) +{ + if(self->prop==NULL) + return 0; + + RNA_property_float_set_index(&self->ptr, self->prop, index, vec_to[index]); + return 1; +} + +Mathutils_Callback mathutils_rna_array_cb = { + mathutils_rna_generic_check, + mathutils_rna_vector_get, + mathutils_rna_vector_set, + mathutils_rna_vector_get_index, + mathutils_rna_vector_set_index +}; + +/* bpyrna matrix callbacks */ +static int mathutils_rna_matrix_cb_index= -1; /* index for our callbacks */ + +static int mathutils_rna_matrix_get(BPy_PropertyRNA *self, int subtype, float *mat_from) +{ + if(self->prop==NULL) + return 0; + + RNA_property_float_get_array(&self->ptr, self->prop, mat_from); + return 1; +} + +static int mathutils_rna_matrix_set(BPy_PropertyRNA *self, int subtype, float *mat_to) +{ + if(self->prop==NULL) + return 0; + + RNA_property_float_set_array(&self->ptr, self->prop, mat_to); + return 1; +} + +Mathutils_Callback mathutils_rna_matrix_cb = { + mathutils_rna_generic_check, + mathutils_rna_matrix_get, + mathutils_rna_matrix_set, + NULL, + NULL +}; + +#endif + static int pyrna_struct_compare( BPy_StructRNA * a, BPy_StructRNA * b ) { return (a->ptr.data==b->ptr.data) ? 0 : -1; @@ -73,14 +162,15 @@ static PyObject *pyrna_prop_richcmp(BPy_PropertyRNA * a, BPy_PropertyRNA * b, in /*----------------------repr--------------------------------------------*/ static PyObject *pyrna_struct_repr( BPy_StructRNA * self ) { - PropertyRNA *prop; - char str[512]; + PyObject *pyob; + char *name; /* print name if available */ - prop= RNA_struct_name_property(self->ptr.type); - if(prop) { - RNA_property_string_get(&self->ptr, prop, str); - return PyUnicode_FromFormat( "[BPy_StructRNA \"%s\" -> \"%s\"]", RNA_struct_identifier(self->ptr.type), str); + name= RNA_struct_name_get_alloc(&self->ptr, NULL, 0); + if(name) { + pyob= PyUnicode_FromFormat( "[BPy_StructRNA \"%s\" -> \"%s\"]", RNA_struct_identifier(self->ptr.type), name); + MEM_freeN(name); + return pyob; } return PyUnicode_FromFormat( "[BPy_StructRNA \"%s\"]", RNA_struct_identifier(self->ptr.type)); @@ -88,20 +178,19 @@ static PyObject *pyrna_struct_repr( BPy_StructRNA * self ) static PyObject *pyrna_prop_repr( BPy_PropertyRNA * self ) { - PropertyRNA *prop; + PyObject *pyob; PointerRNA ptr; - char str[512]; + char *name; /* if a pointer, try to print name of pointer target too */ if(RNA_property_type(self->prop) == PROP_POINTER) { ptr= RNA_property_pointer_get(&self->ptr, self->prop); + name= RNA_struct_name_get_alloc(&ptr, NULL, 0); - if(ptr.data) { - prop= RNA_struct_name_property(ptr.type); - if(prop) { - RNA_property_string_get(&ptr, prop, str); - return PyUnicode_FromFormat( "[BPy_PropertyRNA \"%s\" -> \"%s\" -> \"%s\" ]", RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop), str); - } + if(name) { + pyob= PyUnicode_FromFormat( "[BPy_PropertyRNA \"%s\" -> \"%s\" -> \"%s\" ]", RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop), name); + MEM_freeN(name); + return pyob; } } @@ -116,13 +205,13 @@ static long pyrna_struct_hash( BPy_StructRNA * self ) /* use our own dealloc so we can free a property if we use one */ static void pyrna_struct_dealloc( BPy_StructRNA * self ) { - /* Note!! for some weired reason calling PyObject_DEL() directly crashes blender! */ if (self->freeptr && self->ptr.data) { IDP_FreeProperty(self->ptr.data); MEM_freeN(self->ptr.data); self->ptr.data= NULL; } + /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */ Py_TYPE(self)->tp_free(self); return; } @@ -130,9 +219,8 @@ static void pyrna_struct_dealloc( BPy_StructRNA * self ) static char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop) { const EnumPropertyItem *item; - int totitem; - RNA_property_enum_items(ptr, prop, &item, &totitem); + RNA_property_enum_items(ptr, prop, &item, NULL); return (char*)BPy_enum_as_string((EnumPropertyItem*)item); } @@ -144,7 +232,52 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) if (len > 0) { /* resolve the array from a new pytype */ - return pyrna_prop_CreatePyObject(ptr, prop); + PyObject *ret = pyrna_prop_CreatePyObject(ptr, prop); + +#ifdef USE_MATHUTILS + + /* return a mathutils vector where possible */ + if(RNA_property_type(prop)==PROP_FLOAT) { + switch(RNA_property_subtype(prop)) { + case PROP_VECTOR: + if(len>=2 && len <= 4) { + PyObject *vec_cb= newVectorObject_cb(ret, len, mathutils_rna_array_cb_index, 0); + Py_DECREF(ret); /* the vector owns now */ + ret= vec_cb; /* return the vector instead */ + } + break; + case PROP_MATRIX: + if(len==16) { + PyObject *mat_cb= newMatrixObject_cb(ret, 4,4, mathutils_rna_matrix_cb_index, 0); + Py_DECREF(ret); /* the matrix owns now */ + ret= mat_cb; /* return the matrix instead */ + } + else if (len==9) { + PyObject *mat_cb= newMatrixObject_cb(ret, 3,3, mathutils_rna_matrix_cb_index, 0); + Py_DECREF(ret); /* the matrix owns now */ + ret= mat_cb; /* return the matrix instead */ + } + break; + case PROP_ROTATION: + if(len==3) { /* euler */ + PyObject *eul_cb= newEulerObject_cb(ret, mathutils_rna_array_cb_index, 0); + Py_DECREF(ret); /* the matrix owns now */ + ret= eul_cb; /* return the matrix instead */ + } + else if (len==4) { + PyObject *quat_cb= newQuaternionObject_cb(ret, mathutils_rna_array_cb_index, 0); + Py_DECREF(ret); /* the matrix owns now */ + ret= quat_cb; /* return the matrix instead */ + } + break; + default: + break; + } + } + +#endif + + return ret; } /* see if we can coorce into a python type - PropertyType */ @@ -213,17 +346,9 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const char *error_prefi const char *arg_name= NULL; PyObject *item; - PropertyRNA *prop, *iterprop; - CollectionPropertyIterator iter; - - iterprop= RNA_struct_iterator_property(ptr->type); - RNA_property_collection_begin(ptr, iterprop, &iter); - totkw = kw ? PyDict_Size(kw):0; - for(; iter.valid; RNA_property_collection_next(&iter)) { - prop= iter.ptr.data; - + RNA_STRUCT_BEGIN(ptr, prop) { arg_name= RNA_property_identifier(prop); if (strcmp(arg_name, "rna_type")==0) continue; @@ -249,8 +374,7 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const char *error_prefi totkw--; } - - RNA_property_collection_end(&iter); + RNA_STRUCT_END; if (error_val==0 && totkw > 0) { /* some keywords were given that were not used :/ */ PyObject *key, *value; @@ -271,12 +395,15 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const char *error_prefi static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw); -PyObject *pyrna_func_to_py(PointerRNA *ptr, FunctionRNA *func) +PyObject *pyrna_func_to_py(BPy_StructRNA *pyrna, FunctionRNA *func) { static PyMethodDef func_meth = {"", (PyCFunction)pyrna_func_call, METH_VARARGS|METH_KEYWORDS, "python rna function"}; PyObject *self= PyTuple_New(2); PyObject *ret; - PyTuple_SET_ITEM(self, 0, pyrna_struct_CreatePyObject(ptr)); + + PyTuple_SET_ITEM(self, 0, (PyObject *)pyrna); + Py_INCREF(pyrna); + PyTuple_SET_ITEM(self, 1, PyCObject_FromVoidPtr((void *)func, NULL)); ret= PyCFunction_New(&func_meth, self); @@ -294,15 +421,30 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v if (len > 0) { PyObject *item; + int py_len = -1; int i; - if (!PySequence_Check(value)) { - PyErr_SetString(PyExc_TypeError, "expected a python sequence type assigned to an RNA array."); + +#ifdef USE_MATHUTILS + if(MatrixObject_Check(value)) { + MatrixObject *mat = (MatrixObject*)value; + if(!BaseMath_ReadCallback(mat)) + return -1; + + py_len = mat->rowSize * mat->colSize; + } else /* continue... */ +#endif + if (PySequence_Check(value)) { + py_len= (int)PySequence_Length(value); + } + else { + PyErr_Format(PyExc_TypeError, "RNA array assignment expected a sequence instead of %s instance.", Py_TYPE(value)->tp_name); return -1; } + /* done getting the length */ - if ((int)PySequence_Length(value) != len) { - PyErr_SetString(PyExc_AttributeError, "python sequence length did not match the RNA array."); + if (py_len != len) { + PyErr_Format(PyExc_AttributeError, "python sequence length %d did not match the RNA array length %d.", py_len, len); return -1; } @@ -368,14 +510,21 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v else param_arr = MEM_mallocN(sizeof(float) * len, "pyrna float array"); - - /* collect the variables */ - for (i=0; icontigPtr, sizeof(float) * len); + } else /* continue... */ +#endif + { + /* collect the variables */ + for (i=0; iptr= itemptr; + BLI_addtail(lb, link); + } + else + RNA_property_collection_add(ptr, prop, &itemptr); + if(pyrna_pydict_to_props(&itemptr, item, "Converting a python list to an RNA collection")==-1) { Py_DECREF(item); return -1; @@ -661,108 +821,246 @@ static Py_ssize_t pyrna_prop_len( BPy_PropertyRNA * self ) return len; } -static PyObject *pyrna_prop_subscript( BPy_PropertyRNA * self, PyObject *key ) +/* internal use only */ +static PyObject *prop_subscript_collection_int(BPy_PropertyRNA * self, int keynum) { - PyObject *ret; PointerRNA newptr; - int keynum = 0; - char *keyname = NULL; - + + if(keynum < 0) keynum += RNA_property_collection_length(&self->ptr, self->prop); + + if(RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum, &newptr)) + return pyrna_struct_CreatePyObject(&newptr); + + PyErr_SetString(PyExc_IndexError, "out of range"); + return NULL; +} +static PyObject *prop_subscript_array_int(BPy_PropertyRNA * self, int keynum) +{ + int len= RNA_property_array_length(self->prop); + + if(keynum < 0) keynum += len; + + if(keynum >= 0 && keynum < len) + return pyrna_prop_to_py_index(&self->ptr, self->prop, keynum); + + PyErr_SetString(PyExc_IndexError, "out of range"); + return NULL; +} + +static PyObject *prop_subscript_collection_str(BPy_PropertyRNA * self, char *keyname) +{ + PointerRNA newptr; + if(RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr)) + return pyrna_struct_CreatePyObject(&newptr); + + PyErr_SetString(PyExc_KeyError, "key not found"); + return NULL; +} +/* static PyObject *prop_subscript_array_str(BPy_PropertyRNA * self, char *keyname) */ + + + + +#if PY_VERSION_HEX >= 0x03000000 +static PyObject *prop_subscript_collection_slice(BPy_PropertyRNA * self, int start, int stop) +{ + PointerRNA newptr; + PyObject *list = PyList_New(stop - start); + int count; + + start = MIN2(start,stop); /* values are clamped from */ + + for(count = start; count < stop; count++) { + if(RNA_property_collection_lookup_int(&self->ptr, self->prop, count - start, &newptr)) { + PyList_SetItem(list, count - start, pyrna_struct_CreatePyObject(&newptr)); + } + else { + Py_DECREF(list); + + PyErr_SetString(PyExc_RuntimeError, "error getting an rna struct from a collection"); + return NULL; + } + } + + return list; +} +static PyObject *prop_subscript_array_slice(BPy_PropertyRNA * self, int start, int stop) +{ + PyObject *list = PyList_New(stop - start); + int count; + + start = MIN2(start,stop); /* values are clamped from PySlice_GetIndicesEx */ + + for(count = start; count < stop; count++) + PyList_SetItem(list, count - start, pyrna_prop_to_py_index(&self->ptr, self->prop, count)); + + return list; +} +#endif + +static PyObject *prop_subscript_collection(BPy_PropertyRNA * self, PyObject *key) +{ if (PyUnicode_Check(key)) { - keyname = _PyUnicode_AsString(key); - } else if (PyLong_Check(key)) { - keynum = PyLong_AsSsize_t(key); - } else { + return prop_subscript_collection_str(self, _PyUnicode_AsString(key)); + } + else if (PyLong_Check(key)) { + return prop_subscript_collection_int(self, PyLong_AsSsize_t(key)); + } +#if PY_VERSION_HEX >= 0x03000000 + else if (PySlice_Check(key)) { + int len= RNA_property_collection_length(&self->ptr, self->prop); + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0) + return NULL; + + if (slicelength <= 0) { + return PyList_New(0); + } + else if (step == 1) { + return prop_subscript_collection_slice(self, start, stop); + } + else { + PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna"); + return NULL; + } + } +#endif + else { PyErr_SetString(PyExc_AttributeError, "invalid key, key must be a string or an int"); return NULL; } - - if (RNA_property_type(self->prop) == PROP_COLLECTION) { - int ok; - if (keyname) ok = RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr); - else ok = RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum, &newptr); - - if (ok) { - ret = pyrna_struct_CreatePyObject(&newptr); - } else { - PyErr_SetString(PyExc_AttributeError, "out of range"); - ret = NULL; - } - - } else if (keyname) { - PyErr_SetString(PyExc_AttributeError, "string keys are only supported for collections"); - ret = NULL; - } else { - int len = RNA_property_array_length(self->prop); - - if (len==0) { /* not an array*/ - PyErr_Format(PyExc_AttributeError, "not an array or collection %d", keynum); - ret = NULL; - } - - if (keynum >= len){ - PyErr_SetString(PyExc_AttributeError, "index out of range"); - ret = NULL; - } else { /* not an array*/ - ret = pyrna_prop_to_py_index(&self->ptr, self->prop, keynum); - } - } - - return ret; } - -static int pyrna_prop_assign_subscript( BPy_PropertyRNA * self, PyObject *key, PyObject *value ) +static PyObject *prop_subscript_array(BPy_PropertyRNA * self, PyObject *key) { - int ret = 0; - int keynum = 0; - char *keyname = NULL; + /*if (PyUnicode_Check(key)) { + return prop_subscript_array_str(self, _PyUnicode_AsString(key)); + } else*/ + if (PyLong_Check(key)) { + return prop_subscript_array_int(self, PyLong_AsSsize_t(key)); + } +#if PY_VERSION_HEX >= 0x03000000 + else if (PySlice_Check(key)) { + int len= RNA_property_array_length(self->prop); + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0) + return NULL; + + if (slicelength <= 0) { + return PyList_New(0); + } + else if (step == 1) { + return prop_subscript_array_slice(self, start, stop); + } + else { + PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna"); + return NULL; + } + } +#endif + else { + PyErr_SetString(PyExc_AttributeError, "invalid key, key must be an int"); + return NULL; + } +} + +static PyObject *pyrna_prop_subscript( BPy_PropertyRNA * self, PyObject *key ) +{ + if (RNA_property_type(self->prop) == PROP_COLLECTION) { + return prop_subscript_collection(self, key); + } else if (RNA_property_array_length(self->prop)) { /* arrays are currently fixed length, zero length means its not an array */ + return prop_subscript_array(self, key); + } else { + PyErr_SetString(PyExc_TypeError, "rna type is not an array or a collection"); + return NULL; + } + +} + +#if PY_VERSION_HEX >= 0x03000000 +static int prop_subscript_ass_array_slice(BPy_PropertyRNA * self, int begin, int end, PyObject *value) +{ + int count; + + /* values are clamped from */ + begin = MIN2(begin,end); + + for(count = begin; count < end; count++) { + if(pyrna_py_to_prop_index(&self->ptr, self->prop, count - begin, value) == -1) { + /* TODO - this is wrong since some values have been assigned... will need to fix that */ + return -1; /* pyrna_struct_CreatePyObject should set the error */ + } + } + + return 0; +} +#endif + +static int prop_subscript_ass_array_int(BPy_PropertyRNA * self, int keynum, PyObject *value) +{ + + int len= RNA_property_array_length(self->prop); + + if(keynum < 0) keynum += len; + + if(keynum >= 0 && keynum < len) + return pyrna_py_to_prop_index(&self->ptr, self->prop, keynum, value); + + PyErr_SetString(PyExc_IndexError, "out of range"); + return -1; +} + +static int pyrna_prop_ass_subscript( BPy_PropertyRNA * self, PyObject *key, PyObject *value ) +{ + /* char *keyname = NULL; */ /* not supported yet */ if (!RNA_property_editable(&self->ptr, self->prop)) { PyErr_Format( PyExc_AttributeError, "PropertyRNA - attribute \"%s\" from \"%s\" is read-only", RNA_property_identifier(self->prop), RNA_struct_identifier(self->ptr.type) ); return -1; } - if (PyUnicode_Check(key)) { - keyname = _PyUnicode_AsString(key); - } else if (PyLong_Check(key)) { - keynum = PyLong_AsSsize_t(key); - } else { - PyErr_SetString(PyExc_AttributeError, "PropertyRNA - invalid key, key must be a string or an int"); + /* maybe one day we can support this... */ + if (RNA_property_type(self->prop) == PROP_COLLECTION) { + PyErr_Format( PyExc_AttributeError, "PropertyRNA - attribute \"%s\" from \"%s\" is a collection, assignment not supported", RNA_property_identifier(self->prop), RNA_struct_identifier(self->ptr.type) ); return -1; } - - if (RNA_property_type(self->prop) == PROP_COLLECTION) { - PyErr_SetString(PyExc_AttributeError, "PropertyRNA - assignment is not supported for collections (yet)"); - ret = -1; - } else if (keyname) { - PyErr_SetString(PyExc_AttributeError, "PropertyRNA - string keys are only supported for collections"); - ret = -1; - } else { - int len = RNA_property_array_length(self->prop); - - if (len==0) { /* not an array*/ - PyErr_Format(PyExc_AttributeError, "PropertyRNA - not an array or collection %d", keynum); - ret = -1; + + if (PyLong_Check(key)) { + return prop_subscript_ass_array_int(self, PyLong_AsSsize_t(key), value); + } +#if PY_VERSION_HEX >= 0x03000000 + else if (PySlice_Check(key)) { + int len= RNA_property_array_length(self->prop); + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0) + return -1; + + if (slicelength <= 0) { + return 0; } - - if (keynum >= len){ - PyErr_SetString(PyExc_AttributeError, "PropertyRNA - index out of range"); - ret = -1; - } else { - ret = pyrna_py_to_prop_index(&self->ptr, self->prop, keynum, value); + else if (step == 1) { + return prop_subscript_ass_array_slice(self, start, stop, value); + } + else { + PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna"); + return -1; } } - - return ret; +#endif + else { + PyErr_SetString(PyExc_AttributeError, "invalid key, key must be an int"); + return -1; + } } - static PyMappingMethods pyrna_prop_as_mapping = { ( lenfunc ) pyrna_prop_len, /* mp_length */ ( binaryfunc ) pyrna_prop_subscript, /* mp_subscript */ - ( objobjargproc ) pyrna_prop_assign_subscript, /* mp_ass_subscript */ + ( objobjargproc ) pyrna_prop_ass_subscript, /* mp_ass_subscript */ }; static int pyrna_prop_contains(BPy_PropertyRNA * self, PyObject *value) @@ -804,7 +1102,6 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA * self) PyObject *pystring; /* for looping over attrs and funcs */ - CollectionPropertyIterator iter; PropertyRNA *iterprop; /* Include this incase this instance is a subtype of a python class @@ -833,26 +1130,23 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA * self) /* * Collect RNA attributes */ - PropertyRNA *nameprop; char name[256], *nameptr; iterprop= RNA_struct_iterator_property(self->ptr.type); - RNA_property_collection_begin(&self->ptr, iterprop, &iter); - for(; iter.valid; RNA_property_collection_next(&iter)) { - if(iter.ptr.data && (nameprop = RNA_struct_name_property(iter.ptr.type))) { - nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name)); - + RNA_PROP_BEGIN(&self->ptr, itemptr, iterprop) { + nameptr= RNA_struct_name_get_alloc(&itemptr, name, sizeof(name)); + + if(nameptr) { pystring = PyUnicode_FromString(nameptr); PyList_Append(ret, pystring); Py_DECREF(pystring); - if ((char *)&name != nameptr) + if(name != nameptr) MEM_freeN(nameptr); } } - RNA_property_collection_end(&iter); - + RNA_PROP_END; } @@ -865,15 +1159,12 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA * self) RNA_pointer_create(NULL, &RNA_Struct, self->ptr.type, &tptr); iterprop= RNA_struct_find_property(&tptr, "functions"); - RNA_property_collection_begin(&tptr, iterprop, &iter); - - for(; iter.valid; RNA_property_collection_next(&iter)) { - pystring = PyUnicode_FromString(RNA_function_identifier(iter.ptr.data)); + RNA_PROP_BEGIN(&tptr, itemptr, iterprop) { + pystring = PyUnicode_FromString(RNA_function_identifier(itemptr.data)); PyList_Append(ret, pystring); Py_DECREF(pystring); } - - RNA_property_collection_end(&iter); + RNA_PROP_END; } if(self->ptr.type == &RNA_Context) { @@ -915,7 +1206,7 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname ) ret = pyrna_prop_to_py(&self->ptr, prop); } else if ((func = RNA_struct_find_function(&self->ptr, name))) { - ret = pyrna_func_to_py(&self->ptr, func); + ret = pyrna_func_to_py(self, func); } else if (self->ptr.type == &RNA_Context) { PointerRNA newptr; @@ -978,7 +1269,7 @@ static int pyrna_struct_setattro( BPy_StructRNA * self, PyObject *pyname, PyObje return pyrna_py_to_prop(&self->ptr, prop, NULL, value); } -PyObject *pyrna_prop_keys(BPy_PropertyRNA *self) +static PyObject *pyrna_prop_keys(BPy_PropertyRNA *self) { PyObject *ret; if (RNA_property_type(self->prop) != PROP_COLLECTION) { @@ -986,34 +1277,31 @@ PyObject *pyrna_prop_keys(BPy_PropertyRNA *self) ret = NULL; } else { PyObject *item; - CollectionPropertyIterator iter; - PropertyRNA *nameprop; char name[256], *nameptr; ret = PyList_New(0); - RNA_property_collection_begin(&self->ptr, self->prop, &iter); - for(; iter.valid; RNA_property_collection_next(&iter)) { - if(iter.ptr.data && (nameprop = RNA_struct_name_property(iter.ptr.type))) { - nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name)); - + RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) { + nameptr= RNA_struct_name_get_alloc(&itemptr, name, sizeof(name)); + + if(nameptr) { /* add to python list */ item = PyUnicode_FromString( nameptr ); PyList_Append(ret, item); Py_DECREF(item); /* done */ - if ((char *)&name != nameptr) + if(name != nameptr) MEM_freeN(nameptr); } } - RNA_property_collection_end(&iter); + RNA_PROP_END; } return ret; } -PyObject *pyrna_prop_items(BPy_PropertyRNA *self) +static PyObject *pyrna_prop_items(BPy_PropertyRNA *self) { PyObject *ret; if (RNA_property_type(self->prop) != PROP_COLLECTION) { @@ -1021,28 +1309,25 @@ PyObject *pyrna_prop_items(BPy_PropertyRNA *self) ret = NULL; } else { PyObject *item; - CollectionPropertyIterator iter; - PropertyRNA *nameprop; char name[256], *nameptr; int i= 0; ret = PyList_New(0); - RNA_property_collection_begin(&self->ptr, self->prop, &iter); - for(; iter.valid; RNA_property_collection_next(&iter)) { - if(iter.ptr.data) { + RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) { + if(itemptr.data) { /* add to python list */ item= PyTuple_New(2); - if(nameprop = RNA_struct_name_property(iter.ptr.type)) { - nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name)); + nameptr= RNA_struct_name_get_alloc(&itemptr, name, sizeof(name)); + if(nameptr) { PyTuple_SET_ITEM(item, 0, PyUnicode_FromString( nameptr )); - if ((char *)&name != nameptr) + if(name != nameptr) MEM_freeN(nameptr); } else { PyTuple_SET_ITEM(item, 0, PyLong_FromSsize_t(i)); /* a bit strange but better then returning an empty list */ } - PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&iter.ptr)); + PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&itemptr)); PyList_Append(ret, item); Py_DECREF(item); @@ -1050,14 +1335,14 @@ PyObject *pyrna_prop_items(BPy_PropertyRNA *self) i++; } } - RNA_property_collection_end(&iter); + RNA_PROP_END; } return ret; } -PyObject *pyrna_prop_values(BPy_PropertyRNA *self) +static PyObject *pyrna_prop_values(BPy_PropertyRNA *self) { PyObject *ret; @@ -1066,23 +1351,256 @@ PyObject *pyrna_prop_values(BPy_PropertyRNA *self) ret = NULL; } else { PyObject *item; - CollectionPropertyIterator iter; - PropertyRNA *iterprop; ret = PyList_New(0); - //iterprop= RNA_struct_iterator_property(self->ptr.type); - RNA_property_collection_begin(&self->ptr, self->prop, &iter); - for(; iter.valid; RNA_property_collection_next(&iter)) { - item = pyrna_struct_CreatePyObject(&iter.ptr); + RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) { + item = pyrna_struct_CreatePyObject(&itemptr); PyList_Append(ret, item); Py_DECREF(item); } - RNA_property_collection_end(&iter); + RNA_PROP_END; } return ret; } +#if (PY_VERSION_HEX >= 0x03000000) /* foreach needs py3 */ +static void foreach_attr_type( BPy_PropertyRNA *self, char *attr, + /* values to assign */ + RawPropertyType *raw_type, int *attr_tot, int *attr_signed ) +{ + PropertyRNA *prop; + *raw_type= -1; + *attr_tot= 0; + *attr_signed= 0; + + RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) { + prop = RNA_struct_find_property(&itemptr, attr); + *raw_type= RNA_property_raw_type(prop); + *attr_tot = RNA_property_array_length(prop); + *attr_signed= (RNA_property_subtype(prop)==PROP_UNSIGNED) ? 0:1; + break; + } + RNA_PROP_END; +} + +/* pyrna_prop_foreach_get/set both use this */ +static int foreach_parse_args( + BPy_PropertyRNA *self, PyObject *args, + + /*values to assign */ + char **attr, PyObject **seq, int *tot, int *size, RawPropertyType *raw_type, int *attr_tot, int *attr_signed) +{ +#if 0 + int array_tot; + int target_tot; +#endif + + *size= *raw_type= *attr_tot= *attr_signed= 0; + + if(!PyArg_ParseTuple(args, "sO", attr, seq) || (!PySequence_Check(*seq) && PyObject_CheckBuffer(*seq))) { + PyErr_SetString( PyExc_TypeError, "foreach_get(attr, sequence) expects a string and a sequence" ); + return -1; + } + + *tot= PySequence_Length(*seq); // TODO - buffer may not be a sequence! array.array() is tho. + + if(*tot>0) { + foreach_attr_type(self, *attr, raw_type, attr_tot, attr_signed); + *size= RNA_raw_type_sizeof(*raw_type); + +#if 0 // works fine but not strictly needed, we could allow RNA_property_collection_raw_* to do the checks + if((*attr_tot) < 1) + *attr_tot= 1; + + if (RNA_property_type(self->prop) == PROP_COLLECTION) + array_tot = RNA_property_collection_length(&self->ptr, self->prop); + else + array_tot = RNA_property_array_length(self->prop); + + + target_tot= array_tot * (*attr_tot); + + /* rna_access.c - rna_raw_access(...) uses this same method */ + if(target_tot != (*tot)) { + PyErr_Format( PyExc_TypeError, "foreach_get(attr, sequence) sequence length mismatch given %d, needed %d", *tot, target_tot); + return -1; + } +#endif + } + + return 0; +} + +static int foreach_compat_buffer(RawPropertyType raw_type, int attr_signed, const char *format) +{ + char f = format ? *format:'B'; /* B is assumed when not set */ + + switch(raw_type) { + case PROP_RAW_CHAR: + if (attr_signed) return (f=='b') ? 1:0; + else return (f=='B') ? 1:0; + case PROP_RAW_SHORT: + if (attr_signed) return (f=='h') ? 1:0; + else return (f=='H') ? 1:0; + case PROP_RAW_INT: + if (attr_signed) return (f=='i') ? 1:0; + else return (f=='I') ? 1:0; + case PROP_RAW_FLOAT: + return (f=='f') ? 1:0; + case PROP_RAW_DOUBLE: + return (f=='d') ? 1:0; + } + + return 0; +} + +static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) +{ + PyObject *item; + int i=0, ok, buffer_is_compat; + void *array= NULL; + + /* get/set both take the same args currently */ + char *attr; + PyObject *seq; + int tot, size, attr_tot, attr_signed; + RawPropertyType raw_type; + + if(foreach_parse_args(self, args, &attr, &seq, &tot, &size, &raw_type, &attr_tot, &attr_signed) < 0) + return NULL; + + if(tot==0) + Py_RETURN_NONE; + + + + if(set) { /* get the array from python */ + buffer_is_compat = 0; + if(PyObject_CheckBuffer(seq)) { + Py_buffer buf; + PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT); + + /* check if the buffer matches */ + + buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format); + + if(buffer_is_compat) { + ok = RNA_property_collection_raw_set(NULL, &self->ptr, self->prop, attr, buf.buf, raw_type, tot); + } + + PyBuffer_Release(&buf); + } + + /* could not use the buffer, fallback to sequence */ + if(!buffer_is_compat) { + array= PyMem_Malloc(size * tot); + + for( ; iptr, self->prop, attr, array, raw_type, tot); + } + } + else { + buffer_is_compat = 0; + if(PyObject_CheckBuffer(seq)) { + Py_buffer buf; + PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT); + + /* check if the buffer matches, TODO - signed/unsigned types */ + + buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format); + + if(buffer_is_compat) { + ok = RNA_property_collection_raw_get(NULL, &self->ptr, self->prop, attr, buf.buf, raw_type, tot); + } + + PyBuffer_Release(&buf); + } + + /* could not use the buffer, fallback to sequence */ + if(!buffer_is_compat) { + array= PyMem_Malloc(size * tot); + + ok = RNA_property_collection_raw_get(NULL, &self->ptr, self->prop, attr, array, raw_type, tot); + + if(!ok) i= tot; /* skip the loop */ + + for( ; i= 0x03000000) */ + /* A bit of a kludge, make a list out of a collection or array, * then return the lists iter function, not especially fast but convenient for now */ PyObject *pyrna_prop_iter(BPy_PropertyRNA *self) @@ -1117,14 +1635,20 @@ PyObject *pyrna_prop_iter(BPy_PropertyRNA *self) } static struct PyMethodDef pyrna_struct_methods[] = { - {"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, ""}, + {"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, NULL}, {NULL, NULL, 0, NULL} }; static struct PyMethodDef pyrna_prop_methods[] = { - {"keys", (PyCFunction)pyrna_prop_keys, METH_NOARGS, ""}, - {"items", (PyCFunction)pyrna_prop_items, METH_NOARGS, ""}, - {"values", (PyCFunction)pyrna_prop_values, METH_NOARGS, ""}, + {"keys", (PyCFunction)pyrna_prop_keys, METH_NOARGS, NULL}, + {"items", (PyCFunction)pyrna_prop_items, METH_NOARGS,NULL}, + {"values", (PyCFunction)pyrna_prop_values, METH_NOARGS, NULL}, + +#if (PY_VERSION_HEX >= 0x03000000) + /* array accessor function */ + {"foreach_get", (PyCFunction)pyrna_prop_foreach_get, METH_VARARGS, NULL}, + {"foreach_set", (PyCFunction)pyrna_prop_foreach_set, METH_VARARGS, NULL}, +#endif {NULL, NULL, 0, NULL} }; @@ -1251,10 +1775,21 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data) break; } case PROP_COLLECTION: - /* XXX not supported yet - * ret = pyrna_prop_CreatePyObject(ptr, prop); */ - ret = NULL; + { + ListBase *lb= (ListBase*)data; + CollectionPointerLink *link; + PyObject *linkptr; + + ret = PyList_New(0); + + for(link=lb->first; link; link=link->next) { + linkptr= pyrna_struct_CreatePyObject(&link->ptr); + PyList_Append(ret, linkptr); + Py_DECREF(linkptr); + } + break; + } default: PyErr_Format(PyExc_AttributeError, "RNA Error: unknown type \"%d\" (pyrna_param_to_py)", type); ret = NULL; @@ -1674,6 +2209,11 @@ PyObject *BPY_rna_module( void ) { PointerRNA ptr; +#ifdef USE_MATHUTILS // register mathutils callbacks, ok to run more then once. + mathutils_rna_array_cb_index= Mathutils_RegisterCallback(&mathutils_rna_array_cb); + mathutils_rna_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_rna_matrix_cb); +#endif + /* This can't be set in the pytype struct because some compilers complain */ pyrna_prop_Type.tp_getattro = PyObject_GenericGetAttr; pyrna_prop_Type.tp_setattro = PyObject_GenericSetAttr; @@ -1883,7 +2423,7 @@ PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw) char *id, *name="", *description=""; int def=0; - if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssi:IntProperty", kwlist, &id, &name, &description, &def)) + if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ssi:BoolProperty", kwlist, &id, &name, &description, &def)) return NULL; if (PyTuple_Size(args) > 0) { @@ -1897,7 +2437,7 @@ PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw) Py_RETURN_NONE; } else { PyObject *ret = PyTuple_New(2); - PyTuple_SET_ITEM(ret, 0, PyCObject_FromVoidPtr((void *)BPy_IntProperty, NULL)); + PyTuple_SET_ITEM(ret, 0, PyCObject_FromVoidPtr((void *)BPy_BoolProperty, NULL)); PyTuple_SET_ITEM(ret, 1, kw); Py_INCREF(kw); return ret; diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index 45614e992c6..d2f01b06336 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -1,5 +1,5 @@ /** - * $Id: bpy_rna.h 21247 2009-06-29 21:50:53Z jaguarandi $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/python/intern/bpy_ui.c b/source/blender/python/intern/bpy_ui.c index ccc8b2c206a..088fe436c69 100644 --- a/source/blender/python/intern/bpy_ui.c +++ b/source/blender/python/intern/bpy_ui.c @@ -1,5 +1,5 @@ /** - * $Id: bpy_ui.c 21247 2009-06-29 21:50:53Z jaguarandi $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/python/intern/bpy_ui.h b/source/blender/python/intern/bpy_ui.h index be5e5e87015..4182a32d3f0 100644 --- a/source/blender/python/intern/bpy_ui.h +++ b/source/blender/python/intern/bpy_ui.h @@ -1,5 +1,5 @@ /** - * $Id: bpy_ui.h 21247 2009-06-29 21:50:53Z jaguarandi $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/python/intern/bpy_util.c b/source/blender/python/intern/bpy_util.c index 6ec01e0c3fc..bce73b903c0 100644 --- a/source/blender/python/intern/bpy_util.c +++ b/source/blender/python/intern/bpy_util.c @@ -1,5 +1,5 @@ /** - * $Id: bpy_util.c 21247 2009-06-29 21:50:53Z jaguarandi $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -171,7 +171,7 @@ void PyObSpit(char *name, PyObject *var) { else { PyObject_Print(var, stderr, 0); fprintf(stderr, " ref:%d ", var->ob_refcnt); - fprintf(stderr, " ptr:%ld", (long)var); + fprintf(stderr, " ptr:%p", (void *)var); fprintf(stderr, " type:"); if(Py_TYPE(var)) diff --git a/source/blender/python/intern/bpy_util.h b/source/blender/python/intern/bpy_util.h index bc87da75de6..6429af67eb0 100644 --- a/source/blender/python/intern/bpy_util.h +++ b/source/blender/python/intern/bpy_util.h @@ -1,5 +1,5 @@ /** - * $Id: bpy_util.h 21247 2009-06-29 21:50:53Z jaguarandi $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/radiosity/CMakeLists.txt b/source/blender/radiosity/CMakeLists.txt deleted file mode 100644 index e76f7409f99..00000000000 --- a/source/blender/radiosity/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -# $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, Blender Foundation -# All rights reserved. -# -# The Original Code is: all of this file. -# -# Contributor(s): Jacques Beaurain. -# -# ***** END GPL LICENSE BLOCK ***** - -FILE(GLOB SRC intern/source/*.c) - -SET(INC - extern/include ../blenlib ../blenkernel ../makesdna ../editors/include - ../../../intern/guardedalloc ../render/extern/include - ../render/intern/include ../blenloader ../../../extern/glew/include -) - -BLENDERLIB_NOLIST(blender_radiosity "${SRC}" "${INC}") -#env.BlenderLib ( 'blender_radiosity', sources, Split(incs), [], libtype='core', priority=50 ) diff --git a/source/blender/radiosity/Makefile b/source/blender/radiosity/Makefile deleted file mode 100644 index 91a13e2fd57..00000000000 --- a/source/blender/radiosity/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# -# $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. -# -# The Original Code is: all of this file. -# -# Contributor(s): none yet. -# -# ***** END GPL LICENSE BLOCK ***** -# -# Makes module object directory and bounces make to subdirectories. - -SOURCEDIR = source/blender/radiosity -DIRS = intern - -include nan_subdirs.mk diff --git a/source/blender/radiosity/SConscript b/source/blender/radiosity/SConscript deleted file mode 100644 index 29854d2ee83..00000000000 --- a/source/blender/radiosity/SConscript +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/python -Import ('env') - -sources = env.Glob('intern/source/*.c') - -incs = 'extern/include ../blenlib ../blenkernel ../makesdna ../editors/include' -incs += ' #/intern/guardedalloc ../render/extern/include' -incs += ' ../render/intern/include ../blenloader #/extern/glew/include' - -incs += ' ' + env['BF_OPENGL_INC'] - -env.BlenderLib ( 'bf_radiosity', sources, Split(incs), [], libtype='core', priority=150 ) diff --git a/source/blender/radiosity/extern/include/radio.h b/source/blender/radiosity/extern/include/radio.h deleted file mode 100644 index e7f23302880..00000000000 --- a/source/blender/radiosity/extern/include/radio.h +++ /dev/null @@ -1,173 +0,0 @@ -/* *************************************** - - - - radio.h nov/dec 1992 - revised for Blender may 1999 - - $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. - - The Original Code is: all of this file. - - Contributor(s): none yet. - - ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef RADIO_H -#define RADIO_H -#define RADIO_H - -/* type include */ -#include "radio_types.h" - -extern RadGlobal RG; -struct View3D; -struct Scene; - -/* radfactors.c */ -extern float calcStokefactor(RPatch *shoot, RPatch *rp, RNode *rn, float *area); -extern void calcTopfactors(void); -void calcSidefactors(void); -extern void initradiosity(void); -extern void rad_make_hocos(RadView *vw); -extern void hemizbuf(RadView *vw); -extern int makeformfactors(RPatch *shoot); -extern void applyformfactors(RPatch *shoot); -extern RPatch *findshootpatch(void); -extern void setnodeflags(RNode *rn, int flag, int set); -extern void backface_test(RPatch *shoot); -extern void clear_backface_test(void); -extern void progressiverad(void); -extern void minmaxradelem(RNode *rn, float *min, float *max); -extern void minmaxradelemfilt(RNode *rn, float *min, float *max, float *errmin, float *errmax); -extern void subdivideshootElements(int it); -extern void subdivideshootPatches(int it); -extern void inithemiwindows(void); -extern void closehemiwindows(void); -void rad_init_energy(void); - -/* radio.c */ -void freeAllRad(struct Scene *scene); -int rad_phase(void); -void rad_status_str(char *str); -void rad_printstatus(void); -void rad_setlimits(struct Scene *scene); -void set_radglobal(struct Scene *scene); -void add_radio(struct Scene *scene); -void delete_radio(struct Scene *scene); -int rad_go(struct Scene *scene); -void rad_subdivshootpatch(struct Scene *scene); -void rad_subdivshootelem(struct Scene *scene); -void rad_limit_subdivide(struct Scene *scene); - -/* radnode.c */ -extern void setnodelimit(float limit); -extern float *mallocVert(void); -extern float *callocVert(void); -extern void freeVert(float *vert); -extern int totalRadVert(void); -extern RNode *mallocNode(void); -extern RNode *callocNode(void); -extern void freeNode(RNode *node); -extern void freeNode_recurs(RNode *node); -extern RPatch *mallocPatch(void); -extern RPatch *callocPatch(void); -extern void freePatch(RPatch *patch); -extern void replaceAllNode(RNode *, RNode *); -extern void replaceAllNodeInv(RNode *neighb, RNode *old); -extern void replaceAllNodeUp(RNode *neighb, RNode *old); -extern void replaceTestNode(RNode *, RNode **, RNode *, int , float *); -extern void free_fastAll(void); - -/* radnode.c */ -extern void start_fastmalloc(char *str); -extern int setvertexpointersNode(RNode *neighb, RNode *node, int level, float **v1, float **v2); -extern float edlen(float *v1, float *v2); -extern void deleteNodes(RNode *node); -extern void subdivideTriNode(RNode *node, RNode *edge); -extern void subdivideNode(RNode *node, RNode *edge); -extern int comparelevel(RNode *node, RNode *nb, int level); - -/* radpreprocess.c */ -extern void splitconnected(void); -extern int vergedge(const void *v1,const void *v2); -extern void addedge(float *v1, float *v2, EdSort *es); -extern void setedgepointers(void); -extern void rad_collect_meshes(struct Scene *scene, struct View3D *v3d); -extern void countelem(RNode *rn); -extern void countglobaldata(void); -extern void addelem(RNode ***el, RNode *rn, RPatch *rp); -extern void makeGlobalElemArray(void); -extern void remakeGlobaldata(void); -extern void splitpatch(RPatch *old); -extern void addpatch(RPatch *old, RNode *rn); -extern void converttopatches(void); -extern void make_elements(void); -extern void subdividelamps(void); -extern void maxsizePatches(void); -extern void subdiv_elements(void); - -/* radpostprocess.c */ -void addaccu(register char *z, register char *t); -void addaccuweight(register char *z, register char *t, int w); -void triaweight(Face *face, int *w1, int *w2, int *w3); -void init_face_tab(void); -Face *addface(void); -Face *makeface(float *v1, float *v2, float *v3, float *v4, RNode *rn); -void anchorQuadface(RNode *rn, float *v1, float *v2, float *v3, float *v4, int flag); -void anchorTriface(RNode *rn, float *v1, float *v2, float *v3, int flag); -float *findmiddlevertex(RNode *node, RNode *nb, float *v1, float *v2); -void make_face_tab(void); -void filterFaces(void); -void calcfiltrad(RNode *rn, float *cd); -void filterNodes(void); -void removeEqualNodes(short limit); -void rad_addmesh(struct Scene *scene); -void rad_replacemesh(struct Scene *scene); - -/* raddisplay.c */ -extern char calculatecolor(float col); -extern void make_node_display(void); -extern void drawnodeWire(RNode *rn); -extern void drawsingnodeWire(RNode *rn); -extern void drawnodeSolid(RNode *rn); -extern void drawnodeGour(RNode *rn); -extern void drawpatch(RPatch *patch, unsigned int col); -extern void drawfaceGour(Face *face); -extern void drawfaceSolid(Face *face); -extern void drawfaceWire(Face *face); -extern void drawsquare(float *cent, float size, short cox, short coy); -extern void drawlimits(void); -extern void setcolNode(RNode *rn, unsigned int *col); -extern void pseudoAmb(void); -extern void rad_forcedraw(void); -extern void drawpatch_ext(RPatch *patch, unsigned int col); -extern void RAD_drawall(int depth_is_on); - -/* radrender.c */ -struct Render; -extern void do_radio_render(struct Render *re); -void end_radio_render(void); - -#endif /* RADIO_H */ - diff --git a/source/blender/radiosity/extern/include/radio_types.h b/source/blender/radiosity/extern/include/radio_types.h deleted file mode 100644 index 5a218ee71be..00000000000 --- a/source/blender/radiosity/extern/include/radio_types.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * radio_types.h - * - * $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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/* #include "misc_util.h" */ /* for listbase...*/ - - -#ifndef RADIO_TYPES_H -#define RADIO_TYPES_H - -#include "DNA_listBase.h" -#include "DNA_material_types.h" - -struct Render; -struct CustomData; - -#define PI M_PI -#define RAD_MAXFACETAB 1024 -#define RAD_NEXTFACE(a) if( ((a) & 1023)==0 ) face= RG.facebase[(a)>>10]; else face++; - -/* RG.phase */ -#define RAD_SHOOTE 1 -#define RAD_SHOOTP 2 -#define RAD_SOLVE 3 - -typedef struct RadView { - float cam[3], tar[3], up[3]; - float wx1, wx2, wy1, wy2; - float mynear, myfar; - float viewmat[4][4], winmat[4][4]; - unsigned int *rect, *rectz; - short rectx, recty; - int wid; - -} RadView; - -/* rn->f */ -#define RAD_PATCH 1 -#define RAD_SHOOT 2 -#define RAD_SUBDIV 4 -#define RAD_BACKFACE 8 -#define RAD_TWOSIDED 16 - - -typedef struct RNode { /* length: 104 */ - struct RNode *down1, *down2, *up; - struct RNode *ed1, *ed2, *ed3, *ed4; - struct RPatch *par; - - char lev1, lev2, lev3, lev4; /* edgelevels */ - short type; /* type: 4==QUAD, 3==TRIA */ - short f; - float *v1, *v2, *v3, *v4; - float totrad[3], area; - - unsigned int col; - int orig; /* index in custom face data */ -} RNode; - - -typedef struct Face { /* length: 52 */ - float *v1, *v2, *v3, *v4; - unsigned int col, matindex; - int orig; /* index in custom face data */ -} Face; - -/* rp->f1 */ -#define RAD_NO_SPLIT 1 - -typedef struct RPatch { - struct RPatch *next, *prev; - RNode *first; /* first node==patch */ - - struct Object *from; - - int type; /* 3: TRIA, 4: QUAD */ - short f, f1; /* flags f: if node, only for subdiv */ - - float ref[3], emit[3], unshot[3]; - float cent[3], norm[3]; - float area; - int matindex; - -} RPatch; - - -typedef struct VeNoCo { /* needed for splitconnected */ - struct VeNoCo *next; - float *v; - float *n; - float *col; - int flag; -} VeNoCo; - - -typedef struct EdSort { /* sort edges */ - float *v1, *v2; - RNode *node; - int nr; -} EdSort; - -typedef struct { - struct Radio *radio; - unsigned int *hemibuf; - struct ListBase patchbase; - int totpatch, totelem, totvert, totlamp; - RNode **elem; /* global array with all pointers */ - VeNoCo *verts; /* temporal vertices from patches */ - float *formfactors; /* 1 factor per element */ - float *topfactors, *sidefactors; /* LUT for delta's */ - int *index; /* LUT for above LUT */ - Face **facebase; - int totface; - float min[3], max[3], size[3], cent[3]; /* world */ - float maxsize, totenergy; - float patchmin, patchmax; - float elemmin, elemmax; - float radfactor, lostenergy, igamma; /* radfac is in button, radfactor is calculated */ - int phase; - struct Render *re; /* for calling hemizbuf correctly */ - /* to preserve materials as used before, max 16 */ - Material *matar[MAXMAT]; - int totmat; - - /* for preserving face data */ - int mfdatatot; - struct CustomData *mfdata; - struct RNode **mfdatanodes; - - /* this part is a copy of struct Radio */ - short hemires, maxiter; - short drawtype, flag; /* bit 0 en 1: show limits */ - short subshootp, subshoote, nodelim, maxsublamp; - int maxnode; - float convergence; - float radfac, gamma; /* for display */ - -} RadGlobal; - -#endif /* radio_types.h */ - diff --git a/source/blender/radiosity/intern/Makefile b/source/blender/radiosity/intern/Makefile deleted file mode 100644 index 456b51cc56e..00000000000 --- a/source/blender/radiosity/intern/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# -# $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. -# -# The Original Code is: all of this file. -# -# Contributor(s): none yet. -# -# ***** END GPL LICENSE BLOCK ***** -# -# Makes module object directory and bounces make to subdirectories. - -SOURCEDIR = source/blender/radiosity/intern -DIRS = source - -include nan_subdirs.mk diff --git a/source/blender/radiosity/intern/source/Makefile b/source/blender/radiosity/intern/source/Makefile deleted file mode 100644 index 44b38de9bae..00000000000 --- a/source/blender/radiosity/intern/source/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -# -# $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. -# -# The Original Code is: all of this file. -# -# Contributor(s): none yet. -# -# ***** END GPL LICENSE BLOCK ***** -# -# radiosity uses the render lib -# - -LIBNAME = radiosity -DIR = $(OCGDIR)/blender/$(LIBNAME) - -include nan_compile.mk - -CFLAGS += $(LEVEL_1_C_WARNINGS) - -CPPFLAGS += -I$(NAN_GLEW)/include -CPPFLAGS += -I$(OPENGL_HEADERS) - -# not very neat.... -CPPFLAGS += -I../../../blenkernel -CPPFLAGS += -I../../../blenlib -CPPFLAGS += -I../../../makesdna -CPPFLAGS += -I../../../imbuf -CPPFLAGS += -I../../../ -CPPFLAGS += -I../../../blenloader -CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include - -# first /include is my own includes, second are the external includes -# third is the external interface. there should be a nicer way to say this -CPPFLAGS += -I../include -I../../../editors/include -I../../extern/include -CPPFLAGS += -I../../../render/extern/include -CPPFLAGS += -I../../../render/intern/include diff --git a/source/blender/radiosity/intern/source/raddisplay.c b/source/blender/radiosity/intern/source/raddisplay.c deleted file mode 100644 index ab9e8eedc28..00000000000 --- a/source/blender/radiosity/intern/source/raddisplay.c +++ /dev/null @@ -1,477 +0,0 @@ -/* *************************************** - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - - - - raddisplay.c nov/dec 1992 - may 1999 - - - drawing - - color calculation for display during solving - - $Id$ - - *************************************** */ - -#include -#include - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "BLI_blenlib.h" - -#include "DNA_radio_types.h" -#include "DNA_screen_types.h" -#include "DNA_space_types.h" -#include "DNA_view3d_types.h" - -#include "BKE_global.h" -#include "BKE_main.h" - -#include "BIF_gl.h" - -#include "radio.h" - -/* cpack has to be endian-insensitive! (old irisgl function) */ -#define cpack(x) glColor3ub( ((x)&0xFF), (((x)>>8)&0xFF), (((x)>>16)&0xFF) ) - -char calculatecolor(float col) -{ - int b; - - if(RG.gamma==1.0) { - b= RG.radfactor*col; - } - else if(RG.gamma==2.0) { - b= RG.radfactor*sqrt(col); - } - else { - b= RG.radfactor*pow(col, RG.igamma); - } - - if(b>255) b=255; - return b; -} - -void make_node_display() -{ - RNode *rn, **el; - int a; - char *charcol; - - RG.igamma= 1.0/RG.gamma; - RG.radfactor= RG.radfac*pow(64*64, RG.igamma); - - el= RG.elem; - for(a=RG.totelem; a>0; a--, el++) { - rn= *el; - charcol= (char *)&( rn->col ); - - charcol[3]= calculatecolor(rn->totrad[0]); - charcol[2]= calculatecolor(rn->totrad[1]); - charcol[1]= calculatecolor(rn->totrad[2]); - - /* gouraudcolor */ - *(rn->v1+3)= 0; - *(rn->v2+3)= 0; - *(rn->v3+3)= 0; - if(rn->v4) *(rn->v4+3)= 0; - } - - el= RG.elem; - for(a=RG.totelem; a>0; a--, el++) { - rn= *el; - addaccuweight( (char *)&(rn->col), (char *)(rn->v1+3), 16 ); - addaccuweight( (char *)&(rn->col), (char *)(rn->v2+3), 16 ); - addaccuweight( (char *)&(rn->col), (char *)(rn->v3+3), 16 ); - if(rn->v4) addaccuweight( (char *)&(rn->col), (char *)(rn->v4+3), 16 ); - } -} - -void drawnodeWire(RNode *rn) -{ - - if(rn->down1) { - drawnodeWire(rn->down1); - drawnodeWire(rn->down2); - } - else { - glBegin(GL_LINE_LOOP); - glVertex3fv(rn->v1); - glVertex3fv(rn->v2); - glVertex3fv(rn->v3); - if(rn->type==4) glVertex3fv(rn->v4); - glEnd(); - } -} - -void drawsingnodeWire(RNode *rn) -{ - - glBegin(GL_LINE_LOOP); - glVertex3fv(rn->v1); - glVertex3fv(rn->v2); - glVertex3fv(rn->v3); - if(rn->type==4) glVertex3fv(rn->v4); - glEnd(); -} - -void drawnodeSolid(RNode *rn) -{ - char *cp; - - if(rn->down1) { - drawnodeSolid(rn->down1); - drawnodeSolid(rn->down2); - } - else { - cp= (char *)&rn->col; - glColor3ub(cp[3], cp[2], cp[1]); - glBegin(GL_POLYGON); - glVertex3fv(rn->v1); - glVertex3fv(rn->v2); - glVertex3fv(rn->v3); - if(rn->type==4) glVertex3fv(rn->v4); - glEnd(); - } -} - -void drawnodeGour(RNode *rn) -{ - char *cp; - - if(rn->down1) { - drawnodeGour(rn->down1); - drawnodeGour(rn->down2); - } - else { - glBegin(GL_POLYGON); - cp= (char *)(rn->v1+3); - glColor3ub(cp[3], cp[2], cp[1]); - glVertex3fv(rn->v1); - - cp= (char *)(rn->v2+3); - glColor3ub(cp[3], cp[2], cp[1]); - glVertex3fv(rn->v2); - - cp= (char *)(rn->v3+3); - glColor3ub(cp[3], cp[2], cp[1]); - glVertex3fv(rn->v3); - - if(rn->type==4) { - cp= (char *)(rn->v4+3); - glColor3ub(cp[3], cp[2], cp[1]); - glVertex3fv(rn->v4); - } - glEnd(); - } -} - -void drawpatch_ext(RPatch *patch, unsigned int col) -{ - ScrArea *sa, *oldsa; - View3D *v3d; - glDrawBuffer(GL_FRONT); - - return; // XXX - - cpack(col); - - oldsa= NULL; // XXX curarea; - -// sa= G.curscreen->areabase.first; - while(sa) { - if (sa->spacetype==SPACE_VIEW3D) { - v3d= sa->spacedata.first; - - /* use mywinget() here: otherwise it draws in header */ -// XXX if(sa->win != mywinget()) areawinset(sa->win); -// XXX persp(PERSP_VIEW); - if(v3d->zbuf) glDisable(GL_DEPTH_TEST); - drawnodeWire(patch->first); - if(v3d->zbuf) glEnable(GL_DEPTH_TEST); // pretty useless? - } - sa= sa->next; - } - -// XXX if(oldsa && oldsa!=curarea) areawinset(oldsa->win); - - glFlush(); - glDrawBuffer(GL_BACK); -} - - -void drawfaceGour(Face *face) -{ - char *cp; - - glBegin(GL_POLYGON); - cp= (char *)(face->v1+3); - glColor3ub(cp[3], cp[2], cp[1]); - glVertex3fv(face->v1); - - cp= (char *)(face->v2+3); - glColor3ub(cp[3], cp[2], cp[1]); - glVertex3fv(face->v2); - - cp= (char *)(face->v3+3); - glColor3ub(cp[3], cp[2], cp[1]); - glVertex3fv(face->v3); - - if(face->v4) { - cp= (char *)(face->v4+3); - glColor3ub(cp[3], cp[2], cp[1]); - glVertex3fv(face->v4); - } - glEnd(); - -} - -void drawfaceSolid(Face *face) -{ - char *cp; - - cp= (char *)&face->col; - glColor3ub(cp[3], cp[2], cp[1]); - - glBegin(GL_POLYGON); - glVertex3fv(face->v1); - glVertex3fv(face->v2); - glVertex3fv(face->v3); - if(face->v4) { - glVertex3fv(face->v4); - } - glEnd(); - -} - -void drawfaceWire(Face *face) -{ - char *cp; - - cp= (char *)&face->col; - glColor3ub(cp[3], cp[2], cp[1]); - - glBegin(GL_LINE_LOOP); - glVertex3fv(face->v1); - glVertex3fv(face->v2); - glVertex3fv(face->v3); - if(face->v4) { - glVertex3fv(face->v4); - } - glEnd(); - -} - -void drawsquare(float *cent, float size, short cox, short coy) -{ - float vec[3]; - - vec[0]= cent[0]; - vec[1]= cent[1]; - vec[2]= cent[2]; - - glBegin(GL_LINE_LOOP); - vec[cox]+= .5*size; - vec[coy]+= .5*size; - glVertex3fv(vec); - vec[coy]-= size; - glVertex3fv(vec); - vec[cox]-= size; - glVertex3fv(vec); - vec[coy]+= size; - glVertex3fv(vec); - glEnd(); -} - -void drawlimits() -{ - /* center around cent */ - short cox=0, coy=1; - - if((RG.flag & (RAD_SHOWLIMITS|RAD_SHOWZ))==RAD_SHOWZ) coy= 2; - if((RG.flag & (RAD_SHOWLIMITS|RAD_SHOWZ))==(RAD_SHOWLIMITS|RAD_SHOWZ)) { - cox= 1; - coy= 2; - } - - cpack(0); - drawsquare(RG.cent, sqrt(RG.patchmax), cox, coy); - drawsquare(RG.cent, sqrt(RG.patchmin), cox, coy); - - drawsquare(RG.cent, sqrt(RG.elemmax), cox, coy); - drawsquare(RG.cent, sqrt(RG.elemmin), cox, coy); - - cpack(0xFFFFFF); - drawsquare(RG.cent, sqrt(RG.patchmax), cox, coy); - drawsquare(RG.cent, sqrt(RG.patchmin), cox, coy); - cpack(0xFFFF00); - drawsquare(RG.cent, sqrt(RG.elemmax), cox, coy); - drawsquare(RG.cent, sqrt(RG.elemmin), cox, coy); - -} - -void setcolNode(RNode *rn, unsigned int *col) -{ - - if(rn->down1) { - setcolNode(rn->down1, col); - setcolNode(rn->down2, col); - } - rn->col= *col; - - *((unsigned int *)rn->v1+3)= *col; - *((unsigned int *)rn->v2+3)= *col; - *((unsigned int *)rn->v3+3)= *col; - if(rn->v4) *((unsigned int *)rn->v4+3)= *col; -} - -void pseudoAmb() -{ - RPatch *rp; - float fac; - char col[4]; - - /* sets pseudo ambient color in the nodes */ - - rp= RG.patchbase.first; - while(rp) { - - if(rp->emit[0]!=0.0 || rp->emit[1]!=0.0 || rp->emit[2]!=0.0) { - col[1]= col[2]= col[3]= 255; - } - else { - fac= rp->norm[0]+ rp->norm[1]+ rp->norm[2]; - fac= 225.0*(3+fac)/6.0; - - col[3]= fac*rp->ref[0]; - col[2]= fac*rp->ref[1]; - col[1]= fac*rp->ref[2]; - } - - setcolNode(rp->first, (unsigned int *)col); - - rp= rp->next; - } -} - -void RAD_drawall(int depth_is_on) -{ - /* displays elements or faces */ - Face *face = NULL; - RNode **el; - RPatch *rp; - int a; - - if(!depth_is_on) { - glEnable(GL_DEPTH_TEST); - glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT); - } - - if(RG.totface) { - if(RG.drawtype==RAD_GOURAUD) { - glShadeModel(GL_SMOOTH); - for(a=0; afirst); - rp= rp->next; - } - } - } - else { - el= RG.elem; - if(RG.drawtype==RAD_GOURAUD) { - glShadeModel(GL_SMOOTH); - for(a=RG.totelem; a>0; a--, el++) { - drawnodeGour(*el); - } - } - else if(RG.drawtype==RAD_SOLID) { - for(a=RG.totelem; a>0; a--, el++) { - drawnodeSolid(*el); - } - } - else { - cpack(0); - for(a=RG.totelem; a>0; a--, el++) { - drawnodeWire(*el); - } - } - } - glShadeModel(GL_FLAT); - - if(RG.totpatch) { - if(RG.flag & (RAD_SHOWLIMITS|RAD_SHOWZ)) { - if(depth_is_on) glDisable(GL_DEPTH_TEST); - drawlimits(); - if(depth_is_on) glEnable(GL_DEPTH_TEST); - } - } - if(!depth_is_on) { - glDisable(GL_DEPTH_TEST); - } -} - -void rad_forcedraw() -{ - ScrArea *sa, *oldsa; - - return; // XXX - - oldsa= NULL; // XXX curarea; - -/// sa= G.curscreen->areabase.first; - while(sa) { - if (sa->spacetype==SPACE_VIEW3D) { - /* use mywinget() here: othwerwise it draws in header */ -// XXX if(sa->win != mywinget()) areawinset(sa->win); -// XXX scrarea_do_windraw(sa); - } - sa= sa->next; - } -// XXX screen_swapbuffers(); - -// XXX if(oldsa && oldsa!=curarea) areawinset(oldsa->win); -} - diff --git a/source/blender/radiosity/intern/source/radfactors.c b/source/blender/radiosity/intern/source/radfactors.c deleted file mode 100644 index b87473dd811..00000000000 --- a/source/blender/radiosity/intern/source/radfactors.c +++ /dev/null @@ -1,939 +0,0 @@ -/* *************************************** - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - - - - formfactors.c nov/dec 1992 - - $Id$ - - *************************************** */ - -#include -#include -#include - -#include "MEM_guardedalloc.h" - -#include "BLI_blenlib.h" -#include "BLI_arithb.h" -#include "BLI_rand.h" - -#include "BKE_utildefines.h" -#include "BKE_global.h" -#include "BKE_main.h" - -#include "radio.h" -#include "RE_render_ext.h" /* for `RE_zbufferall_radio and RE_zbufferall_radio */ - -/* locals */ -static void rad_setmatrices(RadView *vw); -static void clearsubflagelem(RNode *rn); -static void setsubflagelem(RNode *rn); - -RadView hemitop, hemiside; - -float calcStokefactor(RPatch *shoot, RPatch *rp, RNode *rn, float *area) -{ - float tvec[3], fac; - float vec[4][3]; /* vectors of shoot->cent to vertices rp */ - float cross[4][3]; /* cross products of this */ - float rad[4]; /* anlgles between vecs */ - - /* test for direction */ - VecSubf(tvec, shoot->cent, rp->cent); - if( tvec[0]*shoot->norm[0]+ tvec[1]*shoot->norm[1]+ tvec[2]*shoot->norm[2]>0.0) - return 0.0; - - if(rp->type==4) { - - /* corner vectors */ - VecSubf(vec[0], shoot->cent, rn->v1); - VecSubf(vec[1], shoot->cent, rn->v2); - VecSubf(vec[2], shoot->cent, rn->v3); - VecSubf(vec[3], shoot->cent, rn->v4); - - Normalize(vec[0]); - Normalize(vec[1]); - Normalize(vec[2]); - Normalize(vec[3]); - - /* cross product */ - Crossf(cross[0], vec[0], vec[1]); - Crossf(cross[1], vec[1], vec[2]); - Crossf(cross[2], vec[2], vec[3]); - Crossf(cross[3], vec[3], vec[0]); - Normalize(cross[0]); - Normalize(cross[1]); - Normalize(cross[2]); - Normalize(cross[3]); - - /* angles */ - rad[0]= vec[0][0]*vec[1][0]+ vec[0][1]*vec[1][1]+ vec[0][2]*vec[1][2]; - rad[1]= vec[1][0]*vec[2][0]+ vec[1][1]*vec[2][1]+ vec[1][2]*vec[2][2]; - rad[2]= vec[2][0]*vec[3][0]+ vec[2][1]*vec[3][1]+ vec[2][2]*vec[3][2]; - rad[3]= vec[3][0]*vec[0][0]+ vec[3][1]*vec[0][1]+ vec[3][2]*vec[0][2]; - - rad[0]= acos(rad[0]); - rad[1]= acos(rad[1]); - rad[2]= acos(rad[2]); - rad[3]= acos(rad[3]); - - /* Stoke formula */ - VecMulf(cross[0], rad[0]); - VecMulf(cross[1], rad[1]); - VecMulf(cross[2], rad[2]); - VecMulf(cross[3], rad[3]); - - VECCOPY(tvec, shoot->norm); - fac= tvec[0]*cross[0][0]+ tvec[1]*cross[0][1]+ tvec[2]*cross[0][2]; - fac+= tvec[0]*cross[1][0]+ tvec[1]*cross[1][1]+ tvec[2]*cross[1][2]; - fac+= tvec[0]*cross[2][0]+ tvec[1]*cross[2][1]+ tvec[2]*cross[2][2]; - fac+= tvec[0]*cross[3][0]+ tvec[1]*cross[3][1]+ tvec[2]*cross[3][2]; - } - else { - /* corner vectors */ - VecSubf(vec[0], shoot->cent, rn->v1); - VecSubf(vec[1], shoot->cent, rn->v2); - VecSubf(vec[2], shoot->cent, rn->v3); - - Normalize(vec[0]); - Normalize(vec[1]); - Normalize(vec[2]); - - /* cross product */ - Crossf(cross[0], vec[0], vec[1]); - Crossf(cross[1], vec[1], vec[2]); - Crossf(cross[2], vec[2], vec[0]); - Normalize(cross[0]); - Normalize(cross[1]); - Normalize(cross[2]); - - /* angles */ - rad[0]= vec[0][0]*vec[1][0]+ vec[0][1]*vec[1][1]+ vec[0][2]*vec[1][2]; - rad[1]= vec[1][0]*vec[2][0]+ vec[1][1]*vec[2][1]+ vec[1][2]*vec[2][2]; - rad[2]= vec[2][0]*vec[0][0]+ vec[2][1]*vec[0][1]+ vec[2][2]*vec[0][2]; - - rad[0]= acos(rad[0]); - rad[1]= acos(rad[1]); - rad[2]= acos(rad[2]); - - /* Stoke formula */ - VecMulf(cross[0], rad[0]); - VecMulf(cross[1], rad[1]); - VecMulf(cross[2], rad[2]); - - VECCOPY(tvec, shoot->norm); - fac= tvec[0]*cross[0][0]+ tvec[1]*cross[0][1]+ tvec[2]*cross[0][2]; - fac+= tvec[0]*cross[1][0]+ tvec[1]*cross[1][1]+ tvec[2]*cross[1][2]; - fac+= tvec[0]*cross[2][0]+ tvec[1]*cross[2][1]+ tvec[2]*cross[2][2]; - } - - *area= -fac/(2.0*PI); - return (*area * (shoot->area/rn->area)); -} - - -void calcTopfactors() -{ - float xsq , ysq, xysq; - float n; - float *fp; - int a, b, hres; - - fp = RG.topfactors; - hres= RG.hemires/2; - n= hres; - - for (a=0; aho); */ - /* ver->clip = testclip(ver->ho); */ -/* */ - /* } */ -} - -static void rad_setmatrices(RadView *vw) /* for hemi's */ -{ - float up1[3], len, twist; - - i_lookat(vw->cam[0], vw->cam[1], vw->cam[2], vw->tar[0], vw->tar[1], vw->tar[2], 0, vw->viewmat); - up1[0] = vw->viewmat[0][0]*vw->up[0] + vw->viewmat[1][0]*vw->up[1] + vw->viewmat[2][0]*vw->up[2]; - up1[1] = vw->viewmat[0][1]*vw->up[0] + vw->viewmat[1][1]*vw->up[1] + vw->viewmat[2][1]*vw->up[2]; - up1[2] = vw->viewmat[0][2]*vw->up[0] + vw->viewmat[1][2]*vw->up[1] + vw->viewmat[2][2]*vw->up[2]; - - len= up1[0]*up1[0]+up1[1]*up1[1]; - if(len>0.0) { - twist= -atan2(up1[0], up1[1]); - } - else twist= 0.0; - - i_lookat(vw->cam[0], vw->cam[1], vw->cam[2], vw->tar[0], vw->tar[1], vw->tar[2], (180.0*twist/M_PI), vw->viewmat); - - /* window matrix was set in inithemiwindows */ - -} - - -void hemizbuf(RadView *vw) -{ - float *factors; - unsigned int *rz; - int a, b, inda, hres; - - rad_setmatrices(vw); - RE_zbufferall_radio(vw, RG.elem, RG.totelem, RG.re); /* Render for when we got renderfaces */ - - /* count factors */ - if(vw->recty==vw->rectx) factors= RG.topfactors; - else factors= RG.sidefactors; - hres= RG.hemires/2; - - rz= vw->rect; - for(a=0; arecty; a++) { - inda= hres*RG.index[a]; - for(b=0; brectx; b++, rz++) { - if(*rznorm, vec); - len= Normalize(up); - /* this safety for input normals that are zero or illegal sized */ - if(a>3) return 0; - } while(len==0.0 || len>1.0); - - VECCOPY(hemitop.up, up); - VECCOPY(hemiside.up, shoot->norm); - - Crossf(side, shoot->norm, up); - - /* five targets */ - VecAddf(tar[0], shoot->cent, shoot->norm); - VecAddf(tar[1], shoot->cent, up); - VecSubf(tar[2], shoot->cent, up); - VecAddf(tar[3], shoot->cent, side); - VecSubf(tar[4], shoot->cent, side); - - /* camera */ - VECCOPY(hemiside.cam, shoot->cent); - VECCOPY(hemitop.cam, shoot->cent); - - /* do it! */ - VECCOPY(hemitop.tar, tar[0]); - hemizbuf(&hemitop); - - for(a=1; a<5; a++) { - VECCOPY(hemiside.tar, tar[a]); - hemizbuf(&hemiside); - } - - /* convert factors to real radiosity */ - re= RG.elem; - fp= RG.formfactors; - - overfl= 0; - for(a= RG.totelem; a>0; a--, re++, fp++) { - - if(*fp!=0.0) { - - *fp *= shoot->area/(*re)->area; - - if(*fp>1.0) { - overfl= 1; - *fp= 1.0001; - } - } - } - - if(overfl) { - if(shoot->first->down1) { - splitpatch(shoot); - return 0; - } - } - - return 1; -} - -void applyformfactors(RPatch *shoot) -{ - RPatch *rp; - RNode **el, *rn; - float *fp, *ref, unr, ung, unb, r, g, b, w; - int a; - - unr= shoot->unshot[0]; - ung= shoot->unshot[1]; - unb= shoot->unshot[2]; - - fp= RG.formfactors; - el= RG.elem; - for(a=0; apar; - ref= rp->ref; - - r= (*fp)*unr*ref[0]; - g= (*fp)*ung*ref[1]; - b= (*fp)*unb*ref[2]; - - w= rn->area/rp->area; - rn->totrad[0]+= r; - rn->totrad[1]+= g; - rn->totrad[2]+= b; - - rp->unshot[0]+= w*r; - rp->unshot[1]+= w*g; - rp->unshot[2]+= w*b; - } - } - - shoot->unshot[0]= shoot->unshot[1]= shoot->unshot[2]= 0.0; -} - -RPatch *findshootpatch() -{ - RPatch *rp, *shoot; - float energy, maxenergy; - - shoot= 0; - maxenergy= 0.0; - rp= RG.patchbase.first; - while(rp) { - energy= rp->unshot[0]*rp->area; - energy+= rp->unshot[1]*rp->area; - energy+= rp->unshot[2]*rp->area; - - if(energy>maxenergy) { - shoot= rp; - maxenergy= energy; - } - rp= rp->next; - } - - if(shoot) { - maxenergy/= RG.totenergy; - if(maxenergydown1) { - setnodeflags(rn->down1, flag, set); - setnodeflags(rn->down2, flag, set); - } - else { - if(set) rn->f |= flag; - else rn->f &= ~flag; - } -} - -void backface_test(RPatch *shoot) -{ - RPatch *rp; - float tvec[3]; - - rp= RG.patchbase.first; - while(rp) { - if(rp!=shoot) { - - VecSubf(tvec, shoot->cent, rp->cent); - if( tvec[0]*rp->norm[0]+ tvec[1]*rp->norm[1]+ tvec[2]*rp->norm[2]<0.0) { - setnodeflags(rp->first, RAD_BACKFACE, 1); - } - } - rp= rp->next; - } -} - -void clear_backface_test() -{ - RNode **re; - int a; - - re= RG.elem; - for(a= RG.totelem-1; a>=0; a--, re++) { - (*re)->f &= ~RAD_BACKFACE; - } - -} - -void rad_init_energy() -{ - /* call before shooting */ - /* keep patches and elements, clear all data */ - RNode **el, *rn; - RPatch *rp; - int a; - - el= RG.elem; - for(a=RG.totelem; a>0; a--, el++) { - rn= *el; - VECCOPY(rn->totrad, rn->par->emit); - } - - RG.totenergy= 0.0; - rp= RG.patchbase.first; - while(rp) { - VECCOPY(rp->unshot, rp->emit); - - RG.totenergy+= rp->unshot[0]*rp->area; - RG.totenergy+= rp->unshot[1]*rp->area; - RG.totenergy+= rp->unshot[2]*rp->area; - - rp->f= 0; - - rp= rp->next; - } -} - -void progressiverad() -{ - RPatch *shoot; - float unshot[3]; - int it= 0; - - rad_printstatus(); - rad_init_energy(); - - shoot=findshootpatch(); - - while( shoot ) { - - setnodeflags(shoot->first, RAD_SHOOT, 1); - - backface_test(shoot); - - drawpatch_ext(shoot, 0x88FF00); - - if(shoot->first->f & RAD_TWOSIDED) { - VECCOPY(unshot, shoot->unshot); - VecNegf(shoot->norm); - if(makeformfactors(shoot)) - applyformfactors(shoot); - VecNegf(shoot->norm); - VECCOPY(shoot->unshot, unshot); - } - - if( makeformfactors(shoot) ) { - applyformfactors(shoot); - - it++; - //XXX set_timecursor(it); - if( (it & 3)==1 ) { - make_node_display(); - rad_forcedraw(); - } - setnodeflags(shoot->first, RAD_SHOOT, 0); - } - - clear_backface_test(); - - //XXX if(blender_test_break()) break; - if(RG.maxiter && RG.maxiter<=it) break; - - shoot=findshootpatch(); - - } - -} - - -/* ************* subdivideshoot *********** */ - -void minmaxradelem(RNode *rn, float *min, float *max) -{ - int c; - - if(rn->down1) { - minmaxradelem(rn->down1, min, max); - minmaxradelem(rn->down2, min, max); - } - else { - for(c=0; c<3; c++) { - min[c]= MIN2(min[c], rn->totrad[c]); - max[c]= MAX2(max[c], rn->totrad[c]); - } - } -} - -void minmaxradelemfilt(RNode *rn, float *min, float *max, float *errmin, float *errmax) -{ - float col[3], area; - int c; - - if(rn->down1) { - minmaxradelemfilt(rn->down1, min, max, errmin, errmax); - minmaxradelemfilt(rn->down2, min, max, errmin, errmax); - } - else { - VECCOPY(col, rn->totrad); - - for(c=0; c<3; c++) { - min[c]= MIN2(min[c], col[c]); - max[c]= MAX2(max[c], col[c]); - } - - VecMulf(col, 2.0); - area= 2.0; - if(rn->ed1) { - VecAddf(col, rn->ed1->totrad, col); - area+= 1.0; - } - if(rn->ed2) { - VecAddf(col, rn->ed2->totrad, col); - area+= 1.0; - } - if(rn->ed3) { - VecAddf(col, rn->ed3->totrad, col); - area+= 1.0; - } - if(rn->ed4) { - VecAddf(col, rn->ed4->totrad, col); - area+= 1.0; - } - VecMulf(col, 1.0/area); - - for(c=0; c<3; c++) { - errmin[c]= MIN2(errmin[c], col[c]); - errmax[c]= MAX2(errmax[c], col[c]); - } - } -} - -static void setsubflagelem(RNode *rn) -{ - - if(rn->down1) { - setsubflagelem(rn->down1); - setsubflagelem(rn->down2); - } - else { - rn->f |= RAD_SUBDIV; - } -} - -static void clearsubflagelem(RNode *rn) -{ - - if(rn->down1) { - setsubflagelem(rn->down1); - setsubflagelem(rn->down2); - } - else { - rn->f &= ~RAD_SUBDIV; - } -} - -void subdivideshootElements(int it) -{ - RPatch *rp, *shoot; - RNode **el, *rn; - float *fp, err, stoke, area, min[3], max[3], errmin[3], errmax[3]; - int a, b, c, d, e, f, contin; - int maxlamp; - - if(RG.maxsublamp==0) maxlamp= RG.totlamp; - else maxlamp= RG.maxsublamp; - - while(it) { - rad_printstatus(); - rad_init_energy(); - it--; - - for(a=0; afirst, RAD_SHOOT, 1); - if( makeformfactors(shoot) ) { - - fp= RG.formfactors; - el= RG.elem; - for(b=RG.totelem; b>0; b--, el++) { - rn= *el; - - if( (rn->f & RAD_SUBDIV)==0 && *fp!=0.0) { - if(rn->par->emit[0]+rn->par->emit[1]+rn->par->emit[2]==0.0) { - - stoke= calcStokefactor(shoot, rn->par, rn, &area); - if(stoke!= 0.0) { - - err= *fp/stoke; - - /* area error */ - area*=(0.5*RG.hemires*RG.hemires); - - if(area>35.0) { - if(err<0.95 || err>1.05) { - if(err>0.05) { - rn->f |= RAD_SUBDIV; - rn->par->f |= RAD_SUBDIV; - } - } - } - } - - } - } - - fp++; - - } - - applyformfactors(shoot); - - if( (a & 3)==1 ) { - make_node_display(); - rad_forcedraw(); - } - - setnodeflags(shoot->first, RAD_SHOOT, 0); - } - else a--; - - //XXX if(blender_test_break()) break; - } - - /* test for extreme small color change within a patch with subdivflag */ - - rp= RG.patchbase.first; - - while(rp) { - if(rp->f & RAD_SUBDIV) { /* rp has elems that need subdiv */ - /* at least 4 levels deep */ - rn= rp->first->down1; - if(rn) { - rn= rn->down1; - if(rn) { - rn= rn->down1; - if(rn) rn= rn->down1; - } - } - if(rn) { - INIT_MINMAX(min, max); - /* errmin and max are the filtered colors */ - INIT_MINMAX(errmin, errmax); - minmaxradelemfilt(rp->first, min, max, errmin, errmax); - - /* if small difference between colors: no subdiv */ - /* also test for the filtered ones: but with higher critical level */ - - contin= 0; - a= abs( calculatecolor(min[0])-calculatecolor(max[0])); - b= abs( calculatecolor(errmin[0])-calculatecolor(errmax[0])); - if(a<15 || b<7) { - c= abs( calculatecolor(min[1])-calculatecolor(max[1])); - d= abs( calculatecolor(errmin[1])-calculatecolor(errmax[1])); - if(c<15 || d<7) { - e= abs( calculatecolor(min[2])-calculatecolor(max[2])); - f= abs( calculatecolor(errmin[2])-calculatecolor(errmax[2])); - if(e<15 || f<7) { - contin= 1; - clearsubflagelem(rp->first); - /* printf("%d %d %d %d %d %d\n", a, b, c, d, e, f); */ - } - } - } - if(contin) { - drawpatch_ext(rp, 0xFFFF); - } - } - } - rp->f &= ~RAD_SUBDIV; - rp= rp->next; - } - - contin= 0; - - el= RG.elem; - for(b=RG.totelem; b>0; b--, el++) { - rn= *el; - if(rn->f & RAD_SUBDIV) { - rn->f-= RAD_SUBDIV; - subdivideNode(rn, 0); - if(rn->down1) { - subdivideNode(rn->down1, 0); - subdivideNode(rn->down2, 0); - contin= 1; - } - } - } - makeGlobalElemArray(); - - //XXX if(contin==0 || blender_test_break()) break; - } - - make_node_display(); -} - -void subdivideshootPatches(int it) -{ - RPatch *rp, *shoot, *next; - float *fp, err, stoke, area; - int a, contin; - int maxlamp; - - if(RG.maxsublamp==0) maxlamp= RG.totlamp; - else maxlamp= RG.maxsublamp; - - while(it) { - rad_printstatus(); - rad_init_energy(); - it--; - - for(a=0; afirst, RAD_SHOOT, 1); - - if( makeformfactors(shoot) ) { - - fp= RG.formfactors; - rp= RG.patchbase.first; - while(rp) { - if(*fp!=0.0 && rp!=shoot) { - - stoke= calcStokefactor(shoot, rp, rp->first, &area); - if(stoke!= 0.0) { - if(area>.1) { /* does patch receive more than (about)10% of energy? */ - rp->f= RAD_SUBDIV; - } - else { - - err= *fp/stoke; - - /* area error */ - area*=(0.5*RG.hemires*RG.hemires); - - if(area>45.0) { - if(err<0.95 || err>1.05) { - if(err>0.05) { - - rp->f= RAD_SUBDIV; - - } - } - } - } - } - } - fp++; - - rp= rp->next; - } - - applyformfactors(shoot); - - if( (a & 3)==1 ) { - make_node_display(); - rad_forcedraw(); - } - - setnodeflags(shoot->first, RAD_SHOOT, 0); - - //XXX if(blender_test_break()) break; - } - else a--; - - } - - contin= 0; - - rp= RG.patchbase.first; - while(rp) { - next= rp->next; - if(rp->f & RAD_SUBDIV) { - if(rp->emit[0]+rp->emit[1]+rp->emit[2]==0.0) { - contin= 1; - subdivideNode(rp->first, 0); - if(rp->first->down1) { - subdivideNode(rp->first->down1, 0); - subdivideNode(rp->first->down2, 0); - } - } - } - rp= next; - } - - converttopatches(); - makeGlobalElemArray(); - - //XXX if(contin==0 || blender_test_break()) break; - } - make_node_display(); -} - -void inithemiwindows() -{ - RadView *vw; - - /* the hemiwindows */ - vw= &(hemitop); - memset(vw, 0, sizeof(RadView)); - vw->rectx= RG.hemires; - vw->recty= RG.hemires; - vw->rectz= MEM_mallocN(sizeof(int)*vw->rectx*vw->recty, "initwindows"); - vw->rect= MEM_mallocN(sizeof(int)*vw->rectx*vw->recty, "initwindows"); - vw->mynear= RG.maxsize/2000.0; - vw->myfar= 2.0*RG.maxsize; - vw->wx1= -vw->mynear; - vw->wx2= vw->mynear; - vw->wy1= -vw->mynear; - vw->wy2= vw->mynear; - - i_window(vw->wx1, vw->wx2, vw->wy1, vw->wy2, vw->mynear, vw->myfar, vw->winmat); - - hemiside= hemitop; - - vw= &(hemiside); - vw->recty/= 2; - vw->wy1= vw->wy2; - vw->wy2= 0.0; - - i_window(vw->wx1, vw->wx2, vw->wy1, vw->wy2, vw->mynear, vw->myfar, vw->winmat); - -} - -void closehemiwindows() -{ - - if(hemiside.rect) MEM_freeN(hemiside.rect); - if(hemiside.rectz) MEM_freeN(hemiside.rectz); - hemiside.rectz= 0; - hemiside.rect= 0; - hemitop.rectz= 0; - hemitop.rect= 0; -} diff --git a/source/blender/radiosity/intern/source/radio.c b/source/blender/radiosity/intern/source/radio.c deleted file mode 100644 index 63032b2d603..00000000000 --- a/source/blender/radiosity/intern/source/radio.c +++ /dev/null @@ -1,390 +0,0 @@ -/* *************************************** - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - - - - radio.c nov/dec 1992 - may 1999 - - $Id$ - - - mainloop - - interactivity - - - - PREPROCES - - collect meshes - - spitconnected (all faces with different color and normals) - - setedgepointers (nodes pointing to neighbours) - - - EDITING - - min-max patch en min-max element size - - using this info patches subdividing - - lamp subdivide - - - if there are too many lamps for subdivide shooting: - - temporal join patches - - - SUBDIVIDE SHOOTING - - except for last shooting, this defines patch subdivide - - if subdivided patches still > 2*minsize : continue - - at the end create as many elements as possible - - als store if lamp (can still) cause subdivide. - - - REFINEMENT SHOOTING - - test for overflows (shootpatch subdivide) - - testen for extreme color transitions: - - if possible: shootpatch subdivide - - elements subdivide = start over ? - - continue itterate until ? - - - DEFINITIVE SHOOTING - - user indicates how many faces maximum and duration of itteration. - - - POST PROCESS - - join element- nodes when nothing happens in it (filter nodes, filter faces) - - define gamma & mul - - *************************************** */ - -#include -#include - -#include "MEM_guardedalloc.h" -#include "PIL_time.h" - -#include "BLI_blenlib.h" - -#include "DNA_object_types.h" -#include "DNA_radio_types.h" -#include "DNA_scene_types.h" -#include "DNA_screen_types.h" - -#include "BKE_customdata.h" -#include "BKE_global.h" -#include "BKE_main.h" - -#include "radio.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -/* locals? This one was already done in radio.h... */ -/* void rad_status_str(char *str); */ - -RadGlobal RG= {0, 0}; - -void freeAllRad(Scene *scene) -{ - Base *base; - extern int Ntotvert, Ntotnode, Ntotpatch; - - /* clear flag that disables drawing the meshes */ - if(scene) { - base= (scene->base.first); - while(base) { - if(base->object->type==OB_MESH) { - base->flag &= ~OB_RADIO; - } - base= base->next; - } - } - - free_fastAll(); /* verts, nodes, patches */ - RG.patchbase.first= RG.patchbase.last= 0; - Ntotvert= Ntotnode= Ntotpatch= 0; - - closehemiwindows(); /* not real windows anymore... */ - if(RG.elem) MEM_freeN(RG.elem); - RG.elem= 0; - if(RG.verts) MEM_freeN(RG.verts); - RG.verts= 0; - if(RG.topfactors) MEM_freeN(RG.topfactors); - RG.topfactors= 0; - if(RG.sidefactors) MEM_freeN(RG.sidefactors); - RG.sidefactors= 0; - if(RG.formfactors) MEM_freeN(RG.formfactors); - RG.formfactors= 0; - if(RG.index) MEM_freeN(RG.index); - RG.index= 0; - if(RG.facebase) { - init_face_tab(); /* frees all tables */ - MEM_freeN(RG.facebase); - RG.facebase= 0; - } - - if(RG.mfdata) { - CustomData_free(RG.mfdata, RG.mfdatatot); - MEM_freeN(RG.mfdata); - MEM_freeN(RG.mfdatanodes); - RG.mfdatanodes= NULL; - RG.mfdata= NULL; - RG.mfdatatot= 0; - } - RG.totelem= RG.totpatch= RG.totvert= RG.totface= RG.totlamp= RG.totmat= 0; -} - -int rad_phase() -{ - int flag= 0; - - if(RG.totpatch) flag |= RAD_PHASE_PATCHES; - if(RG.totface) flag |= RAD_PHASE_FACES; - - return flag; -} - -void rad_status_str(char *str) -{ - extern int totfastmem; - int tot; - char *phase; - - tot= (RG.totface*sizeof(Face))/1024; - tot+= totfastmem/1024; - - if(RG.phase==RAD_SHOOTE) phase= "Phase: ELEMENT SUBD, "; - else if(RG.phase==RAD_SHOOTP) phase= "Phase: PATCH SUBD, "; - else if(RG.phase==RAD_SOLVE) phase= "Phase: SOLVE, "; - else if(RG.totpatch==0) phase= "Phase: COLLECT MESHES "; - else if(RG.totface) phase= "Phase: FINISHED, "; - else phase= "Phase: INIT, "; - - if(RG.totpatch==0) strcpy(str, phase); - else sprintf(str, "%s TotPatch: %d TotElem: %d Emit: %d Faces %d Mem: %d k ", phase, RG.totpatch, RG.totelem, RG.totlamp, RG.totface, tot); - - if(RG.phase==RAD_SOLVE) strcat(str, "(press ESC to stop)"); -} - -void rad_printstatus() -{ - /* actions always are started from a buttonswindow */ -// XX if(curarea) { -// scrarea_do_windraw(curarea); -// screen_swapbuffers(); -// } -} - -void rad_setlimits(Scene *scene) -{ - Radio *rad= scene->radio; - float fac; - - fac= 0.0005*rad->pama; - RG.patchmax= RG.maxsize*fac; - RG.patchmax*= RG.patchmax; - fac= 0.0005*rad->pami; - RG.patchmin= RG.maxsize*fac; - RG.patchmin*= RG.patchmin; - - fac= 0.0005*rad->elma; - RG.elemmax= RG.maxsize*fac; - RG.elemmax*= RG.elemmax; - fac= 0.0005*rad->elmi; - RG.elemmin= RG.maxsize*fac; - RG.elemmin*= RG.elemmin; -} - -void set_radglobal(Scene *scene) -{ - /* always call before any action is performed */ - Radio *rad= scene->radio; - - if(RG.radio==0) { - /* firsttime and to be sure */ - memset(&RG, 0, sizeof(RadGlobal)); - } - - if(rad==0) return; - - if(rad != RG.radio) { - if(RG.radio) freeAllRad(scene); - memset(&RG, 0, sizeof(RadGlobal)); - RG.radio= rad; - } - - RG.hemires= rad->hemires & 0xFFF0; - RG.drawtype= rad->drawtype; - RG.flag= rad->flag; - RG.subshootp= rad->subshootp; - RG.subshoote= rad->subshoote; - RG.nodelim= rad->nodelim; - RG.maxsublamp= rad->maxsublamp; - RG.maxnode= 2*rad->maxnode; /* in button:max elem, subdividing! */ - RG.convergence= rad->convergence/1000.0; - RG.radfac= rad->radfac; - RG.gamma= rad->gamma; - RG.maxiter= rad->maxiter; - - RG.re= NULL; /* struct render, for when call it from render engine */ - - rad_setlimits(scene); -} - -/* called from buttons.c */ -void add_radio(Scene *scene) -{ - Radio *rad; - - if(scene->radio) MEM_freeN(scene->radio); - rad= scene->radio= MEM_callocN(sizeof(Radio), "radio"); - - rad->hemires= 300; - rad->convergence= 0.1; - rad->radfac= 30.0; - rad->gamma= 2.0; - rad->drawtype= RAD_SOLID; - rad->subshootp= 1; - rad->subshoote= 2; - rad->maxsublamp= 0; - - rad->pama= 500; - rad->pami= 200; - rad->elma= 100; - rad->elmi= 20; - rad->nodelim= 0; - rad->maxnode= 10000; - rad->maxiter= 120; // arbitrary - rad->flag= 2; - set_radglobal(scene); -} - -void delete_radio(Scene *scene) -{ - freeAllRad(scene); - if(scene->radio) MEM_freeN(scene->radio); - scene->radio= 0; - - RG.radio= 0; -} - -int rad_go(Scene *scene) /* return 0 when user escapes */ -{ - double stime= PIL_check_seconds_timer(); - int retval; - - if(RG.totface) return 0; - - G.afbreek= 0; - - set_radglobal(scene); - initradiosity(); /* LUT's */ - inithemiwindows(); /* views */ - - maxsizePatches(); - - setnodelimit(RG.patchmin); - RG.phase= RAD_SHOOTP; - subdivideshootPatches(RG.subshootp); - - setnodelimit(RG.elemmin); - RG.phase= RAD_SHOOTE; - subdivideshootElements(RG.subshoote); - - setnodelimit(RG.patchmin); - subdividelamps(); - - setnodelimit(RG.elemmin); - - RG.phase= RAD_SOLVE; - subdiv_elements(); - - progressiverad(); - - removeEqualNodes(RG.nodelim); - - make_face_tab(); /* now anchored */ - - closehemiwindows(); - RG.phase= 0; - - stime= PIL_check_seconds_timer()-stime; - printf("Radiosity solving time: %dms\n", (int) (stime*1000)); - - if(G.afbreek==1) retval= 1; - else retval= 0; - - G.afbreek= 0; - - return retval; -} - -void rad_subdivshootpatch(Scene *scene) -{ - - if(RG.totface) return; - - G.afbreek= 0; - - set_radglobal(scene); - initradiosity(); /* LUT's */ - inithemiwindows(); /* views */ - - subdivideshootPatches(1); - - removeEqualNodes(RG.nodelim); - closehemiwindows(); - -// XXX allqueue(REDRAWVIEW3D, 1); -} - -void rad_subdivshootelem(Scene *scene) -{ - - if(RG.totface) return; - - G.afbreek= 0; - - set_radglobal(scene); - initradiosity(); /* LUT's */ - inithemiwindows(); /* views */ - - subdivideshootElements(1); - - removeEqualNodes(RG.nodelim); - closehemiwindows(); - -// XXX allqueue(REDRAWVIEW3D, 1); -} - -void rad_limit_subdivide(Scene *scene) -{ - - if(scene->radio==0) return; - - set_radglobal(scene); - - if(RG.totpatch==0) { - /* printf("exit: no relevant data\n"); */ - return; - } - - maxsizePatches(); - - init_face_tab(); /* free faces */ -} diff --git a/source/blender/radiosity/intern/source/radnode.c b/source/blender/radiosity/intern/source/radnode.c deleted file mode 100644 index fa23ca5da57..00000000000 --- a/source/blender/radiosity/intern/source/radnode.c +++ /dev/null @@ -1,1103 +0,0 @@ -/* *************************************** - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - - - - node.c nov/dec 1992 - may 1999 - - $Id$ - - *************************************** */ - -#include -#include -#include - -#include "MEM_guardedalloc.h" - -#include "BLI_blenlib.h" -#include "BLI_arithb.h" - -#include "BKE_global.h" -#include "BKE_main.h" - -#include "radio.h" - -#include "BLO_sys_types.h" // for intptr_t support - -#ifdef HAVE_CONFIG_H -#include -#endif - -/* locals */ -static void *malloc_fast(int size); -static void *calloc_fast(int size); -static void free_fast(void *poin, int siz); -static void deleteTriNodes(RNode *node); -/* lower because of local type define */ -/* void check_mallocgroup(MallocGroup *mg); */ - - -/* ********** fastmalloc ************** */ - -#define MAL_GROUPSIZE 256 -#define MAL_AVAILABLE 1 -#define MAL_FULL 2 - - - - -ListBase MallocBase= {0, 0}; -int totfastmem= 0; - -typedef struct MallocGroup { - struct MallocGroup *next, *prev; - short size, flag; - short curfree, tot; - char flags[MAL_GROUPSIZE]; - char *data; -} MallocGroup; - -/* one more local */ -void check_mallocgroup(MallocGroup *mg); - -void check_mallocgroup(MallocGroup *mg) -{ - int a; - char *cp; - - if(mg->tot==MAL_GROUPSIZE) { - mg->flag= MAL_FULL; - return; - } - - cp= mg->flags; - - if(mg->curfreecurfree+1]==0) { - mg->curfree++; - return; - } - } - if(mg->curfree>0) { - if(cp[mg->curfree-1]==0) { - mg->curfree--; - return; - } - } - - for(a=0; acurfree= a; - return; - } - } - printf("fastmalloc: shouldnt be here\n"); -} - -static void *malloc_fast(int size) -{ - MallocGroup *mg; - void *retval; - - mg= MallocBase.last; - while(mg) { - if(mg->size==size) { - if(mg->flag & MAL_AVAILABLE) { - mg->flags[mg->curfree]= 1; - mg->tot++; - retval= mg->data+mg->curfree*mg->size; - check_mallocgroup(mg); - return retval; - } - } - mg= mg->prev; - } - - /* no free block found */ - mg= MEM_callocN(sizeof(MallocGroup), "mallocgroup"); - BLI_addtail(&MallocBase, mg); - mg->data= MEM_mallocN(MAL_GROUPSIZE*size, "mallocgroupdata"); - mg->flag= MAL_AVAILABLE; - mg->flags[0]= 1; - mg->curfree= 1; - mg->size= size; - mg->tot= 1; - - totfastmem+= sizeof(MallocGroup)+MAL_GROUPSIZE*size; - - return mg->data; -} - -static void *calloc_fast(int size) -{ - void *poin; - - poin= malloc_fast(size); - memset(poin, 0, size); - - return poin; -} - -static void free_fast(void *poin, int size) -{ - MallocGroup *mg; - intptr_t val; - - mg= MallocBase.last; - while(mg) { - if(mg->size==size) { - if( ((intptr_t)poin) >= ((intptr_t)mg->data) ) { - if( ((intptr_t)poin) < ((intptr_t)(mg->data+MAL_GROUPSIZE*size)) ) { - val= ((intptr_t)poin) - ((intptr_t)mg->data); - val/= size; - mg->curfree= val; - mg->flags[val]= 0; - mg->flag= MAL_AVAILABLE; - - mg->tot--; - if(mg->tot==0) { - BLI_remlink(&MallocBase, mg); - MEM_freeN(mg->data); - MEM_freeN(mg); - totfastmem-= sizeof(MallocGroup)+MAL_GROUPSIZE*size; - } - return; - } - } - } - mg= mg->prev; - } - printf("fast free: pointer not in memlist %p size %d\n", - poin, size); -} - -/* security: only one function in a time can use it */ -static char *fastmallocstr= 0; - -void free_fastAll() -{ - MallocGroup *mg; - - mg= MallocBase.first; - while(mg) { - BLI_remlink(&MallocBase, mg); - MEM_freeN(mg->data); - MEM_freeN(mg); - mg= MallocBase.first; - } - totfastmem= 0; - fastmallocstr= 0; -} - -void start_fastmalloc(char *str) -{ - if(fastmallocstr) { -// XXX error("Fastmalloc in use: %s", fastmallocstr); - return; - } - fastmallocstr= str; -} - -/* **************************************** */ - -float nodelimit; - -void setnodelimit(float limit) -{ - nodelimit= limit; - -} - -/* ************ memory management *********** */ - -int Ntotvert=0, Ntotnode=0, Ntotpatch=0; - -float *mallocVert() -{ - Ntotvert++; - return (float *)malloc_fast(16); -} - -float *callocVert() -{ - Ntotvert++; - return (float *)calloc_fast(16); -} - -void freeVert(float *vert) -{ - free_fast(vert, 16); - Ntotvert--; -} - -int totalRadVert() -{ - return Ntotvert; -} - -RNode *mallocNode() -{ - Ntotnode++; - return (RNode *)malloc_fast(sizeof(RNode)); -} - -RNode *callocNode() -{ - Ntotnode++; - return (RNode *)calloc_fast(sizeof(RNode)); -} - -void freeNode(RNode *node) -{ - free_fast(node, sizeof(RNode)); - Ntotnode--; -} - -void freeNode_recurs(RNode *node) -{ - - if(node->down1) { - freeNode_recurs(node->down1); - freeNode_recurs(node->down2); - } - - node->down1= node->down2= 0; - freeNode(node); - -} - -RPatch *mallocPatch() -{ - Ntotpatch++; - return (RPatch *)malloc_fast(sizeof(RPatch)); -} - -RPatch *callocPatch() -{ - Ntotpatch++; - return (RPatch *)calloc_fast(sizeof(RPatch)); -} - -void freePatch(RPatch *patch) -{ - free_fast(patch, sizeof(RPatch)); - Ntotpatch--; -} - -/* ************ SUBDIVIDE *********** */ - - -void replaceAllNode(RNode *neighb, RNode *newn) -{ - /* changes from all neighbours the edgepointers that point to newn->up in new */ - int ok= 0; - - - if(neighb==0) return; - if(newn->up==0) return; - - if(neighb->ed1==newn->up) { - neighb->ed1= newn; - ok= 1; - } - else if(neighb->ed2==newn->up) { - neighb->ed2= newn; - ok= 1; - } - else if(neighb->ed3==newn->up) { - neighb->ed3= newn; - ok= 1; - } - else if(neighb->ed4==newn->up) { - neighb->ed4= newn; - ok= 1; - } - - if(ok && neighb->down1) { - replaceAllNode(neighb->down1, newn); - replaceAllNode(neighb->down2, newn); - } -} - -void replaceAllNodeInv(RNode *neighb, RNode *old) -{ - /* changes from all neighbours the edgepointers that point to old in old->up */ - if(neighb==0) return; - if(old->up==0) return; - - if(neighb->ed1==old) { - neighb->ed1= old->up; - } - else if(neighb->ed2==old) { - neighb->ed2= old->up; - } - else if(neighb->ed3==old) { - neighb->ed3= old->up; - } - else if(neighb->ed4==old) { - neighb->ed4= old->up; - } - - if(neighb->down1) { - replaceAllNodeInv(neighb->down1, old); - replaceAllNodeInv(neighb->down2, old); - } -} - -void replaceAllNodeUp(RNode *neighb, RNode *old) -{ - /* changes from all neighbours the edgepointers that point to old in old->up */ - if(neighb==0) return; - if(old->up==0) return; - neighb= neighb->up; - if(neighb==0) return; - - if(neighb->ed1==old) { - neighb->ed1= old->up; - } - else if(neighb->ed2==old) { - neighb->ed2= old->up; - } - else if(neighb->ed3==old) { - neighb->ed3= old->up; - } - else if(neighb->ed4==old) { - neighb->ed4= old->up; - } - - if(neighb->up) { - replaceAllNodeUp(neighb, old); - } -} - - -void replaceTestNode(RNode *neighb, RNode **edpp, RNode *newn, int level, float *vert) -{ - /* IF neighb->ed points to newn->up - * IF edgelevels equal - IF testvert is in neighb->ed - change pointers both ways - ELSE - RETURN - ELSE - IF neighb edgelevel is deeper - change neighb pointer - - */ - int ok= 0; - - if(neighb==0) return; - if(newn->up==0) return; - - if(neighb->ed1==newn->up) { - if(neighb->lev1==level) { - if(vert==neighb->v1 || vert==neighb->v2) { - *edpp= neighb; - neighb->ed1= newn; - } - else return; - } - else if(neighb->lev1>level) { - neighb->ed1= newn; - } - ok= 1; - } - else if(neighb->ed2==newn->up) { - if(neighb->lev2==level) { - if(vert==neighb->v2 || vert==neighb->v3) { - *edpp= neighb; - neighb->ed2= newn; - } - else return; - } - else if(neighb->lev2>level) { - neighb->ed2= newn; - } - ok= 1; - } - else if(neighb->ed3==newn->up) { - if(neighb->lev3==level) { - if(neighb->type==3) { - if(vert==neighb->v3 || vert==neighb->v1) { - *edpp= neighb; - neighb->ed3= newn; - } - else return; - } - else { - if(vert==neighb->v3 || vert==neighb->v4) { - *edpp= neighb; - neighb->ed3= newn; - } - else return; - } - } - else if(neighb->lev3>level) { - neighb->ed3= newn; - } - ok= 1; - } - else if(neighb->ed4==newn->up) { - if(neighb->lev4==level) { - if(vert==neighb->v4 || vert==neighb->v1) { - *edpp= neighb; - neighb->ed4= newn; - } - else return; - } - else if(neighb->lev4>level) { - neighb->ed4= newn; - } - ok= 1; - } - - if(ok && neighb->down1) { - replaceTestNode(neighb->down1, edpp, newn, level, vert); - replaceTestNode(neighb->down2, edpp, newn, level, vert); - } - -} - -int setvertexpointersNode(RNode *neighb, RNode *node, int level, float **v1, float **v2) -{ - /* compares edgelevels , if equal it sets the vertexpointers */ - - if(neighb==0) return 0; - - if(neighb->ed1==node) { - if(neighb->lev1==level) { - *v1= neighb->v1; - *v2= neighb->v2; - return 1; - } - } - else if(neighb->ed2==node) { - if(neighb->lev2==level) { - *v1= neighb->v2; - *v2= neighb->v3; - return 1; - } - } - else if(neighb->ed3==node) { - if(neighb->lev3==level) { - if(neighb->type==3) { - *v1= neighb->v3; - *v2= neighb->v1; - } - else { - *v1= neighb->v3; - *v2= neighb->v4; - } - return 1; - } - } - else if(neighb->ed4==node) { - if(neighb->lev4==level) { - *v1= neighb->v4; - *v2= neighb->v1; - return 1; - } - } - return 0; -} - -float edlen(float *v1, float *v2) -{ - return (v1[0]-v2[0])*(v1[0]-v2[0])+ (v1[1]-v2[1])*(v1[1]-v2[1])+ (v1[2]-v2[2])*(v1[2]-v2[2]); -} - - -void subdivideTriNode(RNode *node, RNode *edge) -{ - RNode *n1, *n2, *up; - float fu, fv, fl, *v1, *v2; /* , AreaT3Dfl(); ... from arithb... */ - int uvl; - - if(node->down1 || node->down2) { - /* printf("trinode: subd already done\n"); */ - return; - } - - /* defines subdivide direction */ - - if(edge==0) { - /* areathreshold */ - if(node->areav1, node->v2); - fv= edlen(node->v2, node->v3); - fl= edlen(node->v3, node->v1); - - if(fu>fv && fu>fl) uvl= 1; - else if(fv>fu && fv>fl) uvl= 2; - else uvl= 3; - } - else { - - if(edge==node->ed1) uvl= 1; - else if(edge==node->ed2) uvl= 2; - else uvl= 3; - } - - /* should neighbour nodes be deeper? Recursive! */ - n1= 0; - if(uvl==1) { - if(node->ed1 && node->ed1->down1==0) n1= node->ed1; - } - else if(uvl==2) { - if(node->ed2 && node->ed2->down1==0) n1= node->ed2; - } - else { - if(node->ed3 && node->ed3->down1==0) n1= node->ed3; - } - if(n1) { - up= node->up; - while(up) { /* also test for ed4 !!! */ - if(n1->ed1==up || n1->ed2==up || n1->ed3==up || n1->ed4==up) { - subdivideNode(n1, up); - break; - } - up= up->up; - } - } - - /* the subdividing */ - n1= mallocNode(); - memcpy(n1, node, sizeof(RNode)); - n2= mallocNode(); - memcpy(n2, node, sizeof(RNode)); - - n1->up= node; - n2->up= node; - - node->down1= n1; - node->down2= n2; - - /* subdivide edge 1 */ - if(uvl==1) { - - /* FIRST NODE gets edge 2 */ - n1->ed3= n2; - n1->lev3= 0; - replaceAllNode(n1->ed2, n1); - n1->lev1++; - replaceTestNode(n1->ed1, &(n1->ed1), n1, n1->lev1, n1->v2); - - /* SECOND NODE gets edge 3 */ - n2->ed2= n1; - n2->lev2= 0; - replaceAllNode(n2->ed3, n2); - n2->lev1++; - replaceTestNode(n2->ed1, &(n2->ed1), n2, n2->lev1, n2->v1); - - /* NEW VERTEX from edge 1 */ - if( setvertexpointersNode(n1->ed1, n1, n1->lev1, &v1, &v2) ) { /* nodes have equal levels */ - if(v1== n1->v2) { - n1->v1= v2; - n2->v2= v2; - } - else { - n1->v1= v1; - n2->v2= v1; - } - } - else { - n1->v1= n2->v2= mallocVert(); - n1->v1[0]= 0.5*(node->v1[0]+ node->v2[0]); - n1->v1[1]= 0.5*(node->v1[1]+ node->v2[1]); - n1->v1[2]= 0.5*(node->v1[2]+ node->v2[2]); - n1->v1[3]= node->v1[3]; /* color */ - } - } - else if(uvl==2) { - - /* FIRST NODE gets edge 1 */ - n1->ed3= n2; - n1->lev3= 0; - replaceAllNode(n1->ed1, n1); - n1->lev2++; - replaceTestNode(n1->ed2, &(n1->ed2), n1, n1->lev2, n1->v2); - - /* SECOND NODE gets edge 3 */ - n2->ed1= n1; - n2->lev1= 0; - replaceAllNode(n2->ed3, n2); - n2->lev2++; - replaceTestNode(n2->ed2, &(n2->ed2), n2, n2->lev2, n2->v3); - - /* NEW VERTEX from edge 2 */ - if( setvertexpointersNode(n1->ed2, n1, n1->lev2, &v1, &v2) ) { /* nodes have equal levels */ - if(v1== n1->v2) { - n1->v3= v2; - n2->v2= v2; - } - else { - n1->v3= v1; - n2->v2= v1; - } - } - else { - n1->v3= n2->v2= mallocVert(); - n1->v3[0]= 0.5*(node->v2[0]+ node->v3[0]); - n1->v3[1]= 0.5*(node->v2[1]+ node->v3[1]); - n1->v3[2]= 0.5*(node->v2[2]+ node->v3[2]); - n1->v3[3]= node->v1[3]; /* color */ - } - } - else if(uvl==3) { - - /* FIRST NODE gets edge 1 */ - n1->ed2= n2; - n1->lev2= 0; - replaceAllNode(n1->ed1, n1); - n1->lev3++; - replaceTestNode(n1->ed3, &(n1->ed3), n1, n1->lev3, n1->v1); - - /* SECOND NODE gets edge 2 */ - n2->ed1= n1; - n2->lev1= 0; - replaceAllNode(n2->ed2, n2); - n2->lev3++; - replaceTestNode(n2->ed3, &(n2->ed3), n2, n2->lev3, n2->v3); - - /* NEW VERTEX from edge 3 */ - if( setvertexpointersNode(n1->ed3, n1, n1->lev3, &v1, &v2) ) { /* nodes have equal levels */ - if(v1== n1->v1) { - n1->v3= v2; - n2->v1= v2; - } - else { - n1->v3= v1; - n2->v1= v1; - } - } - else { - n1->v3= n2->v1= mallocVert(); - n1->v3[0]= 0.5*(node->v1[0]+ node->v3[0]); - n1->v3[1]= 0.5*(node->v1[1]+ node->v3[1]); - n1->v3[2]= 0.5*(node->v1[2]+ node->v3[2]); - n1->v3[3]= node->v3[3]; /* color */ - } - } - n1->area= AreaT3Dfl(n1->v1, n1->v2, n1->v3); - n2->area= AreaT3Dfl(n2->v1, n2->v2, n2->v3); - -} - - -void subdivideNode(RNode *node, RNode *edge) -{ - RNode *n1, *n2, *up; - float fu, fv, *v1, *v2;/*, AreaQ3Dfl(); ... from arithb... */ - int uvl; - - if(Ntotnode>RG.maxnode) return; - - if(node->type==3) { - subdivideTriNode(node, edge); - return; - } - - if(node->down1 || node->down2) { - /* printf("subdivide Node: already done \n"); */ - return; - } - - /* defines subdivide direction */ - - if(edge==0) { - /* areathreshold */ - if(node->areav1[0]- node->v2[0])+ fabs(node->v1[1]- node->v2[1]) +fabs(node->v1[2]- node->v2[2]); - fv= fabs(node->v1[0]- node->v4[0])+ fabs(node->v1[1]- node->v4[1]) +fabs(node->v1[2]- node->v4[2]); - if(fu>fv) uvl= 1; - else uvl= 2; - } - else { - if(edge==node->ed1 || edge==node->ed3) uvl= 1; - else uvl= 2; - } - - /* do neighbour nodes have to be deeper? Recursive! */ - n1= n2= 0; - if(uvl==1) { - if(node->ed1 && node->ed1->down1==0) n1= node->ed1; - if(node->ed3 && node->ed3->down1==0) n2= node->ed3; - } - else { - if(node->ed2 && node->ed2->down1==0) n1= node->ed2; - if(node->ed4 && node->ed4->down1==0) n2= node->ed4; - } - if(n1) { - up= node->up; - while(up) { - if(n1->ed1==up || n1->ed2==up || n1->ed3==up || n1->ed4==up) { - /* printf("recurs subd\n"); */ - subdivideNode(n1, up); - break; - } - up= up->up; - } - } - if(n2) { - up= node->up; - while(up) { - if(n2->ed1==up || n2->ed2==up || n2->ed3==up || n2->ed4==up) { - /* printf("recurs subd\n"); */ - subdivideNode(n2, up); - break; - } - up= up->up; - } - } - - /* the subdividing */ - n1= mallocNode(); - memcpy(n1, node, sizeof(RNode)); - n2= mallocNode(); - memcpy(n2, node, sizeof(RNode)); - - n1->up= node; - n2->up= node; - - node->down1= n1; - node->down2= n2; - - /* subdivide edge 1 and 3 */ - if(uvl==1) { - - /* FIRST NODE gets edge 2 */ - n1->ed4= n2; - n1->lev4= 0; - replaceAllNode(n1->ed2, n1); - n1->lev1++; - n1->lev3++; - replaceTestNode(n1->ed1, &(n1->ed1), n1, n1->lev1, n1->v2); - replaceTestNode(n1->ed3, &(n1->ed3), n1, n1->lev3, n1->v3); - - /* SECOND NODE gets edge 4 */ - n2->ed2= n1; - n2->lev2= 0; - replaceAllNode(n2->ed4, n2); - n2->lev1++; - n2->lev3++; - replaceTestNode(n2->ed1, &(n2->ed1), n2, n2->lev1, n2->v1); - replaceTestNode(n2->ed3, &(n2->ed3), n2, n2->lev3, n2->v4); - - /* NEW VERTEX from edge 1 */ - if( setvertexpointersNode(n1->ed1, n1, n1->lev1, &v1, &v2) ) { /* nodes have equal levels */ - if(v1== n1->v2) { - n1->v1= v2; - n2->v2= v2; - } - else { - n1->v1= v1; - n2->v2= v1; - } - } - else { - n1->v1= n2->v2= mallocVert(); - n1->v1[0]= 0.5*(node->v1[0]+ node->v2[0]); - n1->v1[1]= 0.5*(node->v1[1]+ node->v2[1]); - n1->v1[2]= 0.5*(node->v1[2]+ node->v2[2]); - n1->v1[3]= node->v1[3]; /* color */ - } - - /* NEW VERTEX from edge 3 */ - if( setvertexpointersNode(n1->ed3, n1, n1->lev3, &v1, &v2) ) { /* nodes have equal levels */ - if(v1== n1->v3) { - n1->v4= v2; - n2->v3= v2; - } - else { - n1->v4= v1; - n2->v3= v1; - } - } - else { - n1->v4= n2->v3= mallocVert(); - n1->v4[0]= 0.5*(node->v3[0]+ node->v4[0]); - n1->v4[1]= 0.5*(node->v3[1]+ node->v4[1]); - n1->v4[2]= 0.5*(node->v3[2]+ node->v4[2]); - n1->v4[3]= node->v4[3]; /* color */ - } - } - /* subdivide edge 2 and 4 */ - else if(uvl==2) { - - /* FIRST NODE gets edge 1 */ - n1->ed3= n2; - n1->lev3= 0; - replaceAllNode(n1->ed1, n1); - n1->lev2++; - n1->lev4++; - replaceTestNode(n1->ed2, &(n1->ed2), n1, n1->lev2, n1->v2); - replaceTestNode(n1->ed4, &(n1->ed4), n1, n1->lev4, n1->v1); - - /* SECOND NODE gets edge 3 */ - n2->ed1= n1; - n2->lev1= 0; - replaceAllNode(n2->ed3, n2); - n2->lev2++; - n2->lev4++; - replaceTestNode(n2->ed2, &(n2->ed2), n2, n2->lev2, n2->v3); - replaceTestNode(n2->ed4, &(n2->ed4), n2, n2->lev4, n2->v4); - - /* NEW VERTEX from edge 2 */ - if( setvertexpointersNode(n1->ed2, n1, n1->lev2, &v1, &v2) ) { /* nodes have equal levels */ - if(v1== n1->v2) { - n1->v3= v2; - n2->v2= v2; - } - else { - n1->v3= v1; - n2->v2= v1; - } - } - else { - n1->v3= n2->v2= mallocVert(); - n1->v3[0]= 0.5*(node->v2[0]+ node->v3[0]); - n1->v3[1]= 0.5*(node->v2[1]+ node->v3[1]); - n1->v3[2]= 0.5*(node->v2[2]+ node->v3[2]); - n1->v3[3]= node->v3[3]; /* color */ - } - - /* NEW VERTEX from edge 4 */ - if( setvertexpointersNode(n1->ed4, n1, n1->lev4, &v1, &v2) ) { /* nodes have equal levels */ - if(v1== n1->v1) { - n1->v4= v2; - n2->v1= v2; - } - else { - n1->v4= v1; - n2->v1= v1; - } - } - else { - n1->v4= n2->v1= mallocVert(); - n1->v4[0]= 0.5*(node->v1[0]+ node->v4[0]); - n1->v4[1]= 0.5*(node->v1[1]+ node->v4[1]); - n1->v4[2]= 0.5*(node->v1[2]+ node->v4[2]); - n1->v4[3]= node->v4[3]; /* color */ - } - } - - n1->area= AreaQ3Dfl(n1->v1, n1->v2, n1->v3, n1->v4); - n2->area= AreaQ3Dfl(n2->v1, n2->v2, n2->v3, n2->v4); - -} - -int comparelevel(RNode *node, RNode *nb, int level) -{ - /* recursive descent: test with deepest node */ - /* return 1 means equal or higher */ - - if(nb==0) return 1; - - if(nb->down1) { - return 0; - - /* THERE IS AN ERROR HERE, BUT WHAT? (without this function the system - works too, but is slower) (ton) */ - - /* - n1= nb->down1; - if(n1->ed1==node) return comparelevel(node, n1, level); - if(n1->ed2==node) return comparelevel(node, n1, level); - if(n1->ed3==node) return comparelevel(node, n1, level); - if(n1->ed4==node) return comparelevel(node, n1, level); - n1= nb->down2; - if(n1->ed1==node) return comparelevel(node, n1, level); - if(n1->ed2==node) return comparelevel(node, n1, level); - if(n1->ed3==node) return comparelevel(node, n1, level); - if(n1->ed4==node) return comparelevel(node, n1, level); - printf(" dit kan niet "); - return 0; - */ - - } - - if(nb->down1==0) { - /* if(nb->ed1==node) return (nb->lev1<=level); */ - /* if(nb->ed2==node) return (nb->lev2<=level); */ - /* if(nb->ed3==node) return (nb->lev3<=level); */ - /* if(nb->ed4==node) return (nb->lev4<=level); */ - - return 1; /* is higher node */ - } - return 1; -} - -static void deleteTriNodes(RNode *node) /* both children of node */ -{ - RNode *n1, *n2; - - /* if neighbour nodes are deeper: no delete */ - /* just test 2 nodes, from the others the level doesn't change */ - - n1= node->down1; - n2= node->down2; - - if(n1==0 || n2==0) return; - - if(n1->down1 || n2->down1) return; - - /* at the edges no subdivided node is allowed */ - - if(n1->ed1 && n1->ed1->down1) return; - if(n1->ed2 && n1->ed2->down1) return; - if(n1->ed3 && n1->ed3->down1) return; - - if(n2->ed1 && n2->ed1->down1) return; - if(n2->ed2 && n2->ed2->down1) return; - if(n2->ed3 && n2->ed3->down1) return; - - replaceAllNodeInv(n1->ed1, n1); - replaceAllNodeInv(n1->ed2, n1); - replaceAllNodeInv(n1->ed3, n1); - - replaceAllNodeUp(n1->ed1, n1); - replaceAllNodeUp(n1->ed2, n1); - replaceAllNodeUp(n1->ed3, n1); - - replaceAllNodeInv(n2->ed1, n2); - replaceAllNodeInv(n2->ed2, n2); - replaceAllNodeInv(n2->ed3, n2); - - replaceAllNodeUp(n2->ed1, n2); - replaceAllNodeUp(n2->ed2, n2); - replaceAllNodeUp(n2->ed3, n2); - - n1->down1= (RNode *)12; /* for debug */ - n2->down1= (RNode *)12; - - freeNode(n1); - freeNode(n2); - node->down1= node->down2= 0; - -} - - /* both children of node */ -void deleteNodes(RNode *node) -{ - RNode *n1, *n2; - - /* if neighbour nodes are deeper: no delete */ - /* just test 2 nodes, from the others the level doesn't change */ - - if(node->type==3) { - deleteTriNodes(node); - return; - } - - n1= node->down1; - n2= node->down2; - - if(n1==0 || n2==0) return; - - if(n1->down1 || n2->down1) return; - - if(n1->ed3==n2) { - - /* at the edges no subdivided node is allowed */ - - if(n1->ed1 && n1->ed1->down1) return; - if(n1->ed2 && n1->ed2->down1) return; - if(n1->ed4 && n1->ed4->down1) return; - - if(n2->ed2 && n2->ed2->down1) return; - if(n2->ed3 && n2->ed3->down1) return; - if(n2->ed4 && n2->ed4->down1) return; - - replaceAllNodeInv(n1->ed1, n1); - replaceAllNodeInv(n1->ed2, n1); - replaceAllNodeInv(n1->ed4, n1); - - replaceAllNodeUp(n1->ed1, n1); - replaceAllNodeUp(n1->ed2, n1); - replaceAllNodeUp(n1->ed4, n1); - - replaceAllNodeInv(n2->ed2, n2); - replaceAllNodeInv(n2->ed3, n2); - replaceAllNodeInv(n2->ed4, n2); - - replaceAllNodeUp(n2->ed2, n2); - replaceAllNodeUp(n2->ed3, n2); - replaceAllNodeUp(n2->ed4, n2); - - n1->down1= (RNode *)12; /* for debug */ - n2->down1= (RNode *)12; - - freeNode(n1); - freeNode(n2); - node->down1= node->down2= 0; - - return; - } - else if(n1->ed4==n2) { - - if(n1->ed1 && n1->ed1->down1) return; - if(n1->ed2 && n1->ed2->down1) return; - if(n1->ed3 && n1->ed3->down1) return; - - if(n2->ed1 && n2->ed1->down1) return; - if(n2->ed3 && n2->ed3->down1) return; - if(n2->ed4 && n2->ed4->down1) return; - - replaceAllNodeInv(n1->ed1, n1); - replaceAllNodeInv(n1->ed2, n1); - replaceAllNodeInv(n1->ed3, n1); - - replaceAllNodeUp(n1->ed1, n1); - replaceAllNodeUp(n1->ed2, n1); - replaceAllNodeUp(n1->ed3, n1); - - replaceAllNodeInv(n2->ed1, n2); - replaceAllNodeInv(n2->ed3, n2); - replaceAllNodeInv(n2->ed4, n2); - - replaceAllNodeUp(n2->ed1, n2); - replaceAllNodeUp(n2->ed3, n2); - replaceAllNodeUp(n2->ed4, n2); - - n1->down1= (RNode *)12; /* for debug */ - n2->down1= (RNode *)12; - - freeNode(n1); - freeNode(n2); - node->down1= node->down2= 0; - - return; - } - -} - - diff --git a/source/blender/radiosity/intern/source/radpostprocess.c b/source/blender/radiosity/intern/source/radpostprocess.c deleted file mode 100644 index 6912c737a51..00000000000 --- a/source/blender/radiosity/intern/source/radpostprocess.c +++ /dev/null @@ -1,824 +0,0 @@ -/* *************************************** - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - - - - radpostprocess.c nov/dec 1992 - may 1999 - - - faces - - filtering and node-limit - - apply to meshes - $Id$ - - *************************************** */ - -#include -#include -#include - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "MEM_guardedalloc.h" - -#include "BLI_blenlib.h" -#include "BLI_arithb.h" -#include "BLI_ghash.h" - -#include "DNA_material_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_object_types.h" -#include "DNA_radio_types.h" -#include "DNA_scene_types.h" - -#include "BKE_customdata.h" -#include "BKE_global.h" -#include "BKE_main.h" -#include "BKE_material.h" -#include "BKE_mesh.h" -#include "BKE_object.h" -#include "BKE_utildefines.h" - -#include "radio.h" - -/* locals? not. done in radio.h... */ -/* void rad_addmesh(void); */ -/* void rad_replacemesh(void); */ - -void addaccu(register char *z, register char *t) -{ - register int div, mul; - - mul= *t; - div= mul+1; - (*t)++; - - t[1]= (mul*t[1]+z[1])/div; - t[2]= (mul*t[2]+z[2])/div; - t[3]= (mul*t[3]+z[3])/div; - -} - -void addaccuweight(register char *z, register char *t, int w) -{ - register int div, mul; - - if(w==0) w= 1; - - mul= *t; - div= mul+w; - if(div>255) return; - (*t)= div; - - t[1]= (mul*t[1]+w*z[1])/div; - t[2]= (mul*t[2]+w*z[2])/div; - t[3]= (mul*t[3]+w*z[3])/div; - -} - -void triaweight(Face *face, int *w1, int *w2, int *w3) -{ - float n1[3], n2[3], n3[3], temp; - - n1[0]= face->v2[0]-face->v1[0]; - n1[1]= face->v2[1]-face->v1[1]; - n1[2]= face->v2[2]-face->v1[2]; - n2[0]= face->v3[0]-face->v2[0]; - n2[1]= face->v3[1]-face->v2[1]; - n2[2]= face->v3[2]-face->v2[2]; - n3[0]= face->v1[0]-face->v3[0]; - n3[1]= face->v1[1]-face->v3[1]; - n3[2]= face->v1[2]-face->v3[2]; - Normalize(n1); - Normalize(n2); - Normalize(n3); - temp= 32.0/(PI); - *w1= 0.5+temp*acos(-n1[0]*n3[0]-n1[1]*n3[1]-n1[2]*n3[2]); - *w2= 0.5+temp*acos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]); - *w3= 0.5+temp*acos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]); - -} - - - -void init_face_tab() -{ - int a= 0; - - if(RG.facebase==0) { - RG.facebase= MEM_callocN(sizeof(void *)*RAD_MAXFACETAB, "init_face_tab"); - } - for(a=0; aRAD_MAXFACETAB*1024 ) { - printf("error in addface: %d\n", RG.totface); - return 0; - } - a= RG.totface>>10; - face= RG.facebase[a]; - if(face==0) { - face= MEM_callocN(1024*sizeof(Face),"addface"); - RG.facebase[a]= face; - } - face+= (RG.totface & 1023); - - RG.totface++; - - return face; - -} - -Face * makeface(float *v1, float *v2, float *v3, float *v4, RNode *rn) -{ - Face *face; - - face= addface(); - face->v1= v1; - face->v2= v2; - face->v3= v3; - face->v4= v4; - face->col= rn->col; - face->matindex= rn->par->matindex; - face->orig= rn->orig; - - return face; -} - -void anchorQuadface(RNode *rn, float *v1, float *v2, float *v3, float *v4, int flag) -{ - Face *face; - - switch(flag) { - case 1: - face = makeface(rn->v1, v1, rn->v4, NULL, rn); - face = makeface(v1, rn->v3, rn->v4, NULL, rn); - face = makeface(v1, rn->v2, rn->v3, NULL, rn); - break; - case 2: - face = makeface(rn->v2, v2, rn->v1, NULL, rn); - face = makeface(v2, rn->v4, rn->v1, NULL, rn); - face = makeface(v2, rn->v3, rn->v4, NULL, rn); - break; - case 4: - face = makeface(rn->v3, v3, rn->v2, NULL, rn); - face = makeface(v3, rn->v1, rn->v2, NULL, rn); - face = makeface(v3, rn->v4, rn->v1, NULL, rn); - break; - case 8: - face = makeface(rn->v4, v4, rn->v3, NULL, rn); - face = makeface(v4, rn->v2, rn->v3, NULL, rn); - face = makeface(v4, rn->v1, rn->v2, NULL, rn); - break; - case 3: - face = makeface(rn->v1, v1, rn->v4, NULL, rn); - face = makeface(v1, v2, rn->v4, NULL, rn); - face = makeface(v1, rn->v2, v2, NULL, rn); - face = makeface(v2, rn->v3, rn->v4, NULL, rn); - break; - case 6: - face = makeface(rn->v2, v2, rn->v1, NULL, rn); - face = makeface(v2, v3, rn->v1, NULL, rn); - face = makeface(v2, rn->v3, v3, NULL, rn); - face = makeface(v3, rn->v4, rn->v1, NULL, rn); - break; - case 12: - face = makeface(rn->v3, v3, rn->v2, NULL, rn); - face = makeface(v3, v4, rn->v2, NULL, rn); - face = makeface(v3, rn->v4, v4, NULL, rn); - face = makeface(v4, rn->v1, rn->v2, NULL, rn); - break; - case 9: - face = makeface(rn->v4, v4, rn->v3, NULL, rn); - face = makeface(v4, v1, rn->v3, NULL, rn); - face = makeface(v4, rn->v1, v1, NULL, rn); - face = makeface(v1, rn->v2, rn->v3, NULL, rn); - break; - case 5: - face = makeface(rn->v1, v1, v3, rn->v4, rn); - face = makeface(v1, rn->v2, rn->v3, v3, rn); - break; - case 10: - face = makeface(rn->v1, rn->v2, v2, v4, rn); - face = makeface(v4, v2, rn->v3, rn->v4, rn); - break; - case 7: - face = makeface(rn->v1, v1, v3, rn->v4, rn); - face = makeface(v1, v2, v3, NULL, rn); - face = makeface(v1, rn->v2, v2, NULL, rn); - face = makeface(v2, rn->v3, v3, NULL, rn); - break; - case 14: - face = makeface(rn->v2, v2, v4, rn->v1, rn); - face = makeface(v2, v3, v4, NULL, rn); - face = makeface(v2, rn->v3, v3, NULL, rn); - face = makeface(v3, rn->v4, v4, NULL, rn); - break; - case 13: - face = makeface(rn->v3, v3, v1, rn->v2, rn); - face = makeface(v3, v4, v1, NULL, rn); - face = makeface(v3, rn->v4, v4, NULL, rn); - face = makeface(v4, rn->v1, v1, NULL, rn); - break; - case 11: - face = makeface(rn->v4, v4, v2, rn->v3, rn); - face = makeface(v4, v1, v2, NULL, rn); - face = makeface(v4, rn->v1, v1, NULL, rn); - face = makeface(v1, rn->v2, v2, NULL, rn); - break; - case 15: - face = makeface(v1, v2, v3, v4, rn); - face = makeface(v1, rn->v2, v2, NULL, rn); - face = makeface(v2, rn->v3, v3, NULL, rn); - face = makeface(v3, rn->v4, v4, NULL, rn); - face = makeface(v4, rn->v1, v1, NULL, rn); - break; - } -} - -void anchorTriface(RNode *rn, float *v1, float *v2, float *v3, int flag) -{ - Face *face; - - switch(flag) { - case 1: - face = makeface(rn->v1, v1, rn->v3, NULL, rn); - face = makeface(v1, rn->v2, rn->v3, NULL, rn); - break; - case 2: - face = makeface(rn->v2, v2, rn->v1, NULL, rn); - face = makeface(v2, rn->v3, rn->v1, NULL, rn); - break; - case 4: - face = makeface(rn->v3, v3, rn->v2, NULL, rn); - face = makeface(v3, rn->v1, rn->v2, NULL, rn); - break; - case 3: - face = makeface(rn->v1, v2, rn->v3, NULL, rn); - face = makeface(rn->v1, v1, v2, NULL, rn); - face = makeface(v1, rn->v2, v2, NULL, rn); - break; - case 6: - face = makeface(rn->v2, v3, rn->v1, NULL, rn); - face = makeface(rn->v2, v2, v3, NULL, rn); - face = makeface(v2, rn->v3, v3, NULL, rn); - break; - case 5: - face = makeface(rn->v3, v1, rn->v2, NULL, rn); - face = makeface(rn->v3, v3, v1, NULL, rn); - face = makeface(v3, rn->v1, v1, NULL, rn); - break; - - case 7: - face = makeface(v1, v2, v3, NULL, rn); - face = makeface(rn->v1, v1, v3, NULL, rn); - face = makeface(rn->v2, v2, v1, NULL, rn); - face = makeface(rn->v3, v3, v2, NULL, rn); - break; - } -} - - -float *findmiddlevertex(RNode *node, RNode *nb, float *v1, float *v2) -{ - int test= 0; - - if(nb==0) return 0; - - if(nb->ed1==node) { - if(nb->v1==v1 || nb->v1==v2) test++; - if(nb->v2==v1 || nb->v2==v2) test+=2; - if(test==1) return nb->v2; - else if(test==2) return nb->v1; - } - else if(nb->ed2==node) { - if(nb->v2==v1 || nb->v2==v2) test++; - if(nb->v3==v1 || nb->v3==v2) test+=2; - if(test==1) return nb->v3; - else if(test==2) return nb->v2; - } - else if(nb->ed3==node) { - if(nb->type==4) { - if(nb->v3==v1 || nb->v3==v2) test++; - if(nb->v4==v1 || nb->v4==v2) test+=2; - if(test==1) return nb->v4; - else if(test==2) return nb->v3; - } - else { - if(nb->v3==v1 || nb->v3==v2) test++; - if(nb->v1==v1 || nb->v1==v2) test+=2; - if(test==1) return nb->v1; - else if(test==2) return nb->v3; - } - } - else if(nb->ed4==node) { - if(nb->v4==v1 || nb->v4==v2) test++; - if(nb->v1==v1 || nb->v1==v2) test+=2; - if(test==1) return nb->v1; - else if(test==2) return nb->v4; - } - return 0; -} - -void make_face_tab() /* takes care of anchoring */ -{ - RNode *rn, **el; - Face *face = NULL; - float *v1, *v2, *v3, *v4; - int a, flag, w1, w2, w3; - char *charcol; - - if(RG.totelem==0) return; - - init_face_tab(); - - RG.igamma= 1.0/RG.gamma; - RG.radfactor= RG.radfac*pow(64*64, RG.igamma); - - /* convert face colors */ - el= RG.elem; - for(a=RG.totelem; a>0; a--, el++) { - rn= *el; - charcol= (char *)&( rn->col ); - - charcol[3]= calculatecolor(rn->totrad[0]); - charcol[2]= calculatecolor(rn->totrad[1]); - charcol[1]= calculatecolor(rn->totrad[2]); - } - - /* check nodes and make faces */ - el= RG.elem; - for(a=RG.totelem; a>0; a--, el++) { - - rn= *el; - - rn->v1[3]= 0.0; - rn->v2[3]= 0.0; - rn->v3[3]= 0.0; - if(rn->v4) rn->v4[3]= 0.0; - - /* test edges for subdivide */ - flag= 0; - v1= v2= v3= v4= 0; - if(rn->ed1) { - v1= findmiddlevertex(rn, rn->ed1->down1, rn->v1, rn->v2); - if(v1) flag |= 1; - } - if(rn->ed2) { - v2= findmiddlevertex(rn, rn->ed2->down1, rn->v2, rn->v3); - if(v2) flag |= 2; - } - if(rn->ed3) { - if(rn->type==4) - v3= findmiddlevertex(rn, rn->ed3->down1, rn->v3, rn->v4); - else - v3= findmiddlevertex(rn, rn->ed3->down1, rn->v3, rn->v1); - if(v3) flag |= 4; - } - if(rn->ed4) { - v4= findmiddlevertex(rn, rn->ed4->down1, rn->v4, rn->v1); - if(v4) flag |= 8; - } - - /* using flag and vertexpointers now Faces can be made */ - - if(flag==0) { - makeface(rn->v1, rn->v2, rn->v3, rn->v4, rn); - } - else if(rn->type==4) anchorQuadface(rn, v1, v2, v3, v4, flag); - else anchorTriface(rn, v1, v2, v3, flag); - } - - /* add */ - for(a=0; av4) { - addaccuweight( (char *)&(face->col), (char *)(face->v1+3), 16 ); - addaccuweight( (char *)&(face->col), (char *)(face->v2+3), 16 ); - addaccuweight( (char *)&(face->col), (char *)(face->v3+3), 16 ); - addaccuweight( (char *)&(face->col), (char *)(face->v4+3), 16 ); - } - else { - triaweight(face, &w1, &w2, &w3); - addaccuweight( (char *)&(face->col), (char *)(face->v1+3), w1 ); - addaccuweight( (char *)&(face->col), (char *)(face->v2+3), w2 ); - addaccuweight( (char *)&(face->col), (char *)(face->v3+3), w3 ); - } - } - -} - -void filterFaces() -{ - /* put vertex colors in faces, and put them back */ - - Face *face = NULL; - int a, w1, w2, w3; - - if(RG.totface==0) return; - - /* clear */ - for(a=0; acol= 0; - } - - /* add: vertices with faces */ - for(a=0; av4) { - addaccuweight( (char *)(face->v1+3), (char *)&(face->col), 16 ); - addaccuweight( (char *)(face->v2+3), (char *)&(face->col), 16 ); - addaccuweight( (char *)(face->v3+3), (char *)&(face->col), 16 ); - addaccuweight( (char *)(face->v4+3), (char *)&(face->col), 16 ); - } - else { - triaweight(face, &w1, &w2, &w3); - addaccuweight( (char *)(face->v1+3), (char *)&(face->col), w1 ); - addaccuweight( (char *)(face->v2+3), (char *)&(face->col), w2 ); - addaccuweight( (char *)(face->v3+3), (char *)&(face->col), w3 ); - } - } - - /* clear */ - for(a=0; av1[3]= 0.0; - face->v2[3]= 0.0; - face->v3[3]= 0.0; - if(face->v4) face->v4[3]= 0.0; - } - - - /* add: faces with vertices */ - for(a=0; av4) { - addaccuweight( (char *)&(face->col), (char *)(face->v1+3), 16 ); - addaccuweight( (char *)&(face->col), (char *)(face->v2+3), 16 ); - addaccuweight( (char *)&(face->col), (char *)(face->v3+3), 16 ); - addaccuweight( (char *)&(face->col), (char *)(face->v4+3), 16 ); - } - else { - triaweight(face, &w1, &w2, &w3); - addaccuweight( (char *)&(face->col), (char *)(face->v1+3), w1 ); - addaccuweight( (char *)&(face->col), (char *)(face->v2+3), w2 ); - addaccuweight( (char *)&(face->col), (char *)(face->v3+3), w3 ); - } - } -} - -void calcfiltrad(RNode *rn, float *cd) -{ - float area; - - cd[0]= 2.0*rn->totrad[0]; - cd[1]= 2.0*rn->totrad[1]; - cd[2]= 2.0*rn->totrad[2]; - area= 2.0; - - if(rn->ed1) { - cd[0]+= rn->ed1->totrad[0]; - cd[1]+= rn->ed1->totrad[1]; - cd[2]+= rn->ed1->totrad[2]; - area+= 1.0; - } - if(rn->ed2) { - cd[0]+= rn->ed2->totrad[0]; - cd[1]+= rn->ed2->totrad[1]; - cd[2]+= rn->ed2->totrad[2]; - area+= 1.0; - } - if(rn->ed3) { - cd[0]+= rn->ed3->totrad[0]; - cd[1]+= rn->ed3->totrad[1]; - cd[2]+= rn->ed3->totrad[2]; - area+= 1.0; - } - if(rn->ed4) { - cd[0]+= rn->ed4->totrad[0]; - cd[1]+= rn->ed4->totrad[1]; - cd[2]+= rn->ed4->totrad[2]; - area+= 1.0; - } - cd[0]/= area; - cd[1]/= area; - cd[2]/= area; - -} - -void filterNodes() -{ - /* colors from nodes in tempblock and back */ - - RNode *rn, **el; - float *coldata, *cd; - int a; - - if(RG.totelem==0) return; - /* the up-nodes need a color */ - el= RG.elem; - for(a=0; aup) { - rn->up->totrad[0]= 0.0; - rn->up->totrad[1]= 0.0; - rn->up->totrad[2]= 0.0; - if(rn->up->up) { - rn->up->up->totrad[0]= 0.0; - rn->up->up->totrad[1]= 0.0; - rn->up->up->totrad[2]= 0.0; - } - } - } - el= RG.elem; - for(a=0; aup) { - rn->up->totrad[0]+= 0.5*rn->totrad[0]; - rn->up->totrad[1]+= 0.5*rn->totrad[1]; - rn->up->totrad[2]+= 0.5*rn->totrad[2]; - if(rn->up->up) { - rn->up->up->totrad[0]+= 0.25*rn->totrad[0]; - rn->up->up->totrad[1]+= 0.25*rn->totrad[1]; - rn->up->up->totrad[2]+= 0.25*rn->totrad[2]; - } - } - } - - /* add using area */ - cd= coldata= MEM_mallocN(3*4*RG.totelem, "filterNodes"); - el= RG.elem; - for(a=0; atotrad, cd); - cd+= 3; - } - MEM_freeN(coldata); -} - -void removeEqualNodes(short limit) -{ - /* nodes with equal colors: remove */ - RNode **el, *rn, *rn1; - float thresh, f1, f2; - int a, foundone=1, ok; - int c1, c2; - - if(limit==0) return; - - thresh= 1.0/(256.0*RG.radfactor); - thresh= 3.0*pow(thresh, RG.gamma); - -// XXX waitcursor(1); - - while(foundone) { - foundone= 0; - - el= RG.elem; - for(a=RG.totelem; a>1; a--, el++) { - rn= *el; - rn1= *(el+1); - - if(rn!=rn->par->first && rn1!=rn1->par->first) { - if(rn->up && rn->up==rn1->up) { - f1= rn->totrad[0]+ rn->totrad[1]+ rn->totrad[2]; - f2= rn1->totrad[0]+ rn1->totrad[1]+ rn1->totrad[2]; - - ok= 0; - if(f1totrad[0]); - c2= calculatecolor(rn1->totrad[0]); - - if( abs(c1-c2)<=limit ) { - c1= calculatecolor(rn->totrad[1]); - c2= calculatecolor(rn1->totrad[1]); - - if( abs(c1-c2)<=limit ) { - c1= calculatecolor(rn->totrad[2]); - c2= calculatecolor(rn1->totrad[2]); - - if( abs(c1-c2)<=limit ) { - ok= 1; - } - } - } - } - - if(ok) { - rn->up->totrad[0]= 0.5f*(rn->totrad[0]+rn1->totrad[0]); - rn->up->totrad[1]= 0.5f*(rn->totrad[1]+rn1->totrad[1]); - rn->up->totrad[2]= 0.5f*(rn->totrad[2]+rn1->totrad[2]); - rn1= rn->up; - deleteNodes(rn1); - if(rn1->down1) ; - else { - foundone++; - a--; el++; - } - } - } - } - } - if(foundone) { - makeGlobalElemArray(); - } - } -// XXX waitcursor(0); -} - -unsigned int rad_find_or_add_mvert(Mesh *me, MFace *mf, RNode *orignode, float *w, float *radco, GHash *hash) -{ - MVert *mvert = BLI_ghash_lookup(hash, radco); - - if(!mvert) { - mvert = &me->mvert[me->totvert]; - VECCOPY(mvert->co, radco); - me->totvert++; - - BLI_ghash_insert(hash, radco, mvert); - } - - InterpWeightsQ3Dfl(orignode->v1, orignode->v2, orignode->v3, - orignode->v4, mvert->co, w); - - return (unsigned int)(mvert - me->mvert); -} - -void rad_addmesh(Scene *scene) -{ - Face *face = NULL; - Object *ob; - Mesh *me; - MVert *mvert; - MFace *mf; - RNode *node; - Material *ma=0; - GHash *verthash; - unsigned int *mcol; - float cent[3], min[3], max[3], w[4][4]; - int a; - - if(RG.totface==0) - return; - -// if(RG.totmat==MAXMAT) -// XXX notice("warning: cannot assign more than 16 materials to 1 mesh"); - - /* create the mesh */ - ob= add_object(scene, OB_MESH); - - me= ob->data; - me->totvert= totalRadVert(); - me->totface= RG.totface; - me->flag= 0; - - CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert); - CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface); - CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC, NULL, me->totface); - - CustomData_merge(RG.mfdata, &me->fdata, CD_MASK_MESH, CD_CALLOC, me->totface); - mesh_update_customdata_pointers(me); - - /* create materials and set vertex color flag */ - for(a=0; amode |= MA_VERTEXCOL; - } - - /* create vertices and faces in one go, adding vertices to the end of the - mvert array if they were not added already */ - me->totvert= 0; - verthash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); - - mcol= (unsigned int*)me->mcol; - mf= me->mface; - - for(a=0; atotface; a++, mf++, mcol+=4) { - RAD_NEXTFACE(a); - - /* the original node that this node is a subnode of */ - node= RG.mfdatanodes[face->orig]; - - /* set mverts from the radio data, and compute interpolation weights */ - mf->v1= rad_find_or_add_mvert(me, mf, node, w[0], face->v1, verthash); - mf->v2= rad_find_or_add_mvert(me, mf, node, w[1], face->v2, verthash); - mf->v3= rad_find_or_add_mvert(me, mf, node, w[2], face->v3, verthash); - if(face->v4) - mf->v4= rad_find_or_add_mvert(me, mf, node, w[3], face->v4, verthash); - - /* copy face and interpolate data */ - mf->mat_nr= face->matindex; - - CustomData_copy_data(RG.mfdata, &me->fdata, face->orig, a, 1); - CustomData_interp(RG.mfdata, &me->fdata, &face->orig, NULL, (float*)w, 1, a); - - /* load face vertex colors, with alpha added */ - mcol[0]= *((unsigned int*)face->v1+3) | 0x1000000; - mcol[1]= *((unsigned int*)face->v2+3) | 0x1000000; - mcol[2]= *((unsigned int*)face->v3+3) | 0x1000000; - if(face->v4) - mcol[3]= *((unsigned int*)face->v4+3) | 0x1000000; - - /* reorder face indices if needed to make face->v4 == 0 */ - test_index_face(mf, &me->fdata, a, face->v4? 4: 3); - } - - BLI_ghash_free(verthash, NULL, NULL); - - /* boundbox and center new */ - INIT_MINMAX(min, max); - - mvert= me->mvert; - for(a=0; atotvert; a++, mvert++) { - DO_MINMAX(mvert->co, min, max); - } - - cent[0]= (min[0]+max[0])/2.0f; - cent[1]= (min[1]+max[1])/2.0f; - cent[2]= (min[2]+max[2])/2.0f; - - mvert= me->mvert; - for(a=0; atotvert; a++, mvert++) { - VecSubf(mvert->co, mvert->co, cent); - } - - VECCOPY(ob->loc, cent); - - /* create edges */ - make_edges(me, 0); -} - -void rad_replacemesh(Scene *scene) -{ - RPatch *rp; - -// XXX deselectall(); - - rp= RG.patchbase.first; - while(rp) { - if( exist_object(rp->from)) { - if (rp->from->type == OB_MESH) { - rp->from->flag |= SELECT; - } - } - rp= rp->next; - } - - copy_objectflags(scene); -// XXX delete_obj(1); - - rad_addmesh(scene); -} - diff --git a/source/blender/radiosity/intern/source/radpreprocess.c b/source/blender/radiosity/intern/source/radpreprocess.c deleted file mode 100644 index 2b3ce1a856b..00000000000 --- a/source/blender/radiosity/intern/source/radpreprocess.c +++ /dev/null @@ -1,828 +0,0 @@ - /* *************************************** - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - - - - preproces.c nov/dec 1992 - may 1999 - - - collect from meshes - - countglobaldata() - - makeGlobalElemArray() - - $Id$ - - *************************************** */ - -#include -#include -#include -#include - -#include "MEM_guardedalloc.h" - -#include "BLI_blenlib.h" -#include "BLI_arithb.h" - -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_view3d_types.h" - -#include "BKE_customdata.h" -#include "BKE_global.h" -#include "BKE_main.h" -#include "BKE_material.h" -#include "BKE_mesh.h" -#include "BKE_object.h" /* during_script() */ -#include "BKE_utildefines.h" - -#include "radio.h" - -#include "BLO_sys_types.h" // for intptr_t support - -void setparelem(RNode *rn, RPatch *par); - -void splitconnected() -{ - /* Since input meshes can have faces with sharing vertices, the geometry is being tested here. - * Using normals and colors, faces are split separately. we do this by storing for each - * vertex a normal and a color - */ - RPatch *rp; - RNode *rn; - VeNoCo *vnc, *next, *vnc1; - int a; - - /* test if we need a split */ - - rp= RG.patchbase.first; - while(rp) { - rn= rp->first; - if((rp->f1 & RAD_NO_SPLIT)==0) { - for(a=0; atype; a++) { - - if(a==0) vnc= (VeNoCo *)rn->v1; - else if(a==1) vnc= (VeNoCo *)rn->v2; - else if(a==2) vnc= (VeNoCo *)rn->v3; - else vnc= (VeNoCo *)rn->v4; - - if(vnc->flag==0) { - vnc->n= (float *)rp->norm; - vnc->col= (float *)rp->ref; - vnc->flag= 1; - } - else { /* is face from this vertex allowed for gouraud? */ - vnc1= vnc; - while(vnc1) { - if(VecCompare(vnc1->n, rp->norm, 0.01f)) { - if(VecCompare(vnc1->col, rp->ref, 0.01f)) { - break; - } - } - vnc= vnc1; - vnc1= vnc1->next; - } - if(vnc1==0) { - vnc1= MEM_mallocN(sizeof(VeNoCo), "splitconn"); - vnc1->next= 0; - vnc1->v= mallocVert(); - vnc->next= vnc1; - VECCOPY(vnc1->v, vnc->v); - vnc1->n= (float *)rp->norm; - vnc1->col= (float *)rp->ref; - } - if(a==0) rn->v1= (float *)vnc1; - else if(a==1) rn->v2= (float *)vnc1; - else if(a==2) rn->v3= (float *)vnc1; - else rn->v4= (float *)vnc1; - } - } - } - rp= rp->next; - } - /* adapt vertexpointers from nodes */ - - rp= RG.patchbase.first; - while(rp) { - rn= rp->first; - rn->v1= ((VeNoCo *)(rn->v1))->v; - rn->v2= ((VeNoCo *)(rn->v2))->v; - rn->v3= ((VeNoCo *)(rn->v3))->v; - if(rp->type==4) rn->v4= ((VeNoCo *)(rn->v4))->v; - - rp= rp->next; - } - - - /* free all */ - vnc= RG.verts; - for(a=0; anext; - while(vnc1) { - next= vnc1->next; - MEM_freeN(vnc1); - vnc1= next; - } - vnc++; - } - MEM_freeN(RG.verts); - RG.verts= 0; -} - -int vergedge(const void *v1,const void *v2) -{ - int *e1, *e2; - - e1= (int *)v1; - e2= (int *)v2; - - if( e1[0] > e2[0] ) return 1; - else if( e1[0] < e2[0] ) return -1; - else if( e1[1] > e2[1] ) return 1; - else if( e1[1] < e2[1] ) return -1; - - return 0; -} - - -void addedge(float *v1, float *v2, EdSort *es) -{ - if( ((intptr_t)v1)<((intptr_t)v2) ) { - es->v1= v1; - es->v2= v2; - } - else { - es->v2= v1; - es->v1= v2; - } -} - -static void setedge(RNode *node, RNode *nb, int nr, int nrb) -{ - switch(nr) { - case 1: - node->ed1= nb; - break; - case 2: - node->ed2= nb; - break; - case 3: - node->ed3= nb; - break; - case 4: - node->ed4= nb; - break; - } - switch(nrb) { - case 1: - nb->ed1= node; - break; - case 2: - nb->ed2= node; - break; - case 3: - nb->ed3= node; - break; - case 4: - nb->ed4= node; - break; - } -} - -void setedgepointers() -{ - /* make edge-array and sort it */ - /* pairs of edges are put together: fill in pointers in nodes */ - EdSort *es, *esblock; - RPatch *rp; - RNode *rn; - int tot= 0; - - rp= RG.patchbase.first; - while(rp) { - tot+= rp->type; - rp= rp->next; - } - - if(tot==0) return; - - es=esblock= MEM_mallocN(tot*sizeof(EdSort), "setedgepointers"); - rp= RG.patchbase.first; - while(rp) { - rn= rp->first; - addedge(rn->v1, rn->v2, es); - es->nr= 1; - es->node= rn; - es++; - addedge(rn->v2, rn->v3, es); - es->nr= 2; - es->node= rn; - es++; - if(rp->type==3) { - addedge(rn->v3, rn->v1, es); - es->nr= 3; - es->node= rn; - es++; - } - else { - addedge(rn->v3, rn->v4, es); - es->nr= 3; - es->node= rn; - es++; - addedge(rn->v4, rn->v1, es); - es->nr= 4; - es->node= rn; - es++; - } - rp= rp->next; - } - - qsort(esblock,tot,sizeof(EdSort),vergedge); - - es= esblock; - while(tot>0) { - if( es->v1== (es+1)->v1 ) { - if( es->v2== (es+1)->v2 ) { - setedge(es->node, (es+1)->node, es->nr, (es+1)->nr); - tot--; - es++; - } - } - es++; - tot--; - } - - MEM_freeN(esblock); -} - -static int materialIndex(Material *ma) -{ - int i = 0; - for(i=0;i< RG.totmat; i++) - { - if (RG.matar[i] == ma) { - return i; - } - } - return -1; -} - -void rad_collect_meshes(Scene *scene, View3D *v3d) -{ - extern Material defmaterial; - Base *base; - Object *ob; - Mesh *me; - MVert *mvert; - MFace *mface; - MTFace *tf, *tface; - Material *ma = NULL, *noma= NULL; - RPatch *rp; - RNode *rn; - VeNoCo *vnc, **nodevert; - float *vd, *v1, *v2, *v3, *v4 = NULL; - int a, b, offs, index, mfdatatot; - - if (v3d==NULL) { - printf("Error, trying to collect radiosity meshes with no 3d view\n"); - return; - } - - set_radglobal(scene); - - freeAllRad(scene); - - start_fastmalloc("Radiosity"); - - /* count the number of verts */ - RG.totvert= 0; - RG.totface= 0; - base= (scene->base.first); - while(base) { - if(((base)->flag & SELECT) && ((base)->lay & v3d->lay) ) { - if(base->object->type==OB_MESH) { - base->flag |= OB_RADIO; - me= base->object->data; - RG.totvert+= me->totvert; - } - } - base= base->next; - } - if(RG.totvert==0) { - if (!during_script()); //XXX error("No vertices"); - return; - } - vnc= RG.verts= MEM_callocN(RG.totvert*sizeof(VeNoCo), "radioverts"); - - RG.min[0]= RG.min[1]= RG.min[2]= 1.0e20f; - RG.max[0]= RG.max[1]= RG.max[2]= -1.0e20f; - - mfdatatot= 0; - - /* min-max and material array */ - base= (scene->base.first); - while(base) { - if( ((base)->flag & SELECT) && ((base)->lay & v3d->lay) ) { - if(base->object->type==OB_MESH) { - me= base->object->data; - mvert= me->mvert; - for(a=0; atotvert; a++, mvert++) { - vd= mallocVert(); - VECCOPY(vd, mvert->co); - /* Should make MTC its own module... */ - Mat4MulVecfl(base->object->obmat, vd); - - vnc->v= vd; - for(b=0; b<3; b++) { - RG.min[b]= MIN2(RG.min[b], vd[b]); - RG.max[b]= MAX2(RG.max[b], vd[b]); - } - vnc++; - } - - if(base->object->totcol==0) { - if(RG.totmatobject->totcol; a++) { - if(RG.totmat >= MAXMAT) break; - - ma = give_current_material(base->object, a+1); - - if (materialIndex(ma)!=-1) break; - - RG.matar[RG.totmat]= ma; - RG.totmat++; - } - } - - mfdatatot += me->totface; - } - } - base= base->next; - } - - RG.cent[0]= (RG.min[0]+ RG.max[0])/2; - RG.cent[1]= (RG.min[1]+ RG.max[1])/2; - RG.cent[2]= (RG.min[2]+ RG.max[2])/2; - RG.size[0]= (RG.max[0]- RG.min[0]); - RG.size[1]= (RG.max[1]- RG.min[1]); - RG.size[2]= (RG.max[2]- RG.min[2]); - RG.maxsize= MAX3(RG.size[0],RG.size[1],RG.size[2]); - - RG.mfdata= MEM_callocN(sizeof(CustomData), "radiomfdata"); - RG.mfdatanodes= MEM_mallocN(sizeof(RNode*)*mfdatatot, "radiomfdatanodes"); - RG.mfdatatot= mfdatatot; - - /* make patches */ - - RG.totelem= 0; - RG.totpatch= 0; - RG.totlamp= 0; - offs= 0; - - base= (scene->base.first); - while(base) { - if( ((base)->flag & SELECT) && ((base)->lay & v3d->lay) ) { - if(base->object->type==OB_MESH) { - ob= base->object; - me= ob->data; - mface= me->mface; - tface= me->mtface; - - index= -1; - - CustomData_merge(&me->fdata, RG.mfdata, CD_MASK_DERIVEDMESH, - CD_DEFAULT, mfdatatot); - - for(a=0; atotface; a++, mface++) { - tf= tface? tface+a: NULL; - - if (tf && (tf->mode & TF_INVISIBLE)) - continue; - - rp= callocPatch(); - BLI_addtail(&(RG.patchbase), rp); - rp->from= ob; - - if(mface->v4) rp->type= 4; - else rp->type= 3; - - rp->first= rn= callocNode(); - - if(mface->flag & ME_SMOOTH) rp->f1= RAD_NO_SPLIT; - - /* temporal: we store the venoco in the node */ - rn->v1= (float *)(RG.verts+mface->v1+offs); - v1= (RG.verts+mface->v1+offs)->v; - rn->v2= (float *)(RG.verts+mface->v2+offs); - v2= (RG.verts+mface->v2+offs)->v; - rn->v3= (float *)(RG.verts+mface->v3+offs); - v3= (RG.verts+mface->v3+offs)->v; - - if(mface->v4) { - rn->v4= (float *)(RG.verts+mface->v4+offs); - v4= (RG.verts+mface->v4+offs)->v; - } - rn->par= rp; - rn->f= RAD_PATCH; /* this node is a Patch */ - rn->type= rp->type; - - if(rn->type==4) { - rp->area= AreaQ3Dfl(v1, v2, v3, v4); - CalcNormFloat4(v1, v2, v3, v4, rp->norm); - } - else { - rp->area= AreaT3Dfl(v1, v2, v3); - CalcNormFloat(v1, v2, v3, rp->norm); - } - - rn->area= rp->area; - - /* color and emit */ - if(mface->mat_nr != index) { - index= mface->mat_nr; - ma= give_current_material(ob, index+1); - if(ma==0) ma= &defmaterial; - } - rp->ref[0]= ma->r; - rp->ref[1]= ma->g; - rp->ref[2]= ma->b; - - if(ma->emit) RG.totlamp++; - - rp->emit[0]= rp->emit[1]= rp->emit[2]= ma->emit; - rp->emit[0]*= rp->ref[0]; - rp->emit[1]*= rp->ref[1]; - rp->emit[2]*= rp->ref[2]; - -// uncommented, this is not satisfying, but i leave it in code for now (ton) -// if(ma->translucency!=0.0) rn->f |= RAD_TWOSIDED; - - nodevert= (VeNoCo **)&(rn->v1); - for(b=0; btype; b++) { - rp->cent[0]+= (*nodevert)->v[0]; - rp->cent[1]+= (*nodevert)->v[1]; - rp->cent[2]+= (*nodevert)->v[2]; - nodevert++; - } - rp->cent[0]/= (float)rp->type; - rp->cent[1]/= (float)rp->type; - rp->cent[2]/= (float)rp->type; - - /* for reconstruction materials */ - rp->matindex= materialIndex(ma); - if(rp->matindex==-1) rp->matindex= 1; - - /* these RNode's are stored now for later use in rad_addmesh - they should not get deleted before that */ - rn->orig= RG.totelem; - RG.mfdatanodes[RG.totelem]= rn; - - CustomData_copy_data(&me->fdata, RG.mfdata, a, RG.totelem, 1); - - RG.totelem++; - RG.totpatch++; - } - - offs+= me->totvert; - } - } - base= base->next; - } - - splitconnected(); - setedgepointers(); - - makeGlobalElemArray(); - pseudoAmb(); - rad_setlimits(scene); -} - -void setparelem(RNode *rn, RPatch *par) -{ - - if(rn->down1) { - setparelem(rn->down1, par); - setparelem(rn->down2, par); - } - else { - rn->par= par; - } -} - -void countelem(RNode *rn) -{ - - if(rn->down1) { - countelem(rn->down1); - countelem(rn->down2); - } - else RG.totelem++; -} - -void countglobaldata() -{ - /* counts elements and patches*/ - RPatch *rp; - - RG.totelem= RG.totpatch= 0; - - rp= RG.patchbase.first; - while(rp) { - RG.totpatch++; - countelem(rp->first); - rp= rp->next; - } -} - -void addelem(RNode ***el, RNode *rn, RPatch *rp) -{ - if(rn->down1) { - addelem(el, rn->down1, rp); - addelem(el, rn->down2, rp); - } - else { - rn->par= rp; - **el= rn; - (*el)++; - } -} - -void makeGlobalElemArray() -{ - /* always called when # of elements change */ - RPatch *rp; - RNode **el; - - countglobaldata(); - - if(RG.elem) MEM_freeN(RG.elem); - if(RG.totelem) { - el= RG.elem= MEM_mallocN(sizeof(void *)*RG.totelem, "makeGlobalElemArray"); - } - else { - RG.elem= 0; - return; - } - - /* recursive adding elements */ - rp= RG.patchbase.first; - while(rp) { - addelem(&el, rp->first, rp); - rp= rp->next; - } - - /* formfactor array */ - if(RG.formfactors) MEM_freeN(RG.formfactors); - if(RG.totelem) - RG.formfactors= MEM_mallocN(sizeof(float)*RG.totelem, "formfactors"); - else - RG.formfactors= 0; -} - -void splitpatch(RPatch *old) /* in case of overflow during shoot */ -{ - RNode *rn; - float **fpp; - RPatch *rp; - int a; - - rn= old->first; - if(rn->down1==0) return; - rn= rn->down1; - - old->unshot[0]/=2.0; - old->unshot[1]/=2.0; - old->unshot[2]/=2.0; - setnodeflags(old->first, 2, 0); - - rp= mallocPatch(); - *rp= *old; - BLI_addhead(&RG.patchbase, rp); - rp->first= rn; - rp->area= rn->area; - rp->cent[0]= rp->cent[1]= rp->cent[2]= 0.0; - fpp= &(rn->v1); - for(a=0; atype; a++) { - rp->cent[0]+= (*fpp)[0]; - rp->cent[1]+= (*fpp)[1]; - rp->cent[2]+= (*fpp)[2]; - fpp++; - } - rp->cent[0]/=(float)rp->type; - rp->cent[1]/=(float)rp->type; - rp->cent[2]/=(float)rp->type; - - setparelem(rn, rp); - - rn= old->first->down2; - - rp= mallocPatch(); - *rp= *old; - BLI_addhead(&RG.patchbase, rp); - rp->first= rn; - rp->area= rn->area; - rp->cent[0]= rp->cent[1]= rp->cent[2]= 0.0; - fpp= &(rn->v1); - for(a=0; atype; a++) { - rp->cent[0]+= (*fpp)[0]; - rp->cent[1]+= (*fpp)[1]; - rp->cent[2]+= (*fpp)[2]; - fpp++; - } - rp->cent[0]/=(float)rp->type; - rp->cent[1]/=(float)rp->type; - rp->cent[2]/=(float)rp->type; - - setparelem(rn, rp); - - BLI_remlink(&RG.patchbase, old); - freePatch(old); -} - - -void addpatch(RPatch *old, RNode *rn) -{ - float **fpp; - RPatch *rp; - int a; - - if(rn->down1) { - addpatch(old, rn->down1); - addpatch(old, rn->down2); - } - else { - rp= mallocPatch(); - *rp= *old; - BLI_addhead(&RG.patchbase, rp); - rp->first= rn; - - rp->area= rn->area; - rp->cent[0]= rp->cent[1]= rp->cent[2]= 0.0; - fpp= &(rn->v1); - for(a=0; atype; a++) { - rp->cent[0]+= (*fpp)[0]; - rp->cent[1]+= (*fpp)[1]; - rp->cent[2]+= (*fpp)[2]; - fpp++; - } - rp->cent[0]/=(float)rp->type; - rp->cent[1]/=(float)rp->type; - rp->cent[2]/=(float)rp->type; - - rn->par= rp; - } -} - -void converttopatches() -{ - /* chacks patches list, if node subdivided: new patch */ - RPatch *rp, *next; - - rp= RG.patchbase.first; - while(rp) { - next= rp->next; - if(rp->first->down1) { - addpatch(rp, rp->first); - BLI_remlink(&RG.patchbase, rp); - freePatch(rp); - } - rp= next; - } - -} - -void subdiv_elements() -{ - RNode **el, *rn; - int a, toobig= 1; - - rad_init_energy(); - - /* first maxsize elements */ - - while(toobig) { - toobig= 0; - - el= RG.elem; - for(a=RG.totelem; a>0; a--, el++) { - rn= *el; - if( rn->totrad[0]==0.0 && rn->totrad[1]==0.0 && rn->totrad[2]==0.0) { - if(rn->area>RG.elemmin) { - subdivideNode(rn, 0); - if(rn->down1 ) { - toobig= 1; - if(rn->down1->area>RG.elemmin) - subdivideNode( rn->down1, 0); - if(rn->down2->area>RG.elemmin) - subdivideNode( rn->down2, 0); - } - } - } - } - if(toobig) makeGlobalElemArray(); - } - - el= RG.elem; - for(a=RG.totelem; a>0; a--, el++) { - rn= *el; - if( rn->totrad[0]==0.0 && rn->totrad[1]==0.0 && rn->totrad[2]==0.0) { - subdivideNode(rn, 0); - if( rn->down1 ) { - subdivideNode( rn->down1, 0); - subdivideNode( rn->down2, 0); - } - } - } - makeGlobalElemArray(); -} - -void subdividelamps() -{ - RPatch *rp, *next; - - rp= RG.patchbase.first; - while(rp) { - next= rp->next; - if(rp->emit[0]!=0.0 || rp->emit[1]!=0.0 || rp->emit[2]!=0.0) { - subdivideNode( rp->first, 0); - if(rp->first->down1) { - subdivideNode(rp->first->down1, 0); - subdivideNode(rp->first->down2, 0); - } - - addpatch(rp, rp->first); - BLI_remlink(&RG.patchbase, rp); - freePatch(rp); - } - rp= next; - } - -} - -void maxsizePatches() -{ - RPatch *rp; - int toobig= 1; - - while(toobig) { - toobig= 0; - rp= RG.patchbase.first; - while(rp) { - if(rp->area>RG.patchmax) { - subdivideNode( rp->first, 0); - if(rp->first->down1) toobig= 1; - } - rp= rp->next; - } - - if(toobig) converttopatches(); - } - - /* count lamps */ - rp= RG.patchbase.first; - RG.totlamp= 0; - while(rp) { - if(rp->emit[0]!=0.0 || rp->emit[1]!=0.0 || rp->emit[2]!=0.0) { - RG.totlamp++; - } - rp= rp->next; - } - makeGlobalElemArray(); -} - - - diff --git a/source/blender/radiosity/intern/source/radrender.c b/source/blender/radiosity/intern/source/radrender.c deleted file mode 100644 index d33bbc90ee3..00000000000 --- a/source/blender/radiosity/intern/source/radrender.c +++ /dev/null @@ -1,530 +0,0 @@ -/* *************************************** - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/* radrender.c, aug 2003 - * - * Most of the code here is copied from radiosity code, to optimize for renderfaces. - * Shared function calls mostly reside in radfactors.c - * No adaptive subdivision takes place - * - * - do_radio_render(); main call, extern - * - initradfaces(); add radface structs in render faces, init radio globals - * - - * - initradiosity(); LUTs - * - inithemiwindows(); - * - progressiverad(); main itteration loop - * - hemi zbuffers - * - calc rad factors - * - * - closehemiwindows(); - * - freeAllRad(); - * - make vertex colors - * - * - during render, materials use totrad as ambient replacement - * - free radfaces - */ - -#include -#include -#include - -#include "MEM_guardedalloc.h" - -#include "BLI_blenlib.h" -#include "BLI_arithb.h" -#include "BLI_rand.h" - -#include "BKE_utildefines.h" -#include "BKE_global.h" -#include "BKE_main.h" - -#include "radio.h" - -/* the radiosity module uses internal includes from render! */ -#include "renderpipeline.h" -#include "render_types.h" -#include "renderdatabase.h" - - -/* only needed now for a print, if its useful move to RG */ -static float maxenergy; - -/* find the face with maximum energy to become shooter */ -/* nb: _rr means rad-render version of existing radio call */ -static void findshoot_rr(Render *re, VlakRen **shoot_p, RadFace **shootrf_p) -{ - RadFace *rf, *shootrf, **radface; - ObjectRen *obr; - VlakRen *vlr=NULL, *shoot; - float energy; - int a; - - shoot= NULL; - shootrf= NULL; - maxenergy= 0.0; - - for(obr=re->objecttable.first; obr; obr=obr->next) { - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++; - if((radface=RE_vlakren_get_radface(obr, vlr, 0)) && *radface) { - rf= *radface; - rf->flag &= ~RAD_SHOOT; - - energy= rf->unshot[0]*rf->area; - energy+= rf->unshot[1]*rf->area; - energy+= rf->unshot[2]*rf->area; - - if(energy>maxenergy) { - shoot= vlr; - shootrf= rf; - maxenergy= energy; - } - } - } - } - - if(shootrf) { - maxenergy/= RG.totenergy; - if(maxenergyflag |= RAD_SHOOT; - } - - *shoot_p= shoot; - *shootrf_p= shootrf; -} - -static void backface_test_rr(Render *re, VlakRen *shoot, RadFace *shootrf) -{ - ObjectRen *obr; - VlakRen *vlr=NULL; - RadFace *rf, **radface; - float tvec[3]; - int a; - - /* backface testing */ - for(obr=re->objecttable.first; obr; obr=obr->next) { - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++; - if(vlr != shoot && (radface=RE_vlakren_get_radface(obr, vlr, 0)) && *radface) { - rf= *radface; - VecSubf(tvec, shootrf->cent, rf->cent); - - if(tvec[0]*rf->norm[0]+ tvec[1]*rf->norm[1]+ tvec[2]*rf->norm[2] < 0.0) - rf->flag |= RAD_BACKFACE; - } - } - } -} - -static void clear_backface_test_rr(Render *re) -{ - ObjectRen *obr; - VlakRen *vlr=NULL; - RadFace *rf, **radface; - int a; - - /* backface flag clear */ - for(obr=re->objecttable.first; obr; obr=obr->next) { - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++; - - if((radface=RE_vlakren_get_radface(obr, vlr, 0)) && *radface) { - rf= *radface; - rf->flag &= ~RAD_BACKFACE; - } - } - } -} - -extern RadView hemitop, hemiside; // radfactors.c - -/* hemi-zbuffering, delivers formfactors array */ -static void makeformfactors_rr(Render *re, VlakRen *shoot, RadFace *shootrf) -{ - ObjectRen *obr; - VlakRen *vlr=NULL; - RadFace *rf, **radface; - float len, vec[3], up[3], side[3], tar[5][3], *fp; - int a; - - memset(RG.formfactors, 0, sizeof(float)*RG.totelem); - - /* set up hemiview */ - /* first: upvector for hemitop, we use diagonal hemicubes to prevent aliasing */ - - VecSubf(vec, shoot->v1->co, shootrf->cent); - Crossf(up, shootrf->norm, vec); - len= Normalize(up); - - VECCOPY(hemitop.up, up); - VECCOPY(hemiside.up, shootrf->norm); - - Crossf(side, shootrf->norm, up); - - /* five targets */ - VecAddf(tar[0], shootrf->cent, shootrf->norm); - VecAddf(tar[1], shootrf->cent, up); - VecSubf(tar[2], shootrf->cent, up); - VecAddf(tar[3], shootrf->cent, side); - VecSubf(tar[4], shootrf->cent, side); - - /* camera */ - VECCOPY(hemiside.cam, shootrf->cent); - VECCOPY(hemitop.cam, shootrf->cent); - - /* do it! */ - VECCOPY(hemitop.tar, tar[0]); - hemizbuf(&hemitop); - - for(a=1; a<5; a++) { - VECCOPY(hemiside.tar, tar[a]); - hemizbuf(&hemiside); - } - - /* convert factors to real radiosity */ - fp= RG.formfactors; - - for(obr=re->objecttable.first; obr; obr=obr->next) { - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++; - - if((radface=RE_vlakren_get_radface(obr, vlr, 0)) && *radface) { - rf= *radface; - if(*fp!=0.0 && rf->area!=0.0) { - *fp *= shootrf->area/rf->area; - if(*fp>1.0) *fp= 1.0001; - } - fp++; - } - } - } -} - -/* based at RG.formfactors array, distribute shoot energy over other faces */ -static void applyformfactors_rr(Render *re, VlakRen *shoot, RadFace *shootrf) -{ - ObjectRen *obr; - VlakRen *vlr=NULL; - RadFace *rf, **radface; - float *fp, *ref, unr, ung, unb, r, g, b; - int a; - - unr= shootrf->unshot[0]; - ung= shootrf->unshot[1]; - unb= shootrf->unshot[2]; - - fp= RG.formfactors; - - for(obr=re->objecttable.first; obr; obr=obr->next) { - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++; - - if((radface=RE_vlakren_get_radface(obr, vlr, 0)) && *radface) { - rf= *radface; - if(*fp!= 0.0) { - - ref= &(vlr->mat->r); - - r= (*fp)*unr*ref[0]; - g= (*fp)*ung*ref[1]; - b= (*fp)*unb*ref[2]; - - // if(rf->flag & RAD_BACKFACE) { - - rf->totrad[0]+= r; - rf->totrad[1]+= g; - rf->totrad[2]+= b; - - rf->unshot[0]+= r; - rf->unshot[1]+= g; - rf->unshot[2]+= b; - } - fp++; - } - } - } - /* shoot energy has been shot */ - shootrf->unshot[0]= shootrf->unshot[1]= shootrf->unshot[2]= 0.0; -} - - -/* main loop for itterations */ -static void progressiverad_rr(Render *re) -{ - VlakRen *shoot; - RadFace *shootrf; - float unshot[3]; - int it= 0; - - findshoot_rr(re, &shoot, &shootrf); - while( shoot ) { - - /* backfaces receive no energy, but are zbuffered... */ - backface_test_rr(re, shoot, shootrf); - - /* ...unless it's two sided */ - if(shootrf->flag & RAD_TWOSIDED) { - VECCOPY(unshot, shootrf->unshot); - VecNegf(shootrf->norm); - makeformfactors_rr(re, shoot, shootrf); - applyformfactors_rr(re, shoot, shootrf); - VecNegf(shootrf->norm); - VECCOPY(shootrf->unshot, unshot); - } - - /* hemi-zbuffers */ - makeformfactors_rr(re, shoot, shootrf); - /* based at RG.formfactors array, distribute shoot energy over other faces */ - applyformfactors_rr(re, shoot, shootrf); - - it++; - re->timecursor(re->tch, it); - - clear_backface_test_rr(re); - - if(re->test_break(re->tbh)) break; - if(RG.maxiter && RG.maxiter<=it) break; - - findshoot_rr(re, &shoot, &shootrf); - } - printf(" Unshot energy:%f\n", 1000.0*maxenergy); - - re->timecursor(re->tch, re->scene->r.cfra); -} - -static RadFace *radfaces=NULL; - -static void initradfaces(Render *re) -{ - ObjectRen *obr; - VlakRen *vlr= NULL; - RadFace *rf, **radface; - int a, b; - - /* globals */ - RG.totenergy= 0.0; - RG.totpatch= 0; // we count initial emittors here - RG.totelem= 0; // total # faces are put here (so we can use radfactors.c calls) - /* size is needed for hemicube clipping */ - RG.min[0]= RG.min[1]= RG.min[2]= 1.0e20; - RG.max[0]= RG.max[1]= RG.max[2]= -1.0e20; - - /* count first for fast malloc */ - for(obr=re->objecttable.first; obr; obr=obr->next) { - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++; - - if(vlr->mat->mode & MA_RADIO) { - if(vlr->mat->emit > 0.0) { - RG.totpatch++; - } - RG.totelem++; - } - } - } - -printf(" Rad elems: %d emittors %d\n", RG.totelem, RG.totpatch); - if(RG.totelem==0 || RG.totpatch==0) return; - - /* make/init radfaces */ - rf=radfaces= MEM_callocN(RG.totelem*sizeof(RadFace), "radfaces"); - for(obr=re->objecttable.first; obr; obr=obr->next) { - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++; - - if(vlr->mat->mode & MA_RADIO) { - - /* during render, vlr->n gets flipped/corrected, we cannot have that */ - if (obr->ob->transflag & OB_NEG_SCALE){ - /* The object has negative scale that will cause the normals to flip. - To counter this unwanted normal flip, swap vertex 2 and 4 for a quad - or vertex 2 and 3 (see flip_face) for a triangle in the call to CalcNormFloat4 - in order to flip the normals back to the way they were in the original mesh. */ - if(vlr->v4) CalcNormFloat4(vlr->v1->co, vlr->v4->co, vlr->v3->co, vlr->v2->co, rf->norm); - else CalcNormFloat(vlr->v1->co, vlr->v3->co, vlr->v2->co, rf->norm); - }else{ - if(vlr->v4) CalcNormFloat4(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co, rf->norm); - else CalcNormFloat(vlr->v1->co, vlr->v2->co, vlr->v3->co, rf->norm); - } - - rf->totrad[0]= vlr->mat->emit*vlr->mat->r; - rf->totrad[1]= vlr->mat->emit*vlr->mat->g; - rf->totrad[2]= vlr->mat->emit*vlr->mat->b; - VECCOPY(rf->unshot, rf->totrad); - - if(vlr->v4) { - rf->area= AreaQ3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co); - CalcCent4f(rf->cent, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4->co); - } - else { - rf->area= AreaT3Dfl(vlr->v1->co, vlr->v2->co, vlr->v3->co); - CalcCent3f(rf->cent, vlr->v1->co, vlr->v2->co, vlr->v3->co); - } - - RG.totenergy+= rf->unshot[0]*rf->area; - RG.totenergy+= rf->unshot[1]*rf->area; - RG.totenergy+= rf->unshot[2]*rf->area; - - for(b=0; b<3; b++) { - RG.min[b]= MIN2(RG.min[b], rf->cent[b]); - RG.max[b]= MAX2(RG.max[b], rf->cent[b]); - } - - // uncommented; this isnt satisfying, but i leave it in the code for now (ton) - // if(vlr->mat->translucency!=0.0) rf->flag |= RAD_TWOSIDED; - - radface=RE_vlakren_get_radface(obr, vlr, 1); - *radface= rf++; - } - } - } - RG.size[0]= (RG.max[0]- RG.min[0]); - RG.size[1]= (RG.max[1]- RG.min[1]); - RG.size[2]= (RG.max[2]- RG.min[2]); - RG.maxsize= MAX3(RG.size[0],RG.size[1],RG.size[2]); - - /* formfactor array */ - if(RG.formfactors) MEM_freeN(RG.formfactors); - if(RG.totelem) - RG.formfactors= MEM_mallocN(sizeof(float)*RG.totelem, "formfactors"); - else - RG.formfactors= NULL; - -} - -static void vecaddfac(float *vec, float *v1, float *v2, float fac) -{ - vec[0]= v1[0] + fac*v2[0]; - vec[1]= v1[1] + fac*v2[1]; - vec[2]= v1[2] + fac*v2[2]; - -} - -/* unused now, doesnt work..., find it in cvs of nov 2005 or older */ -/* static void filter_rad_values(void) */ - - -static void make_vertex_rad_values(Render *re) -{ - ObjectRen *obr; - VertRen *v1=NULL; - VlakRen *vlr=NULL; - RadFace *rf, **radface; - float *col; - int a; - - RG.igamma= 1.0/RG.gamma; - RG.radfactor= RG.radfac*pow(64*64, RG.igamma)/128.0; /* compatible with radio-tool */ - - /* accumulate vertexcolors */ - for(obr=re->objecttable.first; obr; obr=obr->next) { - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++; - - if((radface=RE_vlakren_get_radface(obr, vlr, 0)) && *radface) { - rf= *radface; - - /* apply correction */ - rf->totrad[0]= RG.radfactor*pow( rf->totrad[0], RG.igamma); - rf->totrad[1]= RG.radfactor*pow( rf->totrad[1], RG.igamma); - rf->totrad[2]= RG.radfactor*pow( rf->totrad[2], RG.igamma); - - /* correct rf->rad values for color */ - if(vlr->mat->r > 0.0) rf->totrad[0]/= vlr->mat->r; - if(vlr->mat->g > 0.0) rf->totrad[1]/= vlr->mat->g; - if(vlr->mat->b > 0.0) rf->totrad[2]/= vlr->mat->b; - - col= RE_vertren_get_rad(obr, vlr->v1, 1); - vecaddfac(col, col, rf->totrad, rf->area); - col[3]+= rf->area; - - col= RE_vertren_get_rad(obr, vlr->v2, 1); - vecaddfac(col, col, rf->totrad, rf->area); - col[3]+= rf->area; - - col= RE_vertren_get_rad(obr, vlr->v3, 1); - vecaddfac(col, col, rf->totrad, rf->area); - col[3]+= rf->area; - - if(vlr->v4) { - col= RE_vertren_get_rad(obr, vlr->v4, 1); - vecaddfac(col, col, rf->totrad, rf->area); - col[3]+= rf->area; - } - } - } - - /* make vertex colors */ - for(a=0; atotvert; a++) { - if((a & 255)==0) v1= RE_findOrAddVert(obr, a); else v1++; - - col= RE_vertren_get_rad(obr, v1, 0); - if(col && col[3]>0.0) { - col[0]/= col[3]; - col[1]/= col[3]; - col[2]/= col[3]; - } - } - } -} - -/* main call, extern */ -void do_radio_render(Render *re) -{ - if(re->scene->radio==NULL) add_radio(re->scene); - freeAllRad(re->scene); /* just in case radio-tool is still used */ - - set_radglobal(re->scene); /* init the RG struct */ - RG.re= re; /* only used by hemizbuf(), prevents polluting radio code all over */ - - initradfaces(re); /* add radface structs to render faces */ - if(RG.totenergy>0.0) { - - initradiosity(); /* LUT's */ - inithemiwindows(); /* views, need RG.maxsize for clipping */ - - progressiverad_rr(re); /* main radio loop */ - - make_vertex_rad_values(re); /* convert face energy to vertex ones */ - - } - - freeAllRad(re->scene); /* luts, hemis, sets vars at zero */ -} - -/* free call, after rendering, extern */ -void end_radio_render(void) -{ - if(radfaces) MEM_freeN(radfaces); - radfaces= NULL; -} - diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h index 20eea0c98bd..15b59f2c8cc 100644 --- a/source/blender/render/extern/include/RE_render_ext.h +++ b/source/blender/render/extern/include/RE_render_ext.h @@ -47,7 +47,8 @@ struct Render; struct MTex; struct ImBuf; -void RE_zbufferall_radio(struct RadView *vw, struct RNode **rg_elem, int rg_totelem, struct Render *re); +// RADIO REMOVED, Maybe this will be useful later +//void RE_zbufferall_radio(struct RadView *vw, struct RNode **rg_elem, int rg_totelem, struct Render *re); /* particle.c, effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */ int externtex(struct MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *tb, float *ta); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 98e5819c0d3..a00cd2211fc 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -104,7 +104,6 @@ #include "rendercore.h" #include "renderdatabase.h" #include "renderpipeline.h" -#include "radio.h" #include "shadbuf.h" #include "shading.h" #include "strand.h" @@ -1886,6 +1885,9 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem if(psys_get_particle_state(re->scene,ob,psys,a,&state,0)==0) continue; + if(psys->parent) + Mat4MulVecfl(psys->parent->obmat, state.co); + VECCOPY(loc,state.co); if(part->ren_as!=PART_DRAW_BB) MTC_Mat4MulVecfl(re->viewmat,loc); @@ -4308,8 +4310,9 @@ void RE_Database_Free(Render *re) } free_mesh_orco_hash(re); - +#if 0 /* radio can be redone better */ end_radio_render(); +#endif end_render_materials(); end_render_textures(); @@ -4736,10 +4739,11 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view) /* yafray: 'direct' radiosity, environment maps and raytree init not needed for yafray render */ /* although radio mode could be useful at some point, later */ if (re->r.renderer==R_INTERN) { +#if 0 /* RADIO was removed */ /* RADIO (uses no R anymore) */ if(!re->test_break(re->tbh)) if(re->r.mode & R_RADIO) do_radio_render(re); - +#endif /* raytree */ if(!re->test_break(re->tbh)) { if(re->r.mode & R_RAYTRACE) { diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 07560edb76b..ccc793e4235 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -46,6 +46,7 @@ #include "BKE_object.h" #include "BKE_scene.h" #include "BKE_writeavi.h" /* <------ should be replaced once with generic movie module */ +#include "BKE_pointcache.h" #include "MEM_guardedalloc.h" @@ -61,7 +62,6 @@ #include "intern/openexr/openexr_multi.h" #include "RE_pipeline.h" -#include "radio.h" /* internal */ #include "render_types.h" @@ -2413,6 +2413,21 @@ static int is_rendering_allowed(Render *re) return 1; } +static void update_physics_cache(Render *re, Scene *scene) +{ + PTCacheBaker baker; + + baker.scene = scene; + baker.pid = NULL; + baker.bake = 0; + baker.render = 1; + baker.quick_step = 1; + baker.break_test = re->test_break; + baker.break_data = re->tbh; + baker.progressbar = NULL; + + BKE_ptcache_make_cache(&baker); +} /* evaluating scene options for general Blender render */ static int render_initialize_from_scene(Render *re, Scene *scene, int anim) { @@ -2450,6 +2465,9 @@ static int render_initialize_from_scene(Render *re, Scene *scene, int anim) /* check all scenes involved */ tag_scenes_for_render(re); + + /* make sure dynamics are up to date */ + update_physics_cache(re, scene); if(scene->r.scemode & R_SINGLE_LAYER) push_render_result(re); diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index b68cecce7bd..21c3977fc0b 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -49,14 +49,12 @@ #include "DNA_mesh_types.h" #include "DNA_node_types.h" #include "DNA_meshdata_types.h" +#include "DNA_material_types.h" #include "BKE_global.h" #include "BKE_material.h" #include "BKE_utildefines.h" -#include "radio_types.h" -#include "radio.h" /* needs RG, some root data for radiosity */ - #include "RE_render_ext.h" /* local includes */ @@ -2301,110 +2299,6 @@ static int hashlist_projectvert(float *v1, float winmat[][4], float *hoco) return buck->clip; } -/* used for booth radio 'tool' as during render */ -void RE_zbufferall_radio(struct RadView *vw, RNode **rg_elem, int rg_totelem, Render *re) -{ - ZSpan zspan; - float hoco[4][4], winmat[4][4]; - int a, zvlnr; - int c1, c2, c3, c4= 0; - - if(rg_totelem==0) return; - - hashlist_projectvert(NULL, winmat, NULL); - - /* needed for projectvert */ - MTC_Mat4MulMat4(winmat, vw->viewmat, vw->winmat); - - /* 1.0f for clipping in clippyra()... bad stuff actually */ - zbuf_alloc_span(&zspan, vw->rectx, vw->recty, 1.0f); - zspan.zmulx= ((float)vw->rectx)/2.0; - zspan.zmuly= ((float)vw->recty)/2.0; - zspan.zofsx= -0.5f; - zspan.zofsy= -0.5f; - - /* the buffers */ - zspan.rectz= (int *)vw->rectz; - zspan.rectp= (int *)vw->rect; - zspan.recto= MEM_callocN(sizeof(int)*vw->rectx*vw->recty, "radiorecto"); - fillrect(zspan.rectz, vw->rectx, vw->recty, 0x7FFFFFFF); - fillrect(zspan.rectp, vw->rectx, vw->recty, 0xFFFFFF); - - /* filling methods */ - zspan.zbuffunc= zbuffillGL4; - - if(rg_elem) { /* radio tool */ - RNode **re, *rn; - - re= rg_elem; - re+= (rg_totelem-1); - for(a= rg_totelem-1; a>=0; a--, re--) { - rn= *re; - if( (rn->f & RAD_SHOOT)==0 ) { /* no shootelement */ - - if( rn->f & RAD_TWOSIDED) zvlnr= a; - else if( rn->f & RAD_BACKFACE) zvlnr= 0xFFFFFF; - else zvlnr= a; - - c1= hashlist_projectvert(rn->v1, winmat, hoco[0]); - c2= hashlist_projectvert(rn->v2, winmat, hoco[1]); - c3= hashlist_projectvert(rn->v3, winmat, hoco[2]); - - if(rn->v4) { - c4= hashlist_projectvert(rn->v4, winmat, hoco[3]); - } - - if(rn->v4) - zbufclip4(&zspan, 0, zvlnr, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4); - else - zbufclip(&zspan, 0, zvlnr, hoco[0], hoco[1], hoco[2], c1, c2, c3); - } - } - } - else { /* radio render */ - ObjectRen *obr; - VlakRen *vlr=NULL; - RadFace **radface, *rf; - int totface=0; - - /* note: radio render doesn't support duplis */ - for(obr=re->objecttable.first; obr; obr=obr->next) { - hashlist_projectvert(NULL, NULL, NULL); /* clear hashlist */ - - for(a=0; atotvlak; a++) { - if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; else vlr++; - - if((radface=RE_vlakren_get_radface(obr, vlr, 0)) && *radface) { - rf= *radface; - if( (rf->flag & RAD_SHOOT)==0 ) { /* no shootelement */ - - if( rf->flag & RAD_TWOSIDED) zvlnr= totface; - else if( rf->flag & RAD_BACKFACE) zvlnr= 0xFFFFFF; /* receives no energy, but is zbuffered */ - else zvlnr= totface; - - c1= hashlist_projectvert(vlr->v1->co, winmat, hoco[0]); - c2= hashlist_projectvert(vlr->v2->co, winmat, hoco[1]); - c3= hashlist_projectvert(vlr->v3->co, winmat, hoco[2]); - - if(vlr->v4) { - c4= hashlist_projectvert(vlr->v4->co, winmat, hoco[3]); - } - - if(vlr->v4) - zbufclip4(&zspan, 0, zvlnr, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4); - else - zbufclip(&zspan, 0, zvlnr, hoco[0], hoco[1], hoco[2], c1, c2, c3); - } - totface++; - } - } - } - } - - MEM_freeN(zspan.recto); - zbuf_free_span(&zspan); -} - void zbuffer_shadow(Render *re, float winmat[][4], LampRen *lar, int *rectz, int size, float jitx, float jity) { ZbufProjectCache cache[ZBUF_PROJECT_CACHE_SIZE]; diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 7acb2921bec..ffeb342df77 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -79,7 +79,7 @@ void WM_keymap_tweak (ListBase *lb, short type, short val, int modifier, short ListBase *WM_keymap_listbase (struct wmWindowManager *wm, const char *nameid, int spaceid, int regionid); -char *WM_key_event_string(short type); +const char *WM_key_event_string(short type); char *WM_key_event_operator_string(const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, char *str, int len); /* handlers */ @@ -129,6 +129,8 @@ int WM_operator_redo_popup (struct bContext *C, struct wmOperator *op); /* operator api */ void WM_operator_free (struct wmOperator *op); +void WM_operator_stack_clear(struct bContext *C); + wmOperatorType *WM_operatortype_find(const char *idname); wmOperatorType *WM_operatortype_first(void); void WM_operatortype_append (void (*opfunc)(wmOperatorType*)); @@ -212,8 +214,8 @@ void WM_jobs_stop(struct wmWindowManager *wm, void *owner); void WM_jobs_stop_all(struct wmWindowManager *wm); /* clipboard */ -char *WM_clipboard_text_get(int selection); -void WM_clipboard_text_set(char *buf, int selection); +char *WM_clipboard_text_get(int selection); +void WM_clipboard_text_set(char *buf, int selection); #endif /* WM_API_H */ diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 739cfbcc1ac..e3a7a906fef 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -58,37 +58,6 @@ enum { WM_OP_EXEC_SCREEN }; -/* ************** wmEvent ************************ */ - -/* each event should have full modifier state */ -/* event comes from eventmanager and from keymap */ -typedef struct wmEvent { - struct wmEvent *next, *prev; - - short type; /* event code itself (short, is also in keymap) */ - short val; /* press, release, scrollvalue */ - short x, y; /* mouse pointer position, screen coord */ - short mval[2]; /* region mouse position, name convention pre 2.5 :) */ - short prevx, prevy; /* previous mouse pointer position */ - short unicode; /* future, ghost? */ - char ascii; /* from ghost */ - char pad; - - /* modifier states */ - short shift, ctrl, alt, oskey; /* oskey is apple or windowskey, value denotes order of pressed */ - short keymodifier; /* rawkey modifier */ - - /* keymap item, set by handler (weak?) */ - const char *keymap_idname; - - /* custom data */ - short custom; /* custom data type, stylus, 6dof, see wm_event_types.h */ - void *customdata; /* ascii, unicode, mouse coords, angles, vectors, dragdrop info */ - short customdatafree; - -} wmEvent; - - /* ************** wmKeyMap ************************ */ /* modifier */ @@ -159,6 +128,7 @@ typedef struct wmNotifier { #define NC_BRUSH (11<<24) #define NC_TEXT (12<<24) #define NC_WORLD (13<<24) +#define NC_FILE (14<<24) /* data type, 256 entries is enough, it can overlap */ #define NOTE_DATA 0x00FF0000 @@ -213,6 +183,10 @@ typedef struct wmNotifier { /* NC_TEXT Text */ #define ND_CURSOR (50<<16) #define ND_DISPLAY (51<<16) + + /* NC_FILE Filebrowser */ +#define ND_PARAMS (60<<16) +#define ND_FILELIST (61<<16) /* subtype, 256 entries too */ #define NOTE_SUBTYPE 0x0000FF00 diff --git a/source/blender/windowmanager/intern/Makefile b/source/blender/windowmanager/intern/Makefile index 80ae58f9398..8f0f47c52d0 100644 --- a/source/blender/windowmanager/intern/Makefile +++ b/source/blender/windowmanager/intern/Makefile @@ -1,5 +1,5 @@ # -# $Id: Makefile 11904 2007-08-31 16:16:33Z sirdude $ +# $Id$ # # ***** BEGIN GPL LICENSE BLOCK ***** # diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 37fdc9fa2c5..7dec14664ae 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -95,6 +95,18 @@ void wm_operator_register(wmWindowManager *wm, wmOperator *op) } +void WM_operator_stack_clear(bContext *C) +{ + wmWindowManager *wm= CTX_wm_manager(C); + wmOperator *op; + + while((op= wm->operators.first)) { + BLI_remlink(&wm->operators, op); + WM_operator_free(op); + } + +} + /* ****************************************** */ void wm_check(bContext *C) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index ea6a65859e5..e520067b9e5 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -49,6 +49,7 @@ #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_utildefines.h" +#include "BKE_pointcache.h" #include "ED_fileselect.h" #include "ED_screen.h" @@ -234,6 +235,8 @@ void wm_event_do_notifiers(bContext *C) for(base= scene->base.first; base; base= base->next) { object_handle_update(scene, base->object); } + + BKE_ptcache_quick_cache_all(scene); } } CTX_wm_window_set(C, NULL); @@ -730,17 +733,20 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve ScrArea *area= CTX_wm_area(C); ARegion *region= CTX_wm_region(C); ARegion *menu= CTX_wm_menu(C); - int retval; + int retval, always_pass; /* we set context to where ui handler came from */ if(handler->ui_area) CTX_wm_area_set(C, handler->ui_area); if(handler->ui_region) CTX_wm_region_set(C, handler->ui_region); if(handler->ui_menu) CTX_wm_menu_set(C, handler->ui_menu); + /* in advance to avoid access to freed event on window close */ + always_pass= wm_event_always_pass(event); + retval= handler->ui_handle(C, event, handler->ui_userdata); /* putting back screen context */ - if((retval != WM_UI_HANDLER_BREAK) || wm_event_always_pass(event)) { + if((retval != WM_UI_HANDLER_BREAK) || always_pass) { CTX_wm_area_set(C, area); CTX_wm_region_set(C, region); CTX_wm_menu_set(C, menu); @@ -773,7 +779,7 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa case EVT_FILESELECT_OPEN: case EVT_FILESELECT_FULL_OPEN: { - short flag =0; short display =FILE_SHORTDISPLAY; short filter =0; short sort =FILE_SORTALPHA; + short flag =0; short display =FILE_SHORTDISPLAY; short filter =0; short sort =FILE_SORT_ALPHA; char *path= RNA_string_get_alloc(handler->op->ptr, "filename", NULL, 0); if(event->val==EVT_FILESELECT_OPEN) @@ -869,6 +875,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) { wmEventHandler *handler, *nexthandler; int action= WM_HANDLER_CONTINUE; + int always_pass; if(handlers==NULL) return action; @@ -878,6 +885,8 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) /* optional boundbox */ if(handler_boundbox_test(handler, event)) { + /* in advance to avoid access to freed event on window close */ + always_pass= wm_event_always_pass(event); /* modal+blocking handler */ if(handler->flag & WM_HANDLER_BLOCKING) @@ -909,7 +918,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) action= wm_handler_operator_call(C, handlers, handler, event, NULL); } - if(!wm_event_always_pass(event) && action==WM_HANDLER_BREAK) + if(!always_pass && action==WM_HANDLER_BREAK) break; } diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index d13d8ec6ccc..29ec58befd9 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -294,8 +294,6 @@ int WM_read_homefile(bContext *C, wmOperator *op) G.relbase_valid = 0; if (!from_memory) { BLI_make_file_string(G.sce, tstr, home, ".B25.blend"); - if(!BLI_exists(tstr)) - BLI_make_file_string(G.sce, tstr, home, ".B.blend"); } strcpy(scestr, G.sce); /* temporary store */ @@ -577,7 +575,7 @@ void WM_write_file(bContext *C, char *target, ReportList *reports) // } if (G.fileflags & G_AUTOPACK) { - packAll(); + packAll(G.main, reports); } ED_object_exit_editmode(C, 0); diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index adbc43e439d..0bc35ffa9b2 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -58,8 +58,6 @@ #include "RE_pipeline.h" /* RE_ free stuff */ -#include "radio.h" - #ifndef DISABLE_PYTHON #include "BPY_extern.h" #endif @@ -196,9 +194,6 @@ void WM_exit(bContext *C) // BIF_freeRetarget(); BIF_freeTemplates(C); BIF_freeSketch(C); - - /* Context should still working here. but radio tool needs cleaning... */ - freeAllRad(CTX_data_scene(C)); free_ttfont(); /* bke_font.h */ diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 7528321c7c5..b914e63788d 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -44,6 +44,7 @@ #include "RNA_access.h" #include "RNA_types.h" +#include "RNA_enum_types.h" #include "WM_api.h" #include "WM_types.h" @@ -153,315 +154,11 @@ ListBase *WM_keymap_listbase(wmWindowManager *wm, const char *nameid, int spacei /* ***************** get string from key events **************** */ -char *WM_key_event_string(short type) +const char *WM_key_event_string(short type) { - /* not returned: CAPSLOCKKEY, UNKNOWNKEY, COMMANDKEY, GRLESSKEY */ - - switch(type) { - case AKEY: - return "A"; - break; - case BKEY: - return "B"; - break; - case CKEY: - return "C"; - break; - case DKEY: - return "D"; - break; - case EKEY: - return "E"; - break; - case FKEY: - return "F"; - break; - case GKEY: - return "G"; - break; - case HKEY: - return "H"; - break; - case IKEY: - return "I"; - break; - case JKEY: - return "J"; - break; - case KKEY: - return "K"; - break; - case LKEY: - return "L"; - break; - case MKEY: - return "M"; - break; - case NKEY: - return "N"; - break; - case OKEY: - return "O"; - break; - case PKEY: - return "P"; - break; - case QKEY: - return "Q"; - break; - case RKEY: - return "R"; - break; - case SKEY: - return "S"; - break; - case TKEY: - return "T"; - break; - case UKEY: - return "U"; - break; - case VKEY: - return "V"; - break; - case WKEY: - return "W"; - break; - case XKEY: - return "X"; - break; - case YKEY: - return "Y"; - break; - case ZKEY: - return "Z"; - break; - - case ZEROKEY: - return "Zero"; - break; - case ONEKEY: - return "One"; - break; - case TWOKEY: - return "Two"; - break; - case THREEKEY: - return "Three"; - break; - case FOURKEY: - return "Four"; - break; - case FIVEKEY: - return "Five"; - break; - case SIXKEY: - return "Six"; - break; - case SEVENKEY: - return "Seven"; - break; - case EIGHTKEY: - return "Eight"; - break; - case NINEKEY: - return "Nine"; - break; - - case LEFTCTRLKEY: - return "Leftctrl"; - break; - case LEFTALTKEY: - return "Leftalt"; - break; - case RIGHTALTKEY: - return "Rightalt"; - break; - case RIGHTCTRLKEY: - return "Rightctrl"; - break; - case RIGHTSHIFTKEY: - return "Rightshift"; - break; - case LEFTSHIFTKEY: - return "Leftshift"; - break; - - case ESCKEY: - return "Esc"; - break; - case TABKEY: - return "Tab"; - break; - case RETKEY: - return "Ret"; - break; - case SPACEKEY: - return "Space"; - break; - case LINEFEEDKEY: - return "Linefeed"; - break; - case BACKSPACEKEY: - return "Backspace"; - break; - case DELKEY: - return "Del"; - break; - case SEMICOLONKEY: - return "Semicolon"; - break; - case PERIODKEY: - return "Period"; - break; - case COMMAKEY: - return "Comma"; - break; - case QUOTEKEY: - return "Quote"; - break; - case ACCENTGRAVEKEY: - return "Accentgrave"; - break; - case MINUSKEY: - return "Minus"; - break; - case SLASHKEY: - return "Slash"; - break; - case BACKSLASHKEY: - return "Backslash"; - break; - case EQUALKEY: - return "Equal"; - break; - case LEFTBRACKETKEY: - return "Leftbracket"; - break; - case RIGHTBRACKETKEY: - return "Rightbracket"; - break; - - case LEFTARROWKEY: - return "Leftarrow"; - break; - case DOWNARROWKEY: - return "Downarrow"; - break; - case RIGHTARROWKEY: - return "Rightarrow"; - break; - case UPARROWKEY: - return "Uparrow"; - break; - - case PAD2: - return "Numpad 2"; - break; - case PAD4: - return "Numpad 4"; - break; - case PAD6: - return "Numpad 6"; - break; - case PAD8: - return "Numpad 8"; - break; - case PAD1: - return "Numpad 1"; - break; - case PAD3: - return "Numpad 3"; - break; - case PAD5: - return "Numpad 5"; - break; - case PAD7: - return "Numpad 7"; - break; - case PAD9: - return "Numpad 9"; - break; - - case PADPERIOD: - return "Numpad ."; - break; - case PADSLASHKEY: - return "Numpad /"; - break; - case PADASTERKEY: - return "Numpad *"; - break; - - case PAD0: - return "Numpad 0"; - break; - case PADMINUS: - return "Numpad -"; - break; - case PADENTER: - return "Numpad Enter"; - break; - case PADPLUSKEY: - return "Numpad +"; - break; - - case F1KEY: - return "F1"; - break; - case F2KEY: - return "F2"; - break; - case F3KEY: - return "F3"; - break; - case F4KEY: - return "F4"; - break; - case F5KEY: - return "F5"; - break; - case F6KEY: - return "F6"; - break; - case F7KEY: - return "F7"; - break; - case F8KEY: - return "F8"; - break; - case F9KEY: - return "F9"; - break; - case F10KEY: - return "F10"; - break; - case F11KEY: - return "F11"; - break; - case F12KEY: - return "F12"; - break; - - case PAUSEKEY: - return "Pause"; - break; - case INSERTKEY: - return "Insert"; - break; - case HOMEKEY: - return "Home"; - break; - case PAGEUPKEY: - return "Pageup"; - break; - case PAGEDOWNKEY: - return "Pagedown"; - break; - case ENDKEY: - return "End"; - break; - } + const char *name= NULL; + if(RNA_enum_name(event_type_items, (int)type, &name)) + return name; return ""; } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 46e9df10adc..7f9a2153dc3 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -145,7 +145,6 @@ char *WM_operator_pystring(wmOperator *op) const char *arg_name= NULL; PropertyRNA *prop, *iterprop; - CollectionPropertyIterator iter; /* for building the string */ DynStr *dynstr= BLI_dynstr_new(); @@ -155,10 +154,9 @@ char *WM_operator_pystring(wmOperator *op) BLI_dynstr_appendf(dynstr, "%s(", op->idname); iterprop= RNA_struct_iterator_property(op->ptr->type); - RNA_property_collection_begin(op->ptr, iterprop, &iter); - for(; iter.valid; RNA_property_collection_next(&iter)) { - prop= iter.ptr.data; + RNA_PROP_BEGIN(op->ptr, propptr, iterprop) { + prop= propptr.data; arg_name= RNA_property_identifier(prop); if (strcmp(arg_name, "rna_type")==0) continue; @@ -170,8 +168,7 @@ char *WM_operator_pystring(wmOperator *op) MEM_freeN(buf); first_iter = 0; } - - RNA_property_collection_end(&iter); + RNA_PROP_END; BLI_dynstr_append(dynstr, ")"); @@ -291,7 +288,7 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 300, 20, style); - uiDefAutoButsRNA(C, layout, &ptr); + uiDefAutoButsRNA(C, layout, &ptr, 2); uiPopupBoundsBlock(block, 4.0f, 0, 0); uiEndBlock(C, block); @@ -333,7 +330,7 @@ static uiBlock *wm_block_create_menu(bContext *C, ARegion *ar, void *arg_op) uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN|UI_BLOCK_RET_1); layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 300, 20, style); - uiDefAutoButsRNA(C, layout, op->ptr); + uiDefAutoButsRNA(C, layout, op->ptr, 2); uiPopupBoundsBlock(block, 4.0f, 0, 0); uiEndBlock(C, block); @@ -402,7 +399,7 @@ static void operator_search_cb(const struct bContext *C, void *arg, char *str, u name[len]= '|'; } - if(0==uiSearchItemAdd(items, name, ot)) + if(0==uiSearchItemAdd(items, name, ot, 0)) break; } } @@ -421,7 +418,7 @@ static uiBlock *wm_block_search_menu(bContext *C, ARegion *ar, void *arg_op) uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_RET_1); but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 10, 180, 19, ""); - uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb); + uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL); /* fake button, it holds space for search items */ uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxhHeight(), 180, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); @@ -503,7 +500,7 @@ static void WM_OT_read_homefile(wmOperatorType *ot) static int recentfile_exec(bContext *C, wmOperator *op) { - int event= RNA_enum_get(op->ptr, "nr"); + int event= RNA_int_get(op->ptr, "nr"); // XXX wm in context is not set correctly after WM_read_file -> crash // do it before for now, but is this correct with multiple windows? @@ -557,7 +554,7 @@ static void WM_OT_open_recentfile(wmOperatorType *ot) ot->exec= recentfile_exec; ot->poll= WM_operator_winactive; - RNA_def_property(ot->srna, "nr", PROP_ENUM, PROP_NONE); + RNA_def_property(ot->srna, "nr", PROP_INT, PROP_UNSIGNED); } /* ********* main file *********** */ diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c index 9bd55e1c5a7..835fdca52fe 100644 --- a/source/blender/windowmanager/intern/wm_subwindow.c +++ b/source/blender/windowmanager/intern/wm_subwindow.c @@ -1,5 +1,5 @@ /** - * $Id: mywindow.c 9584 2007-01-03 13:45:03Z ton $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/windowmanager/wm_cursors.h b/source/blender/windowmanager/wm_cursors.h index 1a1a0d0b71d..3d1b49983ed 100644 --- a/source/blender/windowmanager/wm_cursors.h +++ b/source/blender/windowmanager/wm_cursors.h @@ -1,5 +1,5 @@ /** - * $Id: BIF_cursors.h 7739 2006-06-15 14:22:59Z broken $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/windowmanager/wm_subwindow.h b/source/blender/windowmanager/wm_subwindow.h index dfba9c27f17..c0c492018ff 100644 --- a/source/blender/windowmanager/wm_subwindow.h +++ b/source/blender/windowmanager/wm_subwindow.h @@ -1,5 +1,5 @@ /** - * $Id: wm_subwindow.h 21247 2009-06-29 21:50:53Z jaguarandi $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 4701eba810f..cd0d551211f 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -151,7 +151,7 @@ IF(WIN32) COMMAND xcopy /E /Y \"${WIN_SOURCE_DIR}\\release\\ui\\*.*\" \"${TARGETDIR}\\.blender\\ui\" COMMAND xcopy /E /Y \"${WIN_SOURCE_DIR}\\release\\plugins\\*.*\" \"${TARGETDIR}\\plugins\" COMMAND copy /Y \"${WIN_SOURCE_DIR}\\release\\text\\*.*\" \"${TARGETDIR}\" - COMMAND copy /Y \"${WIN_SOURCE_DIR}\\release\\windows\\extra\\python25.zip\" \"${TARGETDIR}\\\" + COMMAND copy /Y \"${WIN_SOURCE_DIR}\\release\\windows\\extra\\python26.zip\" \"${TARGETDIR}\\\" ) FILE(TO_NATIVE_PATH "${LIBDIR}" WIN_LIBDIR) @@ -164,7 +164,8 @@ IF(WIN32) COMMAND copy /Y \"${WIN_LIBDIR}\\sdl\\lib\\SDL.dll\" \"${TARGETDIR}\\\" COMMAND copy /Y \"${WIN_LIBDIR}\\zlib\\lib\\zlib.dll\" \"${TARGETDIR}\\\" COMMAND copy /Y \"${WIN_LIBDIR}\\tiff\\lib\\libtiff.dll\" \"${TARGETDIR}\\\" - COMMAND copy /Y \"${WIN_LIBDIR}\\python\\lib\\python25.dll\" \"${TARGETDIR}\\\" + COMMAND copy /Y \"${WIN_LIBDIR}\\python\\lib\\python26.dll\" \"${TARGETDIR}\\\" + COMMAND copy /Y \"${WIN_LIBDIR}\\python\\lib\\python26_d.dll\" \"${TARGETDIR}\\\" COMMAND copy /Y \"${WIN_LIBDIR}\\pthreads\\lib\\pthreadVC2.dll\" \"${TARGETDIR}\\\" ) @@ -198,7 +199,7 @@ ADD_DEPENDENCIES(blender makesdna) FILE(READ ${CMAKE_BINARY_DIR}/cmake_blender_libs.txt BLENDER_LINK_LIBS) -SET(BLENDER_LINK_LIBS bf_nodes ${BLENDER_LINK_LIBS} bf_windowmanager bf_editors blender_render blender_radiosity) +SET(BLENDER_LINK_LIBS bf_nodes ${BLENDER_LINK_LIBS} bf_windowmanager bf_editors blender_render) IF(WITH_ELBEEM) SET(BLENDER_LINK_LIBS ${BLENDER_LINK_LIBS} bf_elbeem) @@ -218,7 +219,6 @@ IF(UNIX) bf_ghost bf_string blender_render - blender_radiosity blender_ONL bf_python bf_gen_python @@ -238,7 +238,6 @@ IF(UNIX) bf_kernel bf_decimation bf_elbeem - bf_yafray bf_IK bf_memutil bf_guardedalloc @@ -264,10 +263,7 @@ IF(UNIX) bf_ngnetwork extern_bullet bf_loopbacknetwork - bf_sumo bf_common - extern_solid - extern_qhull bf_moto bf_python bf_gen_python diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 44678cb73eb..fb222b419c3 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -65,6 +65,14 @@ #include "SYS_System.h" +#include "GPU_extensions.h" +#include "Value.h" + + + +#ifdef __cplusplus +extern "C" { +#endif /***/ #include "DNA_view3d_types.h" #include "DNA_screen_types.h" @@ -77,21 +85,13 @@ //XXX #include "BIF_scrarea.h" #include "BKE_main.h" -//#include "BKE_context.h" #include "BLI_blenlib.h" #include "BLO_readfile.h" #include "DNA_scene_types.h" /***/ -#include "GPU_extensions.h" -#include "Value.h" - - - -#ifdef __cplusplus -extern "C" { -#endif //XXX #include "BSE_headerbuttons.h" +#include "BKE_context.h" #include "../../blender/windowmanager/WM_types.h" #include "../../blender/windowmanager/wm_window.h" #include "../../blender/windowmanager/wm_event_system.h" @@ -118,19 +118,10 @@ static BlendFileData *load_game_data(char *filename) return bfd; } - -/* screw it, BKE_context.h is complaining! */ -extern "C" struct wmWindow *CTX_wm_window(const bContext *C); -extern "C" struct ScrArea *CTX_wm_area(const bContext *C); -extern "C" struct ARegion *CTX_wm_region(const bContext *C); -extern "C" struct Scene *CTX_data_scene(const bContext *C); -extern "C" struct Main *CTX_data_main(const bContext *C); - extern "C" void StartKetsjiShell(struct bContext *C, int always_use_expand_framing) { /* context values */ struct wmWindow *win= CTX_wm_window(C); - struct ScrArea *area= CTX_wm_area(C); // curarea struct ARegion *ar= CTX_wm_region(C); struct Scene *scene= CTX_data_scene(C); struct Main* maggie1= CTX_data_main(C); @@ -159,8 +150,8 @@ extern "C" void StartKetsjiShell(struct bContext *C, int always_use_expand_frami do { - View3D *v3d= (View3D*) area->spacedata.first; - RegionView3D *rv3d= (RegionView3D*) ar->regiondata; + View3D *v3d= CTX_wm_view3d(C); + RegionView3D *rv3d= CTX_wm_region_view3d(C); // get some preferences SYS_SystemHandle syshandle = SYS_GetSystem(); @@ -239,13 +230,12 @@ extern "C" void StartKetsjiShell(struct bContext *C, int always_use_expand_frami scene->camera= v3d->camera; } - // some blender stuff MT_CmMatrix4x4 projmat; MT_CmMatrix4x4 viewmat; float camzoom; int i; - + for (i = 0; i < 16; i++) { float *viewmat_linear= (float*) rv3d->viewmat; @@ -257,7 +247,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, int always_use_expand_frami projmat.setElem(i, projmat_linear[i]); } - if(v3d->persp==V3D_CAMOB) { + if(rv3d->persp==V3D_CAMOB) { camzoom = (1.41421 + (rv3d->camzoom / 50.0)); camzoom *= camzoom; } @@ -348,10 +338,10 @@ extern "C" void StartKetsjiShell(struct bContext *C, int always_use_expand_frami if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME) { - if (v3d->persp != V3D_CAMOB) + if (rv3d->persp != V3D_CAMOB) { ketsjiengine->EnableCameraOverride(startscenename); - ketsjiengine->SetCameraOverrideUseOrtho((v3d->persp == V3D_ORTHO)); + ketsjiengine->SetCameraOverrideUseOrtho((rv3d->persp == V3D_ORTHO)); ketsjiengine->SetCameraOverrideProjectionMatrix(projmat); ketsjiengine->SetCameraOverrideViewMatrix(viewmat); ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far); @@ -587,7 +577,6 @@ extern "C" void StartKetsjiShell(struct bContext *C, int always_use_expand_frami } extern "C" void StartKetsjiShellSimulation(struct wmWindow *win, - struct ScrArea *area, struct ARegion *ar, char* scenename, struct Main* maggie, diff --git a/source/gameengine/BlenderRoutines/CMakeLists.txt b/source/gameengine/BlenderRoutines/CMakeLists.txt index 3b690a21584..2874a0273cc 100644 --- a/source/gameengine/BlenderRoutines/CMakeLists.txt +++ b/source/gameengine/BlenderRoutines/CMakeLists.txt @@ -19,7 +19,8 @@ SET(INC ../../../source/blender/windowmanager ../../../source/blender ../../../source/blender/include - ../../../source/blender/makesdna + ../../../source/blender/makesdna + ../../../source/blender/makesrna ../../../source/gameengine/Rasterizer ../../../source/gameengine/GameLogic ../../../source/gameengine/Expressions diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp index aa83d17a03a..360794ceb33 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp @@ -28,11 +28,13 @@ #include "KX_BlenderCanvas.h" #include "DNA_screen_types.h" +#include "stdio.h" #ifdef HAVE_CONFIG_H #include #endif + KX_BlenderCanvas::KX_BlenderCanvas(struct wmWindow *win, ARegion *ar) : m_win(win), m_ar(ar) diff --git a/source/gameengine/BlenderRoutines/Makefile b/source/gameengine/BlenderRoutines/Makefile index f5486bae87b..ffa99a0c1b2 100644 --- a/source/gameengine/BlenderRoutines/Makefile +++ b/source/gameengine/BlenderRoutines/Makefile @@ -36,8 +36,6 @@ include nan_compile.mk CCFLAGS += $(LEVEL_1_CPP_WARNINGS) CPPFLAGS += -I$(NAN_GLEW)/include -CPPFLAGS += -I$(NAN_SUMO)/include -I$(NAN_SOLID)/include -CPPFLAGS += -I$(NAN_SOLID) CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include CPPFLAGS += -I$(NAN_FUZZICS)/include @@ -56,6 +54,7 @@ CPPFLAGS += -I../../blender/render/extern/include CPPFLAGS += -I../../blender/blenloader CPPFLAGS += -I../../blender/blenfont CPPFLAGS += -I../../blender/gpu +CPPFLAGS += -I../../blender/makesrna CPPFLAGS += -I../Converter CPPFLAGS += -I../Expressions CPPFLAGS += -I../GameLogic @@ -67,7 +66,6 @@ CPPFLAGS += -I../../kernel/gen_system CPPFLAGS += -I../Network CPPFLAGS += -I../Network/LoopBackNetwork CPPFLAGS += -I../Physics/common -CPPFLAGS += -I../Physics/Sumo CPPFLAGS += -I. ifeq ($(OS),windows) diff --git a/source/gameengine/BlenderRoutines/SConscript b/source/gameengine/BlenderRoutines/SConscript index a0cc3af3611..fc12f453d86 100644 --- a/source/gameengine/BlenderRoutines/SConscript +++ b/source/gameengine/BlenderRoutines/SConscript @@ -11,7 +11,8 @@ incs += ' #intern/ghost/include' incs += ' #intern/moto/include #source/gameengine/Ketsji #source/blender/blenlib' incs += ' #source/blender/blenkernel #source/blender' incs += ' #source/blender/blenfont #source/blender/editors/include' -incs += ' #source/blender/makesdna #source/gameengine/Rasterizer #source/gameengine/GameLogic' +incs += ' #source/blender/makesdna #source/blender/makesrna' +incs += ' #source/gameengine/Rasterizer #source/gameengine/GameLogic' incs += ' #source/gameengine/Expressions #source/gameengine/Network' incs += ' #source/gameengine/SceneGraph #source/gameengine/Physics/common' incs += ' #source/gameengine/Physics/Bullet' @@ -20,11 +21,6 @@ incs += ' #intern/SoundSystem #source/blender/misc #source/blender/blenloader' incs += ' #extern/glew/include #source/blender/gpu' incs += ' #source/blender/windowmanager' -if env['WITH_BF_SOLID']: - incs += ' #source/gameengine/Physics/Sumo #source/gameengine/Physics/Sumo/Fuzzics/include' - incs += ' ' + env['BF_SOLID_INC'] - defs.append('USE_SUMO_SOLID') - if env['WITH_BF_FFMPEG']: defs.append('WITH_FFMPEG') diff --git a/source/gameengine/CMakeLists.txt b/source/gameengine/CMakeLists.txt index fd05858710d..f546a31fb2e 100644 --- a/source/gameengine/CMakeLists.txt +++ b/source/gameengine/CMakeLists.txt @@ -38,7 +38,6 @@ ADD_SUBDIRECTORY(Rasterizer) ADD_SUBDIRECTORY(Rasterizer/RAS_OpenGLRasterizer) ADD_SUBDIRECTORY(SceneGraph) ADD_SUBDIRECTORY(Physics/Bullet) -ADD_SUBDIRECTORY(Physics/Sumo) ADD_SUBDIRECTORY(VideoTexture) IF(WITH_PLAYER) diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index c0d28d28bda..bed99a4f502 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -446,7 +446,7 @@ PyObject* BL_ActionActuator::PyGetAction(PyObject* args, ShowDeprecationWarning("getAction()", "the action property"); if (m_action){ - return PyString_FromString(m_action->id.name+2); + return PyUnicode_FromString(m_action->id.name+2); } Py_RETURN_NONE; } @@ -796,7 +796,7 @@ PyObject* BL_ActionActuator::PySetFrameProperty(PyObject* args, } PyObject* BL_ActionActuator::PyGetChannel(PyObject* value) { - char *string= PyString_AsString(value); + char *string= _PyUnicode_AsString(value); if (!string) { PyErr_SetString(PyExc_TypeError, "expected a single string"); @@ -888,7 +888,7 @@ PyObject* BL_ActionActuator::PySetType(PyObject* args, PyObject* BL_ActionActuator::PyGetContinue() { ShowDeprecationWarning("getContinue()", "the continue property"); - return PyInt_FromLong((long)(m_end_reset==0)); + return PyLong_FromSsize_t((long)(m_end_reset==0)); } PyObject* BL_ActionActuator::PySetContinue(PyObject* value) { @@ -962,9 +962,9 @@ KX_PYMETHODDEF_DOC(BL_ActionActuator, setChannel, else { MT_Vector3 loc; MT_Vector3 size; - MT_Vector4 quat; + MT_Quaternion quat; - if (!PyVecTo(pyloc, loc) || !PyVecTo(pysize, size) || !PyVecTo(pyquat, quat)) + if (!PyVecTo(pyloc, loc) || !PyVecTo(pysize, size) || !PyQuatTo(pyquat, quat)) return NULL; // same as above @@ -977,7 +977,7 @@ KX_PYMETHODDEF_DOC(BL_ActionActuator, setChannel, // for some reason loc.setValue(pchan->loc) fails pchan->loc[0]= loc[0]; pchan->loc[1]= loc[1]; pchan->loc[2]= loc[2]; pchan->size[0]= size[0]; pchan->size[1]= size[1]; pchan->size[2]= size[2]; - pchan->quat[0]= quat[0]; pchan->quat[1]= quat[1]; pchan->quat[2]= quat[2]; pchan->quat[3]= quat[3]; + pchan->quat[0]= quat[3]; pchan->quat[1]= quat[0]; pchan->quat[2]= quat[1]; pchan->quat[3]= quat[2]; /* notice xyzw -> wxyz is intentional */ } pchan->flag |= POSE_ROT|POSE_LOC|POSE_SIZE; @@ -1005,19 +1005,15 @@ PyTypeObject BL_ActionActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject BL_ActionActuator::Parents[] = { - &BL_ActionActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef BL_ActionActuator::Methods[] = { @@ -1065,37 +1061,24 @@ PyAttributeDef BL_ActionActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* BL_ActionActuator::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IActuator); -} - -PyObject* BL_ActionActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int BL_ActionActuator::py_setattro(PyObject *attr, PyObject* value) { - py_setattro_up(SCA_IActuator); -} - - PyObject* BL_ActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { BL_ActionActuator* self= static_cast(self_v); - return PyString_FromString(self->GetAction() ? self->GetAction()->id.name+2 : ""); + return PyUnicode_FromString(self->GetAction() ? self->GetAction()->id.name+2 : ""); } int BL_ActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { BL_ActionActuator* self= static_cast(self_v); - if (!PyString_Check(value)) + if (!PyUnicode_Check(value)) { PyErr_SetString(PyExc_ValueError, "actuator.action = val: Action Actuator, expected the string name of the action"); return PY_SET_ATTR_FAIL; } bAction *action= NULL; - STR_String val = PyString_AsString(value); + STR_String val = _PyUnicode_AsString(value); if (val != "") { diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h index 422b16bb3ec..e328ce126ca 100644 --- a/source/gameengine/Converter/BL_ActionActuator.h +++ b/source/gameengine/Converter/BL_ActionActuator.h @@ -49,9 +49,8 @@ public: short blendin, short priority, short end_reset, - float stride, - PyTypeObject* T=&Type) - : SCA_IActuator(gameobj,T), + float stride) + : SCA_IActuator(gameobj), m_lastpos(0, 0, 0), m_blendframe(0), @@ -113,10 +112,6 @@ public: KX_PYMETHOD_DOC(BL_ActionActuator,setChannel); - virtual PyObject* py_getattro(PyObject* attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject* attr, PyObject* value); - static PyObject* pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index b907e300879..177f261e40b 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -163,7 +163,6 @@ extern "C" { #include "SG_BBox.h" #include "SG_Tree.h" -// defines USE_ODE to choose physics engine #include "KX_ConvertPhysicsObject.h" #ifdef USE_BULLET #include "CcdPhysicsEnvironment.h" @@ -1610,18 +1609,6 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, break; #endif -#ifdef USE_SUMO_SOLID - case UseSumo: - KX_ConvertSumoObject(gameobj, meshobj, kxscene, shapeprops, smmaterial, &objprop); - break; -#endif - -#ifdef USE_ODE - case UseODE: - KX_ConvertODEEngineObject(gameobj, meshobj, kxscene, shapeprops, smmaterial, &objprop); - break; -#endif //USE_ODE - case UseDynamo: //KX_ConvertDynamoObject(gameobj,meshobj,kxscene,shapeprops, smmaterial, &objprop); break; diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp index 7aa8714de3a..970539777f4 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -427,20 +427,17 @@ PyTypeObject BL_ShapeActionActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &SCA_IActuator::Type, + 0,0,0,0,0,0, + py_base_new }; -PyParentObject BL_ShapeActionActuator::Parents[] = { - &BL_ShapeActionActuator::Type, - &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL -}; PyMethodDef BL_ShapeActionActuator::Methods[] = { {"setAction", (PyCFunction) BL_ShapeActionActuator::sPySetAction, METH_VARARGS, (PY_METHODCHAR)SetAction_doc}, @@ -480,19 +477,6 @@ PyAttributeDef BL_ShapeActionActuator::Attributes[] = { { NULL } //Sentinel }; - -PyObject* BL_ShapeActionActuator::py_getattro(PyObject* attr) { - py_getattro_up(SCA_IActuator); -} - -PyObject* BL_ShapeActionActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int BL_ShapeActionActuator::py_setattro(PyObject *attr, PyObject* value) { - py_setattro_up(SCA_IActuator); -} - /* setStart */ const char BL_ShapeActionActuator::GetAction_doc[] = "getAction()\n" @@ -501,7 +485,7 @@ const char BL_ShapeActionActuator::GetAction_doc[] = PyObject* BL_ShapeActionActuator::PyGetAction() { ShowDeprecationWarning("getAction()", "the action property"); if (m_action){ - return PyString_FromString(m_action->id.name+2); + return PyUnicode_FromString(m_action->id.name+2); } Py_RETURN_NONE; } @@ -860,21 +844,21 @@ PyObject* BL_ShapeActionActuator::PySetType(PyObject* args) { PyObject* BL_ShapeActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { BL_ShapeActionActuator* self= static_cast(self_v); - return PyString_FromString(self->GetAction() ? self->GetAction()->id.name+2 : ""); + return PyUnicode_FromString(self->GetAction() ? self->GetAction()->id.name+2 : ""); } int BL_ShapeActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { BL_ShapeActionActuator* self= static_cast(self_v); /* exact copy of BL_ActionActuator's function from here down */ - if (!PyString_Check(value)) + if (!PyUnicode_Check(value)) { PyErr_SetString(PyExc_ValueError, "actuator.action = val: Shape Action Actuator, expected the string name of the action"); return PY_SET_ATTR_FAIL; } bAction *action= NULL; - STR_String val = PyString_AsString(value); + STR_String val = _PyUnicode_AsString(value); if (val != "") { diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h index d268eef6d23..890fe3f9de9 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.h +++ b/source/gameengine/Converter/BL_ShapeActionActuator.h @@ -50,9 +50,8 @@ public: short playtype, short blendin, short priority, - float stride, - PyTypeObject* T=&Type) - : SCA_IActuator(gameobj,T), + float stride) + : SCA_IActuator(gameobj), m_lastpos(0, 0, 0), m_blendframe(0), @@ -106,10 +105,6 @@ public: KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetType); KX_PYMETHOD_DOC_VARARGS(BL_ShapeActionActuator,SetType); - virtual PyObject* py_getattro(PyObject* attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject* attr, PyObject* value); - static PyObject* pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 86e20b88580..9e0a710f44f 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -44,21 +44,12 @@ #include "DummyPhysicsEnvironment.h" -//to decide to use sumo/ode or dummy physics - defines USE_ODE #include "KX_ConvertPhysicsObject.h" #ifdef USE_BULLET #include "CcdPhysicsEnvironment.h" #endif -#ifdef USE_ODE -#include "OdePhysicsEnvironment.h" -#endif //USE_ODE - -#ifdef USE_SUMO_SOLID -#include "SumoPhysicsEnvironment.h" -#endif - #include "KX_BlenderSceneConverter.h" #include "KX_BlenderScalarInterpolator.h" #include "BL_BlenderDataConversion.h" @@ -145,10 +136,6 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter() delete (*itm).second; itm++; } - -#ifdef USE_SUMO_SOLID - KX_ClearSumoSharedShapes(); -#endif #ifdef USE_BULLET KX_ClearBulletSharedShapes(); @@ -331,20 +318,7 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename, destinationscene->SetPhysicsEnvironment(ccdPhysEnv); break; } -#endif - -#ifdef USE_SUMO_SOLID - case UseSumo: - destinationscene ->SetPhysicsEnvironment(new SumoPhysicsEnvironment()); - break; -#endif -#ifdef USE_ODE - - case UseODE: - destinationscene ->SetPhysicsEnvironment(new ODEPhysicsEnvironment()); - break; -#endif //USE_ODE - +#endif case UseDynamo: { } diff --git a/source/gameengine/Converter/Makefile b/source/gameengine/Converter/Makefile index abded70f289..ed95aa968c7 100644 --- a/source/gameengine/Converter/Makefile +++ b/source/gameengine/Converter/Makefile @@ -39,8 +39,7 @@ CPPFLAGS += -I$(OPENGL_HEADERS) CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) -CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO) -I$(NAN_MOTO)/include -CPPFLAGS += -I$(NAN_SOLID)/include +CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_MOTO)/include CPPFLAGS += -I$(NAN_BULLET2)/include CPPFLAGS += -I../../blender diff --git a/source/gameengine/Converter/SConscript b/source/gameengine/Converter/SConscript index 3e0929e605a..05ea01c902a 100644 --- a/source/gameengine/Converter/SConscript +++ b/source/gameengine/Converter/SConscript @@ -21,11 +21,6 @@ incs += ' #source/blender/misc #source/blender/blenloader #source/blender/gpu' incs += ' #source/blender/windowmanager' incs += ' #source/blender/makesrna' -if env['WITH_BF_SOLID']: - incs += ' #source/gameengine/Physics/Sumo #source/gameengine/Physics/Sumo/Fuzzics/include' - incs += ' ' + env['BF_SOLID_INC'] - defs.append('USE_SUMO_SOLID') - incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_BULLET_INC'] diff --git a/source/gameengine/Expressions/BoolValue.cpp b/source/gameengine/Expressions/BoolValue.cpp index d90da8b3a92..6779c2ea780 100644 --- a/source/gameengine/Expressions/BoolValue.cpp +++ b/source/gameengine/Expressions/BoolValue.cpp @@ -29,7 +29,6 @@ const STR_String CBoolValue::sTrueString = "TRUE"; const STR_String CBoolValue::sFalseString = "FALSE"; - CBoolValue::CBoolValue() /* pre: false @@ -210,5 +209,5 @@ CValue* CBoolValue::GetReplica() PyObject* CBoolValue::ConvertValueToPython() { - return PyInt_FromLong(m_bool != 0); + return PyBool_FromLong(m_bool != 0); } diff --git a/source/gameengine/Expressions/CMakeLists.txt b/source/gameengine/Expressions/CMakeLists.txt index e3942b46557..dffd13f64ff 100644 --- a/source/gameengine/Expressions/CMakeLists.txt +++ b/source/gameengine/Expressions/CMakeLists.txt @@ -32,6 +32,7 @@ SET(INC ../../../intern/string ../../../intern/moto/include ../../../source/gameengine/SceneGraph + ../../../source/blender/blenloader ${PYTHON_INC} ) diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/IntValue.cpp index 227518e9439..b782de4bef6 100644 --- a/source/gameengine/Expressions/IntValue.cpp +++ b/source/gameengine/Expressions/IntValue.cpp @@ -330,7 +330,7 @@ void CIntValue::SetValue(CValue* newval) PyObject* CIntValue::ConvertValueToPython() { if((m_int > INT_MIN) && (m_int < INT_MAX)) - return PyInt_FromLong(m_int); + return PyLong_FromSsize_t(m_int); else return PyLong_FromLongLong(m_int); } diff --git a/source/gameengine/Expressions/KX_Python.h b/source/gameengine/Expressions/KX_Python.h index b8006fdf0ed..61f7ef05042 100644 --- a/source/gameengine/Expressions/KX_Python.h +++ b/source/gameengine/Expressions/KX_Python.h @@ -32,6 +32,8 @@ //#define USE_DL_EXPORT #include "Python.h" +#define USE_MATHUTILS // Blender 2.5x api will use mathutils, for a while we might want to test without it + #ifdef __FreeBSD__ #include #if __FreeBSD_version > 500039 diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp index 59344ddb7b7..38b00dcc8fb 100644 --- a/source/gameengine/Expressions/ListValue.cpp +++ b/source/gameengine/Expressions/ListValue.cpp @@ -76,9 +76,9 @@ PyObject* listvalue_mapping_subscript(PyObject* self, PyObject* pyindex) return NULL; } - if (PyString_Check(pyindex)) + if (PyUnicode_Check(pyindex)) { - CValue *item = ((CListValue*) list)->FindValue(PyString_AsString(pyindex)); + CValue *item = ((CListValue*) list)->FindValue(_PyUnicode_AsString(pyindex)); if (item) { PyObject* pyobj = item->ConvertValueToPython(); if(pyobj) @@ -87,14 +87,14 @@ PyObject* listvalue_mapping_subscript(PyObject* self, PyObject* pyindex) return item->GetProxy(); } } - else if (PyInt_Check(pyindex)) + else if (PyLong_Check(pyindex)) { - int index = PyInt_AsLong(pyindex); + int index = PyLong_AsSsize_t(pyindex); return listvalue_buffer_item(self, index); /* wont add a ref */ } PyObject *pyindex_str = PyObject_Repr(pyindex); /* new ref */ - PyErr_Format(PyExc_KeyError, "CList[key]: '%s' key not in list", PyString_AsString(pyindex_str)); + PyErr_Format(PyExc_KeyError, "CList[key]: '%s' key not in list", _PyUnicode_AsString(pyindex_str)); Py_DECREF(pyindex_str); return NULL; } @@ -220,12 +220,12 @@ static int listvalue_buffer_contains(PyObject *self_v, PyObject *value) return -1; } - if (PyString_Check(value)) { - if (self->FindValue((const char *)PyString_AsString(value))) { + if (PyUnicode_Check(value)) { + if (self->FindValue((const char *)_PyUnicode_AsString(value))) { return 1; } } - else if (BGE_PROXY_CHECK_TYPE(value)) { /* not dict like at all but this worked before __contains__ was used */ + else if (PyObject_TypeCheck(value, &CValue::Type)) { /* not dict like at all but this worked before __contains__ was used */ CValue *item= static_cast(BGE_PROXY_REF(value)); for (int i=0; i < self->GetCount(); i++) if (self->GetValue(i) == item) // Com @@ -289,25 +289,19 @@ PyTypeObject CListValue::Type = { 0, /*tp_hash*/ 0, /*tp_call */ 0, - py_base_getattro, - py_base_setattro, + NULL, + NULL, 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 0,0,0,0,0,0,0, - Methods -}; - - - -PyParentObject CListValue::Parents[] = { - &CListValue::Type, + Methods, + 0, + 0, &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - - - PyMethodDef CListValue::Methods[] = { /* List style access */ {"append", (PyCFunction)CListValue::sPyappend,METH_O}, @@ -329,21 +323,12 @@ PyAttributeDef CListValue::Attributes[] = { { NULL } //Sentinel }; -PyObject* CListValue::py_getattro(PyObject* attr) { - py_getattro_up(CValue); -} - -PyObject* CListValue::py_getattro_dict() { - py_getattro_dict_up(CValue); -} - - ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// -CListValue::CListValue(PyTypeObject *T ) -: CPropValue(T) +CListValue::CListValue() +: CPropValue() { m_bReleaseContents=true; } @@ -559,7 +544,7 @@ PyObject* CListValue::Pyindex(PyObject *value) CValue* elem = GetValue(i); if (checkobj==elem || CheckEqual(checkobj,elem)) { - result = PyInt_FromLong(i); + result = PyLong_FromSsize_t(i); break; } } @@ -582,7 +567,7 @@ PyObject* CListValue::Pycount(PyObject* value) if (checkobj==NULL) { /* in this case just return that there are no items in the list */ PyErr_Clear(); - return PyInt_FromLong(0); + return PyLong_FromSsize_t(0); } int numelem = GetCount(); @@ -596,7 +581,7 @@ PyObject* CListValue::Pycount(PyObject* value) } checkobj->Release(); - return PyInt_FromLong(numfound); + return PyLong_FromSsize_t(numfound); } /* Matches python dict.get(key, [default]) */ @@ -623,7 +608,7 @@ PyObject* CListValue::Pyget(PyObject *args) /* Matches python dict.has_key() */ PyObject* CListValue::Pyhas_key(PyObject* value) { - if (PyString_Check(value) && FindValue((const char *)PyString_AsString(value))) + if (PyUnicode_Check(value) && FindValue((const char *)_PyUnicode_AsString(value))) Py_RETURN_TRUE; Py_RETURN_FALSE; diff --git a/source/gameengine/Expressions/ListValue.h b/source/gameengine/Expressions/ListValue.h index 68e900e25e0..98e6f216f11 100644 --- a/source/gameengine/Expressions/ListValue.h +++ b/source/gameengine/Expressions/ListValue.h @@ -24,7 +24,7 @@ class CListValue : public CPropValue //PLUGIN_DECLARE_SERIAL (CListValue,CValue) public: - CListValue(PyTypeObject *T = &Type); + CListValue(); virtual ~CListValue(); void AddConfigurationData(CValue* menuvalue); @@ -60,8 +60,6 @@ public: bool CheckEqual(CValue* first,CValue* second); - virtual PyObject* py_getattro(PyObject* attr); - virtual PyObject* py_getattro_dict(); virtual PyObject* py_repr(void) { PyObject *py_proxy= this->GetProxy(); PyObject *py_list= PySequence_List(py_proxy); diff --git a/source/gameengine/Expressions/Makefile b/source/gameengine/Expressions/Makefile index f46c0037200..09512c3ae87 100644 --- a/source/gameengine/Expressions/Makefile +++ b/source/gameengine/Expressions/Makefile @@ -37,6 +37,7 @@ CCFLAGS += $(LEVEL_1_CPP_WARNINGS) CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) CPPFLAGS += -I../../blender/makesdna +CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index defb6853e67..729fff31052 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -74,11 +74,13 @@ PyTypeObject PyObjectPlus::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + NULL // no subtype }; @@ -91,106 +93,9 @@ PyObjectPlus::~PyObjectPlus() // assert(ob_refcnt==0); } -void PyObjectPlus::py_base_dealloc(PyObject *self) // python wrapper -{ - PyObjectPlus *self_plus= BGE_PROXY_REF(self); - if(self_plus) { - if(BGE_PROXY_PYOWNS(self)) { /* Does python own this?, then delete it */ - self_plus->m_proxy = NULL; /* Need this to stop ~PyObjectPlus from decrefing m_proxy otherwise its decref'd twice and py-debug crashes */ - delete self_plus; - } - - BGE_PROXY_REF(self)= NULL; // not really needed - } - PyObject_DEL( self ); -}; - -PyObjectPlus::PyObjectPlus(PyTypeObject *T) : SG_QList() // constructor -{ - MT_assert(T != NULL); - m_proxy= NULL; -}; - -/*------------------------------ - * PyObjectPlus Methods -- Every class, even the abstract one should have a Methods -------------------------------*/ -PyMethodDef PyObjectPlus::Methods[] = { - {"isA", (PyCFunction) sPyisA, METH_O}, - {NULL, NULL} /* Sentinel */ -}; - -PyAttributeDef PyObjectPlus::Attributes[] = { - KX_PYATTRIBUTE_RO_FUNCTION("invalid", PyObjectPlus, pyattr_get_invalid), - {NULL} //Sentinel -}; - -PyObject* PyObjectPlus::pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ - Py_RETURN_FALSE; -} - -/*------------------------------ - * PyObjectPlus Parents -- Every class, even the abstract one should have parents -------------------------------*/ -PyParentObject PyObjectPlus::Parents[] = {&PyObjectPlus::Type, NULL}; - -/*------------------------------ - * PyObjectPlus attributes -- attributes -------------------------------*/ - - -/* This should be the entry in Type since it takes the C++ class from PyObjectPlus_Proxy */ -PyObject *PyObjectPlus::py_base_getattro(PyObject * self, PyObject *attr) -{ - PyObjectPlus *self_plus= BGE_PROXY_REF(self); - if(self_plus==NULL) { - if(!strcmp("invalid", PyString_AsString(attr))) { - Py_RETURN_TRUE; - } - PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); - return NULL; - } - - PyObject *ret= self_plus->py_getattro(attr); - - /* Attribute not found, was this a __dict__ lookup?, otherwise set an error if none is set */ - if(ret==NULL) { - char *attr_str= PyString_AsString(attr); - - if (strcmp(attr_str, "__dict__")==0) - { - /* the error string will probably not - * be set but just incase clear it */ - PyErr_Clear(); - ret= self_plus->py_getattro_dict(); - } - else if (!PyErr_Occurred()) { - /* We looked for an attribute but it wasnt found - * since py_getattro didnt set the error, set it here */ - PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", self->ob_type->tp_name, attr_str); - } - } - return ret; -} - -/* This should be the entry in Type since it takes the C++ class from PyObjectPlus_Proxy */ -int PyObjectPlus::py_base_setattro(PyObject *self, PyObject *attr, PyObject *value) -{ - PyObjectPlus *self_plus= BGE_PROXY_REF(self); - if(self_plus==NULL) { - PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); - return -1; - } - - if (value==NULL) - return self_plus->py_delattro(attr); - - return self_plus->py_setattro(attr, value); -} PyObject *PyObjectPlus::py_base_repr(PyObject *self) // This should be the entry in Type. { - PyObjectPlus *self_plus= BGE_PROXY_REF(self); if(self_plus==NULL) { PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); @@ -200,42 +105,134 @@ PyObject *PyObjectPlus::py_base_repr(PyObject *self) // This should be the ent return self_plus->py_repr(); } -PyObject *PyObjectPlus::py_getattro(PyObject* attr) + +PyObject * PyObjectPlus::py_base_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \ - if (descr == NULL) { - return NULL; /* py_base_getattro sets the error, this way we can avoid setting the error at many levels */ - } else { - /* Copied from py_getattro_up */ - if (PyCObject_Check(descr)) { - return py_get_attrdef((void *)this, (const PyAttributeDef*)PyCObject_AsVoidPtr(descr)); - } else if (descr->ob_type->tp_descr_get) { - return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy); - } else { - return NULL; - } - /* end py_getattro_up copy */ + PyTypeObject *base_type; + PyObjectPlus_Proxy *base = NULL; + + if (!PyArg_ParseTuple(args, "O:Base PyObjectPlus", &base)) + return NULL; + + /* the 'base' PyObject may be subclassed (multiple times even) + * we need to find the first C++ defined class to check 'type' + * is a subclass of the base arguments type. + * + * This way we can share one tp_new function for every PyObjectPlus + * + * eg. + * + * # CustomOb is called 'type' in this C code + * class CustomOb(GameTypes.KX_GameObject): + * pass + * + * # this calls py_base_new(...), the type of 'CustomOb' is checked to be a subclass of the 'cont.owner' type + * ob = CustomOb(cont.owner) + * + * */ + base_type= Py_TYPE(base); + while(base_type && !BGE_PROXY_CHECK_TYPE(base_type)) + base_type= base_type->tp_base; + + if(base_type==NULL || !BGE_PROXY_CHECK_TYPE(base_type)) { + PyErr_SetString(PyExc_TypeError, "can't subclass from a blender game type because the argument given is not a game class or subclass"); + return NULL; } + + /* use base_type rather then Py_TYPE(base) because we could alredy be subtyped */ + if(!PyType_IsSubtype(type, base_type)) { + PyErr_Format(PyExc_TypeError, "can't subclass blender game type <%s> from <%s> because it is not a subclass", base_type->tp_name, type->tp_name); + return NULL; + } + + /* invalidate the existing base and return a new subclassed one, + * this is a bit dodgy in that it also attaches its self to the existing object + * which is not really 'correct' python OO but for our use its OK. */ + + PyObjectPlus_Proxy *ret = (PyObjectPlus_Proxy *) type->tp_alloc(type, 0); /* starts with 1 ref, used for the return ref' */ + ret->ref= base->ref; + base->ref= NULL; /* invalidate! disallow further access */ + + ret->py_owns= base->py_owns; + + ret->ref->m_proxy= NULL; + + /* 'base' may be free'd after this func finished but not necessarily + * there is no reference to the BGE data now so it will throw an error on access */ + Py_DECREF(base); + + ret->ref->m_proxy= (PyObject *)ret; /* no need to add a ref because one is added when creating. */ + Py_INCREF(ret); /* we return a new ref but m_proxy holds a ref so we need to add one */ + + + /* 'ret' will have 2 references. + * - One ref is needed because ret->ref->m_proxy holds a refcount to the current proxy. + * - Another is needed for returning the value. + * + * So we should be ok with 2 refs, but for some reason this crashes. so adding a new ref... + * */ + + return (PyObject *)ret; } -PyObject* PyObjectPlus::py_getattro_dict() { - return py_getattr_dict(NULL, Type.tp_dict); -} - -int PyObjectPlus::py_delattro(PyObject* attr) +void PyObjectPlus::py_base_dealloc(PyObject *self) // python wrapper { - PyErr_SetString(PyExc_AttributeError, "attribute cant be deleted"); - return 1; + PyObjectPlus *self_plus= BGE_PROXY_REF(self); + if(self_plus) { + if(BGE_PROXY_PYOWNS(self)) { /* Does python own this?, then delete it */ + self_plus->m_proxy = NULL; /* Need this to stop ~PyObjectPlus from decrefing m_proxy otherwise its decref'd twice and py-debug crashes */ + delete self_plus; + } + + BGE_PROXY_REF(self)= NULL; // not really needed + } + +#if 0 + /* is ok normally but not for subtyping, use tp_free instead. */ + PyObject_DEL( self ); +#else + Py_TYPE(self)->tp_free(self); +#endif +}; + +PyObjectPlus::PyObjectPlus() : SG_QList() // constructor +{ + m_proxy= NULL; +}; + +/*------------------------------ + * PyObjectPlus Methods -- Every class, even the abstract one should have a Methods +------------------------------*/ +PyMethodDef PyObjectPlus::Methods[] = { + {NULL, NULL} /* Sentinel */ +}; + +#define attr_invalid (&(PyObjectPlus::Attributes[0])) +PyAttributeDef PyObjectPlus::Attributes[] = { + KX_PYATTRIBUTE_RO_FUNCTION("invalid", PyObjectPlus, pyattr_get_invalid), + {NULL} //Sentinel +}; + + + +PyObject* PyObjectPlus::pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + return PyBool_FromLong(self_v ? 1:0); } -int PyObjectPlus::py_setattro(PyObject *attr, PyObject* value) +/* note, this is called as a python 'getset, where the PyAttributeDef is the closure */ +PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *attrdef) { - PyErr_SetString(PyExc_AttributeError, "attribute cant be set"); - return PY_SET_ATTR_MISSING; -} + void *self= (void *)(BGE_PROXY_REF(self_py)); + if(self==NULL) { + if(attrdef == attr_invalid) + Py_RETURN_TRUE; // dont bother running the function + + PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); + return NULL; + } + -PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef) -{ if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY) { // fake attribute, ignore @@ -259,14 +256,14 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef { bool *val = reinterpret_cast(ptr); ptr += sizeof(bool); - PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val)); + PyList_SET_ITEM(resultlist,i,PyLong_FromSsize_t(*val)); break; } case KX_PYATTRIBUTE_TYPE_SHORT: { short int *val = reinterpret_cast(ptr); ptr += sizeof(short int); - PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val)); + PyList_SET_ITEM(resultlist,i,PyLong_FromSsize_t(*val)); break; } case KX_PYATTRIBUTE_TYPE_ENUM: @@ -281,7 +278,7 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef { int *val = reinterpret_cast(ptr); ptr += sizeof(int); - PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val)); + PyList_SET_ITEM(resultlist,i,PyLong_FromSsize_t(*val)); break; } case KX_PYATTRIBUTE_TYPE_FLOAT: @@ -305,12 +302,12 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef case KX_PYATTRIBUTE_TYPE_BOOL: { bool *val = reinterpret_cast(ptr); - return PyInt_FromLong(*val); + return PyLong_FromSsize_t(*val); } case KX_PYATTRIBUTE_TYPE_SHORT: { short int *val = reinterpret_cast(ptr); - return PyInt_FromLong(*val); + return PyLong_FromSsize_t(*val); } case KX_PYATTRIBUTE_TYPE_ENUM: // enum are like int, just make sure the field size is the same @@ -322,7 +319,7 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef case KX_PYATTRIBUTE_TYPE_INT: { int *val = reinterpret_cast(ptr); - return PyInt_FromLong(*val); + return PyLong_FromSsize_t(*val); } case KX_PYATTRIBUTE_TYPE_FLOAT: { @@ -331,18 +328,23 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef } case KX_PYATTRIBUTE_TYPE_VECTOR: { - PyObject* resultlist = PyList_New(3); MT_Vector3 *val = reinterpret_cast(ptr); +#ifdef USE_MATHUTILS + float fval[3]= {(*val)[0], (*val)[1], (*val)[2]}; + return newVectorObject(fval, 3, Py_NEW, NULL); +#else + PyObject* resultlist = PyList_New(3); for (unsigned int i=0; i<3; i++) { PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble((*val)[i])); } return resultlist; +#endif } case KX_PYATTRIBUTE_TYPE_STRING: { STR_String *val = reinterpret_cast(ptr); - return PyString_FromString(*val); + return PyUnicode_FromString(*val); } default: return NULL; @@ -350,8 +352,15 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef } } -int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyObject *value) +/* note, this is called as a python getset */ +int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAttributeDef *attrdef) { + void *self= (void *)(BGE_PROXY_REF(self_py)); + if(self==NULL) { + PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); + return PY_SET_ATTR_FAIL; + } + void *undoBuffer = NULL; void *sourceBuffer = NULL; size_t bufferSize = 0; @@ -416,9 +425,9 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb { bool *var = reinterpret_cast(ptr); ptr += sizeof(bool); - if (PyInt_Check(item)) + if (PyLong_Check(item)) { - *var = (PyInt_AsLong(item) != 0); + *var = (PyLong_AsSsize_t(item) != 0); } else if (PyBool_Check(item)) { @@ -435,9 +444,9 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb { short int *var = reinterpret_cast(ptr); ptr += sizeof(short int); - if (PyInt_Check(item)) + if (PyLong_Check(item)) { - long val = PyInt_AsLong(item); + long val = PyLong_AsSsize_t(item); if (attrdef->m_clamp) { if (val < attrdef->m_imin) @@ -471,9 +480,9 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb { int *var = reinterpret_cast(ptr); ptr += sizeof(int); - if (PyInt_Check(item)) + if (PyLong_Check(item)) { - long val = PyInt_AsLong(item); + long val = PyLong_AsSsize_t(item); if (attrdef->m_clamp) { if (val < attrdef->m_imin) @@ -606,9 +615,9 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb case KX_PYATTRIBUTE_TYPE_BOOL: { bool *var = reinterpret_cast(ptr); - if (PyInt_Check(value)) + if (PyLong_Check(value)) { - *var = (PyInt_AsLong(value) != 0); + *var = (PyLong_AsSsize_t(value) != 0); } else if (PyBool_Check(value)) { @@ -624,9 +633,9 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb case KX_PYATTRIBUTE_TYPE_SHORT: { short int *var = reinterpret_cast(ptr); - if (PyInt_Check(value)) + if (PyLong_Check(value)) { - long val = PyInt_AsLong(value); + long val = PyLong_AsSsize_t(value); if (attrdef->m_clamp) { if (val < attrdef->m_imin) @@ -659,9 +668,9 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb case KX_PYATTRIBUTE_TYPE_INT: { int *var = reinterpret_cast(ptr); - if (PyInt_Check(value)) + if (PyLong_Check(value)) { - long val = PyInt_AsLong(value); + long val = PyLong_AsSsize_t(value); if (attrdef->m_clamp) { if (val < attrdef->m_imin) @@ -746,9 +755,9 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb case KX_PYATTRIBUTE_TYPE_STRING: { STR_String *var = reinterpret_cast(ptr); - if (PyString_Check(value)) + if (PyUnicode_Check(value)) { - char *val = PyString_AsString(value); + char *val = _PyUnicode_AsString(value); if (attrdef->m_clamp) { if (strlen(val) < attrdef->m_imin) @@ -829,48 +838,6 @@ PyObject *PyObjectPlus::py_repr(void) return NULL; } -/*------------------------------ - * PyObjectPlus isA -- the isA functions -------------------------------*/ -bool PyObjectPlus::isA(PyTypeObject *T) // if called with a Type, use "typename" -{ - int i; - PyParentObject P; - PyParentObject *Ps = GetParents(); - - for (P = Ps[i=0]; P != NULL; P = Ps[i++]) - if (P==T) - return true; - - return false; -} - - -bool PyObjectPlus::isA(const char *mytypename) // check typename of each parent -{ - int i; - PyParentObject P; - PyParentObject *Ps = GetParents(); - - for (P = Ps[i=0]; P != NULL; P = Ps[i++]) - if (strcmp(P->tp_name, mytypename)==0) - return true; - - return false; -} - -PyObject *PyObjectPlus::PyisA(PyObject *value) // Python wrapper for isA -{ - if (PyType_Check(value)) { - return PyBool_FromLong(isA((PyTypeObject *)value)); - } else if (PyString_Check(value)) { - return PyBool_FromLong(isA(PyString_AsString(value))); - } - PyErr_SetString(PyExc_TypeError, "object.isA(value): expected a type or a string"); - return NULL; -} - - void PyObjectPlus::ProcessReplica() { /* Clear the proxy, will be created again if needed with GetProxy() @@ -895,27 +862,6 @@ void PyObjectPlus::InvalidateProxy() // check typename of each parent } } -/* Utility function called by the macro py_getattro_up() - * for getting ob.__dict__() values from our PyObject - * this is used by python for doing dir() on an object, so its good - * if we return a list of attributes and methods. - * - * Other then making dir() useful the value returned from __dict__() is not useful - * since every value is a Py_None - * */ -PyObject *py_getattr_dict(PyObject *pydict, PyObject *tp_dict) -{ - if(pydict==NULL) { /* incase calling __dict__ on the parent of this object raised an error */ - PyErr_Clear(); - pydict = PyDict_New(); - } - - PyDict_Update(pydict, tp_dict); - return pydict; -} - - - PyObject *PyObjectPlus::GetProxy_Ext(PyObjectPlus *self, PyTypeObject *tp) { if (self->m_proxy==NULL) @@ -986,7 +932,7 @@ void PyObjectPlus::ShowDeprecationWarning_func(const char* old_way,const char* n co_filename= PyObject_GetAttrString(f_code, "co_filename"); if (co_filename) { - printf("\t%s:%d\n", PyString_AsString(co_filename), (int)PyInt_AsLong(f_lineno)); + printf("\t%s:%d\n", _PyUnicode_AsString(co_filename), (int)PyLong_AsSsize_t(f_lineno)); Py_DECREF(f_lineno); Py_DECREF(f_code); diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index c002dccefe4..a18df9d36a9 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -45,21 +45,15 @@ * Python defines ------------------------------*/ - - -#if PY_VERSION_HEX > 0x03000000 -#define PyString_FromString PyUnicode_FromString -#define PyString_FromFormat PyUnicode_FromFormat -#define PyString_Check PyUnicode_Check -#define PyString_Size PyUnicode_GetSize - -#define PyInt_FromLong PyLong_FromSsize_t -#define PyInt_AsLong PyLong_AsSsize_t -#define PyString_AsString _PyUnicode_AsString -#define PyInt_Check PyLong_Check -#define PyInt_AS_LONG PyLong_AsLong // TODO - check this one +#ifdef USE_MATHUTILS +extern "C" { +#include "../../blender/python/generic/Mathutils.h" /* so we can have mathutils callbacks */ +} #endif +extern "C" { +#include "../../blender/python/intern/bpy_compat.h" +} /* @@ -141,7 +135,7 @@ typedef struct { #define BGE_PROXY_PYOWNS(_self) (((PyObjectPlus_Proxy *)_self)->py_owns) /* Note, sometimes we dont care what BGE type this is as long as its a proxy */ -#define BGE_PROXY_CHECK_TYPE(_self) ((_self)->ob_type->tp_dealloc == PyObjectPlus::py_base_dealloc) +#define BGE_PROXY_CHECK_TYPE(_type) ((_type)->tp_dealloc == PyObjectPlus::py_base_dealloc) // This must be the first line of each @@ -151,41 +145,10 @@ typedef struct { static PyTypeObject Type; \ static PyMethodDef Methods[]; \ static PyAttributeDef Attributes[]; \ - static PyParentObject Parents[]; \ virtual PyTypeObject *GetType(void) {return &Type;}; \ - virtual PyParentObject *GetParents(void) {return Parents;} \ virtual PyObject *GetProxy() {return GetProxy_Ext(this, &Type);}; \ virtual PyObject *NewProxy(bool py_owns) {return NewProxy_Ext(this, &Type, py_owns);}; \ - - - - // This defines the py_getattro_up macro - // which allows attribute and method calls - // to be properly passed up the hierarchy. - // - // Note, PyDict_GetItem() WONT set an exception! - // let the py_base_getattro function do this. - -#define py_getattro_up(Parent) \ - \ - PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \ - \ - if(descr) { \ - if (PyCObject_Check(descr)) { \ - return py_get_attrdef((void *)this, (const PyAttributeDef*)PyCObject_AsVoidPtr(descr)); \ - } else if (descr->ob_type->tp_descr_get) { \ - return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy); \ - } else { \ - return NULL; \ - } \ - } else { \ - return Parent::py_getattro(attr); \ - } - -#define py_getattro_dict_up(Parent) \ - return py_getattr_dict(Parent::py_getattro_dict(), Type.tp_dict); - /* * nonzero values are an error for setattr * however because of the nested lookups we need to know if the errors @@ -197,29 +160,6 @@ typedef struct { #define PY_SET_ATTR_MISSING -1 #define PY_SET_ATTR_SUCCESS 0 -#define py_setattro_up(Parent) \ - PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \ - \ - if(descr) { \ - if (PyCObject_Check(descr)) { \ - const PyAttributeDef* attrdef= reinterpret_cast(PyCObject_AsVoidPtr(descr)); \ - if (attrdef->m_access == KX_PYATTRIBUTE_RO) { \ - PyErr_Format(PyExc_AttributeError, "\"%s\" is read only", PyString_AsString(attr)); \ - return PY_SET_ATTR_FAIL; \ - } \ - else { \ - return py_set_attrdef((void *)this, attrdef, value); \ - } \ - } else { \ - PyErr_Format(PyExc_AttributeError, "\"%s\" cannot be set", PyString_AsString(attr)); \ - return PY_SET_ATTR_FAIL; \ - } \ - } else { \ - PyErr_Clear(); \ - return Parent::py_setattro(attr, value); \ - } - - /** * These macros are helpfull when embedding Python routines. The second * macro is one that also requires a documentation string @@ -489,7 +429,7 @@ class PyObjectPlus : public SG_QList Py_Header; // Always start with Py_Header public: - PyObjectPlus(PyTypeObject *T); + PyObjectPlus(); PyObject *m_proxy; /* actually a PyObjectPlus_Proxy */ @@ -497,30 +437,19 @@ public: /* These static functions are referenced by ALL PyObjectPlus_Proxy types * they take the C++ reference from the PyObjectPlus_Proxy and call - * its own virtual py_getattro, py_setattro etc. functions. + * its own virtual py_repr, py_base_dealloc ,etc. functions. */ + + static PyObject* py_base_new(PyTypeObject *type, PyObject *args, PyObject *kwds); /* allows subclassing */ static void py_base_dealloc(PyObject *self); - static PyObject* py_base_getattro(PyObject * self, PyObject *attr); - static int py_base_setattro(PyObject *self, PyObject *attr, PyObject *value); static PyObject* py_base_repr(PyObject *self); /* These are all virtual python methods that are defined in each class * Our own fake subclassing calls these on each class, then calls the parent */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_delattro(PyObject *attr); - virtual int py_setattro(PyObject *attr, PyObject *value); virtual PyObject* py_repr(void); - static PyObject* py_get_attrdef(void *self, const PyAttributeDef *attrdef); - static int py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyObject *value); - - /* isA() methods, shonky replacement for pythons issubclass() - * which we cant use because we have our own subclass system */ - bool isA(PyTypeObject *T); - bool isA(const char *mytypename); - - KX_PYMETHOD_O(PyObjectPlus,isA); + static PyObject* py_get_attrdef(PyObject *self_py, const PyAttributeDef *attrdef); + static int py_set_attrdef(PyObject *self_py, PyObject *value, const PyAttributeDef *attrdef); /* Kindof dumb, always returns True, the false case is checked for, before this function gets accessed */ static PyObject* pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Expressions/StringValue.h b/source/gameengine/Expressions/StringValue.h index 52f8a580f4d..c580e8fd23a 100644 --- a/source/gameengine/Expressions/StringValue.h +++ b/source/gameengine/Expressions/StringValue.h @@ -40,7 +40,7 @@ public: virtual void SetValue(CValue* newval) { m_strString = newval->GetText(); SetModified(true); }; virtual CValue* GetReplica(); virtual PyObject* ConvertValueToPython() { - return PyString_FromString(m_strString.Ptr()); + return PyUnicode_FromString(m_strString.Ptr()); } private: diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index 61dabff510b..d8c81f56f66 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -54,15 +54,17 @@ PyTypeObject CValue::Type = { py_base_repr, 0, 0,0,0,0,0, - py_base_getattro, - py_base_setattro, - 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject CValue::Parents[] = { - &CValue::Type, - NULL + NULL, + NULL, + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new }; PyMethodDef CValue::Methods[] = { @@ -74,7 +76,7 @@ PyObject* CValue::PyGetName() { ShowDeprecationWarning("getName()", "the name property"); - return PyString_FromString(this->GetName()); + return PyUnicode_FromString(this->GetName()); } /*#define CVALUE_DEBUG*/ @@ -100,8 +102,8 @@ std::vector gRefList; //int gRefCountValue; #endif -CValue::CValue(PyTypeObject *T) - : PyObjectPlus(T), +CValue::CValue() + : PyObjectPlus(), #else CValue::CValue() : @@ -553,33 +555,9 @@ PyAttributeDef CValue::Attributes[] = { { NULL } //Sentinel }; - -PyObject* CValue::py_getattro(PyObject *attr) -{ - char *attr_str= PyString_AsString(attr); - CValue* resultattr = GetProperty(attr_str); - if (resultattr) - { - /* only show the wanting here because python inspects for __class__ and KX_MeshProxy uses CValues name attr */ - ShowDeprecationWarning("val = ob.attr", "val = ob['attr']"); - - PyObject* pyconvert = resultattr->ConvertValueToPython(); - - if (pyconvert) - return pyconvert; - else - return resultattr->GetProxy(); - } - py_getattro_up(PyObjectPlus); -} - -PyObject* CValue::py_getattro_dict() { - py_getattro_dict_up(PyObjectPlus); -} - PyObject * CValue::pyattr_get_name(void * self_v, const KX_PYATTRIBUTE_DEF * attrdef) { CValue * self = static_cast (self_v); - return PyString_FromString(self->GetName()); + return PyUnicode_FromString(self->GetName()); } CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix) @@ -623,30 +601,23 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix) { vallie = new CFloatValue( (float)PyFloat_AsDouble(pyobj) ); } else +#if PY_VERSION_HEX < 0x03000000 if (PyInt_Check(pyobj)) { vallie = new CIntValue( (cInt)PyInt_AS_LONG(pyobj) ); } else +#endif if (PyLong_Check(pyobj)) { vallie = new CIntValue( (cInt)PyLong_AsLongLong(pyobj) ); } else - if (PyString_Check(pyobj)) + if (PyUnicode_Check(pyobj)) { - vallie = new CStringValue(PyString_AsString(pyobj),""); + vallie = new CStringValue(_PyUnicode_AsString(pyobj),""); } else - if (BGE_PROXY_CHECK_TYPE(pyobj)) /* Note, dont let these get assigned to GameObject props, must check elsewhere */ + if (PyObject_TypeCheck(pyobj, &CValue::Type)) /* Note, dont let these get assigned to GameObject props, must check elsewhere */ { - if (BGE_PROXY_REF(pyobj) && (BGE_PROXY_REF(pyobj))->isA(&CValue::Type)) - { - vallie = (static_cast(BGE_PROXY_REF(pyobj)))->AddRef(); - } else { - - if(BGE_PROXY_REF(pyobj)) /* this is not a CValue */ - PyErr_Format(PyExc_TypeError, "%sgame engine python type cannot be used as a property", error_prefix); - else /* PyObjectPlus_Proxy has been removed, cant use */ - PyErr_Format(PyExc_SystemError, "%s"BGE_PROXY_ERROR_MSG, error_prefix); - } + vallie = (static_cast(BGE_PROXY_REF(pyobj)))->AddRef(); } else { /* return an error value from the caller */ @@ -656,57 +627,6 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix) } -int CValue::py_delattro(PyObject *attr) -{ - ShowDeprecationWarning("del ob.attr", "del ob['attr']"); - - char *attr_str= PyString_AsString(attr); - if (RemoveProperty(attr_str)) - return 0; - - PyErr_Format(PyExc_AttributeError, "attribute \"%s\" dosnt exist", attr_str); - return PY_SET_ATTR_MISSING; -} - -int CValue::py_setattro(PyObject *attr, PyObject* pyobj) -{ - ShowDeprecationWarning("ob.attr = val", "ob['attr'] = val"); - - char *attr_str= PyString_AsString(attr); - CValue* oldprop = GetProperty(attr_str); - CValue* vallie; - - /* Dissallow python to assign GameObjects, Scenes etc as values */ - if ((BGE_PROXY_CHECK_TYPE(pyobj)==0) && (vallie = ConvertPythonToValue(pyobj, "cvalue.attr = value: "))) - { - if (oldprop) - oldprop->SetValue(vallie); - else - SetProperty(attr_str, vallie); - - vallie->Release(); - } - else { - // ConvertPythonToValue sets the error message - // must return missing so KX_GameObect knows this - // attribute was not a function or bult in attribute, - // - // CValue attributes override internal attributes - // so if it exists as a CValue attribute already, - // assume your trying to set it to a differnt CValue attribute - // otherwise return PY_SET_ATTR_MISSING so children - // classes know they can set it without conflict - - if (GetProperty(attr_str)) - return PY_SET_ATTR_COERCE_FAIL; /* failed to set an existing attribute */ - else - return PY_SET_ATTR_MISSING; /* allow the KX_GameObject dict to set */ - } - - //PyObjectPlus::py_setattro(attr,value); - return PY_SET_ATTR_SUCCESS; -}; - PyObject* CValue::ConvertKeysToPython( void ) { PyObject *pylist = PyList_New( 0 ); @@ -717,7 +637,7 @@ PyObject* CValue::ConvertKeysToPython( void ) std::map::iterator it; for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++) { - pystr = PyString_FromString( (*it).first ); + pystr = PyUnicode_FromString( (*it).first ); PyList_Append(pylist, pystr); Py_DECREF( pystr ); } diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h index 29ef19b46c9..8c9f99b335e 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/Value.h @@ -215,26 +215,18 @@ public: // Construction / Destruction #ifndef NO_EXP_PYTHON_EMBEDDING - CValue(PyTypeObject *T = &Type); + CValue(); //static PyObject* PyMake(PyObject*,PyObject*); virtual PyObject *py_repr(void) { - return PyString_FromString((const char*)GetText()); + return PyUnicode_FromString((const char*)GetText()); } - - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); virtual PyObject* ConvertValueToPython() { return NULL; } virtual CValue* ConvertPythonToValue(PyObject* pyobj, const char *error_prefix); - - - virtual int py_delattro(PyObject *attr); - virtual int py_setattro(PyObject *attr, PyObject* value); static PyObject * pyattr_get_name(void * self, const KX_PYATTRIBUTE_DEF * attrdef); @@ -417,8 +409,8 @@ class CPropValue : public CValue public: #ifndef NO_EXP_PYTHON_EMBEDDING - CPropValue(PyTypeObject* T=&Type) : - CValue(T), + CPropValue() : + CValue(), #else CPropValue() : #endif //NO_EXP_PYTHON_EMBEDDING diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp index caed85b9938..04d46e259d3 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp @@ -42,9 +42,8 @@ SCA_2DFilterActuator::SCA_2DFilterActuator( float float_arg, int int_arg, RAS_IRasterizer* rasterizer, - RAS_IRenderTools* rendertools, - PyTypeObject* T) - : SCA_IActuator(gameobj, T), + RAS_IRenderTools* rendertools) + : SCA_IActuator(gameobj), m_type(type), m_disableMotionBlur(flag), m_float_arg(float_arg), @@ -124,23 +123,17 @@ PyTypeObject SCA_2DFilterActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &SCA_IActuator::Type, + 0,0,0,0,0,0, + py_base_new }; - -PyParentObject SCA_2DFilterActuator::Parents[] = { - &SCA_2DFilterActuator::Type, - &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL -}; - - PyMethodDef SCA_2DFilterActuator::Methods[] = { /* add python functions to deal with m_msg... */ {NULL,NULL} @@ -154,18 +147,3 @@ PyAttributeDef SCA_2DFilterActuator::Attributes[] = { KX_PYATTRIBUTE_FLOAT_RW("value", 0.0, 100.0, SCA_2DFilterActuator, m_float_arg), { NULL } //Sentinel }; - -PyObject* SCA_2DFilterActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* SCA_2DFilterActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int SCA_2DFilterActuator::py_setattro(PyObject *attr, PyObject* value) -{ - py_setattro_up(SCA_IActuator); -} - diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.h b/source/gameengine/GameLogic/SCA_2DFilterActuator.h index 13b9997a010..c357c4f3e37 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.h +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.h @@ -56,23 +56,12 @@ public: float float_arg, int int_arg, RAS_IRasterizer* rasterizer, - RAS_IRenderTools* rendertools, - PyTypeObject* T=&Type - ); + RAS_IRenderTools* rendertools); void SetShaderText(const char *text); virtual ~SCA_2DFilterActuator(); virtual bool Update(); virtual CValue* GetReplica(); - - /* --------------------------------------------------------------------- */ - /* Python interface ---------------------------------------------------- */ - /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); - }; #endif diff --git a/source/gameengine/GameLogic/SCA_ANDController.cpp b/source/gameengine/GameLogic/SCA_ANDController.cpp index 87f7c612e7c..78e1350428e 100644 --- a/source/gameengine/GameLogic/SCA_ANDController.cpp +++ b/source/gameengine/GameLogic/SCA_ANDController.cpp @@ -42,10 +42,9 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ -SCA_ANDController::SCA_ANDController(SCA_IObject* gameobj, - PyTypeObject* T) +SCA_ANDController::SCA_ANDController(SCA_IObject* gameobj) : - SCA_IController(gameobj,T) + SCA_IController(gameobj) { } @@ -116,19 +115,15 @@ PyTypeObject SCA_ANDController::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_ANDController::Parents[] = { - &SCA_ANDController::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IController::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_ANDController::Methods[] = { @@ -139,12 +134,4 @@ PyAttributeDef SCA_ANDController::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_ANDController::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IController); -} - -PyObject* SCA_ANDController::py_getattro_dict() { - py_getattro_dict_up(SCA_IController); -} - /* eof */ diff --git a/source/gameengine/GameLogic/SCA_ANDController.h b/source/gameengine/GameLogic/SCA_ANDController.h index 9a359d57cb4..cb16d7fca01 100644 --- a/source/gameengine/GameLogic/SCA_ANDController.h +++ b/source/gameengine/GameLogic/SCA_ANDController.h @@ -39,18 +39,10 @@ class SCA_ANDController : public SCA_IController Py_Header; //virtual void Trigger(class SCA_LogicManager* logicmgr); public: - SCA_ANDController(SCA_IObject* gameobj,PyTypeObject* T=&Type); + SCA_ANDController(SCA_IObject* gameobj); virtual ~SCA_ANDController(); virtual CValue* GetReplica(); virtual void Trigger(SCA_LogicManager* logicmgr); - - /* --------------------------------------------------------------------- */ - /* Python interface ---------------------------------------------------- */ - /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - }; #endif //__KX_ANDCONTROLLER diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp index 4dad65c5a25..bdcc923e1d9 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp @@ -40,9 +40,8 @@ SCA_ActuatorSensor::SCA_ActuatorSensor(SCA_EventManager* eventmgr, SCA_IObject* gameobj, - const STR_String& actname, - PyTypeObject* T ) - : SCA_ISensor(gameobj,eventmgr,T), + const STR_String& actname) + : SCA_ISensor(gameobj,eventmgr), m_checkactname(actname) { m_actuator = GetParent()->FindActuator(m_checkactname); @@ -138,19 +137,15 @@ PyTypeObject SCA_ActuatorSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_ActuatorSensor::Parents[] = { - &SCA_ActuatorSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_ActuatorSensor::Methods[] = { @@ -166,18 +161,6 @@ PyAttributeDef SCA_ActuatorSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_ActuatorSensor::py_getattro(PyObject *attr) { - py_getattro_up(SCA_ISensor); -} - -PyObject* SCA_ActuatorSensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int SCA_ActuatorSensor::py_setattro(PyObject *attr, PyObject *value) { - py_setattro_up(SCA_ISensor); -} - int SCA_ActuatorSensor::CheckActuator(void *self, const PyAttributeDef*) { SCA_ActuatorSensor* sensor = reinterpret_cast(self); @@ -197,7 +180,7 @@ const char SCA_ActuatorSensor::GetActuator_doc[] = PyObject* SCA_ActuatorSensor::PyGetActuator() { ShowDeprecationWarning("getActuator()", "the actuator property"); - return PyString_FromString(m_checkactname); + return PyUnicode_FromString(m_checkactname); } /* 4. setActuator */ diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.h b/source/gameengine/GameLogic/SCA_ActuatorSensor.h index 6655e08dc70..cf8e735cad4 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.h +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.h @@ -46,8 +46,7 @@ class SCA_ActuatorSensor : public SCA_ISensor public: SCA_ActuatorSensor(class SCA_EventManager* eventmgr, SCA_IObject* gameobj, - const STR_String& actname, - PyTypeObject* T=&Type ); + const STR_String& actname); virtual ~SCA_ActuatorSensor(); virtual CValue* GetReplica(); @@ -61,10 +60,6 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - /* 3. setProperty */ KX_PYMETHOD_DOC_VARARGS(SCA_ActuatorSensor,SetActuator); /* 4. getProperty */ diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp index ff02680f191..ddb54c580b8 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp +++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp @@ -48,9 +48,8 @@ /* ------------------------------------------------------------------------- */ SCA_AlwaysSensor::SCA_AlwaysSensor(class SCA_EventManager* eventmgr, - SCA_IObject* gameobj, - PyTypeObject* T) - : SCA_ISensor(gameobj,eventmgr, T) + SCA_IObject* gameobj) + : SCA_ISensor(gameobj,eventmgr) { //SetDrawColor(255,0,0); Init(); @@ -121,19 +120,15 @@ PyTypeObject SCA_AlwaysSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_AlwaysSensor::Parents[] = { - &SCA_AlwaysSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_AlwaysSensor::Methods[] = { @@ -144,12 +139,4 @@ PyAttributeDef SCA_AlwaysSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_AlwaysSensor::py_getattro(PyObject *attr) { - py_getattro_up(SCA_ISensor); -} - -PyObject* SCA_AlwaysSensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - /* eof */ diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.h b/source/gameengine/GameLogic/SCA_AlwaysSensor.h index 0f85a641ef1..d58e05564d1 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysSensor.h +++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.h @@ -39,22 +39,12 @@ class SCA_AlwaysSensor : public SCA_ISensor bool m_alwaysresult; public: SCA_AlwaysSensor(class SCA_EventManager* eventmgr, - SCA_IObject* gameobj, - PyTypeObject* T =&Type); + SCA_IObject* gameobj); virtual ~SCA_AlwaysSensor(); virtual CValue* GetReplica(); virtual bool Evaluate(); virtual bool IsPositiveTrigger(); virtual void Init(); - - - /* --------------------------------------------------------------------- */ - /* Python interface ---------------------------------------------------- */ - /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - }; #endif //__KX_ALWAYSSENSOR diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.cpp b/source/gameengine/GameLogic/SCA_DelaySensor.cpp index dcdae0b4e75..11c6996a0a1 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.cpp +++ b/source/gameengine/GameLogic/SCA_DelaySensor.cpp @@ -51,9 +51,8 @@ SCA_DelaySensor::SCA_DelaySensor(class SCA_EventManager* eventmgr, SCA_IObject* gameobj, int delay, int duration, - bool repeat, - PyTypeObject* T) - : SCA_ISensor(gameobj,eventmgr, T), + bool repeat) + : SCA_ISensor(gameobj,eventmgr), m_repeat(repeat), m_delay(delay), m_duration(duration) @@ -147,19 +146,15 @@ PyTypeObject SCA_DelaySensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_DelaySensor::Parents[] = { - &SCA_DelaySensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_DelaySensor::Methods[] = { @@ -183,19 +178,6 @@ PyAttributeDef SCA_DelaySensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_DelaySensor::py_getattro(PyObject *attr) { - py_getattro_up(SCA_ISensor); -} - -PyObject* SCA_DelaySensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int SCA_DelaySensor::py_setattro(PyObject *attr, PyObject *value) { - py_setattro_up(SCA_ISensor); -} - - const char SCA_DelaySensor::SetDelay_doc[] = "setDelay(delay)\n" "\t- delay: length of the initial OFF period as number of frame\n" @@ -262,7 +244,7 @@ const char SCA_DelaySensor::GetDelay_doc[] = PyObject* SCA_DelaySensor::PyGetDelay() { ShowDeprecationWarning("getDelay()", "the delay property"); - return PyInt_FromLong(m_delay); + return PyLong_FromSsize_t(m_delay); } const char SCA_DelaySensor::GetDuration_doc[] = @@ -271,7 +253,7 @@ const char SCA_DelaySensor::GetDuration_doc[] = PyObject* SCA_DelaySensor::PyGetDuration() { ShowDeprecationWarning("getDuration()", "the duration property"); - return PyInt_FromLong(m_duration); + return PyLong_FromSsize_t(m_duration); } const char SCA_DelaySensor::GetRepeat_doc[] = diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.h b/source/gameengine/GameLogic/SCA_DelaySensor.h index 5ccb33f8a16..8270e8959b7 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.h +++ b/source/gameengine/GameLogic/SCA_DelaySensor.h @@ -47,8 +47,7 @@ public: SCA_IObject* gameobj, int delay, int duration, - bool repeat, - PyTypeObject* T =&Type); + bool repeat); virtual ~SCA_DelaySensor(); virtual CValue* GetReplica(); virtual bool Evaluate(); @@ -59,10 +58,6 @@ public: /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); /* setProperty */ KX_PYMETHOD_DOC_VARARGS(SCA_DelaySensor,SetDelay); diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.cpp b/source/gameengine/GameLogic/SCA_ExpressionController.cpp index 8e044b89c71..60969300474 100644 --- a/source/gameengine/GameLogic/SCA_ExpressionController.cpp +++ b/source/gameengine/GameLogic/SCA_ExpressionController.cpp @@ -46,9 +46,8 @@ /* ------------------------------------------------------------------------- */ SCA_ExpressionController::SCA_ExpressionController(SCA_IObject* gameobj, - const STR_String& exprtext, - PyTypeObject* T) - :SCA_IController(gameobj,T), + const STR_String& exprtext) + :SCA_IController(gameobj), m_exprText(exprtext), m_exprCache(NULL) { diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.h b/source/gameengine/GameLogic/SCA_ExpressionController.h index 6a34d7b2dff..705f6dfc415 100644 --- a/source/gameengine/GameLogic/SCA_ExpressionController.h +++ b/source/gameengine/GameLogic/SCA_ExpressionController.h @@ -42,8 +42,7 @@ class SCA_ExpressionController : public SCA_IController public: SCA_ExpressionController(SCA_IObject* gameobj, - const STR_String& exprtext, - PyTypeObject* T=&Type ); + const STR_String& exprtext); virtual ~SCA_ExpressionController(); virtual CValue* GetReplica(); @@ -54,14 +53,6 @@ public: * so that self references are removed before the controller itself is released */ virtual void Delete(); - - /* --------------------------------------------------------------------- */ - /* Python interface ---------------------------------------------------- */ - /* --------------------------------------------------------------------- */ - -// virtual PyObject* py_getattro(PyObject *attr); -// virtual PyObject* py_getattro_dict(); - }; #endif //__KX_EXPRESSIONCONTROLLER diff --git a/source/gameengine/GameLogic/SCA_IActuator.cpp b/source/gameengine/GameLogic/SCA_IActuator.cpp index be7c2651686..0fda75590c1 100644 --- a/source/gameengine/GameLogic/SCA_IActuator.cpp +++ b/source/gameengine/GameLogic/SCA_IActuator.cpp @@ -34,9 +34,8 @@ using namespace std; -SCA_IActuator::SCA_IActuator(SCA_IObject* gameobj, - PyTypeObject* T) : - SCA_ILogicBrick(gameobj,T), +SCA_IActuator::SCA_IActuator(SCA_IObject* gameobj) : + SCA_ILogicBrick(gameobj), m_links(0), m_posevent(false), m_negevent(false) diff --git a/source/gameengine/GameLogic/SCA_IActuator.h b/source/gameengine/GameLogic/SCA_IActuator.h index 27afcbc386b..13c718ee837 100644 --- a/source/gameengine/GameLogic/SCA_IActuator.h +++ b/source/gameengine/GameLogic/SCA_IActuator.h @@ -61,8 +61,7 @@ public: * This class also inherits the default copy constructors */ - SCA_IActuator(SCA_IObject* gameobj, - PyTypeObject* T =&Type); + SCA_IActuator(SCA_IObject* gameobj); /** * UnlinkObject(...) diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp index f2c3c83a2d9..7cbb728753a 100644 --- a/source/gameengine/GameLogic/SCA_IController.cpp +++ b/source/gameengine/GameLogic/SCA_IController.cpp @@ -37,10 +37,9 @@ #include #endif -SCA_IController::SCA_IController(SCA_IObject* gameobj, - PyTypeObject* T) +SCA_IController::SCA_IController(SCA_IObject* gameobj) : - SCA_ILogicBrick(gameobj,T), + SCA_ILogicBrick(gameobj), m_statemask(0), m_justActivated(false) { @@ -216,17 +215,15 @@ PyTypeObject SCA_IController::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_IController::Parents[] = { - &SCA_IController::Type, - &CValue::Type, - NULL + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &SCA_ILogicBrick::Type, + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_IController::Methods[] = { @@ -248,22 +245,6 @@ PyAttributeDef SCA_IController::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_IController::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_ILogicBrick); -} - -PyObject* SCA_IController::py_getattro_dict() { - py_getattro_dict_up(SCA_ILogicBrick); -} - -int SCA_IController::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_ILogicBrick); -} - - - PyObject* SCA_IController::PyGetActuators() { ShowDeprecationWarning("getActuators()", "the actuators property"); @@ -281,7 +262,7 @@ PyObject* SCA_IController::PyGetSensor(PyObject* value) { ShowDeprecationWarning("getSensor(string)", "the sensors[string] property"); - char *scriptArg = PyString_AsString(value); + char *scriptArg = _PyUnicode_AsString(value); if (scriptArg==NULL) { PyErr_SetString(PyExc_TypeError, "controller.getSensor(string): Python Controller, expected a string (sensor name)"); return NULL; @@ -305,7 +286,7 @@ PyObject* SCA_IController::PyGetActuator(PyObject* value) { ShowDeprecationWarning("getActuator(string)", "the actuators[string] property"); - char *scriptArg = PyString_AsString(value); + char *scriptArg = _PyUnicode_AsString(value); if (scriptArg==NULL) { PyErr_SetString(PyExc_TypeError, "controller.getActuator(string): Python Controller, expected a string (actuator name)"); return NULL; @@ -340,13 +321,13 @@ PyObject* SCA_IController::PyGetSensors() PyObject* SCA_IController::PyGetState() { ShowDeprecationWarning("getState()", "the state property"); - return PyInt_FromLong(m_statemask); + return PyLong_FromSsize_t(m_statemask); } PyObject* SCA_IController::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_IController* self= static_cast(self_v); - return PyInt_FromLong(self->m_statemask); + return PyLong_FromSsize_t(self->m_statemask); } PyObject* SCA_IController::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/GameLogic/SCA_IController.h b/source/gameengine/GameLogic/SCA_IController.h index a52c57ab3ed..523878bee26 100644 --- a/source/gameengine/GameLogic/SCA_IController.h +++ b/source/gameengine/GameLogic/SCA_IController.h @@ -47,7 +47,7 @@ protected: bool m_justActivated; bool m_bookmark; public: - SCA_IController(SCA_IObject* gameobj,PyTypeObject* T); + SCA_IController(SCA_IObject* gameobj); virtual ~SCA_IController(); virtual void Trigger(class SCA_LogicManager* logicmgr)=0; void LinkToSensor(SCA_ISensor* sensor); @@ -98,10 +98,6 @@ public: } } - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - KX_PYMETHOD_NOARGS(SCA_IController,GetSensors); KX_PYMETHOD_NOARGS(SCA_IController,GetActuators); KX_PYMETHOD_O(SCA_IController,GetSensor); diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index 2dc80f54568..ccb79a2d49f 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -35,10 +35,9 @@ SCA_LogicManager* SCA_ILogicBrick::m_sCurrentLogicManager = NULL; -SCA_ILogicBrick::SCA_ILogicBrick(SCA_IObject* gameobj, - PyTypeObject* T) +SCA_ILogicBrick::SCA_ILogicBrick(SCA_IObject* gameobj) : - CValue(T), + CValue(), m_gameobj(gameobj), m_Execute_Priority(0), m_Execute_Ueber_Priority(0), @@ -194,23 +193,17 @@ PyTypeObject SCA_ILogicBrick::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - - - -PyParentObject SCA_ILogicBrick::Parents[] = { - &SCA_ILogicBrick::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - - PyMethodDef SCA_ILogicBrick::Methods[] = { // --> Deprecated {"getOwner", (PyCFunction) SCA_ILogicBrick::sPyGetOwner, METH_NOARGS}, @@ -245,21 +238,6 @@ int SCA_ILogicBrick::CheckProperty(void *self, const PyAttributeDef *attrdef) return 0; } -PyObject* SCA_ILogicBrick::py_getattro(PyObject *attr) -{ - py_getattro_up(CValue); -} - -PyObject* SCA_ILogicBrick::py_getattro_dict() { - py_getattro_dict_up(CValue); -} - -int SCA_ILogicBrick::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(CValue); -} - - PyObject* SCA_ILogicBrick::PyGetOwner() { ShowDeprecationWarning("getOwner()", "the owner property"); @@ -296,7 +274,7 @@ PyObject* SCA_ILogicBrick::PySetExecutePriority(PyObject* args) PyObject* SCA_ILogicBrick::PyGetExecutePriority() { ShowDeprecationWarning("getExecutePriority()", "the executePriority property"); - return PyInt_FromLong(m_Execute_Priority); + return PyLong_FromSsize_t(m_Execute_Priority); } @@ -326,5 +304,5 @@ bool SCA_ILogicBrick::PyArgToBool(int boolArg) PyObject* SCA_ILogicBrick::BoolToPyArg(bool boolarg) { - return PyInt_FromLong(boolarg? KX_TRUE: KX_FALSE); + return PyLong_FromSsize_t(boolarg? KX_TRUE: KX_FALSE); } diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h index 779e5397a6a..50679856802 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.h +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h @@ -53,7 +53,7 @@ protected: CValue* GetEvent(); public: - SCA_ILogicBrick(SCA_IObject* gameobj,PyTypeObject* T ); + SCA_ILogicBrick(SCA_IObject* gameobj); virtual ~SCA_ILogicBrick(); void SetExecutePriority(int execute_Priority); @@ -121,10 +121,6 @@ public: } virtual bool LessComparedTo(SCA_ILogicBrick* other); - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); static class SCA_LogicManager* m_sCurrentLogicManager; diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp index 9876f2512c0..6cd11f9e553 100644 --- a/source/gameengine/GameLogic/SCA_IObject.cpp +++ b/source/gameengine/GameLogic/SCA_IObject.cpp @@ -41,8 +41,11 @@ MT_Point3 SCA_IObject::m_sDummy=MT_Point3(0,0,0); SG_QList SCA_IObject::m_activeBookmarkedControllers; -SCA_IObject::SCA_IObject(PyTypeObject* T): CValue(T), m_initState(0), m_state(0), m_firstState(NULL) - +SCA_IObject::SCA_IObject(): + CValue(), + m_initState(0), + m_state(0), + m_firstState(NULL) { m_suspended = false; } @@ -218,51 +221,6 @@ SCA_IActuator* SCA_IObject::FindActuator(const STR_String& actuatorname) } - -#if 0 -const MT_Point3& SCA_IObject::ConvertPythonPylist(PyObject* pylist) -{ - bool error = false; - m_sDummy = MT_Vector3(0,0,0); - if (pylist->ob_type == &CListValue::Type) - { - CListValue* listval = (CListValue*) pylist; - int numelem = listval->GetCount(); - if ( numelem <= 3) - { - int index; - for (index = 0;indexGetValue(index)->GetNumber(); - } - } else - { - error = true; - } - - } else - { - - // assert the list is long enough... - int numitems = PyList_Size(pylist); - if (numitems <= 3) - { - int index; - for (index=0;indexIsTriggered(this); - return PyInt_FromLong(retval); + return PyLong_FromSsize_t(retval); } /** @@ -355,7 +354,7 @@ const char SCA_ISensor::GetFrequency_doc[] = PyObject* SCA_ISensor::PyGetFrequency() { ShowDeprecationWarning("getFrequency()", "the frequency property"); - return PyInt_FromLong(m_pulse_frequency); + return PyLong_FromSsize_t(m_pulse_frequency); } /** @@ -489,19 +488,17 @@ PyTypeObject SCA_ISensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &SCA_ILogicBrick::Type, + 0,0,0,0,0,0, + py_base_new }; -PyParentObject SCA_ISensor::Parents[] = { - &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL -}; PyMethodDef SCA_ISensor::Methods[] = { //Deprecated functions -----> {"isPositive", (PyCFunction) SCA_ISensor::sPyIsPositive, @@ -548,19 +545,6 @@ PyAttributeDef SCA_ISensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_ISensor::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_ILogicBrick); -} - -PyObject* SCA_ISensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ILogicBrick); -} - -int SCA_ISensor::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_ILogicBrick); -} PyObject* SCA_ISensor::pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { @@ -568,13 +552,13 @@ PyObject* SCA_ISensor::pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_D int retval = 0; if (SCA_PythonController::m_sCurrentController) retval = SCA_PythonController::m_sCurrentController->IsTriggered(self); - return PyInt_FromLong(retval); + return PyLong_FromSsize_t(retval); } PyObject* SCA_ISensor::pyattr_get_positive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_ISensor* self= static_cast(self_v); - return PyInt_FromLong(self->GetState()); + return PyLong_FromSsize_t(self->GetState()); } int SCA_ISensor::pyattr_check_level(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index 9bbd6ed41e4..81864ab6a34 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -101,8 +101,7 @@ public: }; SCA_ISensor(SCA_IObject* gameobj, - class SCA_EventManager* eventmgr, - PyTypeObject* T );; + class SCA_EventManager* eventmgr);; ~SCA_ISensor(); virtual void ReParent(SCA_IObject* parent); @@ -173,10 +172,6 @@ public: { return !m_links; } /* Python functions: */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); //Deprecated functions -----> KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsPositive); diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index 336529667d7..f55921e648b 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -46,9 +46,8 @@ SCA_JoystickSensor::SCA_JoystickSensor(class SCA_JoystickManager* eventmgr, short int joymode, int axis, int axisf,int prec, int button, - int hat, int hatf, bool allevents, - PyTypeObject* T ) - :SCA_ISensor(gameobj,eventmgr,T), + int hat, int hatf, bool allevents) + :SCA_ISensor(gameobj,eventmgr), m_pJoystickMgr(eventmgr), m_axis(axis), m_axisf(axisf), @@ -269,23 +268,17 @@ PyTypeObject SCA_JoystickSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - - -PyParentObject SCA_JoystickSensor::Parents[] = { - &SCA_JoystickSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - PyMethodDef SCA_JoystickSensor::Methods[] = { //Deprecated functions ------> {"getIndex", (PyCFunction) SCA_JoystickSensor::sPyGetIndex, METH_NOARGS, (PY_METHODCHAR)GetIndex_doc}, @@ -328,20 +321,6 @@ PyAttributeDef SCA_JoystickSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_JoystickSensor::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_ISensor); -} - -PyObject* SCA_JoystickSensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int SCA_JoystickSensor::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_ISensor); -} - /* get index ---------------------------------------------------------- */ const char SCA_JoystickSensor::GetIndex_doc[] = @@ -349,7 +328,7 @@ const char SCA_JoystickSensor::GetIndex_doc[] = "\tReturns the joystick index to use.\n"; PyObject* SCA_JoystickSensor::PyGetIndex( ) { ShowDeprecationWarning("getIndex()", "the index property"); - return PyInt_FromLong(m_joyindex); + return PyLong_FromSsize_t(m_joyindex); } @@ -359,7 +338,7 @@ const char SCA_JoystickSensor::SetIndex_doc[] = "\tSets the joystick index to use.\n"; PyObject* SCA_JoystickSensor::PySetIndex( PyObject* value ) { ShowDeprecationWarning("setIndex()", "the index property"); - int index = PyInt_AsLong( value ); /* -1 on error, will raise an error in this case */ + int index = PyLong_AsSsize_t( value ); /* -1 on error, will raise an error in this case */ if (index < 0 || index >= JOYINDEX_MAX) { PyErr_SetString(PyExc_ValueError, "joystick index out of range or not an int"); return NULL; @@ -410,7 +389,7 @@ PyObject* SCA_JoystickSensor::PyGetAxisValue( ) { PyObject *list= PyList_New(axis_index); while(axis_index--) { - PyList_SET_ITEM(list, axis_index, PyInt_FromLong(joy->GetAxisPosition(axis_index))); + PyList_SET_ITEM(list, axis_index, PyLong_FromSsize_t(joy->GetAxisPosition(axis_index))); } return list; @@ -423,7 +402,7 @@ const char SCA_JoystickSensor::GetThreshold_doc[] = "\tReturns the threshold of the axis.\n"; PyObject* SCA_JoystickSensor::PyGetThreshold( ) { ShowDeprecationWarning("getThreshold()", "the threshold property"); - return PyInt_FromLong(m_precision); + return PyLong_FromSsize_t(m_precision); } @@ -447,7 +426,7 @@ const char SCA_JoystickSensor::GetButton_doc[] = "\tReturns the current button this sensor is checking.\n"; PyObject* SCA_JoystickSensor::PyGetButton( ) { ShowDeprecationWarning("getButton()", "the button property"); - return PyInt_FromLong(m_button); + return PyLong_FromSsize_t(m_button); } /* set button -------------------------------------------------------- */ @@ -456,7 +435,7 @@ const char SCA_JoystickSensor::SetButton_doc[] = "\tSets the button the sensor reacts to.\n"; PyObject* SCA_JoystickSensor::PySetButton( PyObject* value ) { ShowDeprecationWarning("setButton()", "the button property"); - int button = PyInt_AsLong(value); + int button = PyLong_AsSsize_t(value); if(button==-1 && PyErr_Occurred()) { PyErr_SetString(PyExc_ValueError, "expected an int"); return NULL; @@ -487,7 +466,7 @@ PyObject* SCA_JoystickSensor::PyGetButtonActiveList( ) { if(joy) { for (i=0; i < joy->GetNumberOfButtons(); i++) { if (joy->aButtonPressIsPositive(i)) { - value = PyInt_FromLong(i); + value = PyLong_FromSsize_t(i); PyList_Append(ls, value); Py_DECREF(value); } @@ -549,7 +528,7 @@ PyObject* SCA_JoystickSensor::PyNumberOfAxes( ) { ShowDeprecationWarning("getNumAxes()", "the numAxis property"); SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); // when the joystick is null their is 0 exis still. dumb but scripters should use isConnected() - return PyInt_FromLong( joy ? joy->GetNumberOfAxes() : 0 ); + return PyLong_FromSsize_t( joy ? joy->GetNumberOfAxes() : 0 ); } @@ -559,7 +538,7 @@ const char SCA_JoystickSensor::NumberOfButtons_doc[] = PyObject* SCA_JoystickSensor::PyNumberOfButtons( ) { ShowDeprecationWarning("getNumButtons()", "the numButtons property"); SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); - return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 ); + return PyLong_FromSsize_t( joy ? joy->GetNumberOfButtons() : 0 ); } @@ -569,7 +548,7 @@ const char SCA_JoystickSensor::NumberOfHats_doc[] = PyObject* SCA_JoystickSensor::PyNumberOfHats( ) { ShowDeprecationWarning("getNumHats()", "the numHats property"); SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); - return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 ); + return PyLong_FromSsize_t( joy ? joy->GetNumberOfHats() : 0 ); } const char SCA_JoystickSensor::Connected_doc[] = @@ -591,7 +570,7 @@ PyObject* SCA_JoystickSensor::pyattr_get_axis_values(void *self_v, const KX_PYAT PyObject *list= PyList_New(axis_index); while(axis_index--) { - PyList_SET_ITEM(list, axis_index, PyInt_FromLong(joy->GetAxisPosition(axis_index))); + PyList_SET_ITEM(list, axis_index, PyLong_FromSsize_t(joy->GetAxisPosition(axis_index))); } return list; @@ -607,7 +586,7 @@ PyObject* SCA_JoystickSensor::pyattr_get_axis_single(void *self_v, const KX_PYAT return NULL; } - return PyInt_FromLong(joy->GetAxisPosition(self->m_axis-1)); + return PyLong_FromSsize_t(joy->GetAxisPosition(self->m_axis-1)); } PyObject* SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -619,7 +598,7 @@ PyObject* SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATT PyObject *list= PyList_New(hat_index); while(hat_index--) { - PyList_SET_ITEM(list, hat_index, PyInt_FromLong(joy->GetHat(hat_index))); + PyList_SET_ITEM(list, hat_index, PyLong_FromSsize_t(joy->GetHat(hat_index))); } return list; @@ -630,28 +609,28 @@ PyObject* SCA_JoystickSensor::pyattr_get_hat_single(void *self_v, const KX_PYATT SCA_JoystickSensor* self= static_cast(self_v); SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex); - return PyInt_FromLong(joy->GetHat(self->m_hat-1)); + return PyLong_FromSsize_t(joy->GetHat(self->m_hat-1)); } PyObject* SCA_JoystickSensor::pyattr_get_num_axis(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_JoystickSensor* self= static_cast(self_v); SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex); - return PyInt_FromLong( joy ? joy->GetNumberOfAxes() : 0 ); + return PyLong_FromSsize_t( joy ? joy->GetNumberOfAxes() : 0 ); } PyObject* SCA_JoystickSensor::pyattr_get_num_buttons(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_JoystickSensor* self= static_cast(self_v); SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex); - return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 ); + return PyLong_FromSsize_t( joy ? joy->GetNumberOfButtons() : 0 ); } PyObject* SCA_JoystickSensor::pyattr_get_num_hats(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_JoystickSensor* self= static_cast(self_v); SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex); - return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 ); + return PyLong_FromSsize_t( joy ? joy->GetNumberOfHats() : 0 ); } PyObject* SCA_JoystickSensor::pyattr_get_connected(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.h b/source/gameengine/GameLogic/SCA_JoystickSensor.h index e6a1d2eef32..32f8ce567d2 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.h +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.h @@ -106,8 +106,7 @@ public: short int joymode, int axis, int axisf,int prec, int button, - int hat, int hatf, bool allevents, - PyTypeObject* T=&Type ); + int hat, int hatf, bool allevents); virtual ~SCA_JoystickSensor(); virtual CValue* GetReplica(); @@ -123,10 +122,6 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - /* Joystick Index */ KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetIndex); KX_PYMETHOD_DOC_O(SCA_JoystickSensor,SetIndex); diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index f8ee8ed8b41..999e34dfa36 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -48,9 +48,8 @@ SCA_KeyboardSensor::SCA_KeyboardSensor(SCA_KeyboardManager* keybdmgr, bool bAllKeys, const STR_String& targetProp, const STR_String& toggleProp, - SCA_IObject* gameobj, - PyTypeObject* T ) - :SCA_ISensor(gameobj,keybdmgr,T), + SCA_IObject* gameobj) + :SCA_ISensor(gameobj,keybdmgr), m_pKeyboardMgr(keybdmgr), m_hotkey(hotkey), m_qual(qual), @@ -418,7 +417,7 @@ const char SCA_KeyboardSensor::GetKey_doc[] = PyObject* SCA_KeyboardSensor::PyGetKey() { ShowDeprecationWarning("getKey()", "the key property"); - return PyInt_FromLong(m_hotkey); + return PyLong_FromSsize_t(m_hotkey); } /** 2. SetKey: change the key to look at */ @@ -450,7 +449,7 @@ const char SCA_KeyboardSensor::GetHold1_doc[] = PyObject* SCA_KeyboardSensor::PyGetHold1() { ShowDeprecationWarning("getHold1()", "the hold1 property"); - return PyInt_FromLong(m_qual); + return PyLong_FromSsize_t(m_qual); } /** 4. SetHold1: change the first bucky bit */ @@ -482,7 +481,7 @@ const char SCA_KeyboardSensor::GetHold2_doc[] = PyObject* SCA_KeyboardSensor::PyGetHold2() { ShowDeprecationWarning("getHold2()", "the hold2 property"); - return PyInt_FromLong(m_qual2); + return PyLong_FromSsize_t(m_qual2); } /** 6. SetHold2: change the second bucky bit */ @@ -532,8 +531,8 @@ PyObject* SCA_KeyboardSensor::PyGetPressedKeys() || (inevent.m_status == SCA_InputEvent::KX_JUSTRELEASED)) { PyObject* keypair = PyList_New(2); - PyList_SET_ITEM(keypair,0,PyInt_FromLong(i)); - PyList_SET_ITEM(keypair,1,PyInt_FromLong(inevent.m_status)); + PyList_SET_ITEM(keypair,0,PyLong_FromSsize_t(i)); + PyList_SET_ITEM(keypair,1,PyLong_FromSsize_t(inevent.m_status)); PyList_SET_ITEM(resultlist,index,keypair); index++; @@ -572,8 +571,8 @@ PyObject* SCA_KeyboardSensor::PyGetCurrentlyPressedKeys() || (inevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED)) { PyObject* keypair = PyList_New(2); - PyList_SET_ITEM(keypair,0,PyInt_FromLong(i)); - PyList_SET_ITEM(keypair,1,PyInt_FromLong(inevent.m_status)); + PyList_SET_ITEM(keypair,0,PyLong_FromSsize_t(i)); + PyList_SET_ITEM(keypair,1,PyLong_FromSsize_t(inevent.m_status)); PyList_SET_ITEM(resultlist,index,keypair); index++; @@ -592,12 +591,12 @@ KX_PYMETHODDEF_DOC_O(SCA_KeyboardSensor, getKeyStatus, "getKeyStatus(keycode)\n" "\tGet the given key's status (KX_NO_INPUTSTATUS, KX_JUSTACTIVATED, KX_ACTIVE or KX_JUSTRELEASED).\n") { - if (!PyInt_Check(value)) { + if (!PyLong_Check(value)) { PyErr_SetString(PyExc_ValueError, "sensor.getKeyStatus(int): Keyboard Sensor, expected an int"); return NULL; } - int keycode = PyInt_AsLong(value); + int keycode = PyLong_AsSsize_t(value); if ((keycode < SCA_IInputDevice::KX_BEGINKEY) || (keycode > SCA_IInputDevice::KX_ENDKEY)){ @@ -607,7 +606,7 @@ KX_PYMETHODDEF_DOC_O(SCA_KeyboardSensor, getKeyStatus, SCA_IInputDevice* inputdev = m_pKeyboardMgr->GetInputDevice(); const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) keycode); - return PyInt_FromLong(inevent.m_status); + return PyLong_FromSsize_t(inevent.m_status); } /* ------------------------------------------------------------------------- */ @@ -631,19 +630,15 @@ PyTypeObject SCA_KeyboardSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_KeyboardSensor::Parents[] = { - &SCA_KeyboardSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_KeyboardSensor::Methods[] = { @@ -672,20 +667,6 @@ PyAttributeDef SCA_KeyboardSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_KeyboardSensor::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_ISensor); -} - -PyObject* SCA_KeyboardSensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int SCA_KeyboardSensor::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_ISensor); -} - PyObject* SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { @@ -701,8 +682,8 @@ PyObject* SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBU if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) { PyObject* keypair = PyList_New(2); - PyList_SET_ITEM(keypair,0,PyInt_FromLong(i)); - PyList_SET_ITEM(keypair,1,PyInt_FromLong(inevent.m_status)); + PyList_SET_ITEM(keypair,0,PyLong_FromSsize_t(i)); + PyList_SET_ITEM(keypair,1,PyLong_FromSsize_t(inevent.m_status)); PyList_Append(resultlist,keypair); } } diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.h b/source/gameengine/GameLogic/SCA_KeyboardSensor.h index 033225cd9be..3185b386d41 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.h +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.h @@ -94,8 +94,7 @@ public: bool bAllKeys, const STR_String& targetProp, const STR_String& toggleProp, - SCA_IObject* gameobj, - PyTypeObject* T=&Type ); + SCA_IObject* gameobj); virtual ~SCA_KeyboardSensor(); virtual CValue* GetReplica(); virtual void Init(); @@ -110,10 +109,6 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - //Deprecated functions -----> /** 1. GetKey : check which key this sensor looks at */ KX_PYMETHOD_DOC_NOARGS(SCA_KeyboardSensor,GetKey); diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp index 83271288154..b782c6dfb93 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.cpp +++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp @@ -307,6 +307,7 @@ void SCA_LogicManager::AddTriggeredController(SCA_IController* controller, SCA_I controller->Activate(m_triggeredControllerSet); // so that the controller knows which sensor has activited it // only needed for python controller + // Note that this is safe even if the controller is subclassed. if (controller->GetType() == &SCA_PythonController::Type) { SCA_PythonController* pythonController = (SCA_PythonController*)controller; diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index c5e1c3c0441..49fa19dce38 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -49,9 +49,8 @@ SCA_MouseSensor::SCA_MouseSensor(SCA_MouseManager* eventmgr, int startx,int starty, short int mousemode, - SCA_IObject* gameobj, - PyTypeObject* T) - : SCA_ISensor(gameobj,eventmgr, T), + SCA_IObject* gameobj) + : SCA_ISensor(gameobj,eventmgr), m_pMouseMgr(eventmgr), m_x(startx), m_y(starty) @@ -254,7 +253,7 @@ const char SCA_MouseSensor::GetXPosition_doc[] = "\tpixels\n"; PyObject* SCA_MouseSensor::PyGetXPosition() { ShowDeprecationWarning("getXPosition()", "the position property"); - return PyInt_FromLong(m_x); + return PyLong_FromSsize_t(m_x); } /* get y position ---------------------------------------------------------- */ @@ -265,7 +264,7 @@ const char SCA_MouseSensor::GetYPosition_doc[] = "\tpixels\n"; PyObject* SCA_MouseSensor::PyGetYPosition() { ShowDeprecationWarning("getYPosition()", "the position property"); - return PyInt_FromLong(m_y); + return PyLong_FromSsize_t(m_y); } //<----- Deprecated @@ -273,9 +272,9 @@ KX_PYMETHODDEF_DOC_O(SCA_MouseSensor, getButtonStatus, "getButtonStatus(button)\n" "\tGet the given button's status (KX_INPUT_NONE, KX_INPUT_NONE, KX_INPUT_JUST_ACTIVATED, KX_INPUT_ACTIVE, KX_INPUT_JUST_RELEASED).\n") { - if (PyInt_Check(value)) + if (PyLong_Check(value)) { - int button = PyInt_AsLong(value); + int button = PyLong_AsSsize_t(value); if ((button < SCA_IInputDevice::KX_LEFTMOUSE) || (button > SCA_IInputDevice::KX_RIGHTMOUSE)){ @@ -285,7 +284,7 @@ KX_PYMETHODDEF_DOC_O(SCA_MouseSensor, getButtonStatus, SCA_IInputDevice* mousedev = m_pMouseMgr->GetInputDevice(); const SCA_InputEvent& event = mousedev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) button); - return PyInt_FromLong(event.m_status); + return PyLong_FromSsize_t(event.m_status); } Py_RETURN_NONE; @@ -312,19 +311,15 @@ PyTypeObject SCA_MouseSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_MouseSensor::Parents[] = { - &SCA_MouseSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_MouseSensor::Methods[] = { @@ -342,18 +337,4 @@ PyAttributeDef SCA_MouseSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_MouseSensor::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_ISensor); -} - -PyObject* SCA_MouseSensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int SCA_MouseSensor::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_ISensor); -} - /* eof */ diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.h b/source/gameengine/GameLogic/SCA_MouseSensor.h index 6d6302b514a..47f0378bf69 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.h +++ b/source/gameengine/GameLogic/SCA_MouseSensor.h @@ -92,8 +92,7 @@ class SCA_MouseSensor : public SCA_ISensor SCA_MouseSensor(class SCA_MouseManager* keybdmgr, int startx,int starty, short int mousemode, - SCA_IObject* gameobj, - PyTypeObject* T=&Type ); + SCA_IObject* gameobj); virtual ~SCA_MouseSensor(); virtual CValue* GetReplica(); @@ -109,10 +108,6 @@ class SCA_MouseSensor : public SCA_ISensor /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - //Deprecated functions -----> /* read x-coordinate */ KX_PYMETHOD_DOC_NOARGS(SCA_MouseSensor,GetXPosition); diff --git a/source/gameengine/GameLogic/SCA_NANDController.cpp b/source/gameengine/GameLogic/SCA_NANDController.cpp index d27aea5e6f7..c00e5d6e617 100644 --- a/source/gameengine/GameLogic/SCA_NANDController.cpp +++ b/source/gameengine/GameLogic/SCA_NANDController.cpp @@ -42,10 +42,9 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ -SCA_NANDController::SCA_NANDController(SCA_IObject* gameobj, - PyTypeObject* T) +SCA_NANDController::SCA_NANDController(SCA_IObject* gameobj) : - SCA_IController(gameobj,T) + SCA_IController(gameobj) { } @@ -116,19 +115,15 @@ PyTypeObject SCA_NANDController::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_NANDController::Parents[] = { - &SCA_NANDController::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IController::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_NANDController::Methods[] = { @@ -139,12 +134,4 @@ PyAttributeDef SCA_NANDController::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_NANDController::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IController); -} - -PyObject* SCA_NANDController::py_getattro_dict() { - py_getattro_dict_up(SCA_IController); -} - /* eof */ diff --git a/source/gameengine/GameLogic/SCA_NANDController.h b/source/gameengine/GameLogic/SCA_NANDController.h index 0ae0ff19745..36a145e5f2b 100644 --- a/source/gameengine/GameLogic/SCA_NANDController.h +++ b/source/gameengine/GameLogic/SCA_NANDController.h @@ -39,7 +39,7 @@ class SCA_NANDController : public SCA_IController Py_Header; //virtual void Trigger(class SCA_LogicManager* logicmgr); public: - SCA_NANDController(SCA_IObject* gameobj,PyTypeObject* T=&Type); + SCA_NANDController(SCA_IObject* gameobj); virtual ~SCA_NANDController(); virtual CValue* GetReplica(); virtual void Trigger(SCA_LogicManager* logicmgr); @@ -47,10 +47,6 @@ public: /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - }; #endif //__KX_NANDCONTROLLER diff --git a/source/gameengine/GameLogic/SCA_NORController.cpp b/source/gameengine/GameLogic/SCA_NORController.cpp index 6c9141636b2..9762d44fd5d 100644 --- a/source/gameengine/GameLogic/SCA_NORController.cpp +++ b/source/gameengine/GameLogic/SCA_NORController.cpp @@ -42,10 +42,9 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ -SCA_NORController::SCA_NORController(SCA_IObject* gameobj, - PyTypeObject* T) +SCA_NORController::SCA_NORController(SCA_IObject* gameobj) : - SCA_IController(gameobj,T) + SCA_IController(gameobj) { } @@ -116,19 +115,15 @@ PyTypeObject SCA_NORController::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_NORController::Parents[] = { - &SCA_NORController::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IController::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_NORController::Methods[] = { @@ -139,12 +134,4 @@ PyAttributeDef SCA_NORController::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_NORController::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IController); -} - -PyObject* SCA_NORController::py_getattro_dict() { - py_getattro_dict_up(SCA_IController); -} - /* eof */ diff --git a/source/gameengine/GameLogic/SCA_NORController.h b/source/gameengine/GameLogic/SCA_NORController.h index 06cbb70a489..b96232375d6 100644 --- a/source/gameengine/GameLogic/SCA_NORController.h +++ b/source/gameengine/GameLogic/SCA_NORController.h @@ -39,18 +39,10 @@ class SCA_NORController : public SCA_IController Py_Header; //virtual void Trigger(class SCA_LogicManager* logicmgr); public: - SCA_NORController(SCA_IObject* gameobj,PyTypeObject* T=&Type); + SCA_NORController(SCA_IObject* gameobj); virtual ~SCA_NORController(); virtual CValue* GetReplica(); virtual void Trigger(SCA_LogicManager* logicmgr); - - /* --------------------------------------------------------------------- */ - /* Python interface ---------------------------------------------------- */ - /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - }; #endif //__KX_NORCONTROLLER diff --git a/source/gameengine/GameLogic/SCA_ORController.cpp b/source/gameengine/GameLogic/SCA_ORController.cpp index 42c0a67d657..a526dd8353c 100644 --- a/source/gameengine/GameLogic/SCA_ORController.cpp +++ b/source/gameengine/GameLogic/SCA_ORController.cpp @@ -42,9 +42,8 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ -SCA_ORController::SCA_ORController(SCA_IObject* gameobj, - PyTypeObject* T) - :SCA_IController(gameobj, T) +SCA_ORController::SCA_ORController(SCA_IObject* gameobj) + :SCA_IController(gameobj) { } @@ -110,19 +109,15 @@ PyTypeObject SCA_ORController::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_ORController::Parents[] = { - &SCA_ORController::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IController::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_ORController::Methods[] = { @@ -133,13 +128,4 @@ PyAttributeDef SCA_ORController::Attributes[] = { { NULL } //Sentinel }; - -PyObject* SCA_ORController::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IController); -} - -PyObject* SCA_ORController::py_getattro_dict() { - py_getattro_dict_up(SCA_IController); -} - /* eof */ diff --git a/source/gameengine/GameLogic/SCA_ORController.h b/source/gameengine/GameLogic/SCA_ORController.h index 66f772c739e..09d31a85190 100644 --- a/source/gameengine/GameLogic/SCA_ORController.h +++ b/source/gameengine/GameLogic/SCA_ORController.h @@ -39,18 +39,11 @@ class SCA_ORController : public SCA_IController Py_Header; //virtual void Trigger(class SCA_LogicManager* logicmgr); public: - SCA_ORController(SCA_IObject* gameobj, PyTypeObject* T=&Type); + SCA_ORController(SCA_IObject* gameobj); virtual ~SCA_ORController(); virtual CValue* GetReplica(); virtual void Trigger(SCA_LogicManager* logicmgr); - - /* --------------------------------------------------------------------- */ - /* Python interface ---------------------------------------------------- */ - /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); }; #endif //__KX_ORCONTROLLER diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp index 4faa4b55d4a..215e30eceaf 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp @@ -42,8 +42,8 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ -SCA_PropertyActuator::SCA_PropertyActuator(SCA_IObject* gameobj,SCA_IObject* sourceObj,const STR_String& propname,const STR_String& expr,int acttype,PyTypeObject* T ) - : SCA_IActuator(gameobj,T), +SCA_PropertyActuator::SCA_PropertyActuator(SCA_IObject* gameobj,SCA_IObject* sourceObj,const STR_String& propname,const STR_String& expr,int acttype) + : SCA_IActuator(gameobj), m_type(acttype), m_propname(propname), m_exprtxt(expr), @@ -244,19 +244,15 @@ PyTypeObject SCA_PropertyActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_PropertyActuator::Parents[] = { - &SCA_PropertyActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_PropertyActuator::Methods[] = { @@ -276,18 +272,6 @@ PyAttributeDef SCA_PropertyActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_PropertyActuator::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IActuator); -} - -PyObject* SCA_PropertyActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int SCA_PropertyActuator::py_setattro(PyObject *attr, PyObject *value) { - py_setattro_up(SCA_IActuator); -} - /* 1. setProperty */ const char SCA_PropertyActuator::SetProperty_doc[] = "setProperty(name)\n" @@ -322,7 +306,7 @@ const char SCA_PropertyActuator::GetProperty_doc[] = PyObject* SCA_PropertyActuator::PyGetProperty(PyObject* args, PyObject* kwds) { ShowDeprecationWarning("getProperty()", "the 'propName' property"); - return PyString_FromString(m_propname); + return PyUnicode_FromString(m_propname); } /* 3. setValue */ @@ -352,7 +336,7 @@ const char SCA_PropertyActuator::GetValue_doc[] = PyObject* SCA_PropertyActuator::PyGetValue(PyObject* args, PyObject* kwds) { ShowDeprecationWarning("getValue()", "the value property"); - return PyString_FromString(m_exprtxt); + return PyUnicode_FromString(m_exprtxt); } /* eof */ diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.h b/source/gameengine/GameLogic/SCA_PropertyActuator.h index a8df08dfc6e..8fb2e7a7bc5 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.h +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.h @@ -64,9 +64,7 @@ public: SCA_IObject* sourceObj, const STR_String& propname, const STR_String& expr, - int acttype, - PyTypeObject* T=&Type - ); + int acttype); ~SCA_PropertyActuator(); @@ -86,10 +84,6 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - // python wrapped methods KX_PYMETHOD_DOC(SCA_PropertyActuator,SetProperty); KX_PYMETHOD_DOC(SCA_PropertyActuator,GetProperty); diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp index 3b343af3cba..6d2e1a0aca5 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp +++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp @@ -48,9 +48,8 @@ SCA_PropertySensor::SCA_PropertySensor(SCA_EventManager* eventmgr, const STR_String& propname, const STR_String& propval, const STR_String& propmaxval, - KX_PROPSENSOR_TYPE checktype, - PyTypeObject* T ) - : SCA_ISensor(gameobj,eventmgr,T), + KX_PROPSENSOR_TYPE checktype) + : SCA_ISensor(gameobj,eventmgr), m_checktype(checktype), m_checkpropval(propval), m_checkpropmaxval(propmaxval), @@ -319,19 +318,15 @@ PyTypeObject SCA_PropertySensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_PropertySensor::Parents[] = { - &SCA_PropertySensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_PropertySensor::Methods[] = { @@ -353,19 +348,6 @@ PyAttributeDef SCA_PropertySensor::Attributes[] = { { NULL } //Sentinel }; - -PyObject* SCA_PropertySensor::py_getattro(PyObject *attr) { - py_getattro_up(SCA_ISensor); -} - -PyObject* SCA_PropertySensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int SCA_PropertySensor::py_setattro(PyObject *attr, PyObject *value) { - py_setattro_up(SCA_ISensor); -} - /* 1. getType */ const char SCA_PropertySensor::GetType_doc[] = "getType()\n" @@ -373,7 +355,7 @@ const char SCA_PropertySensor::GetType_doc[] = PyObject* SCA_PropertySensor::PyGetType() { ShowDeprecationWarning("getType()", "the mode property"); - return PyInt_FromLong(m_checktype); + return PyLong_FromSsize_t(m_checktype); } /* 2. setType */ @@ -407,7 +389,7 @@ const char SCA_PropertySensor::GetProperty_doc[] = PyObject* SCA_PropertySensor::PyGetProperty() { ShowDeprecationWarning("getProperty()", "the 'propName' property"); - return PyString_FromString(m_checkpropname); + return PyUnicode_FromString(m_checkpropname); } /* 4. setProperty */ @@ -444,7 +426,7 @@ const char SCA_PropertySensor::GetValue_doc[] = PyObject* SCA_PropertySensor::PyGetValue() { ShowDeprecationWarning("getValue()", "the value property"); - return PyString_FromString(m_checkpropval); + return PyUnicode_FromString(m_checkpropval); } /* 6. setValue */ diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.h b/source/gameengine/GameLogic/SCA_PropertySensor.h index 538ecd65949..3513fcdf5ae 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.h +++ b/source/gameengine/GameLogic/SCA_PropertySensor.h @@ -67,8 +67,7 @@ public: const STR_String& propname, const STR_String& propval, const STR_String& propmaxval, - KX_PROPSENSOR_TYPE checktype, - PyTypeObject* T=&Type ); + KX_PROPSENSOR_TYPE checktype); /** * For property sensor, it is used to release the pre-calculated expression @@ -89,10 +88,6 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - /* 1. getType */ KX_PYMETHOD_DOC_NOARGS(SCA_PropertySensor,GetType); /* 2. setType */ diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index 80e4f54c9c5..ffd95f00699 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -47,10 +47,8 @@ SCA_PythonController* SCA_PythonController::m_sCurrentController = NULL; -SCA_PythonController::SCA_PythonController(SCA_IObject* gameobj, - int mode, - PyTypeObject* T) - : SCA_IController(gameobj, T), +SCA_PythonController::SCA_PythonController(SCA_IObject* gameobj, int mode) + : SCA_IController(gameobj), m_bytecode(NULL), m_function(NULL), m_function_argc(0), @@ -150,7 +148,7 @@ void SCA_PythonController::SetDictionary(PyObject* pythondictionary) /* Without __file__ set the sys.argv[0] is used for the filename * which ends up with lines from the blender binary being printed in the console */ - PyDict_SetItemString(m_pythondictionary, "__file__", PyString_FromString(m_scriptName.Ptr())); + PyDict_SetItemString(m_pythondictionary, "__file__", PyUnicode_FromString(m_scriptName.Ptr())); } @@ -180,16 +178,16 @@ SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value) std::vector lacts = m_sCurrentController->GetLinkedActuators(); std::vector::iterator it; - if (PyString_Check(value)) { + if (PyUnicode_Check(value)) { /* get the actuator from the name */ - char *name= PyString_AsString(value); + char *name= _PyUnicode_AsString(value); for(it = lacts.begin(); it!= lacts.end(); ++it) { if( name == (*it)->GetName() ) { return *it; } } } - else if (BGE_PROXY_CHECK_TYPE(value)) { + else if (PyObject_TypeCheck(value, &SCA_IActuator::Type)) { PyObjectPlus *value_plus= BGE_PROXY_REF(value); for(it = lacts.begin(); it!= lacts.end(); ++it) { if( static_cast(value_plus) == (*it) ) { @@ -200,7 +198,7 @@ SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value) /* set the exception */ PyObject *value_str = PyObject_Repr(value); /* new ref */ - PyErr_Format(PyExc_ValueError, "'%s' not in this python controllers actuator list", PyString_AsString(value_str)); + PyErr_Format(PyExc_ValueError, "'%s' not in this python controllers actuator list", _PyUnicode_AsString(value_str)); Py_DECREF(value_str); return false; @@ -245,19 +243,17 @@ PyTypeObject SCA_PythonController::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &SCA_IController::Type, + 0,0,0,0,0,0, + py_base_new }; -PyParentObject SCA_PythonController::Parents[] = { - &SCA_PythonController::Type, - &SCA_IController::Type, - &CValue::Type, - NULL -}; PyMethodDef SCA_PythonController::Methods[] = { {"activate", (PyCFunction) SCA_PythonController::sPyActivate, METH_O}, {"deactivate", (PyCFunction) SCA_PythonController::sPyDeActivate, METH_O}, @@ -490,22 +486,6 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) m_sCurrentController = NULL; } - - -PyObject* SCA_PythonController::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IController); -} - -PyObject* SCA_PythonController::py_getattro_dict() { - py_getattro_dict_up(SCA_IController); -} - -int SCA_PythonController::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_IController); -} - PyObject* SCA_PythonController::PyActivate(PyObject *value) { if(m_sCurrentController != this) { @@ -540,13 +520,13 @@ PyObject* SCA_PythonController::PyDeActivate(PyObject *value) PyObject* SCA_PythonController::PyGetScript() { ShowDeprecationWarning("getScript()", "the script property"); - return PyString_FromString(m_scriptText); + return PyUnicode_FromString(m_scriptText); } /* 2. setScript */ PyObject* SCA_PythonController::PySetScript(PyObject* value) { - char *scriptArg = PyString_AsString(value); + char *scriptArg = _PyUnicode_AsString(value); ShowDeprecationWarning("setScript()", "the script property"); @@ -565,15 +545,20 @@ PyObject* SCA_PythonController::PySetScript(PyObject* value) PyObject* SCA_PythonController::pyattr_get_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { + //SCA_PythonController* self= static_cast(static_cast(static_cast(static_cast(static_cast(self_v))))); + // static_cast(dynamic_cast(obj)) - static_cast(obj) + SCA_PythonController* self= static_cast(self_v); - return PyString_FromString(self->m_scriptText); + return PyUnicode_FromString(self->m_scriptText); } + + int SCA_PythonController::pyattr_set_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { SCA_PythonController* self= static_cast(self_v); - char *scriptArg = PyString_AsString(value); + char *scriptArg = _PyUnicode_AsString(value); if (scriptArg==NULL) { PyErr_SetString(PyExc_TypeError, "controller.script = string: Python Controller, expected a string script text"); diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h index 0c2af79c3a3..9311b3f355e 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.h +++ b/source/gameengine/GameLogic/SCA_PythonController.h @@ -72,7 +72,7 @@ class SCA_PythonController : public SCA_IController //virtual CValue* AddRef(); //virtual int Release(); // Release a reference to this value (when reference count reaches 0, the value is removed from the heap) - SCA_PythonController(SCA_IObject* gameobj, int mode, PyTypeObject* T = &Type); + SCA_PythonController(SCA_IObject* gameobj, int mode); virtual ~SCA_PythonController(); virtual CValue* GetReplica(); @@ -96,10 +96,6 @@ class SCA_PythonController : public SCA_IController static PyObject* sPyAddActiveActuator(PyObject* self, PyObject* args); static SCA_IActuator* LinkedActuatorFromPy(PyObject *value); - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); KX_PYMETHOD_O(SCA_PythonController,Activate); diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp index a722590dd10..e903d10f9a5 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp @@ -50,9 +50,8 @@ SCA_RandomActuator::SCA_RandomActuator(SCA_IObject *gameobj, SCA_RandomActuator::KX_RANDOMACT_MODE mode, float para1, float para2, - const STR_String &propName, - PyTypeObject* T) - : SCA_IActuator(gameobj, T), + const STR_String &propName) + : SCA_IActuator(gameobj), m_propname(propName), m_parameter1(para1), m_parameter2(para2), @@ -332,19 +331,15 @@ PyTypeObject SCA_RandomActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_RandomActuator::Parents[] = { - &SCA_RandomActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_RandomActuator::Methods[] = { @@ -384,14 +379,14 @@ PyAttributeDef SCA_RandomActuator::Attributes[] = { PyObject* SCA_RandomActuator::pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { SCA_RandomActuator* act = static_cast(self); - return PyInt_FromLong(act->m_base->GetSeed()); + return PyLong_FromSsize_t(act->m_base->GetSeed()); } int SCA_RandomActuator::pyattr_set_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { SCA_RandomActuator* act = static_cast(self); - if (PyInt_Check(value)) { - int ival = PyInt_AsLong(value); + if (PyLong_Check(value)) { + int ival = PyLong_AsSsize_t(value); act->m_base->SetSeed(ival); return PY_SET_ATTR_SUCCESS; } else { @@ -400,19 +395,6 @@ int SCA_RandomActuator::pyattr_set_seed(void *self, const struct KX_PYATTRIBUTE_ } } -PyObject* SCA_RandomActuator::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IActuator); -} - -PyObject* SCA_RandomActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int SCA_RandomActuator::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_IActuator); -} - /* 1. setSeed */ const char SCA_RandomActuator::SetSeed_doc[] = "setSeed(seed)\n" @@ -439,7 +421,7 @@ const char SCA_RandomActuator::GetSeed_doc[] = PyObject* SCA_RandomActuator::PyGetSeed() { ShowDeprecationWarning("getSeed()", "the seed property"); - return PyInt_FromLong(m_base->GetSeed()); + return PyLong_FromSsize_t(m_base->GetSeed()); } /* 4. getPara1 */ @@ -473,7 +455,7 @@ const char SCA_RandomActuator::GetDistribution_doc[] = PyObject* SCA_RandomActuator::PyGetDistribution() { ShowDeprecationWarning("getDistribution()", "the distribution property"); - return PyInt_FromLong(m_distribution); + return PyLong_FromSsize_t(m_distribution); } /* 9. setProperty */ @@ -508,7 +490,7 @@ const char SCA_RandomActuator::GetProperty_doc[] = PyObject* SCA_RandomActuator::PyGetProperty() { ShowDeprecationWarning("getProperty()", "the 'propName' property"); - return PyString_FromString(m_propname); + return PyUnicode_FromString(m_propname); } /* 11. setBoolConst */ diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.h b/source/gameengine/GameLogic/SCA_RandomActuator.h index 59863589b60..c7d3fe21217 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.h +++ b/source/gameengine/GameLogic/SCA_RandomActuator.h @@ -85,8 +85,7 @@ class SCA_RandomActuator : public SCA_IActuator KX_RANDOMACT_MODE mode, float para1, float para2, - const STR_String &propName, - PyTypeObject* T=&Type); + const STR_String &propName); virtual ~SCA_RandomActuator(); virtual bool Update(); @@ -97,10 +96,6 @@ class SCA_RandomActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - static PyObject* pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp index d5cbeef01ae..e036a77707e 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp +++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp @@ -46,9 +46,8 @@ SCA_RandomSensor::SCA_RandomSensor(SCA_EventManager* eventmgr, SCA_IObject* gameobj, - int startseed, - PyTypeObject* T) - : SCA_ISensor(gameobj,eventmgr, T) + int startseed) + : SCA_ISensor(gameobj,eventmgr) { m_basegenerator = new SCA_RandomNumberGenerator(startseed); Init(); @@ -147,19 +146,15 @@ PyTypeObject SCA_RandomSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_RandomSensor::Parents[] = { - &SCA_RandomSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_RandomSensor::Methods[] = { @@ -177,19 +172,6 @@ PyAttributeDef SCA_RandomSensor::Attributes[] = { {NULL} //Sentinel }; -PyObject* SCA_RandomSensor::py_getattro(PyObject *attr) { - py_getattro_up(SCA_ISensor); -} - -PyObject* SCA_RandomSensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int SCA_RandomSensor::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_ISensor); -} - /* 1. setSeed */ const char SCA_RandomSensor::SetSeed_doc[] = "setSeed(seed)\n" @@ -216,7 +198,7 @@ const char SCA_RandomSensor::GetSeed_doc[] = "\tequal series.\n"; PyObject* SCA_RandomSensor::PyGetSeed() { ShowDeprecationWarning("getSeed()", "the seed property"); - return PyInt_FromLong(m_basegenerator->GetSeed()); + return PyLong_FromSsize_t(m_basegenerator->GetSeed()); } /* 3. getLastDraw */ @@ -225,24 +207,24 @@ const char SCA_RandomSensor::GetLastDraw_doc[] = "\tReturn the last value that was drawn.\n"; PyObject* SCA_RandomSensor::PyGetLastDraw() { ShowDeprecationWarning("getLastDraw()", "the lastDraw property"); - return PyInt_FromLong(m_lastdraw); + return PyLong_FromSsize_t(m_lastdraw); } PyObject* SCA_RandomSensor::pyattr_get_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_RandomSensor* self= static_cast(self_v); - return PyInt_FromLong(self->m_basegenerator->GetSeed()); + return PyLong_FromSsize_t(self->m_basegenerator->GetSeed()); } int SCA_RandomSensor::pyattr_set_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { SCA_RandomSensor* self= static_cast(self_v); - if (!PyInt_Check(value)) { + if (!PyLong_Check(value)) { PyErr_SetString(PyExc_TypeError, "sensor.seed = int: Random Sensor, expected an integer"); return PY_SET_ATTR_FAIL; } - self->m_basegenerator->SetSeed(PyInt_AsLong(value)); + self->m_basegenerator->SetSeed(PyLong_AsSsize_t(value)); return PY_SET_ATTR_SUCCESS; } diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.h b/source/gameengine/GameLogic/SCA_RandomSensor.h index b2bf2440966..5e66c36cccf 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.h +++ b/source/gameengine/GameLogic/SCA_RandomSensor.h @@ -48,8 +48,7 @@ class SCA_RandomSensor : public SCA_ISensor public: SCA_RandomSensor(class SCA_EventManager* rndmgr, SCA_IObject* gameobj, - int startseed, - PyTypeObject* T=&Type); + int startseed); virtual ~SCA_RandomSensor(); virtual CValue* GetReplica(); virtual void ProcessReplica(); @@ -61,10 +60,6 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - /* 1. setSeed */ KX_PYMETHOD_DOC_VARARGS(SCA_RandomSensor,SetSeed); /* 2. getSeed */ diff --git a/source/gameengine/GameLogic/SCA_XNORController.cpp b/source/gameengine/GameLogic/SCA_XNORController.cpp index aee8e26c21a..527adc70cc6 100644 --- a/source/gameengine/GameLogic/SCA_XNORController.cpp +++ b/source/gameengine/GameLogic/SCA_XNORController.cpp @@ -42,10 +42,9 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ -SCA_XNORController::SCA_XNORController(SCA_IObject* gameobj, - PyTypeObject* T) +SCA_XNORController::SCA_XNORController(SCA_IObject* gameobj) : - SCA_IController(gameobj,T) + SCA_IController(gameobj) { } @@ -120,19 +119,15 @@ PyTypeObject SCA_XNORController::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_XNORController::Parents[] = { - &SCA_XNORController::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IController::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_XNORController::Methods[] = { @@ -143,12 +138,4 @@ PyAttributeDef SCA_XNORController::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_XNORController::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IController); -} - -PyObject* SCA_XNORController::py_getattro_dict() { - py_getattro_dict_up(SCA_IController); -} - /* eof */ diff --git a/source/gameengine/GameLogic/SCA_XNORController.h b/source/gameengine/GameLogic/SCA_XNORController.h index 4aad5763cb0..18e77fae665 100644 --- a/source/gameengine/GameLogic/SCA_XNORController.h +++ b/source/gameengine/GameLogic/SCA_XNORController.h @@ -39,7 +39,7 @@ class SCA_XNORController : public SCA_IController Py_Header; //virtual void Trigger(class SCA_LogicManager* logicmgr); public: - SCA_XNORController(SCA_IObject* gameobj,PyTypeObject* T=&Type); + SCA_XNORController(SCA_IObject* gameobj); virtual ~SCA_XNORController(); virtual CValue* GetReplica(); virtual void Trigger(SCA_LogicManager* logicmgr); @@ -48,9 +48,6 @@ public: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - }; #endif //__KX_XNORCONTROLLER diff --git a/source/gameengine/GameLogic/SCA_XORController.cpp b/source/gameengine/GameLogic/SCA_XORController.cpp index 5afb3a750f5..c0916224fe6 100644 --- a/source/gameengine/GameLogic/SCA_XORController.cpp +++ b/source/gameengine/GameLogic/SCA_XORController.cpp @@ -42,10 +42,9 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ -SCA_XORController::SCA_XORController(SCA_IObject* gameobj, - PyTypeObject* T) +SCA_XORController::SCA_XORController(SCA_IObject* gameobj) : - SCA_IController(gameobj,T) + SCA_IController(gameobj) { } @@ -120,19 +119,15 @@ PyTypeObject SCA_XORController::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject SCA_XORController::Parents[] = { - &SCA_XORController::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IController::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef SCA_XORController::Methods[] = { @@ -143,12 +138,4 @@ PyAttributeDef SCA_XORController::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_XORController::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IController); -} - -PyObject* SCA_XORController::py_getattro_dict() { - py_getattro_dict_up(SCA_IController); -} - /* eof */ diff --git a/source/gameengine/GameLogic/SCA_XORController.h b/source/gameengine/GameLogic/SCA_XORController.h index feb9f2ed07c..2607a533661 100644 --- a/source/gameengine/GameLogic/SCA_XORController.h +++ b/source/gameengine/GameLogic/SCA_XORController.h @@ -39,18 +39,10 @@ class SCA_XORController : public SCA_IController Py_Header; //virtual void Trigger(class SCA_LogicManager* logicmgr); public: - SCA_XORController(SCA_IObject* gameobj,PyTypeObject* T=&Type); + SCA_XORController(SCA_IObject* gameobj); virtual ~SCA_XORController(); virtual CValue* GetReplica(); virtual void Trigger(SCA_LogicManager* logicmgr); - - /* --------------------------------------------------------------------- */ - /* Python interface ---------------------------------------------------- */ - /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - }; #endif //__KX_XORCONTROLLER diff --git a/source/gameengine/GamePlayer/common/Makefile b/source/gameengine/GamePlayer/common/Makefile index 84b4a4170a9..4a952856739 100644 --- a/source/gameengine/GamePlayer/common/Makefile +++ b/source/gameengine/GamePlayer/common/Makefile @@ -50,8 +50,6 @@ CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include CPPFLAGS += -I$(NAN_FUZZICS)/include CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include -CPPFLAGS += -I$(NAN_SUMO)/include -CPPFLAGS += -I$(NAN_SOLID)/include CPPFLAGS += -I$(NAN_PNG)/include CPPFLAGS += -I$(NAN_ZLIB)/include CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) @@ -69,7 +67,6 @@ CPPFLAGS += -I../../../gameengine/Network/LoopBackNetwork CPPFLAGS += -I../../../gameengine/Rasterizer CPPFLAGS += -I../../../gameengine/SceneGraph CPPFLAGS += -I../../../gameengine/Rasterizer/RAS_OpenGLRasterizer -CPPFLAGS += -I../../../gameengine/Physics/Sumo CPPFLAGS += -I../../../gameengine/Physics/common ############################### diff --git a/source/gameengine/GamePlayer/common/SConscript b/source/gameengine/GamePlayer/common/SConscript index e96b2c5400b..f899385c841 100644 --- a/source/gameengine/GamePlayer/common/SConscript +++ b/source/gameengine/GamePlayer/common/SConscript @@ -59,11 +59,6 @@ incs = ['.', # 'unix/GPU_System.cpp'] # gp_common_env.Append ( CPPPATH = ['unix']) -if env['WITH_BF_SOLID']: - incs.append('#source/gameengine/Physics/Sumo') - incs.append('#source/gameengine/Physics/Sumo/Fuzzics/include') - incs += Split(env['BF_SOLID_INC']) - incs += Split(env['BF_PYTHON_INC']) incs += Split(env['BF_PNG_INC']) incs += Split(env['BF_ZLIB_INC']) diff --git a/source/gameengine/GamePlayer/common/unix/GPU_Engine.cpp b/source/gameengine/GamePlayer/common/unix/GPU_Engine.cpp index a5dec02c753..0ef087efbfe 100644 --- a/source/gameengine/GamePlayer/common/unix/GPU_Engine.cpp +++ b/source/gameengine/GamePlayer/common/unix/GPU_Engine.cpp @@ -44,9 +44,6 @@ #include "NG_LoopBackNetworkDeviceInterface.h" #include "SND_DeviceManager.h" #include "KX_BlenderSceneConverter.h" -#ifdef USE_SUMO_SOLID - #include "SM_Scene.h" -#endif #include "KX_KetsjiEngine.h" #include "GPC_RenderTools.h" diff --git a/source/gameengine/GamePlayer/common/unix/Makefile b/source/gameengine/GamePlayer/common/unix/Makefile index 90342c7b735..08c52ddc904 100644 --- a/source/gameengine/GamePlayer/common/unix/Makefile +++ b/source/gameengine/GamePlayer/common/unix/Makefile @@ -57,10 +57,8 @@ CPPFLAGS += -I../../../../gameengine/Rasterizer/RAS_OpenGLRasterizer CPPFLAGS += -I../../../../gameengine/SceneGraph CPPFLAGS += -I$(NAN_FUZZICS)/include -CPPFLAGS += -I$(NAN_SUMO)/include CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include CPPFLAGS += -I$(NAN_MOTO)/include -CPPFLAGS += -I$(NAN_SOLID)/include # Blender stuff CPPFLAGS += -I../../../../blender/blenkernel diff --git a/source/gameengine/GamePlayer/ghost/SConscript b/source/gameengine/GamePlayer/ghost/SConscript index 390b6f5e089..19234cb663c 100644 --- a/source/gameengine/GamePlayer/ghost/SConscript +++ b/source/gameengine/GamePlayer/ghost/SConscript @@ -41,10 +41,6 @@ incs = ['.', '#source/blender/gpu', '#extern/glew/include'] -if env['WITH_BF_SOLID']: - incs.append(['#source/gameengine/Physics/Sumo', '#source/gameengine/Physics/Sumo/Fuzzics/include']) - incs += Split(env['BF_SOLID_INC']) - incs += Split(env['BF_PYTHON_INC']) cxxflags = [] diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index c5c517c8a65..8bde5dd3a51 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -113,8 +113,8 @@ bool BL_Shader::Ok()const return (mShader !=0 && mOk && mUse); } -BL_Shader::BL_Shader(PyTypeObject *T) -: PyObjectPlus(T), +BL_Shader::BL_Shader() +: PyObjectPlus(), mShader(0), mPass(1), mOk(0), @@ -728,17 +728,6 @@ void BL_Shader::SetUniform(int uniform, const int* val, int len) } } - -PyObject* BL_Shader::py_getattro(PyObject *attr) -{ - py_getattro_up(PyObjectPlus); -} - -PyObject* BL_Shader::py_getattro_dict() { - py_getattro_dict_up(PyObjectPlus); -} - - PyMethodDef BL_Shader::Methods[] = { // creation @@ -792,21 +781,17 @@ PyTypeObject BL_Shader::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new }; - -PyParentObject BL_Shader::Parents[] = { - &BL_Shader::Type, - &PyObjectPlus::Type, - NULL -}; - - KX_PYMETHODDEF_DOC( BL_Shader, setSource," setSource(vertexProgram, fragmentProgram)" ) { if(mShader !=0 && mOk ) @@ -848,17 +833,17 @@ KX_PYMETHODDEF_DOC( BL_Shader, delSource, "delSource( )" ) KX_PYMETHODDEF_DOC( BL_Shader, isValid, "isValid()" ) { - return PyInt_FromLong( ( mShader !=0 && mOk ) ); + return PyLong_FromSsize_t( ( mShader !=0 && mOk ) ); } KX_PYMETHODDEF_DOC( BL_Shader, getVertexProg ,"getVertexProg( )" ) { - return PyString_FromString(vertProg?vertProg:""); + return PyUnicode_FromString(vertProg?vertProg:""); } KX_PYMETHODDEF_DOC( BL_Shader, getFragmentProg ,"getFragmentProg( )" ) { - return PyString_FromString(fragProg?fragProg:""); + return PyUnicode_FromString(fragProg?fragProg:""); } KX_PYMETHODDEF_DOC( BL_Shader, validate, "validate()") @@ -1223,7 +1208,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( uniform_name, (list2 for(unsigned int i=0; (i // 1. SetToPropName PyObject* KX_NetworkMessageActuator::PySetToPropName( @@ -240,4 +223,4 @@ PyObject* KX_NetworkMessageActuator::PySetBody( Py_RETURN_NONE; } -// <----- Deprecated \ No newline at end of file +// <----- Deprecated diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h index cf92fd46fe0..b4f55f2a466 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h @@ -50,8 +50,7 @@ public: const STR_String &toPropName, const STR_String &subject, int bodyType, - const STR_String &body, - PyTypeObject* T=&Type); + const STR_String &body); virtual ~KX_NetworkMessageActuator(); virtual bool Update(); @@ -61,10 +60,6 @@ public: /* Python interface ------------------------------------------- */ /* ------------------------------------------------------------ */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - // Deprecated -----> KX_PYMETHOD(KX_NetworkMessageActuator, SetToPropName); KX_PYMETHOD(KX_NetworkMessageActuator, SetSubject); diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp index 8ddcd87b66f..78dda1f6db7 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp @@ -50,10 +50,9 @@ KX_NetworkMessageSensor::KX_NetworkMessageSensor( class KX_NetworkEventManager* eventmgr, // our eventmanager class NG_NetworkScene *NetworkScene, // our scene SCA_IObject* gameobj, // the sensor controlling object - const STR_String &subject, - PyTypeObject* T + const STR_String &subject ) : - SCA_ISensor(gameobj,eventmgr,T), + SCA_ISensor(gameobj,eventmgr), m_Networkeventmgr(eventmgr), m_NetworkScene(NetworkScene), m_subject(subject), @@ -182,19 +181,15 @@ PyTypeObject KX_NetworkMessageSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_NetworkMessageSensor::Parents[] = { - &KX_NetworkMessageSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_NetworkMessageSensor::Methods[] = { @@ -226,18 +221,6 @@ PyAttributeDef KX_NetworkMessageSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_NetworkMessageSensor::py_getattro(PyObject *attr) { - py_getattro_up(SCA_ISensor); -} - -PyObject* KX_NetworkMessageSensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int KX_NetworkMessageSensor::py_setattro(PyObject *attr, PyObject *value) { - return SCA_ISensor::py_setattro(attr, value); -} - PyObject* KX_NetworkMessageSensor::pyattr_get_bodies(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_NetworkMessageSensor *self = static_cast(self_v); @@ -267,7 +250,7 @@ const char KX_NetworkMessageSensor::SetSubjectFilterText_doc[] = PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText(PyObject* value) { ShowDeprecationWarning("setSubjectFilterText()", "subject"); - char* Subject = PyString_AsString(value); + char* Subject = _PyUnicode_AsString(value); if (Subject==NULL) { PyErr_SetString(PyExc_TypeError, "sensor.tsetSubjectFilterText(string): KX_NetworkMessageSensor, expected a string message"); return NULL; @@ -285,7 +268,7 @@ const char KX_NetworkMessageSensor::GetFrameMessageCount_doc[] = PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount() { ShowDeprecationWarning("getFrameMessageCount()", "frameMessageCount"); - return PyInt_FromLong(long(m_frame_message_count)); + return PyLong_FromSsize_t(long(m_frame_message_count)); } // 3. Get the message bodies @@ -311,7 +294,7 @@ const char KX_NetworkMessageSensor::GetSubject_doc[] = PyObject* KX_NetworkMessageSensor::PyGetSubject() { ShowDeprecationWarning("getSubject()", "subject"); - return PyString_FromString(m_subject ? m_subject : ""); + return PyUnicode_FromString(m_subject ? m_subject : ""); } // 5. Get the message subjects @@ -328,4 +311,4 @@ PyObject* KX_NetworkMessageSensor::PyGetSubjects() return (new CListValue())->NewProxy(true); } } -// <----- Deprecated \ No newline at end of file +// <----- Deprecated diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h index 53183f33826..ade87697303 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h @@ -57,8 +57,7 @@ public: KX_NetworkEventManager* eventmgr, // our eventmanager NG_NetworkScene *NetworkScene, // our scene SCA_IObject* gameobj, // the sensor controlling object - const STR_String &subject, - PyTypeObject* T=&Type + const STR_String &subject ); virtual ~KX_NetworkMessageSensor(); @@ -72,10 +71,6 @@ public: /* Python interface -------------------------------------------- */ /* ------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - // Deprecated -----> KX_PYMETHOD_DOC_O(KX_NetworkMessageSensor, SetSubjectFilterText); KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetFrameMessageCount); diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 30057fc039d..314becc702d 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -42,10 +42,8 @@ BL_BlenderShader *KX_BlenderMaterial::mLastBlenderShader = NULL; //static PyObject *gTextureDict = 0; -KX_BlenderMaterial::KX_BlenderMaterial( - PyTypeObject *T - ) -: PyObjectPlus(T), +KX_BlenderMaterial::KX_BlenderMaterial() +: PyObjectPlus(), RAS_IPolyMaterial(), mMaterial(NULL), mShader(0), @@ -813,36 +811,17 @@ PyTypeObject KX_BlenderMaterial::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new }; - -PyParentObject KX_BlenderMaterial::Parents[] = { - &KX_BlenderMaterial::Type, - &PyObjectPlus::Type, - NULL -}; - - -PyObject* KX_BlenderMaterial::py_getattro(PyObject *attr) -{ - py_getattro_up(PyObjectPlus); -} - -PyObject* KX_BlenderMaterial::py_getattro_dict() { - py_getattro_dict_up(PyObjectPlus); -} - -int KX_BlenderMaterial::py_setattro(PyObject *attr, PyObject *pyvalue) -{ - return PyObjectPlus::py_setattro(attr, pyvalue); -} - - KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") { if( !GLEW_ARB_fragment_shader) { @@ -912,7 +891,7 @@ void KX_BlenderMaterial::SetBlenderGLSLShader(int layer) KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()") { - return PyInt_FromLong( GetMaterialIndex() ); + return PyLong_FromSsize_t( GetMaterialIndex() ); } KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getTexture, "getTexture( index )" ) diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index b29f2df98db..1f5edc1d7d1 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -23,9 +23,7 @@ class KX_BlenderMaterial : public PyObjectPlus, public RAS_IPolyMaterial Py_Header; public: // -------------------------------- - KX_BlenderMaterial( - PyTypeObject* T=&Type - ); + KX_BlenderMaterial(); void Initialize( class KX_Scene* scene, BL_Material* mat, @@ -83,10 +81,7 @@ public: ); // -------------------------------- - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *pyvalue); - virtual PyObject* py_repr(void) { return PyString_FromString(mMaterial->matname.ReadPtr()); } + virtual PyObject* py_repr(void) { return PyUnicode_FromString(mMaterial->matname.ReadPtr()); } KX_PYMETHOD_DOC( KX_BlenderMaterial, getShader ); KX_PYMETHOD_DOC( KX_BlenderMaterial, getMaterialIndex ); diff --git a/source/gameengine/Ketsji/KX_CDActuator.cpp b/source/gameengine/Ketsji/KX_CDActuator.cpp index 8511526fd5f..bfca81f45d9 100644 --- a/source/gameengine/Ketsji/KX_CDActuator.cpp +++ b/source/gameengine/Ketsji/KX_CDActuator.cpp @@ -48,9 +48,8 @@ KX_CDActuator::KX_CDActuator(SCA_IObject* gameobject, KX_CDACT_TYPE type, int track, short start, - short end, - PyTypeObject* T) - : SCA_IActuator(gameobject,T) + short end) + : SCA_IActuator(gameobject) { m_soundscene = soundscene; m_type = type; @@ -171,25 +170,17 @@ PyTypeObject KX_CDActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - - - -PyParentObject KX_CDActuator::Parents[] = { - &KX_CDActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - - PyMethodDef KX_CDActuator::Methods[] = { // Deprecated -----> {"setGain",(PyCFunction) KX_CDActuator::sPySetGain,METH_VARARGS,NULL}, @@ -217,22 +208,6 @@ int KX_CDActuator::pyattr_setGain(void *self, const struct KX_PYATTRIBUTE_DEF *a return PY_SET_ATTR_SUCCESS; } -PyObject* KX_CDActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_CDActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_CDActuator::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_IActuator); -} - - - KX_PYMETHODDEF_DOC_NOARGS(KX_CDActuator, startCD, "startCD()\n" "\tStarts the CD playing.\n") @@ -273,8 +248,8 @@ KX_PYMETHODDEF_DOC_O(KX_CDActuator, playTrack, "playTrack(trackNumber)\n" "\tPlays the track selected.\n") { - if (PyInt_Check(value)) { - int track = PyInt_AsLong(value); + if (PyLong_Check(value)) { + int track = PyLong_AsSsize_t(value); SND_CDObject::Instance()->SetPlaymode(SND_CD_TRACK); SND_CDObject::Instance()->SetTrack(track); SND_CDObject::Instance()->SetPlaystate(SND_MUST_PLAY); diff --git a/source/gameengine/Ketsji/KX_CDActuator.h b/source/gameengine/Ketsji/KX_CDActuator.h index 2fd05ab72e5..b01ad73777e 100644 --- a/source/gameengine/Ketsji/KX_CDActuator.h +++ b/source/gameengine/Ketsji/KX_CDActuator.h @@ -68,8 +68,7 @@ public: KX_CDACT_TYPE type, int track, short start, - short end, - PyTypeObject* T=&Type); + short end); ~KX_CDActuator(); @@ -81,10 +80,6 @@ public: /* Python interface --------------------------------------------------- */ /* -------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - // Deprecated -----> KX_PYMETHOD_VARARGS(KX_CDActuator,SetGain); KX_PYMETHOD_VARARGS(KX_CDActuator,GetGain); diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index 40f6c99c03c..f762699f780 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -42,10 +42,9 @@ KX_Camera::KX_Camera(void* sgReplicationInfo, SG_Callbacks callbacks, const RAS_CameraData& camdata, bool frustum_culling, - bool delete_node, - PyTypeObject *T) + bool delete_node) : - KX_GameObject(sgReplicationInfo,callbacks,T), + KX_GameObject(sgReplicationInfo,callbacks), m_camdata(camdata), m_dirty(true), m_normalized(false), @@ -551,41 +550,19 @@ PyTypeObject KX_Camera::Type = { &KX_GameObject::Sequence, &KX_GameObject::Mapping, 0,0,0, - py_base_getattro, - py_base_setattro, + NULL, + NULL, 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 0,0,0,0,0,0,0, - Methods + Methods, + 0, + 0, + &KX_GameObject::Type, + 0,0,0,0,0,0, + py_base_new }; - - - - - -PyParentObject KX_Camera::Parents[] = { - &KX_Camera::Type, - &KX_GameObject::Type, - &SCA_IObject::Type, - &CValue::Type, - NULL -}; - -PyObject* KX_Camera::py_getattro(PyObject *attr) -{ - py_getattro_up(KX_GameObject); -} - -PyObject* KX_Camera::py_getattro_dict() { - py_getattro_dict_up(KX_GameObject); -} - -int KX_Camera::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(KX_GameObject); -} - KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum, "sphereInsideFrustum(center, radius) -> Integer\n" "\treturns INSIDE, OUTSIDE or INTERSECT if the given sphere is\n" @@ -611,7 +588,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum, MT_Point3 center; if (PyVecTo(pycenter, center)) { - return PyInt_FromLong(SphereInsideFrustum(center, radius)); /* new ref */ + return PyLong_FromSsize_t(SphereInsideFrustum(center, radius)); /* new ref */ } } @@ -662,7 +639,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, boxInsideFrustum, return NULL; } - return PyInt_FromLong(BoxInsideFrustum(box)); /* new ref */ + return PyLong_FromSsize_t(BoxInsideFrustum(box)); /* new ref */ } KX_PYMETHODDEF_DOC_O(KX_Camera, pointInsideFrustum, @@ -684,7 +661,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, pointInsideFrustum, MT_Point3 point; if (PyVecTo(value, point)) { - return PyInt_FromLong(PointInsideFrustum(point)); /* new ref */ + return PyLong_FromSsize_t(PointInsideFrustum(point)); /* new ref */ } PyErr_SetString(PyExc_TypeError, "camera.pointInsideFrustum(point): KX_Camera, expected point argument."); @@ -952,11 +929,11 @@ PyObject* KX_Camera::pyattr_get_world_to_camera(void *self_v, const KX_PYATTRIBU PyObject* KX_Camera::pyattr_get_INSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ return PyInt_FromLong(INSIDE); } +{ return PyLong_FromSsize_t(INSIDE); } PyObject* KX_Camera::pyattr_get_OUTSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ return PyInt_FromLong(OUTSIDE); } +{ return PyLong_FromSsize_t(OUTSIDE); } PyObject* KX_Camera::pyattr_get_INTERSECT(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ return PyInt_FromLong(INTERSECT); } +{ return PyLong_FromSsize_t(INTERSECT); } bool ConvertPythonToCamera(PyObject * value, KX_Camera **object, bool py_none_ok, const char *error_prefix) @@ -978,14 +955,14 @@ bool ConvertPythonToCamera(PyObject * value, KX_Camera **object, bool py_none_ok } } - if (PyString_Check(value)) { - STR_String value_str = PyString_AsString(value); + if (PyUnicode_Check(value)) { + STR_String value_str = _PyUnicode_AsString(value); *object = KX_GetActiveScene()->FindCamera(value_str); if (*object) { return true; } else { - PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_Camera in this scene", error_prefix, PyString_AsString(value)); + PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_Camera in this scene", error_prefix, _PyUnicode_AsString(value)); return false; } } @@ -1142,7 +1119,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenRay, PyTuple_SET_ITEM(argValue, 0, PyObjectFrom(vect)); PyTuple_SET_ITEM(argValue, 1, PyFloat_FromDouble(dist)); if (propName) - PyTuple_SET_ITEM(argValue, 2, PyString_FromString(propName)); + PyTuple_SET_ITEM(argValue, 2, PyUnicode_FromString(propName)); PyObject* ret= this->PyrayCastTo(argValue,NULL); Py_DECREF(argValue); diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h index aef21cd91e4..74c8e6d4e4f 100644 --- a/source/gameengine/Ketsji/KX_Camera.h +++ b/source/gameengine/Ketsji/KX_Camera.h @@ -143,7 +143,7 @@ public: enum { INSIDE, INTERSECT, OUTSIDE } ; - KX_Camera(void* sgReplicationInfo,SG_Callbacks callbacks,const RAS_CameraData& camdata, bool frustum_culling = true, bool delete_node = false, PyTypeObject *T = &Type); + KX_Camera(void* sgReplicationInfo,SG_Callbacks callbacks,const RAS_CameraData& camdata, bool frustum_culling = true, bool delete_node = false); virtual ~KX_Camera(); /** @@ -265,6 +265,7 @@ public: */ int GetViewportTop() const; + virtual int GetGameObjectType() { return OBJ_CAMERA; } KX_PYMETHOD_DOC_VARARGS(KX_Camera, sphereInsideFrustum); KX_PYMETHOD_DOC_O(KX_Camera, boxInsideFrustum); @@ -282,10 +283,6 @@ public: KX_PYMETHOD_DOC_O(KX_Camera, getScreenPosition); KX_PYMETHOD_DOC_VARARGS(KX_Camera, getScreenVect); KX_PYMETHOD_DOC_VARARGS(KX_Camera, getScreenRay); - - virtual PyObject* py_getattro(PyObject *attr); /* lens, near, far, projection_matrix */ - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *pyvalue); static PyObject* pyattr_get_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index f8557dac2c4..3d3b68ed85d 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -56,10 +56,9 @@ KX_CameraActuator::KX_CameraActuator( float hght, float minhght, float maxhght, - bool xytog, - PyTypeObject* T + bool xytog ): - SCA_IActuator(gameobj, T), + SCA_IActuator(gameobj), m_ob (obj), m_height (hght), m_minHeight (minhght), @@ -385,19 +384,15 @@ PyTypeObject KX_CameraActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_CameraActuator::Parents[] = { - &KX_CameraActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_CameraActuator::Methods[] = { @@ -424,18 +419,6 @@ PyAttributeDef KX_CameraActuator::Attributes[] = { {NULL} }; -PyObject* KX_CameraActuator::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_CameraActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_CameraActuator::py_setattro(PyObject *attr, PyObject* value) { - py_setattro_up(SCA_IActuator); -} - /* get obj ---------------------------------------------------------- */ const char KX_CameraActuator::GetObject_doc[] = "getObject(name_only = 1)\n" @@ -454,7 +437,7 @@ PyObject* KX_CameraActuator::PyGetObject(PyObject* args) Py_RETURN_NONE; if (ret_name_only) - return PyString_FromString(m_ob->GetName().ReadPtr()); + return PyUnicode_FromString(m_ob->GetName().ReadPtr()); else return m_ob->GetProxy(); } @@ -579,7 +562,7 @@ const char KX_CameraActuator::GetXY_doc[] = PyObject* KX_CameraActuator::PyGetXY() { ShowDeprecationWarning("getXY()", "the xy property"); - return PyInt_FromLong(m_x); + return PyLong_FromSsize_t(m_x); } PyObject* KX_CameraActuator::pyattr_get_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/Ketsji/KX_CameraActuator.h b/source/gameengine/Ketsji/KX_CameraActuator.h index efa4e2f38d7..057c6fed770 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.h +++ b/source/gameengine/Ketsji/KX_CameraActuator.h @@ -91,9 +91,7 @@ private : float hght, float minhght, float maxhght, - bool xytog, - PyTypeObject* T=&Type - + bool xytog ); @@ -120,10 +118,6 @@ private : /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); - /* set object to look at */ KX_PYMETHOD_DOC_O(KX_CameraActuator,SetObject); /* get current object */ diff --git a/source/gameengine/Ketsji/KX_ClientObjectInfo.h b/source/gameengine/Ketsji/KX_ClientObjectInfo.h index 077ac96f0ac..1898dc71ef8 100644 --- a/source/gameengine/Ketsji/KX_ClientObjectInfo.h +++ b/source/gameengine/Ketsji/KX_ClientObjectInfo.h @@ -30,9 +30,6 @@ #define __KX_CLIENTOBJECT_INFO_H /* Note, the way this works with/without sumo is a bit odd */ -#ifdef USE_SUMO_SOLID -#include -#endif //USE_SUMO_SOLID #include @@ -42,9 +39,6 @@ class KX_GameObject; * Client Type and Additional Info. This structure can be use instead of a bare void* pointer, for safeness, and additional info for callbacks */ struct KX_ClientObjectInfo -#ifdef USE_SUMO_SOLID - : public SM_ClientObject -#endif { enum clienttype { STATIC, @@ -59,18 +53,12 @@ struct KX_ClientObjectInfo std::list m_sensors; public: KX_ClientObjectInfo(KX_GameObject *gameobject, clienttype type = STATIC, void *auxilary_info = NULL) : -#ifdef USE_SUMO_SOLID - SM_ClientObject(), -#endif m_type(type), m_gameobject(gameobject), m_auxilary_info(auxilary_info) {} KX_ClientObjectInfo(const KX_ClientObjectInfo ©) : -#ifdef USE_SUMO_SOLID - SM_ClientObject(copy), -#endif m_type(copy.m_type), m_gameobject(copy.m_gameobject), m_auxilary_info(copy.m_auxilary_info) diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp index bd03dea486b..d09eae647c8 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp @@ -54,9 +54,8 @@ KX_ConstraintActuator::KX_ConstraintActuator(SCA_IObject *gameobj, int locrotxyz, int time, int option, - char *property, - PyTypeObject* T) : - SCA_IActuator(gameobj, T), + char *property) : + SCA_IActuator(gameobj), m_refDirVector(refDir), m_currentTime(0) { @@ -581,19 +580,15 @@ PyTypeObject KX_ConstraintActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_ConstraintActuator::Parents[] = { - &KX_ConstraintActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_ConstraintActuator::Methods[] = { @@ -639,21 +634,6 @@ PyAttributeDef KX_ConstraintActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_ConstraintActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_ConstraintActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_ConstraintActuator::py_setattro(PyObject *attr, PyObject* value) -{ - py_setattro_up(SCA_IActuator); -} - - int KX_ConstraintActuator::pyattr_check_direction(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_ConstraintActuator* act = static_cast(self); @@ -691,7 +671,7 @@ const char KX_ConstraintActuator::GetDamp_doc[] = "\tReturns the damping parameter.\n"; PyObject* KX_ConstraintActuator::PyGetDamp(){ ShowDeprecationWarning("getDamp()", "the damp property"); - return PyInt_FromLong(m_posDampTime); + return PyLong_FromSsize_t(m_posDampTime); } /* 2. setRotDamp */ @@ -718,7 +698,7 @@ const char KX_ConstraintActuator::GetRotDamp_doc[] = "\tReturns the damping time for application of the constraint.\n"; PyObject* KX_ConstraintActuator::PyGetRotDamp(){ ShowDeprecationWarning("getRotDamp()", "the rotDamp property"); - return PyInt_FromLong(m_rotDampTime); + return PyLong_FromSsize_t(m_rotDampTime); } /* 2. setDirection */ @@ -791,7 +771,7 @@ const char KX_ConstraintActuator::GetOption_doc[] = "\tReturns the option parameter.\n"; PyObject* KX_ConstraintActuator::PyGetOption(){ ShowDeprecationWarning("getOption()", "the option property"); - return PyInt_FromLong(m_option); + return PyLong_FromSsize_t(m_option); } /* 2. setTime */ @@ -820,7 +800,7 @@ const char KX_ConstraintActuator::GetTime_doc[] = "\tReturns the time parameter.\n"; PyObject* KX_ConstraintActuator::PyGetTime(){ ShowDeprecationWarning("getTime()", "the time property"); - return PyInt_FromLong(m_activeTime); + return PyLong_FromSsize_t(m_activeTime); } /* 2. setProperty */ @@ -849,7 +829,7 @@ const char KX_ConstraintActuator::GetProperty_doc[] = "\tReturns the property parameter.\n"; PyObject* KX_ConstraintActuator::PyGetProperty(){ ShowDeprecationWarning("getProperty()", "the 'property' property"); - return PyString_FromString(m_property.Ptr()); + return PyUnicode_FromString(m_property.Ptr()); } /* 4. setDistance */ @@ -978,7 +958,7 @@ const char KX_ConstraintActuator::GetLimit_doc[] = "\tReturns the type of constraint.\n"; PyObject* KX_ConstraintActuator::PyGetLimit() { ShowDeprecationWarning("setLimit()", "the limit property"); - return PyInt_FromLong(m_locrot); + return PyLong_FromSsize_t(m_locrot); } /* eof */ diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h index 40607b44947..677904aedc9 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.h +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h @@ -126,8 +126,7 @@ protected: int locrot, int time, int option, - char *property, - PyTypeObject* T=&Type); + char *property); virtual ~KX_ConstraintActuator(); virtual CValue* GetReplica() { KX_ConstraintActuator* replica = new KX_ConstraintActuator(*this); @@ -141,10 +140,6 @@ protected: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); - static int pyattr_check_direction(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_check_min(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp index c5cf67af67d..ec7bb470235 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp @@ -38,8 +38,8 @@ KX_ConstraintWrapper::KX_ConstraintWrapper( PHY_ConstraintType ctype, int constraintId, - PHY_IPhysicsEnvironment* physenv,PyTypeObject *T) : - PyObjectPlus(T), + PHY_IPhysicsEnvironment* physenv) : + PyObjectPlus(), m_constraintId(constraintId), m_constraintType(ctype), m_physenv(physenv) @@ -51,7 +51,7 @@ KX_ConstraintWrapper::~KX_ConstraintWrapper() PyObject* KX_ConstraintWrapper::PyGetConstraintId() { - return PyInt_FromLong(m_constraintId); + return PyLong_FromSsize_t(m_constraintId); } @@ -99,37 +99,17 @@ PyTypeObject KX_ConstraintWrapper::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new }; -PyParentObject KX_ConstraintWrapper::Parents[] = { - &KX_ConstraintWrapper::Type, - NULL -}; - -//here you can search for existing data members (like mass,friction etc.) -PyObject* KX_ConstraintWrapper::py_getattro(PyObject *attr) -{ - py_getattro_up(PyObjectPlus); -} - -PyObject* KX_ConstraintWrapper::py_getattro_dict() { - py_getattro_dict_up(PyObjectPlus); -} - -int KX_ConstraintWrapper::py_setattro(PyObject *attr,PyObject* value) -{ - py_setattro_up(PyObjectPlus); -}; - - - - - PyMethodDef KX_ConstraintWrapper::Methods[] = { {"getConstraintId",(PyCFunction) KX_ConstraintWrapper::sPyGetConstraintId, METH_NOARGS}, {"setParam",(PyCFunction) KX_ConstraintWrapper::sPySetParam, METH_VARARGS}, diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.h b/source/gameengine/Ketsji/KX_ConstraintWrapper.h index 03813e0f167..74670944415 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.h +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.h @@ -35,11 +35,8 @@ class KX_ConstraintWrapper : public PyObjectPlus { Py_Header; - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); public: - KX_ConstraintWrapper(PHY_ConstraintType ctype,int constraintId,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type); + KX_ConstraintWrapper(PHY_ConstraintType ctype,int constraintId,class PHY_IPhysicsEnvironment* physenv); virtual ~KX_ConstraintWrapper (); int getConstraintId() { return m_constraintId;}; diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h index 74042366bae..9d3b9cdaf74 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h @@ -32,11 +32,8 @@ /* These are defined by the build system... */ //but the build system is broken, because it doesn't allow for 2 or more defines at once. //Please leave Sumo _AND_ Bullet enabled -//#define USE_SUMO_SOLID // scons defines this #define USE_BULLET -//#define USE_ODE - //on visual studio 7/8, always enable BULLET for now //you can have multiple physics engines running anyway, and //the scons build system doesn't really support this at the moment. @@ -148,20 +145,6 @@ struct KX_ObjectProperties } m_boundobject; }; -#ifdef USE_ODE - - -void KX_ConvertODEEngineObject(KX_GameObject* gameobj, - RAS_MeshObject* meshobj, - KX_Scene* kxscene, - struct PHY_ShapeProps* shapeprops, - struct PHY_MaterialProps* smmaterial, - struct KX_ObjectProperties* objprop); - - -#endif //USE_ODE - - void KX_ConvertDynamoObject(KX_GameObject* gameobj, RAS_MeshObject* meshobj, KX_Scene* kxscene, @@ -169,19 +152,6 @@ void KX_ConvertDynamoObject(KX_GameObject* gameobj, struct PHY_MaterialProps* smmaterial, struct KX_ObjectProperties* objprop); -#ifdef USE_SUMO_SOLID - -void KX_ConvertSumoObject( class KX_GameObject* gameobj, - class RAS_MeshObject* meshobj, - class KX_Scene* kxscene, - struct PHY_ShapeProps* shapeprops, - struct PHY_MaterialProps* smmaterial, - struct KX_ObjectProperties* objprop); - -void KX_ClearSumoSharedShapes(); -bool KX_ReInstanceShapeFromMesh(RAS_MeshObject* meshobj); - -#endif #ifdef USE_BULLET diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 51c41c0686d..64b5760de28 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -32,7 +32,6 @@ #include "MT_assert.h" -// defines USE_ODE to choose physics engine #include "KX_ConvertPhysicsObject.h" #include "BL_DeformableGameObject.h" #include "RAS_MeshObject.h" @@ -56,597 +55,6 @@ extern "C"{ #include "BKE_DerivedMesh.h" } -#ifdef USE_ODE - -#include "KX_OdePhysicsController.h" -#include "OdePhysicsEnvironment.h" -#endif //USE_ODE - - -// USE_SUMO_SOLID is defined in headerfile KX_ConvertPhysicsObject.h -#ifdef USE_SUMO_SOLID - - -#include "SumoPhysicsEnvironment.h" -#include "KX_SumoPhysicsController.h" - - -// sumo physics specific -#include "SM_Object.h" -#include "SM_FhObject.h" -#include "SM_Scene.h" -#include "SM_ClientObjectInfo.h" - -#include "KX_SumoPhysicsController.h" - -struct KX_PhysicsInstance -{ - DT_VertexBaseHandle m_vertexbase; - RAS_DisplayArray* m_darray; - RAS_IPolyMaterial* m_material; - - KX_PhysicsInstance(DT_VertexBaseHandle vertex_base, RAS_DisplayArray *darray, RAS_IPolyMaterial* mat) - : m_vertexbase(vertex_base), - m_darray(darray), - m_material(mat) - { - } - - ~KX_PhysicsInstance() - { - DT_DeleteVertexBase(m_vertexbase); - } -}; - -static GEN_Map map_gamemesh_to_sumoshape; -static GEN_Map map_gamemesh_to_instance; - -// forward declarations -static void BL_RegisterSumoObject(KX_GameObject* gameobj,class SM_Scene* sumoScene,class SM_Object* sumoObj,const STR_String& matname,bool isDynamic,bool isActor); -static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope); - -void KX_ConvertSumoObject( KX_GameObject* gameobj, - RAS_MeshObject* meshobj, - KX_Scene* kxscene, - PHY_ShapeProps* kxshapeprops, - PHY_MaterialProps* kxmaterial, - struct KX_ObjectProperties* objprop) - - -{ - SM_ShapeProps* smprop = new SM_ShapeProps; - - smprop->m_ang_drag = kxshapeprops->m_ang_drag; - smprop->m_do_anisotropic = kxshapeprops->m_do_anisotropic; - smprop->m_do_fh = kxshapeprops->m_do_fh; - smprop->m_do_rot_fh = kxshapeprops->m_do_rot_fh ; - smprop->m_friction_scaling[0] = kxshapeprops->m_friction_scaling[0]; - smprop->m_friction_scaling[1] = kxshapeprops->m_friction_scaling[1]; - smprop->m_friction_scaling[2] = kxshapeprops->m_friction_scaling[2]; - smprop->m_inertia = MT_Vector3(1., 1., 1.) * kxshapeprops->m_inertia; - smprop->m_lin_drag = kxshapeprops->m_lin_drag; - smprop->m_mass = kxshapeprops->m_mass; - smprop->m_radius = objprop->m_radius; - - - SM_MaterialProps* smmaterial = new SM_MaterialProps; - - smmaterial->m_fh_damping = kxmaterial->m_fh_damping; - smmaterial->m_fh_distance = kxmaterial->m_fh_distance; - smmaterial->m_fh_normal = kxmaterial->m_fh_normal; - smmaterial->m_fh_spring = kxmaterial->m_fh_spring; - smmaterial->m_friction = kxmaterial->m_friction; - smmaterial->m_restitution = kxmaterial->m_restitution; - - SumoPhysicsEnvironment* sumoEnv = - (SumoPhysicsEnvironment*)kxscene->GetPhysicsEnvironment(); - - SM_Scene* sceneptr = sumoEnv->GetSumoScene(); - - SM_Object* sumoObj=NULL; - - if (objprop->m_dyna && objprop->m_isactor) - { - DT_ShapeHandle shape = NULL; - bool polytope = false; - switch (objprop->m_boundclass) - { - case KX_BOUNDBOX: - shape = DT_NewBox(objprop->m_boundobject.box.m_extends[0], - objprop->m_boundobject.box.m_extends[1], - objprop->m_boundobject.box.m_extends[2]); - smprop->m_inertia.scale(objprop->m_boundobject.box.m_extends[0]*objprop->m_boundobject.box.m_extends[0], - objprop->m_boundobject.box.m_extends[1]*objprop->m_boundobject.box.m_extends[1], - objprop->m_boundobject.box.m_extends[2]*objprop->m_boundobject.box.m_extends[2]); - smprop->m_inertia *= smprop->m_mass/MT_Vector3(objprop->m_boundobject.box.m_extends).length(); - break; - case KX_BOUNDCYLINDER: - shape = DT_NewCylinder(smprop->m_radius, objprop->m_boundobject.c.m_height); - smprop->m_inertia.scale(smprop->m_mass*smprop->m_radius*smprop->m_radius, - smprop->m_mass*smprop->m_radius*smprop->m_radius, - smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height); - break; - case KX_BOUNDCONE: - shape = DT_NewCone(objprop->m_radius, objprop->m_boundobject.c.m_height); - smprop->m_inertia.scale(smprop->m_mass*smprop->m_radius*smprop->m_radius, - smprop->m_mass*smprop->m_radius*smprop->m_radius, - smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height); - break; - /* Dynamic mesh objects. WARNING! slow. */ - case KX_BOUNDPOLYTOPE: - polytope = true; - // fall through - case KX_BOUNDMESH: - if (meshobj && meshobj->NumPolygons() > 0) - { - if ((shape = CreateShapeFromMesh(meshobj, polytope))) - { - // TODO: calculate proper inertia - smprop->m_inertia *= smprop->m_mass*smprop->m_radius*smprop->m_radius; - break; - } - } - /* If CreateShapeFromMesh fails, fall through and use sphere */ - default: - case KX_BOUNDSPHERE: - shape = DT_NewSphere(objprop->m_radius); - smprop->m_inertia *= smprop->m_mass*smprop->m_radius*smprop->m_radius; - break; - - } - - sumoObj = new SM_Object(shape, !objprop->m_ghost?smmaterial:NULL,smprop,NULL); - - sumoObj->setRigidBody(objprop->m_angular_rigidbody?true:false); - - BL_RegisterSumoObject(gameobj,sceneptr,sumoObj,"",true, true); - - } - else { - // non physics object - if (meshobj) - { - int numpolys = meshobj->NumPolygons(); - { - - DT_ShapeHandle complexshape=0; - bool polytope = false; - - switch (objprop->m_boundclass) - { - case KX_BOUNDBOX: - complexshape = DT_NewBox(objprop->m_boundobject.box.m_extends[0], objprop->m_boundobject.box.m_extends[1], objprop->m_boundobject.box.m_extends[2]); - break; - case KX_BOUNDSPHERE: - complexshape = DT_NewSphere(objprop->m_boundobject.c.m_radius); - break; - case KX_BOUNDCYLINDER: - complexshape = DT_NewCylinder(objprop->m_boundobject.c.m_radius, objprop->m_boundobject.c.m_height); - break; - case KX_BOUNDCONE: - complexshape = DT_NewCone(objprop->m_boundobject.c.m_radius, objprop->m_boundobject.c.m_height); - break; - case KX_BOUNDPOLYTOPE: - polytope = true; - // fall through - default: - case KX_BOUNDMESH: - if (numpolys>0) - { - complexshape = CreateShapeFromMesh(meshobj, polytope); - //std::cout << "Convert Physics Mesh: " << meshobj->GetName() << std::endl; -/* if (!complexshape) - { - // Something has to be done here - if the object has no polygons, it will not be able to have - // sensors attached to it. - DT_Vector3 pt = {0., 0., 0.}; - complexshape = DT_NewSphere(1.0); - objprop->m_ghost = evilObject = true; - } */ - } - break; - } - - if (complexshape) - { - SM_Object *dynamicParent = NULL; - - if (objprop->m_dynamic_parent) - { - // problem is how to find the dynamic parent - // in the scenegraph - KX_SumoPhysicsController* sumoctrl = - (KX_SumoPhysicsController*) - objprop->m_dynamic_parent->GetPhysicsController(); - - if (sumoctrl) - { - dynamicParent = sumoctrl->GetSumoObject(); - } - - MT_assert(dynamicParent); - } - - - sumoObj = new SM_Object(complexshape,!objprop->m_ghost?smmaterial:NULL,NULL, dynamicParent); - const STR_String& matname=meshobj->GetMaterialName(0); - - - BL_RegisterSumoObject(gameobj,sceneptr, - sumoObj, - matname, - objprop->m_dyna, - objprop->m_isactor); - } - } - } - } - - // physics object get updated here ! - - - // lazy evaluation because we might not support scaling !gameobj->UpdateTransform(); - - if (objprop->m_in_active_layer && sumoObj) - { - sceneptr->add(*sumoObj); - } - -} - - - -static void BL_RegisterSumoObject( - KX_GameObject* gameobj, - class SM_Scene* sumoScene, - class SM_Object* sumoObj, - const STR_String& matname, - bool isDynamic, - bool isActor) -{ - PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode()); - - // need easy access, not via 'node' etc. - KX_SumoPhysicsController* physicscontroller = new KX_SumoPhysicsController(sumoScene,sumoObj,motionstate,isDynamic); - gameobj->SetPhysicsController(physicscontroller,isDynamic); - - - if (!gameobj->getClientInfo()) - std::cout << "BL_RegisterSumoObject: WARNING: Object " << gameobj->GetName() << " has no client info" << std::endl; - physicscontroller->setNewClientInfo(gameobj->getClientInfo()); - - - gameobj->GetSGNode()->AddSGController(physicscontroller); - - gameobj->getClientInfo()->m_type = (isActor ? KX_ClientObjectInfo::ACTOR : KX_ClientObjectInfo::STATIC); - - // store materialname in auxinfo, needed for touchsensors - gameobj->getClientInfo()->m_auxilary_info = (matname.Length() ? (void*)(matname.ReadPtr()+2) : NULL); - - physicscontroller->SetObject(gameobj->GetSGNode()); -} - -static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, RAS_DisplayArray *darray, RAS_IPolyMaterial *mat) -{ - // instance a mesh from a single vertex array & material - const RAS_TexVert *vertex_array = &darray->m_vertex[0]; - DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getXYZ(), sizeof(RAS_TexVert)); - - DT_ShapeHandle shape = DT_NewComplexShape(vertex_base); - - std::vector indices; - for (int p = 0; p < meshobj->NumPolygons(); p++) - { - RAS_Polygon* poly = meshobj->GetPolygon(p); - - // only add polygons that have the collisionflag set - if (poly->IsCollider()) - { - DT_Begin(); - DT_VertexIndex(poly->GetVertexOffset(0)); - DT_VertexIndex(poly->GetVertexOffset(1)); - DT_VertexIndex(poly->GetVertexOffset(2)); - DT_End(); - - // tesselate - if (poly->VertexCount() == 4) - { - DT_Begin(); - DT_VertexIndex(poly->GetVertexOffset(0)); - DT_VertexIndex(poly->GetVertexOffset(2)); - DT_VertexIndex(poly->GetVertexOffset(3)); - DT_End(); - } - } - } - - //DT_VertexIndices(indices.size(), &indices[0]); - DT_EndComplexShape(); - - map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, darray, mat)); - return shape; -} - -static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, RAS_DisplayArray *darray, RAS_IPolyMaterial *mat) -{ - // instance a mesh from a single vertex array & material - const RAS_TexVert *vertex_array = &darray->m_vertex[0]; - DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getXYZ(), sizeof(RAS_TexVert)); - - std::vector indices; - for (int p = 0; p < meshobj->NumPolygons(); p++) - { - RAS_Polygon* poly = meshobj->GetPolygon(p); - - // only add polygons that have the collisionflag set - if (poly->IsCollider()) - { - indices.push_back(poly->GetVertexOffset(0)); - indices.push_back(poly->GetVertexOffset(1)); - indices.push_back(poly->GetVertexOffset(2)); - - if (poly->VertexCount() == 4) - indices.push_back(poly->GetVertexOffset(3)); - } - } - - DT_ShapeHandle shape = DT_NewPolytope(vertex_base); - DT_VertexIndices(indices.size(), &indices[0]); - DT_EndPolytope(); - - map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, darray, mat)); - return shape; -} - -// This will have to be a method in a class somewhere... -// Update SOLID with a changed physics mesh. -// not used... yet. -bool KX_ReInstanceShapeFromMesh(RAS_MeshObject* meshobj) -{ - KX_PhysicsInstance *instance = *map_gamemesh_to_instance[GEN_HashedPtr(meshobj)]; - if (instance) - { - const RAS_TexVert *vertex_array = &instance->m_darray->m_vertex[0]; - DT_ChangeVertexBase(instance->m_vertexbase, vertex_array[0].getXYZ()); - return true; - } - return false; -} - -static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope) -{ - - DT_ShapeHandle *shapeptr = map_gamemesh_to_sumoshape[GEN_HashedPtr(meshobj)]; - // Mesh has already been converted: reuse - if (shapeptr) - { - return *shapeptr; - } - - // Mesh has no polygons! - int numpolys = meshobj->NumPolygons(); - if (!numpolys) - { - return NULL; - } - - // Count the number of collision polygons and check they all come from the same - // vertex array - int numvalidpolys = 0; - RAS_DisplayArray *darray = NULL; - RAS_IPolyMaterial *poly_material = NULL; - bool reinstance = true; - - for (int p=0; pGetPolygon(p); - - // only add polygons that have the collisionflag set - if (poly->IsCollider()) - { - // check polygon is from the same vertex array - if (poly->GetDisplayArray() != darray) - { - if (darray == NULL) - darray = poly->GetDisplayArray(); - else - { - reinstance = false; - darray = NULL; - } - } - - // check poly is from the same material - if (poly->GetMaterial()->GetPolyMaterial() != poly_material) - { - if (poly_material) - { - reinstance = false; - poly_material = NULL; - } - else - poly_material = poly->GetMaterial()->GetPolyMaterial(); - } - - // count the number of collision polys - numvalidpolys++; - - // We have one collision poly, and we can't reinstance, so we - // might as well break here. - if (!reinstance) - break; - } - } - - // No collision polygons - if (numvalidpolys < 1) - return NULL; - - DT_ShapeHandle shape; - if (reinstance) - { - if (polytope) - shape = InstancePhysicsPolytope(meshobj, darray, poly_material); - else - shape = InstancePhysicsComplex(meshobj, darray, poly_material); - } - else - { - if (polytope) - { - std::cout << "CreateShapeFromMesh: " << meshobj->GetName() << " is not suitable for polytope." << std::endl; - if (!poly_material) - std::cout << " Check mesh materials." << std::endl; - if (darray == NULL) - std::cout << " Check number of vertices." << std::endl; - } - - shape = DT_NewComplexShape(NULL); - - numvalidpolys = 0; - - for (int p2=0; p2GetPolygon(p2); - - // only add polygons that have the collisionflag set - if (poly->IsCollider()) - { /* We have to tesselate here because SOLID can only raycast triangles */ - DT_Begin(); - /* V1, V2, V3 */ - DT_Vertex(poly->GetVertex(2)->getXYZ()); - DT_Vertex(poly->GetVertex(1)->getXYZ()); - DT_Vertex(poly->GetVertex(0)->getXYZ()); - - numvalidpolys++; - DT_End(); - - if (poly->VertexCount() == 4) - { - DT_Begin(); - /* V1, V3, V4 */ - DT_Vertex(poly->GetVertex(3)->getXYZ()); - DT_Vertex(poly->GetVertex(2)->getXYZ()); - DT_Vertex(poly->GetVertex(0)->getXYZ()); - - numvalidpolys++; - DT_End(); - } - - } - } - - DT_EndComplexShape(); - } - - if (numvalidpolys > 0) - { - map_gamemesh_to_sumoshape.insert(GEN_HashedPtr(meshobj),shape); - return shape; - } - - delete shape; - return NULL; -} - -void KX_ClearSumoSharedShapes() -{ - int numshapes = map_gamemesh_to_sumoshape.size(); - int i; - for (i=0;im_dyna; - bool fullRigidBody= ( objprop->m_dyna && objprop->m_angular_rigidbody) != 0; - bool phantom = objprop->m_ghost; - class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode()); - - class ODEPhysicsEnvironment* odeEnv = - (ODEPhysicsEnvironment*)kxscene->GetPhysicsEnvironment(); - - dxSpace* space = odeEnv->GetOdeSpace(); - dxWorld* world = odeEnv->GetOdeWorld(); - - bool isSphere = false; - - switch (objprop->m_boundclass) - { - case KX_BOUNDBOX: - { - - KX_OdePhysicsController* physicscontroller = - new KX_OdePhysicsController( - dyna, - fullRigidBody, - phantom, - motionstate, - space, - world, - shapeprops->m_mass, - smmaterial->m_friction, - smmaterial->m_restitution, - isSphere, - objprop->m_boundobject.box.m_center, - objprop->m_boundobject.box.m_extends, - objprop->m_boundobject.c.m_radius - ); - - gameobj->SetPhysicsController(physicscontroller); - physicscontroller->setNewClientInfo(gameobj->getClientInfo()); - gameobj->GetSGNode()->AddSGController(physicscontroller); - - bool isActor = objprop->m_isactor; - STR_String materialname; - if (meshobj) - materialname = meshobj->GetMaterialName(0); - - const char* matname = materialname.ReadPtr(); - - - physicscontroller->SetObject(gameobj->GetSGNode()); - - break; - } - default: - { - } - }; - -} - - -#endif // USE_ODE - - #ifdef USE_BULLET #include "CcdPhysicsEnvironment.h" diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp index 28bf12f5e87..560c7fa4bb4 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.cpp +++ b/source/gameengine/Ketsji/KX_GameActuator.cpp @@ -49,9 +49,8 @@ KX_GameActuator::KX_GameActuator(SCA_IObject *gameobj, const STR_String& filename, const STR_String& loadinganimationname, KX_Scene* scene, - KX_KetsjiEngine* ketsjiengine, - PyTypeObject* T) - : SCA_IActuator(gameobj, T) + KX_KetsjiEngine* ketsjiengine) + : SCA_IActuator(gameobj) { m_mode = mode; m_filename = filename; @@ -224,26 +223,17 @@ PyTypeObject KX_GameActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - - - -PyParentObject KX_GameActuator::Parents[] = -{ - &KX_GameActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - - PyMethodDef KX_GameActuator::Methods[] = { // Deprecated -----> @@ -259,21 +249,6 @@ PyAttributeDef KX_GameActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_GameActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_GameActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_GameActuator::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_IActuator); -} - - // Deprecated -----> /* getFile */ const char KX_GameActuator::GetFile_doc[] = @@ -282,7 +257,7 @@ const char KX_GameActuator::GetFile_doc[] = PyObject* KX_GameActuator::PyGetFile(PyObject* args, PyObject* kwds) { ShowDeprecationWarning("getFile()", "the fileName property"); - return PyString_FromString(m_filename); + return PyUnicode_FromString(m_filename); } /* setFile */ diff --git a/source/gameengine/Ketsji/KX_GameActuator.h b/source/gameengine/Ketsji/KX_GameActuator.h index b2b1d6ec2b9..cabbf827b40 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.h +++ b/source/gameengine/Ketsji/KX_GameActuator.h @@ -65,8 +65,7 @@ protected: const STR_String& filename, const STR_String& loadinganimationname, KX_Scene* scene, - KX_KetsjiEngine* ketsjiEngine, - PyTypeObject* T=&Type); + KX_KetsjiEngine* ketsjiEngine); virtual ~KX_GameActuator(); virtual CValue* GetReplica(); @@ -77,10 +76,6 @@ protected: /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - // Deprecated functions -----> KX_PYMETHOD_DOC(KX_GameActuator,GetFile); KX_PYMETHOD_DOC(KX_GameActuator,SetFile); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index b266095c715..bf80eec36d9 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -86,10 +86,8 @@ static MT_Matrix3x3 dummy_orientation = MT_Matrix3x3( 1.0, 0.0, 0.0, KX_GameObject::KX_GameObject( void* sgReplicationInfo, - SG_Callbacks callbacks, - PyTypeObject* T -) : - SCA_IObject(T), + SG_Callbacks callbacks) + : SCA_IObject(), m_bDyna(false), m_layer(0), m_pBlenderObject(NULL), @@ -983,7 +981,17 @@ void KX_GameObject::NodeSetLocalOrientation(const MT_Matrix3x3& rot) GetSGNode()->SetLocalOrientation(rot); } +void KX_GameObject::NodeSetGlobalOrientation(const MT_Matrix3x3& rot) +{ + // check on valid node in case a python controller holds a reference to a deleted object + if (!GetSGNode()) + return; + if (GetSGNode()->GetSGParent()) + GetSGNode()->SetLocalOrientation(GetSGNode()->GetSGParent()->GetWorldOrientation().inverse()*rot); + else + GetSGNode()->SetLocalOrientation(rot); +} void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale) { @@ -1062,7 +1070,13 @@ const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const return GetSGNode()->GetWorldOrientation(); } - +const MT_Matrix3x3& KX_GameObject::NodeGetLocalOrientation() const +{ + // check on valid node in case a python controller holds a reference to a deleted object + if (!GetSGNode()) + return dummy_orientation; + return GetSGNode()->GetLocalOrientation(); +} const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const { @@ -1073,7 +1087,14 @@ const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const return GetSGNode()->GetWorldScaling(); } +const MT_Vector3& KX_GameObject::NodeGetLocalScaling() const +{ + // check on valid node in case a python controller holds a reference to a deleted object + if (!GetSGNode()) + return dummy_scaling; + return GetSGNode()->GetLocalScale(); +} const MT_Point3& KX_GameObject::NodeGetWorldPosition() const { @@ -1084,6 +1105,16 @@ const MT_Point3& KX_GameObject::NodeGetWorldPosition() const return dummy_point; } +const MT_Point3& KX_GameObject::NodeGetLocalPosition() const +{ + // check on valid node in case a python controller holds a reference to a deleted object + if (GetSGNode()) + return GetSGNode()->GetLocalPosition(); + else + return dummy_point; +} + + /* Suspend/ resume: for the dynamic behaviour, there is a simple * method. For the residual motion, there is not. I wonder what the * correct solution is for Sumo. Remove from the motion-update tree? @@ -1151,6 +1182,181 @@ CListValue* KX_GameObject::GetChildrenRecursive() return list; } +#ifdef USE_MATHUTILS + +/* These require an SGNode */ +#define MATHUTILS_VEC_CB_POS_LOCAL 1 +#define MATHUTILS_VEC_CB_POS_GLOBAL 2 +#define MATHUTILS_VEC_CB_SCALE_LOCAL 3 +#define MATHUTILS_VEC_CB_SCALE_GLOBAL 4 +#define MATHUTILS_VEC_CB_INERTIA_LOCAL 5 + +static int mathutils_kxgameob_vector_cb_index= -1; /* index for our callbacks */ + +static int mathutils_kxgameob_generic_check(PyObject *self_v) +{ + KX_GameObject* self= static_castBGE_PROXY_REF(self_v); + if(self==NULL) + return 0; + + return 1; +} + +static int mathutils_kxgameob_vector_get(PyObject *self_v, int subtype, float *vec_from) +{ + KX_GameObject* self= static_castBGE_PROXY_REF(self_v); + if(self==NULL) + return 0; + + switch(subtype) { + case MATHUTILS_VEC_CB_POS_LOCAL: + self->NodeGetLocalPosition().getValue(vec_from); + break; + case MATHUTILS_VEC_CB_POS_GLOBAL: + self->NodeGetWorldPosition().getValue(vec_from); + break; + case MATHUTILS_VEC_CB_SCALE_LOCAL: + self->NodeGetLocalScaling().getValue(vec_from); + break; + case MATHUTILS_VEC_CB_SCALE_GLOBAL: + self->NodeGetWorldScaling().getValue(vec_from); + break; + case MATHUTILS_VEC_CB_INERTIA_LOCAL: + if(!self->GetPhysicsController()) return 0; + self->GetPhysicsController()->GetLocalInertia().getValue(vec_from); + break; + } + + return 1; +} + +static int mathutils_kxgameob_vector_set(PyObject *self_v, int subtype, float *vec_to) +{ + KX_GameObject* self= static_castBGE_PROXY_REF(self_v); + if(self==NULL) + return 0; + + switch(subtype) { + case MATHUTILS_VEC_CB_POS_LOCAL: + self->NodeSetLocalPosition(MT_Point3(vec_to)); + self->NodeUpdateGS(0.f); + break; + case MATHUTILS_VEC_CB_POS_GLOBAL: + self->NodeSetWorldPosition(MT_Point3(vec_to)); + self->NodeUpdateGS(0.f); + break; + case MATHUTILS_VEC_CB_SCALE_LOCAL: + self->NodeSetLocalScale(MT_Point3(vec_to)); + self->NodeUpdateGS(0.f); + break; + case MATHUTILS_VEC_CB_SCALE_GLOBAL: + break; + case MATHUTILS_VEC_CB_INERTIA_LOCAL: + /* read only */ + break; + } + + return 1; +} + +static int mathutils_kxgameob_vector_get_index(PyObject *self_v, int subtype, float *vec_from, int index) +{ + float f[4]; + /* lazy, avoid repeteing the case statement */ + if(!mathutils_kxgameob_vector_get(self_v, subtype, f)) + return 0; + + vec_from[index]= f[index]; + return 1; +} + +static int mathutils_kxgameob_vector_set_index(PyObject *self_v, int subtype, float *vec_to, int index) +{ + float f= vec_to[index]; + + /* lazy, avoid repeteing the case statement */ + if(!mathutils_kxgameob_vector_get(self_v, subtype, vec_to)) + return 0; + + vec_to[index]= f; + mathutils_kxgameob_vector_set(self_v, subtype, vec_to); + + return 1; +} + +Mathutils_Callback mathutils_kxgameob_vector_cb = { + mathutils_kxgameob_generic_check, + mathutils_kxgameob_vector_get, + mathutils_kxgameob_vector_set, + mathutils_kxgameob_vector_get_index, + mathutils_kxgameob_vector_set_index +}; + +/* Matrix */ +#define MATHUTILS_MAT_CB_ORI_LOCAL 1 +#define MATHUTILS_MAT_CB_ORI_GLOBAL 2 + +static int mathutils_kxgameob_matrix_cb_index= -1; /* index for our callbacks */ + +static int mathutils_kxgameob_matrix_get(PyObject *self_v, int subtype, float *mat_from) +{ + KX_GameObject* self= static_castBGE_PROXY_REF(self_v); + if(self==NULL) + return 0; + + switch(subtype) { + case MATHUTILS_MAT_CB_ORI_LOCAL: + self->NodeGetLocalOrientation().getValue3x3(mat_from); + break; + case MATHUTILS_MAT_CB_ORI_GLOBAL: + self->NodeGetWorldOrientation().getValue3x3(mat_from); + break; + } + + return 1; +} + + +static int mathutils_kxgameob_matrix_set(PyObject *self_v, int subtype, float *mat_to) +{ + KX_GameObject* self= static_castBGE_PROXY_REF(self_v); + if(self==NULL) + return 0; + + MT_Matrix3x3 mat3x3; + switch(subtype) { + case MATHUTILS_MAT_CB_ORI_LOCAL: + mat3x3.setValue3x3(mat_to); + self->NodeSetLocalOrientation(mat3x3); + self->NodeUpdateGS(0.f); + break; + case MATHUTILS_MAT_CB_ORI_GLOBAL: + mat3x3.setValue3x3(mat_to); + self->NodeSetLocalOrientation(mat3x3); + self->NodeUpdateGS(0.f); + break; + } + + return 1; +} + +Mathutils_Callback mathutils_kxgameob_matrix_cb = { + mathutils_kxgameob_generic_check, + mathutils_kxgameob_matrix_get, + mathutils_kxgameob_matrix_set, + NULL, + NULL +}; + + +void KX_GameObject_Mathutils_Callback_Init(void) +{ + // register mathutils callbacks, ok to run more then once. + mathutils_kxgameob_vector_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_vector_cb); + mathutils_kxgameob_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_matrix_cb); +} + +#endif // USE_MATHUTILS /* ------- python stuff ---------------------------------------------------*/ @@ -1290,7 +1496,7 @@ PyObject* KX_GameObject::PyGetPosition() static PyObject *Map_GetItem(PyObject *self_v, PyObject *item) { KX_GameObject* self= static_castBGE_PROXY_REF(self_v); - const char *attr_str= PyString_AsString(item); + const char *attr_str= _PyUnicode_AsString(item); CValue* resultattr; PyObject* pyconvert; @@ -1324,7 +1530,7 @@ static PyObject *Map_GetItem(PyObject *self_v, PyObject *item) static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) { KX_GameObject* self= static_castBGE_PROXY_REF(self_v); - const char *attr_str= PyString_AsString(key); + const char *attr_str= _PyUnicode_AsString(key); if(attr_str==NULL) PyErr_Clear(); @@ -1356,7 +1562,7 @@ static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) int set= 0; /* as CValue */ - if(attr_str && BGE_PROXY_CHECK_TYPE(val)==0) /* dont allow GameObjects for eg to be assigned to CValue props */ + if(attr_str && PyObject_TypeCheck(val, &PyObjectPlus::Type)==0) /* dont allow GameObjects for eg to be assigned to CValue props */ { CValue* vallie = self->ConvertPythonToValue(val, ""); /* error unused */ @@ -1418,7 +1624,7 @@ static int Seq_Contains(PyObject *self_v, PyObject *value) return -1; } - if(PyString_Check(value) && self->GetProperty(PyString_AsString(value))) + if(PyUnicode_Check(value) && self->GetProperty(_PyUnicode_AsString(value))) return 1; if (self->m_attr_dict && PyDict_GetItem(self->m_attr_dict, value)) @@ -1466,30 +1672,23 @@ PyTypeObject KX_GameObject::Type = { &Sequence, &Mapping, 0,0,0, - py_base_getattro, - py_base_setattro, + NULL, + NULL, 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 0,0,0,0,0,0,0, - Methods -}; - - - - - - -PyParentObject KX_GameObject::Parents[] = { - &KX_GameObject::Type, + Methods, + 0, + 0, &SCA_IObject::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyObject* KX_GameObject::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self= static_cast(self_v); - return PyString_FromString(self->GetName().ReadPtr()); + return PyUnicode_FromString(self->GetName().ReadPtr()); } PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -1596,7 +1795,11 @@ int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *at PyObject* KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self= static_cast(self_v); +#ifdef USE_MATHUTILS + return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL); +#else return PyObjectFrom(self->NodeGetWorldPosition()); +#endif } int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -1614,10 +1817,11 @@ int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_D PyObject* KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self= static_cast(self_v); - if (self->GetSGNode()) - return PyObjectFrom(self->GetSGNode()->GetLocalPosition()); - else - return PyObjectFrom(dummy_point); +#ifdef USE_MATHUTILS + return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL); +#else + return PyObjectFrom(self->NodeGetLocalPosition()); +#endif } int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -1635,17 +1839,23 @@ int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_D PyObject* KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self= static_cast(self_v); +#ifdef USE_MATHUTILS + return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL); +#else if (self->GetPhysicsController()) - { return PyObjectFrom(self->GetPhysicsController()->GetLocalInertia()); - } return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f); +#endif } PyObject* KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { +#ifdef USE_MATHUTILS + return newMatrixObject_cb((PyObject *)self_v, 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL); +#else KX_GameObject* self= static_cast(self_v); return PyObjectFrom(self->NodeGetWorldOrientation()); +#endif } int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -1657,12 +1867,7 @@ int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUT if (!PyOrientationTo(value, rot, "gameOb.worldOrientation = sequence: KX_GameObject, ")) return PY_SET_ATTR_FAIL; - if (self->GetSGNode() && self->GetSGNode()->GetSGParent()) { - self->NodeSetLocalOrientation(self->GetSGNode()->GetSGParent()->GetWorldOrientation().inverse()*rot); - } - else { - self->NodeSetLocalOrientation(rot); - } + self->NodeSetGlobalOrientation(rot); self->NodeUpdateGS(0.f); return PY_SET_ATTR_SUCCESS; @@ -1670,11 +1875,12 @@ int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUT PyObject* KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { +#ifdef USE_MATHUTILS + return newMatrixObject_cb((PyObject *)self_v, 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL); +#else KX_GameObject* self= static_cast(self_v); - if (self->GetSGNode()) - return PyObjectFrom(self->GetSGNode()->GetLocalOrientation()); - else - return PyObjectFrom(dummy_orientation); + return PyObjectFrom(self->NodeGetLocalOrientation()); +#endif } int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -1694,16 +1900,21 @@ int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUT PyObject* KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self= static_cast(self_v); +#ifdef USE_MATHUTILS + return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL); +#else return PyObjectFrom(self->NodeGetWorldScaling()); +#endif } PyObject* KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self= static_cast(self_v); - if (self->GetSGNode()) - return PyObjectFrom(self->GetSGNode()->GetLocalScale()); - else - return PyObjectFrom(dummy_scaling); +#ifdef USE_MATHUTILS + return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL); +#else + return PyObjectFrom(self->NodeGetLocalScaling()); +#endif } int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -1750,13 +1961,13 @@ PyObject* KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF KX_GameObject* self= static_cast(self_v); int state = 0; state |= self->GetState(); - return PyInt_FromLong(state); + return PyLong_FromSsize_t(state); } int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_GameObject* self= static_cast(self_v); - int state_i = PyInt_AsLong(value); + int state_i = PyLong_AsSsize_t(value); unsigned int state = 0; if (state_i == -1 && PyErr_Occurred()) { @@ -1827,128 +2038,6 @@ PyObject* KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_ return self->m_attr_dict; } -/* We need these because the macros have a return in them */ -PyObject* KX_GameObject::py_getattro__internal(PyObject *attr) -{ - py_getattro_up(SCA_IObject); -} - -int KX_GameObject::py_setattro__internal(PyObject *attr, PyObject *value) // py_setattro method -{ - py_setattro_up(SCA_IObject); -} - - -PyObject* KX_GameObject::py_getattro(PyObject *attr) -{ - PyObject *object= py_getattro__internal(attr); - - if (object==NULL && m_attr_dict) - { - /* backup the exception incase the attr doesnt exist in the dict either */ - PyObject *err_type, *err_value, *err_tb; - PyErr_Fetch(&err_type, &err_value, &err_tb); - - object= PyDict_GetItem(m_attr_dict, attr); - if (object) { - Py_INCREF(object); - - PyErr_Clear(); - Py_XDECREF( err_type ); - Py_XDECREF( err_value ); - Py_XDECREF( err_tb ); - } - else { - PyErr_Restore(err_type, err_value, err_tb); /* use the error from the parent function */ - } - } - return object; -} - -PyObject* KX_GameObject::py_getattro_dict() { - //py_getattro_dict_up(SCA_IObject); - PyObject *dict= py_getattr_dict(SCA_IObject::py_getattro_dict(), Type.tp_dict); - if(dict==NULL) - return NULL; - - /* normally just return this but KX_GameObject has some more items */ - - - /* Not super fast getting as a list then making into dict keys but its only for dir() */ - PyObject *list= ConvertKeysToPython(); - if(list) - { - int i; - for(i=0; iGetUserData(); } - return PyInt_FromLong((long)physid); + return PyLong_FromSsize_t((long)physid); } PyObject* KX_GameObject::PyGetPropertyNames() @@ -2788,8 +2877,8 @@ PyObject* KX_GameObject::Pyget(PyObject *args) return NULL; - if(PyString_Check(key)) { - CValue *item = GetProperty(PyString_AsString(key)); + if(PyUnicode_Check(key)) { + CValue *item = GetProperty(_PyUnicode_AsString(key)); if (item) { ret = item->ConvertValueToPython(); if(ret) @@ -2858,13 +2947,13 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py } } - if (PyString_Check(value)) { - *object = (KX_GameObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( PyString_AsString(value) )); + if (PyUnicode_Check(value)) { + *object = (KX_GameObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( _PyUnicode_AsString(value) )); if (*object) { return true; } else { - PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_GameObject in this scene", error_prefix, PyString_AsString(value)); + PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_GameObject in this scene", error_prefix, _PyUnicode_AsString(value)); return false; } } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index ff5c8a01e6e..947cc9959ff 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -63,6 +63,10 @@ struct Object; /* utility conversion function */ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix); +#ifdef USE_MATHUTILS +void KX_GameObject_Mathutils_Callback_Init(void); +#endif + /** * KX_GameObject is the main class for dynamic objects. */ @@ -185,8 +189,7 @@ public: KX_GameObject( void* sgReplicationInfo, - SG_Callbacks callbacks, - PyTypeObject* T=&Type + SG_Callbacks callbacks ); virtual @@ -393,6 +396,7 @@ public: void NodeSetLocalPosition(const MT_Point3& trans ); void NodeSetLocalOrientation(const MT_Matrix3x3& rot ); + void NodeSetGlobalOrientation(const MT_Matrix3x3& rot ); void NodeSetLocalScale( const MT_Vector3& scale ); @@ -406,21 +410,13 @@ public: double time ); - const - MT_Matrix3x3& - NodeGetWorldOrientation( - ) const; - - const - MT_Vector3& - NodeGetWorldScaling( - ) const; - - const - MT_Point3& - NodeGetWorldPosition( - ) const; + const MT_Matrix3x3& NodeGetWorldOrientation( ) const; + const MT_Vector3& NodeGetWorldScaling( ) const; + const MT_Point3& NodeGetWorldPosition( ) const; + const MT_Matrix3x3& NodeGetLocalOrientation( ) const; + const MT_Vector3& NodeGetLocalScaling( ) const; + const MT_Point3& NodeGetLocalPosition( ) const; /** * @section scene graph node accessor functions. @@ -811,22 +807,10 @@ public: /** * @section Python interface functions. */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); // py_setattro method - virtual int py_delattro(PyObject *attr); virtual PyObject* py_repr(void) { - return PyString_FromString(GetName().ReadPtr()); + return PyUnicode_FromString(GetName().ReadPtr()); } - - - /* quite annoying that we need these but the bloody - * py_getattro_up and py_setattro_up macro's have a returns in them! */ - PyObject* py_getattro__internal(PyObject *attr); - int py_setattro__internal(PyObject *attr, PyObject *value); // py_setattro method - KX_PYMETHOD_NOARGS(KX_GameObject,GetPosition); KX_PYMETHOD_O(KX_GameObject,SetPosition); diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp index 3ec0598ac03..73a370a1681 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.cpp +++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp @@ -70,9 +70,8 @@ KX_IpoActuator::KX_IpoActuator(SCA_IObject* gameobj, int acttype, bool ipo_as_force, bool ipo_add, - bool ipo_local, - PyTypeObject* T) - : SCA_IActuator(gameobj,T), + bool ipo_local) + : SCA_IActuator(gameobj), m_bNegativeEvent(false), m_startframe (starttime), m_endframe(endtime), @@ -429,19 +428,15 @@ PyTypeObject KX_IpoActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_IpoActuator::Parents[] = { - &KX_IpoActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_IpoActuator::Methods[] = { @@ -477,18 +472,6 @@ PyAttributeDef KX_IpoActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_IpoActuator::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_IpoActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_IpoActuator::py_setattro(PyObject *attr, PyObject *value) // py_setattro method -{ - py_setattro_up(SCA_IActuator); -} /* set --------------------------------------------------------------------- */ const char KX_IpoActuator::Set_doc[] = @@ -689,7 +672,7 @@ const char KX_IpoActuator::GetType_doc[] = "\tReturns the operation mode of the actuator.\n"; PyObject* KX_IpoActuator::PyGetType() { ShowDeprecationWarning("getType()", "the mode property"); - return PyInt_FromLong(m_type); + return PyLong_FromSsize_t(m_type); } /* 10. setForceIpoActsLocal: */ diff --git a/source/gameengine/Ketsji/KX_IpoActuator.h b/source/gameengine/Ketsji/KX_IpoActuator.h index 9ea597def1e..01051ca82dc 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.h +++ b/source/gameengine/Ketsji/KX_IpoActuator.h @@ -121,8 +121,7 @@ public: int acttype, bool ipo_as_force, bool ipo_add, - bool ipo_local, - PyTypeObject* T=&Type); + bool ipo_local); virtual ~KX_IpoActuator() {}; virtual CValue* GetReplica() { @@ -138,10 +137,6 @@ public: /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); //KX_PYMETHOD_DOC KX_PYMETHOD_DOC_VARARGS(KX_IpoActuator,Set); diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index a43ea59220b..cc0f50d9e7a 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -61,10 +61,6 @@ #include "KX_PyConstraintBinding.h" #include "PHY_IPhysicsEnvironment.h" -#ifdef USE_SUMO_SOLID -#include "SumoPhysicsEnvironment.h" -#endif - #include "SND_Scene.h" #include "SND_IAudioDevice.h" @@ -400,9 +396,9 @@ void KX_KetsjiEngine::StartEngine(bool clearIpo) World* world = m_scenes[0]->GetBlenderScene()->world; if (world) { - m_ticrate = world->ticrate; - m_maxLogicFrame = world->maxlogicstep; - m_maxPhysicsFrame = world->maxphystep; + m_ticrate = world->ticrate ? world->ticrate : DEFAULT_LOGIC_TIC_RATE; + m_maxLogicFrame = world->maxlogicstep ? world->maxlogicstep : 5; + m_maxPhysicsFrame = world->maxphystep ? world->maxlogicstep : 5; } else { diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index ae9e097a96e..fb385f8a9a2 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -51,12 +51,9 @@ KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks, class RAS_IRenderTools* rendertools, const RAS_LightObject& lightobj, - bool glsl, - PyTypeObject* T - ) - : - KX_GameObject(sgReplicationInfo,callbacks,T), - m_rendertools(rendertools) + bool glsl) + : KX_GameObject(sgReplicationInfo,callbacks), + m_rendertools(rendertools) { m_lightobj = lightobj; m_lightobj.m_scene = sgReplicationInfo; @@ -271,11 +268,6 @@ void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras) /* Python Integration Hooks */ /* ------------------------------------------------------------------------- */ -PyObject* KX_LightObject::py_getattro_dict() { - py_getattro_dict_up(KX_GameObject); -} - - PyTypeObject KX_LightObject::Type = { #if (PY_VERSION_HEX >= 0x02060000) PyVarObject_HEAD_INIT(NULL, 0) @@ -297,20 +289,17 @@ PyTypeObject KX_LightObject::Type = { &KX_GameObject::Sequence, &KX_GameObject::Mapping, 0,0,0, - py_base_getattro, - py_base_setattro, + NULL, + NULL, 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_LightObject::Parents[] = { - &KX_LightObject::Type, - &KX_GameObject::Type, - &SCA_IObject::Type, - &CValue::Type, - NULL + Methods, + 0, + 0, + &KX_GameObject::Type, + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_LightObject::Methods[] = { @@ -362,11 +351,11 @@ PyObject* KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUT const char* type = attrdef->m_name; if(strcmp(type, "SPOT")) { - retvalue = PyInt_FromLong(RAS_LightObject::LIGHT_SPOT); + retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_SPOT); } else if (strcmp(type, "SUN")) { - retvalue = PyInt_FromLong(RAS_LightObject::LIGHT_SUN); + retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_SUN); } else if (strcmp(type, "NORMAL")) { - retvalue = PyInt_FromLong(RAS_LightObject::LIGHT_NORMAL); + retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_NORMAL); } return retvalue; @@ -375,13 +364,13 @@ PyObject* KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUT PyObject* KX_LightObject::pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_LightObject* self = static_cast(self_v); - return PyInt_FromLong(self->m_lightobj.m_type); + return PyLong_FromSsize_t(self->m_lightobj.m_type); } int KX_LightObject::pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value) { KX_LightObject* self = static_cast(self_v); - int val = PyInt_AsLong(value); + int val = PyLong_AsSsize_t(value); if((val==-1 && PyErr_Occurred()) || val<0 || val>2) { PyErr_SetString(PyExc_ValueError, "light.type= val: KX_LightObject, expected an int between 0 and 2"); return PY_SET_ATTR_FAIL; @@ -401,14 +390,3 @@ int KX_LightObject::pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attr return PY_SET_ATTR_SUCCESS; } - - -PyObject* KX_LightObject::py_getattro(PyObject *attr) -{ - py_getattro_up(KX_GameObject); -} - -int KX_LightObject::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(KX_GameObject); -} diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index 358c705080a..0b7ccbe81ab 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -49,7 +49,7 @@ protected: Scene* m_blenderscene; public: - KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,class RAS_IRenderTools* rendertools,const struct RAS_LightObject& lightobj, bool glsl, PyTypeObject *T = &Type); + KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,class RAS_IRenderTools* rendertools,const struct RAS_LightObject& lightobj, bool glsl); virtual ~KX_LightObject(); virtual CValue* GetReplica(); RAS_LightObject* GetLightData() { return &m_lightobj;} @@ -64,10 +64,6 @@ public: void BindShadowBuffer(class RAS_IRasterizer *ras, class KX_Camera *cam, class MT_Transform& camtrans); void UnbindShadowBuffer(class RAS_IRasterizer *ras); void Update(); - - virtual PyObject* py_getattro(PyObject *attr); /* lens, near, far, projection_matrix */ - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *pyvalue); /* attributes */ static PyObject* pyattr_get_color(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index 11effa1ca98..96e8f61e4c8 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -62,18 +62,15 @@ PyTypeObject KX_MeshProxy::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_MeshProxy::Parents[] = { - &KX_MeshProxy::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &CValue::Type, - &PyObjectPlus::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_MeshProxy::Methods[] = { @@ -106,24 +103,8 @@ void KX_MeshProxy::SetMeshModified(bool v) m_meshobj->SetMeshModified(v); } - -PyObject* KX_MeshProxy::py_getattro(PyObject *attr) -{ - py_getattro_up(CValue); -} - -PyObject* KX_MeshProxy::py_getattro_dict() { - py_getattro_dict_up(CValue); -} - -int KX_MeshProxy::py_setattro(PyObject *attr, PyObject* value) -{ - py_setattro_up(CValue); -} - - KX_MeshProxy::KX_MeshProxy(RAS_MeshObject* mesh) - : CValue(&Type), m_meshobj(mesh) + : CValue(), m_meshobj(mesh) { } @@ -150,14 +131,14 @@ PyObject* KX_MeshProxy::PyGetNumMaterials(PyObject* args, PyObject* kwds) { int num = m_meshobj->NumMaterials(); ShowDeprecationWarning("getNumMaterials()", "the numMaterials property"); - return PyInt_FromLong(num); + return PyLong_FromSsize_t(num); } PyObject* KX_MeshProxy::PyGetNumPolygons() { int num = m_meshobj->NumPolygons(); ShowDeprecationWarning("getNumPolygons()", "the numPolygons property"); - return PyInt_FromLong(num); + return PyLong_FromSsize_t(num); } PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* args, PyObject* kwds) @@ -173,7 +154,7 @@ PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* args, PyObject* kwds) return NULL; } - return PyString_FromString(matname.Ptr()); + return PyUnicode_FromString(matname.Ptr()); } @@ -191,7 +172,7 @@ PyObject* KX_MeshProxy::PyGetTextureName(PyObject* args, PyObject* kwds) return NULL; } - return PyString_FromString(matname.Ptr()); + return PyUnicode_FromString(matname.Ptr()); } @@ -214,7 +195,7 @@ PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* args, PyObject* kwds) length = m_meshobj->NumVertices(mat); } - return PyInt_FromLong(length); + return PyLong_FromSsize_t(length); } @@ -304,12 +285,12 @@ PyObject* KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_ PyObject * KX_MeshProxy::pyattr_get_numMaterials(void * selfv, const KX_PYATTRIBUTE_DEF * attrdef) { KX_MeshProxy * self = static_cast (selfv); - return PyInt_FromLong(self->m_meshobj->NumMaterials()); + return PyLong_FromSsize_t(self->m_meshobj->NumMaterials()); } PyObject * KX_MeshProxy::pyattr_get_numPolygons(void * selfv, const KX_PYATTRIBUTE_DEF * attrdef) { KX_MeshProxy * self = static_cast (selfv); - return PyInt_FromLong(self->m_meshobj->NumPolygons()); + return PyLong_FromSsize_t(self->m_meshobj->NumPolygons()); } /* a close copy of ConvertPythonToGameObject but for meshes */ @@ -332,13 +313,13 @@ bool ConvertPythonToMesh(PyObject * value, RAS_MeshObject **object, bool py_none } } - if (PyString_Check(value)) { - *object = (RAS_MeshObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String( PyString_AsString(value) )); + if (PyUnicode_Check(value)) { + *object = (RAS_MeshObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String( _PyUnicode_AsString(value) )); if (*object) { return true; } else { - PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_MeshProxy in this scene", error_prefix, PyString_AsString(value)); + PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_MeshProxy in this scene", error_prefix, _PyUnicode_AsString(value)); return false; } } diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h index bfdd4be4118..4b6543677ad 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.h +++ b/source/gameengine/Ketsji/KX_MeshProxy.h @@ -56,9 +56,6 @@ public: virtual CValue* GetReplica(); // stuff for python integration - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); KX_PYMETHOD(KX_MeshProxy,GetNumMaterials); // Deprecated KX_PYMETHOD(KX_MeshProxy,GetMaterialName); diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index fde10a493db..ba4b47cb03f 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -63,9 +63,8 @@ KX_MouseFocusSensor::KX_MouseFocusSensor(SCA_MouseManager* eventmgr, int focusmode, KX_Scene* kxscene, KX_KetsjiEngine *kxengine, - SCA_IObject* gameobj, - PyTypeObject* T) - : SCA_MouseSensor(eventmgr, startx, starty, mousemode, gameobj, T), + SCA_IObject* gameobj) + : SCA_MouseSensor(eventmgr, startx, starty, mousemode, gameobj), m_focusmode(focusmode), m_kxscene(kxscene), m_kxengine(kxengine) @@ -356,20 +355,15 @@ PyTypeObject KX_MouseFocusSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_MouseFocusSensor::Parents[] = { - &KX_MouseFocusSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_MouseSensor::Type, - &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_MouseFocusSensor::Methods[] = { @@ -393,15 +387,6 @@ PyAttributeDef KX_MouseFocusSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_MouseFocusSensor::py_getattro(PyObject *attr) { - py_getattro_up(SCA_MouseSensor); -} - -PyObject* KX_MouseFocusSensor::py_getattro_dict() { - py_getattro_dict_up(SCA_MouseSensor); -} - - const char KX_MouseFocusSensor::GetHitObject_doc[] = "getHitObject()\n" "\tReturns the object that was hit by this ray.\n"; diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h index 29d674eb305..dfada7a59cc 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h @@ -56,8 +56,7 @@ class KX_MouseFocusSensor : public SCA_MouseSensor int focusmode, KX_Scene* kxscene, KX_KetsjiEngine* kxengine, - SCA_IObject* gameobj, - PyTypeObject* T=&Type ); + SCA_IObject* gameobj); virtual ~KX_MouseFocusSensor() { ; }; virtual CValue* GetReplica() { @@ -89,8 +88,6 @@ class KX_MouseFocusSensor : public SCA_MouseSensor /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetRayTarget); KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetRaySource); diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp index 44842b7f5b3..1a211a64b35 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.cpp +++ b/source/gameengine/Ketsji/KX_NearSensor.cpp @@ -48,15 +48,13 @@ KX_NearSensor::KX_NearSensor(SCA_EventManager* eventmgr, bool bFindMaterial, const STR_String& touchedpropname, class KX_Scene* scene, - PHY_IPhysicsController* ctrl, - PyTypeObject* T) + PHY_IPhysicsController* ctrl) :KX_TouchSensor(eventmgr, gameobj, bFindMaterial, false, - touchedpropname, - /* scene, */ - T), + touchedpropname + /*, scene */), m_Margin(margin), m_ResetMargin(resetmargin) @@ -272,26 +270,17 @@ PyTypeObject KX_NearSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - - - -PyParentObject KX_NearSensor::Parents[] = { - &KX_NearSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &KX_TouchSensor::Type, - &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - - PyMethodDef KX_NearSensor::Methods[] = { //No methods {NULL,NULL} //Sentinel @@ -302,18 +291,3 @@ PyAttributeDef KX_NearSensor::Attributes[] = { KX_PYATTRIBUTE_FLOAT_RW_CHECK("resetDistance", 0, 100, KX_NearSensor, m_ResetMargin, CheckResetDistance), {NULL} //Sentinel }; - - -PyObject* KX_NearSensor::py_getattro(PyObject *attr) -{ - py_getattro_up(KX_TouchSensor); -} - -PyObject* KX_NearSensor::py_getattro_dict() { - py_getattro_dict_up(KX_TouchSensor); -} - -int KX_NearSensor::py_setattro(PyObject*attr, PyObject* value) -{ - py_setattro_up(KX_TouchSensor); -} diff --git a/source/gameengine/Ketsji/KX_NearSensor.h b/source/gameengine/Ketsji/KX_NearSensor.h index 63099e181a0..f3c1d74805c 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.h +++ b/source/gameengine/Ketsji/KX_NearSensor.h @@ -54,8 +54,7 @@ public: bool bFindMaterial, const STR_String& touchedpropname, class KX_Scene* scene, - PHY_IPhysicsController* ctrl, - PyTypeObject* T=&Type); + PHY_IPhysicsController* ctrl); /* public: KX_NearSensor(class SCA_EventManager* eventmgr, @@ -64,8 +63,7 @@ public: double resetmargin, bool bFindMaterial, const STR_String& touchedpropname, - class KX_Scene* scene, - PyTypeObject* T=&Type); + class KX_Scene* scene); */ virtual ~KX_NearSensor(); virtual void SynchronizeTransform(); @@ -83,9 +81,6 @@ public: /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); //No methods diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index eaae04d406d..ae340d12be4 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -53,10 +53,9 @@ KX_ObjectActuator( const MT_Vector3& linV, const MT_Vector3& angV, const short damping, - const KX_LocalFlags& flag, - PyTypeObject* T + const KX_LocalFlags& flag ) : - SCA_IActuator(gameobj,T), + SCA_IActuator(gameobj), m_force(force), m_torque(torque), m_dloc(dloc), @@ -342,19 +341,15 @@ PyTypeObject KX_ObjectActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_ObjectActuator::Parents[] = { - &KX_ObjectActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_ObjectActuator::Methods[] = { @@ -396,9 +391,14 @@ PyAttributeDef KX_ObjectActuator::Attributes[] = { KX_PYATTRIBUTE_BOOL_RW("useLocalDLoc", KX_ObjectActuator, m_bitLocalFlag.DLoc), KX_PYATTRIBUTE_VECTOR_RW_CHECK("dRot", -1000, 1000, false, KX_ObjectActuator, m_drot, PyUpdateFuzzyFlags), KX_PYATTRIBUTE_BOOL_RW("useLocalDRot", KX_ObjectActuator, m_bitLocalFlag.DRot), +#ifdef USE_MATHUTILS + KX_PYATTRIBUTE_RW_FUNCTION("linV", KX_ObjectActuator, pyattr_get_linV, pyattr_set_linV), + KX_PYATTRIBUTE_RW_FUNCTION("angV", KX_ObjectActuator, pyattr_get_angV, pyattr_set_angV), +#else KX_PYATTRIBUTE_VECTOR_RW_CHECK("linV", -1000, 1000, false, KX_ObjectActuator, m_linear_velocity, PyUpdateFuzzyFlags), - KX_PYATTRIBUTE_BOOL_RW("useLocalLinV", KX_ObjectActuator, m_bitLocalFlag.LinearVelocity), KX_PYATTRIBUTE_VECTOR_RW_CHECK("angV", -1000, 1000, false, KX_ObjectActuator, m_angular_velocity, PyUpdateFuzzyFlags), +#endif + KX_PYATTRIBUTE_BOOL_RW("useLocalLinV", KX_ObjectActuator, m_bitLocalFlag.LinearVelocity), KX_PYATTRIBUTE_BOOL_RW("useLocalAngV", KX_ObjectActuator, m_bitLocalFlag.AngularVelocity), KX_PYATTRIBUTE_SHORT_RW("damping", 0, 1000, false, KX_ObjectActuator, m_damping), KX_PYATTRIBUTE_RW_FUNCTION("forceLimitX", KX_ObjectActuator, pyattr_get_forceLimitX, pyattr_set_forceLimitX), @@ -409,22 +409,131 @@ PyAttributeDef KX_ObjectActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_ObjectActuator::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IActuator); -} - - -PyObject* KX_ObjectActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_ObjectActuator::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_IActuator); -} - /* Attribute get/set functions */ +#ifdef USE_MATHUTILS + +/* These require an SGNode */ +#define MATHUTILS_VEC_CB_LINV 1 +#define MATHUTILS_VEC_CB_ANGV 2 + +static int mathutils_kxobactu_vector_cb_index= -1; /* index for our callbacks */ + +static int mathutils_obactu_generic_check(PyObject *self_v) +{ + KX_ObjectActuator* self= static_castBGE_PROXY_REF(self_v); + if(self==NULL) + return 0; + + return 1; +} + +static int mathutils_obactu_vector_get(PyObject *self_v, int subtype, float *vec_from) +{ + KX_ObjectActuator* self= static_castBGE_PROXY_REF(self_v); + if(self==NULL) + return 0; + + switch(subtype) { + case MATHUTILS_VEC_CB_LINV: + self->m_linear_velocity.getValue(vec_from); + break; + case MATHUTILS_VEC_CB_ANGV: + self->m_angular_velocity.getValue(vec_from); + break; + } + + return 1; +} + +static int mathutils_obactu_vector_set(PyObject *self_v, int subtype, float *vec_to) +{ + KX_ObjectActuator* self= static_castBGE_PROXY_REF(self_v); + if(self==NULL) + return 0; + + switch(subtype) { + case MATHUTILS_VEC_CB_LINV: + self->m_linear_velocity.setValue(vec_to); + break; + case MATHUTILS_VEC_CB_ANGV: + self->m_angular_velocity.setValue(vec_to); + break; + } + + return 1; +} + +static int mathutils_obactu_vector_get_index(PyObject *self_v, int subtype, float *vec_from, int index) +{ + float f[4]; + /* lazy, avoid repeteing the case statement */ + if(!mathutils_obactu_vector_get(self_v, subtype, f)) + return 0; + + vec_from[index]= f[index]; + return 1; +} + +static int mathutils_obactu_vector_set_index(PyObject *self_v, int subtype, float *vec_to, int index) +{ + float f= vec_to[index]; + + /* lazy, avoid repeteing the case statement */ + if(!mathutils_obactu_vector_get(self_v, subtype, vec_to)) + return 0; + + vec_to[index]= f; + mathutils_obactu_vector_set(self_v, subtype, vec_to); + + return 1; +} + +Mathutils_Callback mathutils_obactu_vector_cb = { + mathutils_obactu_generic_check, + mathutils_obactu_vector_get, + mathutils_obactu_vector_set, + mathutils_obactu_vector_get_index, + mathutils_obactu_vector_set_index +}; + +PyObject* KX_ObjectActuator::pyattr_get_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV); +} + +int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_ObjectActuator* self= static_cast(self_v); + if (!PyVecTo(value, self->m_linear_velocity)) + return PY_SET_ATTR_FAIL; + + return PY_SET_ATTR_SUCCESS; +} + +PyObject* KX_ObjectActuator::pyattr_get_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV); +} + +int KX_ObjectActuator::pyattr_set_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_ObjectActuator* self= static_cast(self_v); + if (!PyVecTo(value, self->m_angular_velocity)) + return PY_SET_ATTR_FAIL; + + return PY_SET_ATTR_SUCCESS; +} + + +void KX_ObjectActuator_Mathutils_Callback_Init(void) +{ + // register mathutils callbacks, ok to run more then once. + mathutils_kxobactu_vector_cb_index= Mathutils_RegisterCallback(&mathutils_obactu_vector_cb); +} + +#endif // USE_MATHUTILS + PyObject* KX_ObjectActuator::pyattr_get_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_ObjectActuator* self = reinterpret_cast(self_v); @@ -446,7 +555,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitX(void *self_v, const KX_PYATTRIBUTE { self->m_drot[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)); self->m_dloc[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)); - self->m_bitLocalFlag.Torque = (PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0); + self->m_bitLocalFlag.Torque = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0); if (!PyErr_Occurred()) { @@ -482,7 +591,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitY(void *self_v, const KX_PYATTRIBUTE { self->m_drot[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)); self->m_dloc[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)); - self->m_bitLocalFlag.DLoc = (PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0); + self->m_bitLocalFlag.DLoc = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0); if (!PyErr_Occurred()) { @@ -518,7 +627,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitZ(void *self_v, const KX_PYATTRIBUTE { self->m_drot[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)); self->m_dloc[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)); - self->m_bitLocalFlag.DRot = (PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0); + self->m_bitLocalFlag.DRot = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0); if (!PyErr_Occurred()) { diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h index f9bd2a0c748..20aec9e0e86 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.h +++ b/source/gameengine/Ketsji/KX_ObjectActuator.h @@ -35,6 +35,10 @@ #include "SCA_IActuator.h" #include "MT_Vector3.h" +#ifdef USE_MATHUTILS +void KX_ObjectActuator_Mathutils_Callback_Init(void); +#endif + class KX_GameObject; // @@ -131,8 +135,7 @@ public: const MT_Vector3& linV, const MT_Vector3& angV, const short damping, - const KX_LocalFlags& flag, - PyTypeObject* T=&Type + const KX_LocalFlags& flag ); ~KX_ObjectActuator(); CValue* GetReplica(); @@ -159,10 +162,6 @@ public: /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForce); KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetForce); @@ -197,6 +196,13 @@ public: static PyObject* pyattr_get_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); +#ifdef USE_MATHUTILS + static PyObject* pyattr_get_linV(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_linV(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_angV(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_angV(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); +#endif + // This lets the attribute macros use UpdateFuzzyFlags() static int PyUpdateFuzzyFlags(void *self, const PyAttributeDef *attrdef) { diff --git a/source/gameengine/Ketsji/KX_OdePhysicsController.cpp b/source/gameengine/Ketsji/KX_OdePhysicsController.cpp deleted file mode 100644 index dc6990267d4..00000000000 --- a/source/gameengine/Ketsji/KX_OdePhysicsController.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * The contents of this file may be used under the terms of either the GNU - * General Public License Version 2 or later (the "GPL", see - * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or - * later (the "BL", see http://www.blender.org/BL/ ) which has to be - * bought from the Blender Foundation to become active, in which case the - * above mentioned GPL option does not apply. - * - * The Original Code is Copyright (C) 2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#include "KX_ConvertPhysicsObject.h" - -#ifdef USE_ODE - -#include "KX_OdePhysicsController.h" -#include "KX_GameObject.h" -#include "KX_MotionState.h" - -#include "MT_assert.h" - -#include "PHY_IPhysicsEnvironment.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -KX_OdePhysicsController::KX_OdePhysicsController( - bool dyna, - bool fullRigidBody, - bool phantom, - class PHY_IMotionState* motionstate, - struct dxSpace* space, - struct dxWorld* world, - float mass, - float friction, - float restitution, - bool implicitsphere, - float center[3], - float extends[3], - float radius - ) -: KX_IPhysicsController(dyna,false,(PHY_IPhysicsController*)this), -ODEPhysicsController( -dyna,fullRigidBody,phantom,motionstate, -space,world,mass,friction,restitution, -implicitsphere,center,extends,radius) -{ -}; - - -bool KX_OdePhysicsController::Update(double time) -{ - return SynchronizeMotionStates(time); -} - -void KX_OdePhysicsController::SetObject (SG_IObject* object) -{ - SG_Controller::SetObject(object); - - // cheating here... - KX_GameObject* gameobj = (KX_GameObject*) object->GetSGClientObject(); - gameobj->SetPhysicsController(this); - -} - - - -void KX_OdePhysicsController::applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse) -{ - ODEPhysicsController::applyImpulse(attach[0],attach[1],attach[2],impulse[0],impulse[1],impulse[2]); -} - - - -void KX_OdePhysicsController::RelativeTranslate(const MT_Vector3& dloc,bool local) -{ - ODEPhysicsController::RelativeTranslate(dloc[0],dloc[1],dloc[2],local); - -} -void KX_OdePhysicsController::RelativeRotate(const MT_Matrix3x3& drot,bool local) -{ - double oldmat[12]; - drot.getValue(oldmat); - float newmat[9]; - float *m = &newmat[0]; - double *orgm = &oldmat[0]; - - *m++ = *orgm++;*m++ = *orgm++;*m++ = *orgm++;orgm++; - *m++ = *orgm++;*m++ = *orgm++;*m++ = *orgm++;orgm++; - *m++ = *orgm++;*m++ = *orgm++;*m++ = *orgm++;orgm++; - - ODEPhysicsController::RelativeRotate(newmat,local); - -} - -void KX_OdePhysicsController::ApplyTorque(const MT_Vector3& torque,bool local) -{ - ODEPhysicsController::ApplyTorque(torque[0],torque[1],torque[2],local); - -} -void KX_OdePhysicsController::ApplyForce(const MT_Vector3& force,bool local) -{ - ODEPhysicsController::ApplyForce(force[0],force[1],force[2],local); - -} -MT_Vector3 KX_OdePhysicsController::GetLinearVelocity() -{ - return MT_Vector3(0,0,0); -} - -MT_Vector3 KX_OdePhysicsController::GetVelocity(const MT_Point3& pos) -{ - return MT_Vector3(0,0,0); -} - -void KX_OdePhysicsController::SetAngularVelocity(const MT_Vector3& ang_vel,bool local) -{ - -} -void KX_OdePhysicsController::SetLinearVelocity(const MT_Vector3& lin_vel,bool local) -{ - ODEPhysicsController::SetLinearVelocity(lin_vel[0],lin_vel[1],lin_vel[2],local); -} - -void KX_OdePhysicsController::setOrientation(const MT_Matrix3x3& rot) -{ - MT_Quaternion orn = rot.getRotation(); - ODEPhysicsController::setOrientation(orn[0],orn[1],orn[2],orn[3]); -} - -void KX_OdePhysicsController::getOrientation(MT_Quaternion& orn) -{ - float florn[4]; - florn[0]=orn[0]; - florn[1]=orn[1]; - florn[2]=orn[2]; - florn[3]=orn[3]; - ODEPhysicsController::getOrientation(florn[0],florn[1],florn[2],florn[3]); - orn[0] = florn[0]; - orn[1] = florn[1]; - orn[2] = florn[2]; - orn[3] = florn[3]; - - -} - -void KX_OdePhysicsController::setPosition(const MT_Point3& pos) -{ - ODEPhysicsController::setPosition(pos[0],pos[1],pos[2]); -} - -void KX_OdePhysicsController::setScaling(const MT_Vector3& scaling) -{ -} - -MT_Scalar KX_OdePhysicsController::GetMass() -{ - return ODEPhysicsController::getMass(); -} - -MT_Scalar KX_OdePhysicsController::GetRadius() -{ - return MT_Scalar(0.f); -} - -MT_Vector3 KX_OdePhysicsController::getReactionForce() -{ - return MT_Vector3(0,0,0); -} -void KX_OdePhysicsController::setRigidBody(bool rigid) -{ - -} - -void KX_OdePhysicsController::SuspendDynamics(bool) -{ - ODEPhysicsController::SuspendDynamics(); -} -void KX_OdePhysicsController::RestoreDynamics() -{ - ODEPhysicsController::RestoreDynamics(); -} - - -SG_Controller* KX_OdePhysicsController::GetReplica(class SG_Node* destnode) -{ - PHY_IMotionState* motionstate = new KX_MotionState(destnode); - KX_OdePhysicsController* copyctrl = new KX_OdePhysicsController(*this); - - // nlin: copied from KX_SumoPhysicsController.cpp. Not 100% sure what this does.... - // furthermore, the parentctrl is not used in ODEPhysicsController::PostProcessReplica, but - // maybe it can/should be used in the future... - - // begin copy block ------------------------------------------------------------------ - - //parentcontroller is here be able to avoid collisions between parent/child - - PHY_IPhysicsController* parentctrl = NULL; - - if (destnode != destnode->GetRootSGParent()) - { - KX_GameObject* clientgameobj = (KX_GameObject*) destnode->GetRootSGParent()->GetSGClientObject(); - if (clientgameobj) - { - parentctrl = (KX_OdePhysicsController*)clientgameobj->GetPhysicsController(); - } else - { - // it could be a false node, try the children - NodeList::const_iterator childit; - for ( - childit = destnode->GetSGChildren().begin(); - childit!= destnode->GetSGChildren().end(); - ++childit - ) { - KX_GameObject* clientgameobj = static_cast( (*childit)->GetSGClientObject()); - if (clientgameobj) - { - parentctrl = (KX_OdePhysicsController*)clientgameobj->GetPhysicsController(); - } - } - } - } - // end copy block ------------------------------------------------------------------ - - copyctrl->PostProcessReplica(motionstate, this); - - return copyctrl; - -} - -void KX_OdePhysicsController::resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ) -{ -} - - -void KX_OdePhysicsController::SetSumoTransform(bool nondynaonly) -{ - -} - // todo: remove next line ! -void KX_OdePhysicsController::SetSimulatedTime(double time) -{ - -} - -#endif //USE_ODE diff --git a/source/gameengine/Ketsji/KX_OdePhysicsController.h b/source/gameengine/Ketsji/KX_OdePhysicsController.h deleted file mode 100644 index 8c3974c38a3..00000000000 --- a/source/gameengine/Ketsji/KX_OdePhysicsController.h +++ /dev/null @@ -1,109 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * The contents of this file may be used under the terms of either the GNU - * General Public License Version 2 or later (the "GPL", see - * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or - * later (the "BL", see http://www.blender.org/BL/ ) which has to be - * bought from the Blender Foundation to become active, in which case the - * above mentioned GPL option does not apply. - * - * The Original Code is Copyright (C) 2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef __KX_ODEPHYSICSCONTROLLER_H -#define __KX_ODEPHYSICSCONTROLLER_H - -#include "KX_IPhysicsController.h" -#include "OdePhysicsController.h" - -/** - Physics Controller, a special kind of Scene Graph Transformation Controller. - It get's callbacks from Physics in case a transformation change took place. - Each time the scene graph get's updated, the controller get's a chance - in the 'Update' method to reflect changed. -*/ - -class KX_OdePhysicsController : public KX_IPhysicsController, public ODEPhysicsController - -{ - -public: - KX_OdePhysicsController( - bool dyna, - bool fullRigidBody, - bool phantom, - class PHY_IMotionState* motionstate, - struct dxSpace* space, - struct dxWorld* world, - float mass, - float friction, - float restitution, - bool implicitsphere, - float center[3], - float extends[3], - float radius); - - virtual ~KX_OdePhysicsController() {}; - - virtual void applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse); - virtual void SetObject (SG_IObject* object); - - virtual void RelativeTranslate(const MT_Vector3& dloc,bool local); - virtual void RelativeRotate(const MT_Matrix3x3& drot,bool local); - virtual void ApplyTorque(const MT_Vector3& torque,bool local); - virtual void ApplyForce(const MT_Vector3& force,bool local); - virtual MT_Vector3 GetLinearVelocity(); - virtual MT_Vector3 GetVelocity(const MT_Point3& pos); - virtual void SetAngularVelocity(const MT_Vector3& ang_vel,bool local); - virtual void SetLinearVelocity(const MT_Vector3& lin_vel,bool local); - virtual void resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ); - virtual void getOrientation(MT_Quaternion& orn); - virtual void setOrientation(const MT_Matrix3x3& orn); - virtual void setPosition(const MT_Point3& pos); - virtual void setScaling(const MT_Vector3& scaling); - virtual void SetTransform() {} - virtual MT_Scalar GetMass(); - virtual MT_Vector3 getReactionForce(); - virtual void setRigidBody(bool rigid); - virtual void AddCompoundChild(KX_IPhysicsController* child) { } - virtual void RemoveCompoundChild(KX_IPhysicsController* child) { } - - virtual void SuspendDynamics(bool); - virtual void RestoreDynamics(); - virtual MT_Scalar GetRadius(); - - virtual SG_Controller* GetReplica(class SG_Node* destnode); - - virtual float GetLinVelocityMin() { return ODEPhysicsController::GetLinVelocityMin(); } - virtual void SetLinVelocityMin(float val) { ODEPhysicsController::SetLinVelocityMin(val); } - virtual float GetLinVelocityMax() { return ODEPhysicsController::GetLinVelocityMax(); } - virtual void SetLinVelocityMax(float val) { ODEPhysicsController::SetLinVelocityMax(val); } - - virtual void SetSumoTransform(bool nondynaonly); - // todo: remove next line ! - virtual void SetSimulatedTime(double time); - - // call from scene graph to update - virtual bool Update(double time); - - void - SetOption( - int option, - int value - ){ - // intentionally empty - }; - -}; - -#endif //__KX_ODEPHYSICSCONTROLLER_H - diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index cd2ed456c48..befa2aaff56 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -50,9 +50,8 @@ KX_ParentActuator::KX_ParentActuator(SCA_IObject *gameobj, int mode, bool addToCompound, bool ghost, - SCA_IObject *ob, - PyTypeObject* T) - : SCA_IActuator(gameobj, T), + SCA_IObject *ob) + : SCA_IActuator(gameobj), m_mode(mode), m_addToCompound(addToCompound), m_ghost(ghost), @@ -157,19 +156,15 @@ PyTypeObject KX_ParentActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_ParentActuator::Parents[] = { - &KX_ParentActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_ParentActuator::Methods[] = { @@ -217,18 +212,6 @@ int KX_ParentActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE } -PyObject* KX_ParentActuator::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_ParentActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_ParentActuator::py_setattro(PyObject *attr, PyObject* value) { - py_setattro_up(SCA_IActuator); -} - /* Deprecated -----> */ /* 1. setObject */ const char KX_ParentActuator::SetObject_doc[] = @@ -273,7 +256,7 @@ PyObject* KX_ParentActuator::PyGetObject(PyObject* args) Py_RETURN_NONE; if (ret_name_only) - return PyString_FromString(m_ob->GetName().ReadPtr()); + return PyUnicode_FromString(m_ob->GetName().ReadPtr()); else return m_ob->GetProxy(); } diff --git a/source/gameengine/Ketsji/KX_ParentActuator.h b/source/gameengine/Ketsji/KX_ParentActuator.h index 148375e994c..aeb39eabf89 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.h +++ b/source/gameengine/Ketsji/KX_ParentActuator.h @@ -68,8 +68,7 @@ class KX_ParentActuator : public SCA_IActuator int mode, bool addToCompound, bool ghost, - SCA_IObject *ob, - PyTypeObject* T=&Type); + SCA_IObject *ob); virtual ~KX_ParentActuator(); virtual bool Update(); @@ -82,10 +81,6 @@ class KX_ParentActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); - /* These are used to get and set m_ob */ static PyObject* pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp index c968e50957e..7bce311f1b6 100644 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp +++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp @@ -39,8 +39,8 @@ KX_PhysicsObjectWrapper::KX_PhysicsObjectWrapper( PHY_IPhysicsController* ctrl, - PHY_IPhysicsEnvironment* physenv,PyTypeObject *T) : - PyObjectPlus(T), + PHY_IPhysicsEnvironment* physenv) : + PyObjectPlus(), m_ctrl(ctrl), m_physenv(physenv) { @@ -129,46 +129,17 @@ PyTypeObject KX_PhysicsObjectWrapper::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new }; -PyParentObject KX_PhysicsObjectWrapper::Parents[] = { - &KX_PhysicsObjectWrapper::Type, - NULL -}; - -PyObject* KX_PhysicsObjectWrapper::py_getattro(PyObject *attr) -{ - py_getattro_up(PyObjectPlus); -} - -PyObject* KX_PhysicsObjectWrapper::py_getattro_dict() { - py_getattro_dict_up(PyObjectPlus); -} - -int KX_PhysicsObjectWrapper::py_setattro(PyObject *attr,PyObject *pyobj) -{ - int result = 1; - - if (PyInt_Check(pyobj)) - { - result = 0; - } - if (PyString_Check(pyobj)) - { - result = 0; - } - if (result) - result = PyObjectPlus::py_setattro(attr,pyobj); - - return result; -}; - - PyMethodDef KX_PhysicsObjectWrapper::Methods[] = { {"setPosition",(PyCFunction) KX_PhysicsObjectWrapper::sPySetPosition, METH_VARARGS}, {"setLinearVelocity",(PyCFunction) KX_PhysicsObjectWrapper::sPySetLinearVelocity, METH_VARARGS}, diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h index 1b59686babc..fa6fd1d1f2a 100644 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h +++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h @@ -35,12 +35,8 @@ class KX_PhysicsObjectWrapper : public PyObjectPlus { Py_Header; - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); public: - KX_PhysicsObjectWrapper(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type); + KX_PhysicsObjectWrapper(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsEnvironment* physenv); virtual ~KX_PhysicsObjectWrapper(); KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetPosition); diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp index b56b5500c39..a1571b17756 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.cpp +++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp @@ -55,18 +55,15 @@ PyTypeObject KX_PolyProxy::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_PolyProxy::Parents[] = { - &KX_PolyProxy::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &CValue::Type, - &PyObjectPlus::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_PolyProxy::Methods[] = { @@ -98,16 +95,17 @@ PyAttributeDef KX_PolyProxy::Attributes[] = { { NULL } //Sentinel }; +#if 0 PyObject* KX_PolyProxy::py_getattro(PyObject *attr) { - char *attr_str= PyString_AsString(attr); + char *attr_str= _PyUnicode_AsString(attr); if (!strcmp(attr_str, "matname")) { - return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName()); + return PyUnicode_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName()); } if (!strcmp(attr_str, "texture")) { - return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName()); + return PyUnicode_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName()); } if (!strcmp(attr_str, "material")) { @@ -136,38 +134,35 @@ PyObject* KX_PolyProxy::py_getattro(PyObject *attr) // found it break; } - return PyInt_FromLong(matid); + return PyLong_FromSsize_t(matid); } if (!strcmp(attr_str, "v1")) { - return PyInt_FromLong(m_polygon->GetVertexOffset(0)); + return PyLong_FromSsize_t(m_polygon->GetVertexOffset(0)); } if (!strcmp(attr_str, "v2")) { - return PyInt_FromLong(m_polygon->GetVertexOffset(1)); + return PyLong_FromSsize_t(m_polygon->GetVertexOffset(1)); } if (!strcmp(attr_str, "v3")) { - return PyInt_FromLong(m_polygon->GetVertexOffset(2)); + return PyLong_FromSsize_t(m_polygon->GetVertexOffset(2)); } if (!strcmp(attr_str, "v4")) { - return PyInt_FromLong(((m_polygon->VertexCount()>3)?m_polygon->GetVertexOffset(3):0)); + return PyLong_FromSsize_t(((m_polygon->VertexCount()>3)?m_polygon->GetVertexOffset(3):0)); } if (!strcmp(attr_str, "visible")) { - return PyInt_FromLong(m_polygon->IsVisible()); + return PyLong_FromSsize_t(m_polygon->IsVisible()); } if (!strcmp(attr_str, "collide")) { - return PyInt_FromLong(m_polygon->IsCollider()); + return PyLong_FromSsize_t(m_polygon->IsCollider()); } - py_getattro_up(CValue); -} - -PyObject* KX_PolyProxy::py_getattro_dict() { - py_getattro_dict_up(CValue); + // py_getattro_up(CValue); // XXX -- todo, make all these attributes } +#endif KX_PolyProxy::KX_PolyProxy(const RAS_MeshObject*mesh, RAS_Polygon* polygon) : m_polygon(polygon), @@ -204,37 +199,37 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialIndex, // found it break; } - return PyInt_FromLong(matid); + return PyLong_FromSsize_t(matid); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getNumVertex, "getNumVertex() : returns the number of vertex of the polygon, 3 or 4\n") { - return PyInt_FromLong(m_polygon->VertexCount()); + return PyLong_FromSsize_t(m_polygon->VertexCount()); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, isVisible, "isVisible() : returns whether the polygon is visible or not\n") { - return PyInt_FromLong(m_polygon->IsVisible()); + return PyLong_FromSsize_t(m_polygon->IsVisible()); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, isCollider, "isCollider() : returns whether the polygon is receives collision or not\n") { - return PyInt_FromLong(m_polygon->IsCollider()); + return PyLong_FromSsize_t(m_polygon->IsCollider()); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialName, "getMaterialName() : returns the polygon material name, \"NoMaterial\" if no material\n") { - return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName()); + return PyUnicode_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName()); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getTextureName, "getTexturelName() : returns the polygon texture name, \"NULL\" if no texture\n") { - return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName()); + return PyUnicode_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName()); } KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex, @@ -255,9 +250,9 @@ KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex, } if (index < m_polygon->VertexCount()) { - return PyInt_FromLong(m_polygon->GetVertexOffset(index)); + return PyLong_FromSsize_t(m_polygon->GetVertexOffset(index)); } - return PyInt_FromLong(0); + return PyLong_FromSsize_t(0); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMesh, diff --git a/source/gameengine/Ketsji/KX_PolyProxy.h b/source/gameengine/Ketsji/KX_PolyProxy.h index d8fd36fec6c..e619617d312 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.h +++ b/source/gameengine/Ketsji/KX_PolyProxy.h @@ -52,8 +52,6 @@ public: // stuff for python integration - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterialIndex) KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getNumVertex) diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index 506c167a905..9bc84127572 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -51,8 +51,8 @@ #include "KX_PyMath.h" -KX_PolygonMaterial::KX_PolygonMaterial(PyTypeObject *T) - : PyObjectPlus(T), +KX_PolygonMaterial::KX_PolygonMaterial() + : PyObjectPlus(), RAS_IPolyMaterial(), m_tface(NULL), @@ -115,7 +115,7 @@ bool KX_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingI PyObject *ret = PyObject_CallMethod(m_pymaterial, "activate", "(NNO)", pyRasty, pyCachingInfo, (PyObject*) this->m_proxy); if (ret) { - bool value = PyInt_AsLong(ret); + bool value = PyLong_AsSsize_t(ret); Py_DECREF(ret); dopass = value; } @@ -255,33 +255,17 @@ PyTypeObject KX_PolygonMaterial::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new }; -PyParentObject KX_PolygonMaterial::Parents[] = { - &KX_PolygonMaterial::Type, - &PyObjectPlus::Type, - NULL -}; - -PyObject* KX_PolygonMaterial::py_getattro(PyObject *attr) -{ - py_getattro_up(PyObjectPlus); -} - -PyObject* KX_PolygonMaterial::py_getattro_dict() { - py_getattro_dict_up(PyObjectPlus); -} - -int KX_PolygonMaterial::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(PyObjectPlus); -} - KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setCustomMaterial, "setCustomMaterial(material)") { PyObject *material; @@ -347,13 +331,13 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, activate, "activate(rasty, cachingInfo)") PyObject* KX_PolygonMaterial::pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_PolygonMaterial* self= static_cast(self_v); - return PyString_FromString(self->m_texturename.ReadPtr()); + return PyUnicode_FromString(self->m_texturename.ReadPtr()); } PyObject* KX_PolygonMaterial::pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_PolygonMaterial* self= static_cast(self_v); - return PyString_FromString(self->m_materialname.ReadPtr()); + return PyUnicode_FromString(self->m_materialname.ReadPtr()); } /* this does not seem useful */ @@ -370,7 +354,7 @@ PyObject* KX_PolygonMaterial::pyattr_get_gl_texture(void *self_v, const KX_PYATT if (self->m_tface && self->m_tface->tpage) bindcode= self->m_tface->tpage->bindcode; - return PyInt_FromLong(bindcode); + return PyLong_FromSsize_t(bindcode); } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index 89ecb026da9..266b4d7e789 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -57,7 +57,7 @@ private: mutable int m_pass; public: - KX_PolygonMaterial(PyTypeObject *T = &Type); + KX_PolygonMaterial(); void Initialize(const STR_String &texname, Material* ma, int materialindex, @@ -116,10 +116,7 @@ public: KX_PYMETHOD_DOC(KX_PolygonMaterial, setCustomMaterial); KX_PYMETHOD_DOC(KX_PolygonMaterial, loadProgram); - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *pyvalue); - virtual PyObject* py_repr(void) { return PyString_FromString(m_material ? ((ID *)m_material)->name+2 : ""); } + virtual PyObject* py_repr(void) { return PyUnicode_FromString(m_material ? ((ID *)m_material)->name+2 : ""); } static PyObject* pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index 4ec901a2f5e..94e8d1fd583 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -640,7 +640,7 @@ PyObject* initPythonConstraintBinding() // Add some symbolic constants to the module d = PyModule_GetDict(m); - ErrorObject = PyString_FromString("PhysicsConstraints.error"); + ErrorObject = PyUnicode_FromString("PhysicsConstraints.error"); PyDict_SetItemString(d, "error", ErrorObject); Py_DECREF(ErrorObject); diff --git a/source/gameengine/Ketsji/KX_PyMath.cpp b/source/gameengine/Ketsji/KX_PyMath.cpp index 051d7ae7dba..6d33c38190c 100644 --- a/source/gameengine/Ketsji/KX_PyMath.cpp +++ b/source/gameengine/Ketsji/KX_PyMath.cpp @@ -46,35 +46,6 @@ #include "KX_Python.h" #include "KX_PyMath.h" -bool PyObject_IsMT_Matrix(PyObject *pymat, unsigned int rank) -{ - if (!pymat) - return false; - - unsigned int y; - if (PySequence_Check(pymat)) - { - unsigned int rows = PySequence_Size(pymat); - if (rows != rank) - return false; - - bool ismatrix = true; - for (y = 0; y < rank && ismatrix; y++) - { - PyObject *pyrow = PySequence_GetItem(pymat, y); /* new ref */ - if (PySequence_Check(pyrow)) - { - if (((unsigned int)PySequence_Size(pyrow)) != rank) - ismatrix = false; - } else - ismatrix = false; - Py_DECREF(pyrow); - } - return ismatrix; - } - return false; -} - bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &rot, const char *error_prefix) { int size= PySequence_Size(pyval); @@ -82,7 +53,7 @@ bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &rot, const char *error_prefi if (size == 4) { MT_Quaternion qrot; - if (PyVecTo(pyval, qrot)) + if (PyQuatTo(pyval, qrot)) { rot.setRotation(qrot); return true; @@ -108,14 +79,27 @@ bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &rot, const char *error_prefi return false; } +bool PyQuatTo(PyObject* pyval, MT_Quaternion &qrot) +{ + if(!PyVecTo(pyval, qrot)) + return false; + + /* annoying!, Blender/Mathutils have the W axis first! */ + MT_Scalar w= qrot[0]; /* from python, this is actually the W */ + qrot[0]= qrot[1]; + qrot[1]= qrot[2]; + qrot[2]= qrot[3]; + qrot[3]= w; + + return true; +} + PyObject* PyObjectFrom(const MT_Matrix4x4 &mat) { -#if 0 - return Py_BuildValue("[[ffff][ffff][ffff][ffff]]", - mat[0][0], mat[0][1], mat[0][2], mat[0][3], - mat[1][0], mat[1][1], mat[1][2], mat[1][3], - mat[2][0], mat[2][1], mat[2][2], mat[2][3], - mat[3][0], mat[3][1], mat[3][2], mat[3][3]); +#ifdef USE_MATHUTILS + float fmat[16]; + mat.getValue(fmat); + return newMatrixObject(fmat, 4, 4, Py_NEW, NULL); #else PyObject *list = PyList_New(4); PyObject *sublist; @@ -136,11 +120,10 @@ PyObject* PyObjectFrom(const MT_Matrix4x4 &mat) PyObject* PyObjectFrom(const MT_Matrix3x3 &mat) { -#if 0 - return Py_BuildValue("[[fff][fff][fff]]", - mat[0][0], mat[0][1], mat[0][2], - mat[1][0], mat[1][1], mat[1][2], - mat[2][0], mat[2][1], mat[2][2]); +#ifdef USE_MATHUTILS + float fmat[9]; + mat.getValue3x3(fmat); + return newMatrixObject(fmat, 3, 3, Py_NEW, NULL); #else PyObject *list = PyList_New(3); PyObject *sublist; @@ -158,11 +141,20 @@ PyObject* PyObjectFrom(const MT_Matrix3x3 &mat) #endif } +#ifdef USE_MATHUTILS +PyObject* PyObjectFrom(const MT_Quaternion &qrot) +{ + /* NOTE, were re-ordering here for Mathutils compat */ + float fvec[4]= {qrot[3], qrot[0], qrot[1], qrot[2]}; + return newQuaternionObject(fvec, Py_WRAP, NULL); +} +#endif + PyObject* PyObjectFrom(const MT_Tuple4 &vec) { -#if 0 - return Py_BuildValue("[ffff]", - vec[0], vec[1], vec[2], vec[3]); +#ifdef USE_MATHUTILS + float fvec[4]= {vec[0], vec[1], vec[2], vec[3]}; + return newVectorObject(fvec, 4, Py_WRAP, NULL); #else PyObject *list = PyList_New(4); PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); @@ -175,9 +167,9 @@ PyObject* PyObjectFrom(const MT_Tuple4 &vec) PyObject* PyObjectFrom(const MT_Tuple3 &vec) { -#if 0 - return Py_BuildValue("[fff]", - vec[0], vec[1], vec[2]); +#ifdef USE_MATHUTILS + float fvec[3]= {vec[0], vec[1], vec[2]}; + return newVectorObject(fvec, 3, Py_WRAP, NULL); #else PyObject *list = PyList_New(3); PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); @@ -189,9 +181,9 @@ PyObject* PyObjectFrom(const MT_Tuple3 &vec) PyObject* PyObjectFrom(const MT_Tuple2 &vec) { -#if 0 - return Py_BuildValue("[ff]", - vec[0], vec[1]); +#ifdef USE_MATHUTILS + float fvec[2]= {vec[0], vec[1]}; + return newVectorObject(fvec, 2, Py_WRAP, NULL); #else PyObject *list = PyList_New(2); PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); diff --git a/source/gameengine/Ketsji/KX_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h index a7ce4bc6930..9ee11c9e745 100644 --- a/source/gameengine/Ketsji/KX_PyMath.h +++ b/source/gameengine/Ketsji/KX_PyMath.h @@ -42,6 +42,12 @@ #include "KX_Python.h" #include "PyObjectPlus.h" +#ifdef USE_MATHUTILS +extern "C" { +#include "../../blender/python/generic/Mathutils.h" /* so we can have mathutils callbacks */ +} +#endif + inline unsigned int Size(const MT_Matrix4x4&) { return 4; } inline unsigned int Size(const MT_Matrix3x3&) { return 3; } inline unsigned int Size(const MT_Tuple2&) { return 2; } @@ -98,7 +104,38 @@ bool PyMatTo(PyObject* pymat, T& mat) template bool PyVecTo(PyObject* pyval, T& vec) { - +#ifdef USE_MATHUTILS + /* no need for BaseMath_ReadCallback() here, reading the sequences will do this */ + + if(VectorObject_Check(pyval)) { + VectorObject *pyvec= (VectorObject *)pyval; + if (pyvec->size != Size(vec)) { + PyErr_Format(PyExc_AttributeError, "error setting vector, %d args, should be %d", pyvec->size, Size(vec)); + return false; + } + vec.getValue((float *) pyvec->vec); + return true; + } + else if(QuaternionObject_Check(pyval)) { + QuaternionObject *pyquat= (QuaternionObject *)pyval; + if (4 != Size(vec)) { + PyErr_Format(PyExc_AttributeError, "error setting vector, %d args, should be %d", 4, Size(vec)); + return false; + } + /* xyzw -> wxyz reordering is done by PyQuatTo */ + vec.getValue((float *) pyquat->quat); + return true; + } + else if(EulerObject_Check(pyval)) { + EulerObject *pyeul= (EulerObject *)pyval; + if (3 != Size(vec)) { + PyErr_Format(PyExc_AttributeError, "error setting vector, %d args, should be %d", 3, Size(vec)); + return false; + } + vec.getValue((float *) pyeul->eul); + return true; + } else +#endif if(PyTuple_Check(pyval)) { unsigned int numitems = PyTuple_GET_SIZE(pyval); @@ -117,7 +154,7 @@ bool PyVecTo(PyObject* pyval, T& vec) return true; } - else if (BGE_PROXY_CHECK_TYPE(pyval)) + else if (PyObject_TypeCheck(pyval, &PyObjectPlus::Type)) { /* note, include this check because PySequence_Check does too much introspection * on the PyObject (like getting its __class__, on a BGE type this means searching up * the parent list each time only to discover its not a sequence. @@ -159,6 +196,9 @@ bool PyVecTo(PyObject* pyval, T& vec) return false; } + +bool PyQuatTo(PyObject* pyval, MT_Quaternion &qrot); + bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &mat, const char *error_prefix); /** @@ -181,15 +221,16 @@ PyObject* PyObjectFrom(const MT_Tuple2 &vec); */ PyObject* PyObjectFrom(const MT_Tuple3 &vec); +#ifdef USE_MATHUTILS +/** + * Converts an MT_Quaternion to a python object. + */ +PyObject* PyObjectFrom(const MT_Quaternion &qrot); +#endif + /** * Converts an MT_Tuple4 to a python object. */ PyObject* PyObjectFrom(const MT_Tuple4 &pos); -/** - * True if the given PyObject can be converted to an MT_Matrix - * @param rank = 3 (for MT_Matrix3x3) or 4 (for MT_Matrix4x4) - */ -bool PyObject_IsMT_Matrix(PyObject *pymat, unsigned int rank); - #endif diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 736460d33db..eead7a51885 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -130,10 +130,10 @@ void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,cons } /* Macro for building the keyboard translation */ -//#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyInt_FromLong(SCA_IInputDevice::KX_##name)) -#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, item=PyInt_FromLong(name)); Py_DECREF(item) +//#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyLong_FromSsize_t(SCA_IInputDevice::KX_##name)) +#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, item=PyLong_FromSsize_t(name)); Py_DECREF(item) /* For the defines for types from logic bricks, we do stuff explicitly... */ -#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyInt_FromLong(name2)); Py_DECREF(item) +#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyLong_FromSsize_t(name2)); Py_DECREF(item) // temporarily python stuff, will be put in another place later ! @@ -181,7 +181,7 @@ static PyObject* gPyExpandPath(PyObject*, PyObject* args) BLI_strncpy(expanded, filename, FILE_MAXDIR + FILE_MAXFILE); BLI_convertstringcode(expanded, gp_GamePythonPath); - return PyString_FromString(expanded); + return PyUnicode_FromString(expanded); } static char gPySendMessage_doc[] = @@ -306,7 +306,7 @@ static PyObject* gPySetMaxLogicFrame(PyObject*, PyObject* args) static PyObject* gPyGetMaxLogicFrame(PyObject*) { - return PyInt_FromLong(KX_KetsjiEngine::GetMaxLogicFrame()); + return PyLong_FromSsize_t(KX_KetsjiEngine::GetMaxLogicFrame()); } static PyObject* gPySetMaxPhysicsFrame(PyObject*, PyObject* args) @@ -321,7 +321,7 @@ static PyObject* gPySetMaxPhysicsFrame(PyObject*, PyObject* args) static PyObject* gPyGetMaxPhysicsFrame(PyObject*) { - return PyInt_FromLong(KX_KetsjiEngine::GetMaxPhysicsFrame()); + return PyLong_FromSsize_t(KX_KetsjiEngine::GetMaxPhysicsFrame()); } static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args) @@ -386,7 +386,7 @@ static PyObject* gPyGetBlendFileList(PyObject*, PyObject* args) while ((dirp = readdir(dp)) != NULL) { if (BLI_testextensie(dirp->d_name, ".blend")) { - value = PyString_FromString(dirp->d_name); + value = PyUnicode_FromString(dirp->d_name); PyList_Append(list, value); Py_DECREF(value); } @@ -500,7 +500,7 @@ static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *) static PyObject *gEvalExpression(PyObject*, PyObject* value) { - char* txt= PyString_AsString(value); + char* txt= _PyUnicode_AsString(value); if (txt==NULL) { PyErr_SetString(PyExc_TypeError, "Expression.calc(text): expects a single string argument"); @@ -558,14 +558,14 @@ static struct PyMethodDef game_methods[] = { static PyObject* gPyGetWindowHeight(PyObject*, PyObject* args) { - return PyInt_FromLong((gp_Canvas ? gp_Canvas->GetHeight() : 0)); + return PyLong_FromSsize_t((gp_Canvas ? gp_Canvas->GetHeight() : 0)); } static PyObject* gPyGetWindowWidth(PyObject*, PyObject* args) { - return PyInt_FromLong((gp_Canvas ? gp_Canvas->GetWidth() : 0)); + return PyLong_FromSsize_t((gp_Canvas ? gp_Canvas->GetWidth() : 0)); } @@ -893,7 +893,7 @@ static PyObject* gPyGetGLSLMaterialSetting(PyObject*, } enabled = ((G.fileflags & flag) != 0); - return PyInt_FromLong(enabled); + return PyLong_FromSsize_t(enabled); } #define KX_TEXFACE_MATERIAL 0 @@ -937,7 +937,7 @@ static PyObject* gPyGetMaterialType(PyObject*) else flag = KX_TEXFACE_MATERIAL; - return PyInt_FromLong(flag); + return PyLong_FromSsize_t(flag); } static PyObject* gPyDrawLine(PyObject*, PyObject* args) @@ -1075,7 +1075,7 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack PyDict_SetItemString(d, "globalDict", item=PyDict_New()); Py_DECREF(item); - ErrorObject = PyString_FromString("GameLogic.error"); + ErrorObject = PyUnicode_FromString("GameLogic.error"); PyDict_SetItemString(d, "error", ErrorObject); Py_DECREF(ErrorObject); @@ -1362,7 +1362,7 @@ PyObject *KXpy_import(PyObject *self, PyObject *args) /* check for builtin modules */ m = PyImport_AddModule("sys"); l = PyObject_GetAttrString(m, "builtin_module_names"); - n = PyString_FromString(name); + n = PyUnicode_FromString(name); if (PySequence_Contains(l, n)) { return PyImport_ImportModuleEx(name, globals, locals, fromlist); @@ -1538,7 +1538,7 @@ static void initPySysObjects__append(PyObject *sys_path, char *filename) BLI_split_dirfile_basic(filename, expanded, NULL); /* get the dir part of filename only */ BLI_convertstringcode(expanded, gp_GamePythonPath); /* filename from lib->filename is (always?) absolute, so this may not be needed but it wont hurt */ BLI_cleanup_file(gp_GamePythonPath, expanded); /* Dont use BLI_cleanup_dir because it adds a slash - BREAKS WIN32 ONLY */ - item= PyString_FromString(expanded); + item= PyUnicode_FromString(expanded); // printf("SysPath - '%s', '%s', '%s'\n", expanded, filename, gp_GamePythonPath); @@ -1735,7 +1735,7 @@ PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas) // Add some symbolic constants to the module d = PyModule_GetDict(m); - ErrorObject = PyString_FromString("Rasterizer.error"); + ErrorObject = PyUnicode_FromString("Rasterizer.error"); PyDict_SetItemString(d, "error", ErrorObject); Py_DECREF(ErrorObject); @@ -1813,10 +1813,10 @@ static PyObject* gPyEventToCharacter(PyObject*, PyObject* args) if(IsPrintable(event)) { char ch[2] = {'\0', '\0'}; ch[0] = ToCharacter(event, (bool)shift); - return PyString_FromString(ch); + return PyUnicode_FromString(ch); } else { - return PyString_FromString(""); + return PyUnicode_FromString(""); } } @@ -2044,7 +2044,7 @@ int saveGamePythonConfig( char **marshal_buffer) char *marshal_cstring; #if PY_VERSION_HEX < 0x03000000 - marshal_cstring = PyString_AsString(pyGlobalDictMarshal); + marshal_cstring = _PyUnicode_AsString(pyGlobalDictMarshal); marshal_length= PyString_Size(pyGlobalDictMarshal); #else // py3 uses byte arrays marshal_cstring = PyBytes_AsString(pyGlobalDictMarshal); diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp index 83c4dcbb34c..8ff0bfd5379 100644 --- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp +++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp @@ -87,69 +87,54 @@ #include "SCA_RandomActuator.h" #include "SCA_IController.h" - -void initPyObjectPlusType(PyTypeObject **parents) -{ - int i; - - for (i=0; parents[i]; i++) { - if(PyType_Ready(parents[i]) < 0) { - /* This is very very unlikely */ - printf("Error, pytype could not initialize, Blender may crash \"%s\"\n", parents[i]->tp_name); - return; - } - -#if 0 - PyObject_Print(reinterpret_castparents[i], stderr, 0); - fprintf(stderr, "\n"); - PyObject_Print(parents[i]->tp_dict, stderr, 0); - fprintf(stderr, "\n\n"); -#endif - - } - - PyObject *dict= NULL; - - while(i) { - i--; - - if (dict) { - PyDict_Update(parents[i]->tp_dict, dict); - } - dict= parents[i]->tp_dict; - -#if 1 - PyObject_Print(reinterpret_cast(parents[i]), stderr, 0); - fprintf(stderr, "\n"); - PyObject_Print(parents[i]->tp_dict, stderr, 0); - fprintf(stderr, "\n\n"); -#endif - - } -} - - - - -static void PyType_Ready_ADD(PyObject *dict, PyTypeObject *tp, PyAttributeDef *attributes) +static void PyType_Ready_ADD(PyObject *dict, PyTypeObject *tp, PyAttributeDef *attributes, int init_getset) { PyAttributeDef *attr; - PyObject *item; + + if(init_getset) { + /* we need to do this for all types before calling PyType_Ready + * since they will call the parents PyType_Ready and those might not have initialized vars yet */ + + //if(tp->tp_base==NULL) + // printf("Debug: No Parents - '%s'\n" , tp->tp_name); + + if(tp->tp_getset==NULL && attributes->m_name) { + PyGetSetDef *attr_getset; + int attr_tot= 0; + + for(attr= attributes; attr->m_name; attr++, attr_tot++) {}; + + tp->tp_getset = attr_getset = reinterpret_cast(PyMem_Malloc((attr_tot+1) * sizeof(PyGetSetDef))); // XXX - Todo, free + + + for(attr= attributes; attr->m_name; attr++, attr_getset++) { + attr_getset->name= (char *)attr->m_name; + attr_getset->doc= NULL; + + attr_getset->get= reinterpret_cast(PyObjectPlus::py_get_attrdef); + + if(attr->m_access==KX_PYATTRIBUTE_RO) + attr_getset->set= NULL; + else + attr_getset->set= reinterpret_cast(PyObjectPlus::py_set_attrdef); + + attr_getset->closure= reinterpret_cast(attr); + } + + memset(attr_getset, 0, sizeof(PyGetSetDef)); + } + } else { - PyType_Ready(tp); - PyDict_SetItemString(dict, tp->tp_name, reinterpret_cast(tp)); - - /* store attr defs in the tp_dict for to avoid string lookups */ - for(attr= attributes; attr->m_name; attr++) { - item= PyCObject_FromVoidPtr(attr, NULL); - PyDict_SetItemString(tp->tp_dict, attr->m_name, item); - Py_DECREF(item); + PyObject *item; + + PyType_Ready(tp); + PyDict_SetItemString(dict, tp->tp_name, reinterpret_cast(tp)); } } -#define PyType_Ready_Attr(d, n) PyType_Ready_ADD(d, &n::Type, n::Attributes) +#define PyType_Ready_Attr(d, n, i) PyType_Ready_ADD(d, &n::Type, n::Attributes, i) void initPyTypes(void) { @@ -165,72 +150,82 @@ void initPyTypes(void) PyDict_SetItemString(PySys_GetObject((char *)"modules"), (char *)"GameTypes", mod); Py_DECREF(mod); - PyType_Ready_Attr(dict, BL_ActionActuator); - PyType_Ready_Attr(dict, BL_Shader); - PyType_Ready_Attr(dict, BL_ShapeActionActuator); - PyType_Ready_Attr(dict, CListValue); - PyType_Ready_Attr(dict, CValue); - PyType_Ready_Attr(dict, KX_BlenderMaterial); - PyType_Ready_Attr(dict, KX_CDActuator); - PyType_Ready_Attr(dict, KX_Camera); - PyType_Ready_Attr(dict, KX_CameraActuator); - PyType_Ready_Attr(dict, KX_ConstraintActuator); - PyType_Ready_Attr(dict, KX_ConstraintWrapper); - PyType_Ready_Attr(dict, KX_GameActuator); - PyType_Ready_Attr(dict, KX_GameObject); - PyType_Ready_Attr(dict, KX_IpoActuator); - PyType_Ready_Attr(dict, KX_LightObject); - PyType_Ready_Attr(dict, KX_MeshProxy); - PyType_Ready_Attr(dict, KX_MouseFocusSensor); - PyType_Ready_Attr(dict, KX_NearSensor); - PyType_Ready_Attr(dict, KX_NetworkMessageActuator); - PyType_Ready_Attr(dict, KX_NetworkMessageSensor); - PyType_Ready_Attr(dict, KX_ObjectActuator); - PyType_Ready_Attr(dict, KX_ParentActuator); - PyType_Ready_Attr(dict, KX_PhysicsObjectWrapper); - PyType_Ready_Attr(dict, KX_PolyProxy); - PyType_Ready_Attr(dict, KX_PolygonMaterial); - PyType_Ready_Attr(dict, KX_RadarSensor); - PyType_Ready_Attr(dict, KX_RaySensor); - PyType_Ready_Attr(dict, KX_SCA_AddObjectActuator); - PyType_Ready_Attr(dict, KX_SCA_DynamicActuator); - PyType_Ready_Attr(dict, KX_SCA_EndObjectActuator); - PyType_Ready_Attr(dict, KX_SCA_ReplaceMeshActuator); - PyType_Ready_Attr(dict, KX_Scene); - PyType_Ready_Attr(dict, KX_SceneActuator); - PyType_Ready_Attr(dict, KX_SoundActuator); - PyType_Ready_Attr(dict, KX_StateActuator); - PyType_Ready_Attr(dict, KX_TouchSensor); - PyType_Ready_Attr(dict, KX_TrackToActuator); - PyType_Ready_Attr(dict, KX_VehicleWrapper); - PyType_Ready_Attr(dict, KX_VertexProxy); - PyType_Ready_Attr(dict, KX_VisibilityActuator); - PyType_Ready_Attr(dict, PyObjectPlus); - PyType_Ready_Attr(dict, SCA_2DFilterActuator); - PyType_Ready_Attr(dict, SCA_ANDController); - PyType_Ready_Attr(dict, SCA_ActuatorSensor); - PyType_Ready_Attr(dict, SCA_AlwaysSensor); - PyType_Ready_Attr(dict, SCA_DelaySensor); - PyType_Ready_Attr(dict, SCA_ILogicBrick); - PyType_Ready_Attr(dict, SCA_IObject); - PyType_Ready_Attr(dict, SCA_ISensor); - PyType_Ready_Attr(dict, SCA_JoystickSensor); - PyType_Ready_Attr(dict, SCA_KeyboardSensor); - PyType_Ready_Attr(dict, SCA_MouseSensor); - PyType_Ready_Attr(dict, SCA_NANDController); - PyType_Ready_Attr(dict, SCA_NORController); - PyType_Ready_Attr(dict, SCA_ORController); - PyType_Ready_Attr(dict, SCA_PropertyActuator); - PyType_Ready_Attr(dict, SCA_PropertySensor); - PyType_Ready_Attr(dict, SCA_PythonController); - PyType_Ready_Attr(dict, SCA_RandomActuator); - PyType_Ready_Attr(dict, SCA_RandomSensor); - PyType_Ready_Attr(dict, SCA_XNORController); - PyType_Ready_Attr(dict, SCA_XORController); - PyType_Ready_Attr(dict, SCA_IController); + for(int init_getset= 1; init_getset > -1; init_getset--) { /* run twice, once to init the getsets another to run PyType_Ready */ + PyType_Ready_Attr(dict, BL_ActionActuator, init_getset); + PyType_Ready_Attr(dict, BL_Shader, init_getset); + PyType_Ready_Attr(dict, BL_ShapeActionActuator, init_getset); + PyType_Ready_Attr(dict, CListValue, init_getset); + PyType_Ready_Attr(dict, CValue, init_getset); + PyType_Ready_Attr(dict, KX_BlenderMaterial, init_getset); + PyType_Ready_Attr(dict, KX_CDActuator, init_getset); + PyType_Ready_Attr(dict, KX_Camera, init_getset); + PyType_Ready_Attr(dict, KX_CameraActuator, init_getset); + PyType_Ready_Attr(dict, KX_ConstraintActuator, init_getset); + PyType_Ready_Attr(dict, KX_ConstraintWrapper, init_getset); + PyType_Ready_Attr(dict, KX_GameActuator, init_getset); + PyType_Ready_Attr(dict, KX_GameObject, init_getset); + PyType_Ready_Attr(dict, KX_IpoActuator, init_getset); + PyType_Ready_Attr(dict, KX_LightObject, init_getset); + PyType_Ready_Attr(dict, KX_MeshProxy, init_getset); + PyType_Ready_Attr(dict, KX_MouseFocusSensor, init_getset); + PyType_Ready_Attr(dict, KX_NearSensor, init_getset); + PyType_Ready_Attr(dict, KX_NetworkMessageActuator, init_getset); + PyType_Ready_Attr(dict, KX_NetworkMessageSensor, init_getset); + PyType_Ready_Attr(dict, KX_ObjectActuator, init_getset); + PyType_Ready_Attr(dict, KX_ParentActuator, init_getset); + PyType_Ready_Attr(dict, KX_PhysicsObjectWrapper, init_getset); + PyType_Ready_Attr(dict, KX_PolyProxy, init_getset); + PyType_Ready_Attr(dict, KX_PolygonMaterial, init_getset); + PyType_Ready_Attr(dict, KX_RadarSensor, init_getset); + PyType_Ready_Attr(dict, KX_RaySensor, init_getset); + PyType_Ready_Attr(dict, KX_SCA_AddObjectActuator, init_getset); + PyType_Ready_Attr(dict, KX_SCA_DynamicActuator, init_getset); + PyType_Ready_Attr(dict, KX_SCA_EndObjectActuator, init_getset); + PyType_Ready_Attr(dict, KX_SCA_ReplaceMeshActuator, init_getset); + PyType_Ready_Attr(dict, KX_Scene, init_getset); + PyType_Ready_Attr(dict, KX_SceneActuator, init_getset); + PyType_Ready_Attr(dict, KX_SoundActuator, init_getset); + PyType_Ready_Attr(dict, KX_StateActuator, init_getset); + PyType_Ready_Attr(dict, KX_TouchSensor, init_getset); + PyType_Ready_Attr(dict, KX_TrackToActuator, init_getset); + PyType_Ready_Attr(dict, KX_VehicleWrapper, init_getset); + PyType_Ready_Attr(dict, KX_VertexProxy, init_getset); + PyType_Ready_Attr(dict, KX_VisibilityActuator, init_getset); + PyType_Ready_Attr(dict, PyObjectPlus, init_getset); + PyType_Ready_Attr(dict, SCA_2DFilterActuator, init_getset); + PyType_Ready_Attr(dict, SCA_ANDController, init_getset); + PyType_Ready_Attr(dict, SCA_ActuatorSensor, init_getset); + PyType_Ready_Attr(dict, SCA_AlwaysSensor, init_getset); + PyType_Ready_Attr(dict, SCA_DelaySensor, init_getset); + PyType_Ready_Attr(dict, SCA_ILogicBrick, init_getset); + PyType_Ready_Attr(dict, SCA_IObject, init_getset); + PyType_Ready_Attr(dict, SCA_ISensor, init_getset); + PyType_Ready_Attr(dict, SCA_JoystickSensor, init_getset); + PyType_Ready_Attr(dict, SCA_KeyboardSensor, init_getset); + PyType_Ready_Attr(dict, SCA_MouseSensor, init_getset); + PyType_Ready_Attr(dict, SCA_NANDController, init_getset); + PyType_Ready_Attr(dict, SCA_NORController, init_getset); + PyType_Ready_Attr(dict, SCA_ORController, init_getset); + PyType_Ready_Attr(dict, SCA_PropertyActuator, init_getset); + PyType_Ready_Attr(dict, SCA_PropertySensor, init_getset); + PyType_Ready_Attr(dict, SCA_PythonController, init_getset); + PyType_Ready_Attr(dict, SCA_RandomActuator, init_getset); + PyType_Ready_Attr(dict, SCA_RandomSensor, init_getset); + PyType_Ready_Attr(dict, SCA_XNORController, init_getset); + PyType_Ready_Attr(dict, SCA_XORController, init_getset); + PyType_Ready_Attr(dict, SCA_IController, init_getset); + } + + /* Normal python type */ PyType_Ready(&KX_PythonSeq_Type); + +#ifdef USE_MATHUTILS + /* Init mathutils callbacks */ + KX_GameObject_Mathutils_Callback_Init(); + KX_ObjectActuator_Mathutils_Callback_Init(); +#endif } -#endif \ No newline at end of file +#endif diff --git a/source/gameengine/Ketsji/KX_PythonSeq.cpp b/source/gameengine/Ketsji/KX_PythonSeq.cpp index 524d957a80c..5b4d77156db 100644 --- a/source/gameengine/Ketsji/KX_PythonSeq.cpp +++ b/source/gameengine/Ketsji/KX_PythonSeq.cpp @@ -221,11 +221,11 @@ static PyObject * KX_PythonSeq_subscript(PyObject * self, PyObject *key) return NULL; } - if (PyInt_Check(key)) { - return KX_PythonSeq_getIndex(self, PyInt_AS_LONG( key )); + if (PyLong_Check(key)) { + return KX_PythonSeq_getIndex(self, PyLong_AsSsize_t( key )); } - else if ( PyString_Check(key) ) { - char *name = PyString_AsString(key); + else if ( PyUnicode_Check(key) ) { + char *name = _PyUnicode_AsString(key); PyObjectPlus *ret = KX_PythonSeq_subscript__internal(self, name); if(ret) { @@ -250,12 +250,12 @@ static int KX_PythonSeq_contains(PyObject *self, PyObject *key) PyErr_SetString(PyExc_SystemError, "key in seq, KX_PythonSeq: "BGE_PROXY_ERROR_MSG); return -1; } - if(!PyString_Check(key)) { + if(!PyUnicode_Check(key)) { PyErr_SetString(PyExc_SystemError, "key in seq, KX_PythonSeq: key must be a string"); return -1; } - if(KX_PythonSeq_subscript__internal(self, PyString_AsString(key))) + if(KX_PythonSeq_subscript__internal(self, _PyUnicode_AsString(key))) return 1; return 0; diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp index 064dc9126ac..e39d3756b71 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.cpp +++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp @@ -49,8 +49,7 @@ KX_RadarSensor::KX_RadarSensor(SCA_EventManager* eventmgr, double resetmargin, bool bFindMaterial, const STR_String& touchedpropname, - class KX_Scene* kxscene, - PyTypeObject* T) + class KX_Scene* kxscene) : KX_NearSensor( eventmgr, @@ -61,8 +60,8 @@ KX_RadarSensor::KX_RadarSensor(SCA_EventManager* eventmgr, bFindMaterial, touchedpropname, kxscene, - physCtrl, - T), + physCtrl), + m_coneradius(coneradius), m_coneheight(coneheight), m_axis(axis) @@ -245,21 +244,15 @@ PyTypeObject KX_RadarSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_RadarSensor::Parents[] = { - &KX_RadarSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &KX_NearSensor::Type, - &KX_TouchSensor::Type, - &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_RadarSensor::Methods[] = { @@ -283,16 +276,3 @@ PyAttributeDef KX_RadarSensor::Attributes[] = { {NULL} //Sentinel }; -PyObject* KX_RadarSensor::py_getattro(PyObject *attr) -{ - py_getattro_up(KX_NearSensor); -} - -PyObject* KX_RadarSensor::py_getattro_dict() { - py_getattro_dict_up(KX_NearSensor); -} - -int KX_RadarSensor::py_setattro(PyObject *attr, PyObject* value) -{ - py_setattro_up(KX_NearSensor); -} diff --git a/source/gameengine/Ketsji/KX_RadarSensor.h b/source/gameengine/Ketsji/KX_RadarSensor.h index 2e5a0e68bed..344be0e399f 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.h +++ b/source/gameengine/Ketsji/KX_RadarSensor.h @@ -70,8 +70,7 @@ public: double resetmargin, bool bFindMaterial, const STR_String& touchedpropname, - class KX_Scene* kxscene, - PyTypeObject* T = &Type); + class KX_Scene* kxscene); KX_RadarSensor(); virtual ~KX_RadarSensor(); virtual void SynchronizeTransform(); @@ -89,9 +88,7 @@ public: KX_RADAR_AXIS_NEG_Z }; - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); + /* python */ virtual sensortype GetSensorType() { return ST_RADAR; } //Deprecated -----> diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp index 78a61e9d95e..3f27496df71 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.cpp +++ b/source/gameengine/Ketsji/KX_RaySensor.cpp @@ -55,9 +55,8 @@ KX_RaySensor::KX_RaySensor(class SCA_EventManager* eventmgr, bool bXRay, double distance, int axis, - KX_Scene* ketsjiScene, - PyTypeObject* T) - : SCA_ISensor(gameobj,eventmgr, T), + KX_Scene* ketsjiScene) + : SCA_ISensor(gameobj,eventmgr), m_propertyname(propname), m_bFindMaterial(bFindMaterial), m_bXRay(bXRay), @@ -336,20 +335,16 @@ PyTypeObject KX_RaySensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods - -}; - -PyParentObject KX_RaySensor::Parents[] = { - &KX_RaySensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new + }; PyMethodDef KX_RaySensor::Methods[] = { @@ -447,18 +442,4 @@ PyObject* KX_RaySensor::PyGetHitNormal() return retVal; } - - -PyObject* KX_RaySensor::py_getattro(PyObject *attr) { - py_getattro_up(SCA_ISensor); -} - -PyObject* KX_RaySensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int KX_RaySensor::py_setattro(PyObject *attr, PyObject *value) { - py_setattro_up(SCA_ISensor); -} - // <----- Deprecated diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h index 9efb046742f..530c8ce54e5 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.h +++ b/source/gameengine/Ketsji/KX_RaySensor.h @@ -62,8 +62,7 @@ public: bool bXRay, double distance, int axis, - class KX_Scene* ketsjiScene, - PyTypeObject* T = &Type); + class KX_Scene* ketsjiScene); virtual ~KX_RaySensor(); virtual CValue* GetReplica(); @@ -84,11 +83,6 @@ public: KX_RAY_AXIS_NEG_Y, KX_RAY_AXIS_NEG_Z }; - - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); // Deprecated -----> KX_PYMETHOD_DOC_NOARGS(KX_RaySensor,GetHitObject); diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index 75435b97797..239c4a0be67 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -55,10 +55,9 @@ KX_SCA_AddObjectActuator::KX_SCA_AddObjectActuator(SCA_IObject *gameobj, const float *linvel, bool linv_local, const float *angvel, - bool angv_local, - PyTypeObject* T) + bool angv_local) : - SCA_IActuator(gameobj, T), + SCA_IActuator(gameobj), m_OriginalObject(original), m_scene(scene), @@ -187,20 +186,17 @@ PyTypeObject KX_SCA_AddObjectActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &SCA_IActuator::Type, + 0,0,0,0,0,0, + py_base_new }; -PyParentObject KX_SCA_AddObjectActuator::Parents[] = { - &KX_SCA_AddObjectActuator::Type, - &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL -}; PyMethodDef KX_SCA_AddObjectActuator::Methods[] = { // ---> deprecated {"setTime", (PyCFunction) KX_SCA_AddObjectActuator::sPySetTime, METH_O, (PY_METHODCHAR)SetTime_doc}, @@ -263,21 +259,6 @@ PyObject* KX_SCA_AddObjectActuator::pyattr_get_objectLastCreated(void *self, con return actuator->m_lastCreatedObject->GetProxy(); } - -PyObject* KX_SCA_AddObjectActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_SCA_AddObjectActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_SCA_AddObjectActuator::py_setattro(PyObject *attr, PyObject* value) -{ - py_setattro_up(SCA_IActuator); -} - /* 1. setObject */ const char KX_SCA_AddObjectActuator::SetObject_doc[] = "setObject(object)\n" @@ -316,7 +297,7 @@ const char KX_SCA_AddObjectActuator::SetTime_doc[] = PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* value) { ShowDeprecationWarning("setTime()", "the time property"); - int deltatime = PyInt_AsLong(value); + int deltatime = PyLong_AsSsize_t(value); if (deltatime==-1 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "expected an int"); return NULL; @@ -339,7 +320,7 @@ const char KX_SCA_AddObjectActuator::GetTime_doc[] = PyObject* KX_SCA_AddObjectActuator::PyGetTime() { ShowDeprecationWarning("getTime()", "the time property"); - return PyInt_FromLong(m_timeProp); + return PyLong_FromSsize_t(m_timeProp); } @@ -361,7 +342,7 @@ PyObject* KX_SCA_AddObjectActuator::PyGetObject(PyObject* args) Py_RETURN_NONE; if (ret_name_only) - return PyString_FromString(m_OriginalObject->GetName().ReadPtr()); + return PyUnicode_FromString(m_OriginalObject->GetName().ReadPtr()); else return m_OriginalObject->GetProxy(); } diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h index 6746b7d1bc6..3151e7a89ca 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h @@ -88,8 +88,7 @@ public: const float *linvel, bool linv_local, const float *angvel, - bool angv_local, - PyTypeObject* T=&Type + bool angv_local ); ~KX_SCA_AddObjectActuator(void); @@ -110,10 +109,6 @@ public: virtual bool Update(); - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); - SCA_IObject* GetLastCreatedObject( ) const ; diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp index a50764a54e6..423fd0db7f2 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp @@ -47,9 +47,7 @@ /* Integration hooks ------------------------------------------------------- */ - PyTypeObject - -KX_SCA_DynamicActuator::Type = { +PyTypeObject KX_SCA_DynamicActuator::Type = { #if (PY_VERSION_HEX >= 0x02060000) PyVarObject_HEAD_INIT(NULL, 0) #else @@ -66,22 +64,17 @@ KX_SCA_DynamicActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_SCA_DynamicActuator::Parents[] = { - &KX_SCA_DynamicActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - PyMethodDef KX_SCA_DynamicActuator::Methods[] = { // ---> deprecated KX_PYMETHODTABLE(KX_SCA_DynamicActuator, setOperation), @@ -96,21 +89,6 @@ PyAttributeDef KX_SCA_DynamicActuator::Attributes[] = { }; -PyObject* KX_SCA_DynamicActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_SCA_DynamicActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_SCA_DynamicActuator::py_setattro(PyObject *attr, PyObject* value) -{ - py_setattro_up(SCA_IActuator); -} - - /* 1. setOperation */ KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, setOperation, "setOperation(operation?)\n" @@ -142,7 +120,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, getOperation, ) { ShowDeprecationWarning("getOperation()", "the mode property"); - return PyInt_FromLong((long)m_dyn_operation); + return PyLong_FromSsize_t((long)m_dyn_operation); } @@ -152,10 +130,9 @@ KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, getOperation, KX_SCA_DynamicActuator::KX_SCA_DynamicActuator(SCA_IObject *gameobj, short dyn_operation, - float setmass, - PyTypeObject* T) : + float setmass) : - SCA_IActuator(gameobj, T), + SCA_IActuator(gameobj), m_dyn_operation(dyn_operation), m_setmass(setmass) { diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h index 4add707f8cd..8b598c9ecfa 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h @@ -50,8 +50,7 @@ class KX_SCA_DynamicActuator : public SCA_IActuator KX_SCA_DynamicActuator( SCA_IObject* gameobj, short dyn_operation, - float setmass, - PyTypeObject* T=&Type + float setmass ); ~KX_SCA_DynamicActuator( @@ -73,11 +72,6 @@ class KX_SCA_DynamicActuator : public SCA_IActuator KX_DYN_SET_MASS, }; - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - /* 1. setOperation */ KX_PYMETHOD_DOC(KX_SCA_DynamicActuator,setOperation); KX_PYMETHOD_DOC(KX_SCA_DynamicActuator,getOperation); diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp index 728254e7f48..47c5c3aeeeb 100644 --- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp @@ -43,9 +43,8 @@ #endif KX_SCA_EndObjectActuator::KX_SCA_EndObjectActuator(SCA_IObject *gameobj, - SCA_IScene* scene, - PyTypeObject* T): - SCA_IActuator(gameobj, T), + SCA_IScene* scene): + SCA_IActuator(gameobj), m_scene(scene) { // intentionally empty @@ -108,24 +107,17 @@ PyTypeObject KX_SCA_EndObjectActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - - -PyParentObject KX_SCA_EndObjectActuator::Parents[] = { - &KX_SCA_EndObjectActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - - PyMethodDef KX_SCA_EndObjectActuator::Methods[] = { {NULL,NULL} //Sentinel }; @@ -134,13 +126,4 @@ PyAttributeDef KX_SCA_EndObjectActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_SCA_EndObjectActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_SCA_EndObjectActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - /* eof */ diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h index 70d72f1f8da..782a24b1ef1 100644 --- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h @@ -47,8 +47,7 @@ class KX_SCA_EndObjectActuator : public SCA_IActuator public: KX_SCA_EndObjectActuator( SCA_IObject* gameobj, - SCA_IScene* scene, - PyTypeObject* T=&Type + SCA_IScene* scene ); ~KX_SCA_EndObjectActuator(); @@ -63,9 +62,6 @@ class KX_SCA_EndObjectActuator : public SCA_IActuator /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); }; /* end of class KX_EditObjectActuator : public SCA_PropertyActuator */ diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp index 00842d7012a..2884bb76565 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp @@ -50,9 +50,7 @@ /* Integration hooks ------------------------------------------------------- */ - PyTypeObject - -KX_SCA_ReplaceMeshActuator::Type = { +PyTypeObject KX_SCA_ReplaceMeshActuator::Type = { #if (PY_VERSION_HEX >= 0x02060000) PyVarObject_HEAD_INIT(NULL, 0) #else @@ -69,23 +67,17 @@ KX_SCA_ReplaceMeshActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_SCA_ReplaceMeshActuator::Parents[] = { - &KX_SCA_ReplaceMeshActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - - PyMethodDef KX_SCA_ReplaceMeshActuator::Methods[] = { KX_PYMETHODTABLE(KX_SCA_ReplaceMeshActuator, instantReplaceMesh), // Deprecated -----> @@ -99,20 +91,6 @@ PyAttributeDef KX_SCA_ReplaceMeshActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_SCA_ReplaceMeshActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_SCA_ReplaceMeshActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_SCA_ReplaceMeshActuator::py_setattro(PyObject *attr, PyObject* value) -{ - py_setattro_up(SCA_IActuator); -} - PyObject* KX_SCA_ReplaceMeshActuator::pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SCA_ReplaceMeshActuator* actuator = static_cast(self); @@ -161,7 +139,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, getMesh, if (!m_mesh) Py_RETURN_NONE; - return PyString_FromString(const_cast(m_mesh->GetName().ReadPtr())); + return PyUnicode_FromString(const_cast(m_mesh->GetName().ReadPtr())); } @@ -178,10 +156,9 @@ KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, instantReplaceMesh, KX_SCA_ReplaceMeshActuator::KX_SCA_ReplaceMeshActuator(SCA_IObject *gameobj, class RAS_MeshObject *mesh, - SCA_IScene* scene, - PyTypeObject* T) : + SCA_IScene* scene) : - SCA_IActuator(gameobj, T), + SCA_IActuator(gameobj), m_mesh(mesh), m_scene(scene) { diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h index 0e7f7852701..6a68bd88cc5 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h @@ -55,9 +55,7 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator KX_SCA_ReplaceMeshActuator( SCA_IObject* gameobj, RAS_MeshObject *mesh, - SCA_IScene* scene, - PyTypeObject* T=&Type - ); + SCA_IScene* scene); ~KX_SCA_ReplaceMeshActuator( ); @@ -71,10 +69,7 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator void InstantReplaceMesh(); - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); - + /* python api */ static PyObject* pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index c0d8a7090c4..51f5276e075 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -138,7 +138,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, class SND_IAudioDevice* adi, const STR_String& sceneName, Scene *scene): - PyObjectPlus(&KX_Scene::Type), + PyObjectPlus(), m_keyboardmgr(NULL), m_mousemgr(NULL), m_sceneConverter(NULL), @@ -1629,17 +1629,15 @@ PyTypeObject KX_Scene::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_Scene::Parents[] = { - &KX_Scene::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_Scene::Methods[] = { @@ -1654,7 +1652,7 @@ PyMethodDef KX_Scene::Methods[] = { PyObject* KX_Scene::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_Scene* self= static_cast(self_v); - return PyString_FromString(self->GetName().ReadPtr()); + return PyUnicode_FromString(self->GetName().ReadPtr()); } PyObject* KX_Scene::pyattr_get_objects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -1730,72 +1728,6 @@ PyAttributeDef KX_Scene::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_Scene::py_getattro__internal(PyObject *attr) -{ - py_getattro_up(PyObjectPlus); -} - -int KX_Scene::py_setattro__internal(PyObject *attr, PyObject *value) -{ - py_setattro_up(PyObjectPlus); -} - -PyObject* KX_Scene::py_getattro(PyObject *attr) -{ - PyObject *object = py_getattro__internal(attr); - - if (object==NULL) - { - PyErr_Clear(); - object = PyDict_GetItem(m_attr_dict, attr); - if(object) { - Py_INCREF(object); - } - else { - PyErr_Format(PyExc_AttributeError, "value = scene.myAttr: KX_Scene, attribute \"%s\" not found", PyString_AsString(attr)); - } - } - - return object; -} - -PyObject* KX_Scene::py_getattro_dict() { - //py_getattro_dict_up(PyObjectPlus); - - PyObject *dict= py_getattr_dict(PyObjectPlus::py_getattro_dict(), Type.tp_dict); - if(dict==NULL) - return NULL; - - /* normally just return this but KX_Scene has some more items */ - - PyDict_Update(dict, m_attr_dict); - return dict; -} - -int KX_Scene::py_setattro(PyObject *attr, PyObject *value) -{ - int ret= py_setattro__internal(attr, value); - - if (ret==PY_SET_ATTR_MISSING) { - if (PyDict_SetItem(m_attr_dict, attr, value)==0) { - PyErr_Clear(); - ret= PY_SET_ATTR_SUCCESS; - } - else { - PyErr_SetString(PyExc_AttributeError, "scene.UserAttr = value: KX_Scenes, failed assigning value to internal dictionary"); - ret= PY_SET_ATTR_FAIL; - } - } - - return ret; -} - -int KX_Scene::py_delattro(PyObject *attr) -{ - PyDict_DelItem(m_attr_dict, attr); - return 0; -} - KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getLightList, "getLightList() -> list [KX_Light]\n" "Returns a list of all lights in the scene.\n" @@ -1820,7 +1752,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getName, ) { ShowDeprecationWarning("getName()", "the name property"); - return PyString_FromString(GetName()); + return PyUnicode_FromString(GetName()); } KX_PYMETHODDEF_DOC(KX_Scene, addObject, diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 79d3f7fd828..2792f1f5fe4 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -563,15 +563,7 @@ public: static PyObject* pyattr_get_active_camera(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); - virtual PyObject* py_getattro(PyObject *attr); /* name, active_camera, gravity, suspended, viewport, framing, activity_culling, activity_culling_radius */ - virtual PyObject* py_getattro_dict(); - - virtual int py_setattro(PyObject *attr, PyObject *value); - virtual int py_delattro(PyObject *attr); - virtual PyObject* py_repr(void) { return PyString_FromString(GetName().ReadPtr()); } - - PyObject* py_getattro__internal(PyObject *attr); - int py_setattro__internal(PyObject *attr, PyObject *pyvalue); + virtual PyObject* py_repr(void) { return PyUnicode_FromString(GetName().ReadPtr()); } /** * Sets the time the scene was suspended diff --git a/source/gameengine/Ketsji/KX_SceneActuator.cpp b/source/gameengine/Ketsji/KX_SceneActuator.cpp index 1b790ec9824..5528e58ef77 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.cpp +++ b/source/gameengine/Ketsji/KX_SceneActuator.cpp @@ -49,9 +49,8 @@ KX_SceneActuator::KX_SceneActuator(SCA_IObject *gameobj, KX_Scene *scene, KX_KetsjiEngine* ketsjiEngine, const STR_String& nextSceneName, - KX_Camera* camera, - PyTypeObject* T) - : SCA_IActuator(gameobj, T) + KX_Camera* camera) + : SCA_IActuator(gameobj) { m_mode = mode; m_scene = scene; @@ -134,7 +133,7 @@ bool KX_SceneActuator::Update() { // if no camera is set and the parent object is a camera, use it as the camera SCA_IObject* parent = GetParent(); - if (parent->isA(&KX_Camera::Type)) + if (parent->GetGameObjectType()==SCA_IObject::OBJ_CAMERA) { m_scene->SetActiveCamera((KX_Camera*)parent); } @@ -239,26 +238,17 @@ PyTypeObject KX_SceneActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - - - -PyParentObject KX_SceneActuator::Parents[] = -{ - &KX_SceneActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - - PyMethodDef KX_SceneActuator::Methods[] = { //Deprecated functions ------> @@ -280,20 +270,6 @@ PyAttributeDef KX_SceneActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_SceneActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_SceneActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_SceneActuator::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_IActuator); -} - PyObject* KX_SceneActuator::pyattr_get_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SceneActuator* actuator = static_cast(self); @@ -355,7 +331,7 @@ const char KX_SceneActuator::GetUseRestart_doc[] = PyObject* KX_SceneActuator::PyGetUseRestart() { ShowDeprecationWarning("getUseRestart()", "the useRestart property"); - return PyInt_FromLong(!(m_restart == 0)); + return PyLong_FromSsize_t(!(m_restart == 0)); } @@ -391,7 +367,7 @@ const char KX_SceneActuator::GetScene_doc[] = PyObject* KX_SceneActuator::PyGetScene() { ShowDeprecationWarning("getScene()", "the scene property"); - return PyString_FromString(m_nextSceneName); + return PyUnicode_FromString(m_nextSceneName); } @@ -432,7 +408,7 @@ PyObject* KX_SceneActuator::PyGetCamera() { ShowDeprecationWarning("getCamera()", "the camera property"); if (m_camera) { - return PyString_FromString(m_camera->GetName()); + return PyUnicode_FromString(m_camera->GetName()); } else { Py_RETURN_NONE; diff --git a/source/gameengine/Ketsji/KX_SceneActuator.h b/source/gameengine/Ketsji/KX_SceneActuator.h index 2412dd02590..86de3395d1e 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.h +++ b/source/gameengine/Ketsji/KX_SceneActuator.h @@ -77,8 +77,7 @@ class KX_SceneActuator : public SCA_IActuator KX_Scene* scene, KX_KetsjiEngine* ketsjiEngine, const STR_String& nextSceneName, - KX_Camera* camera, - PyTypeObject* T=&Type); + KX_Camera* camera); virtual ~KX_SceneActuator(); virtual CValue* GetReplica(); @@ -92,10 +91,6 @@ class KX_SceneActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - /* 1. set */ /* Removed */ diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index c13271f66a5..673f42283dd 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -50,9 +50,8 @@ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj, SND_Scene* sndscene, KX_SOUNDACT_TYPE type, short start, - short end, - PyTypeObject* T) - : SCA_IActuator(gameobj,T) + short end) + : SCA_IActuator(gameobj) { m_soundObject = sndobj; m_soundScene = sndscene; @@ -250,25 +249,17 @@ PyTypeObject KX_SoundActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - - - -PyParentObject KX_SoundActuator::Parents[] = { - &KX_SoundActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; - - PyMethodDef KX_SoundActuator::Methods[] = { // Deprecated -----> {"setFilename", (PyCFunction) KX_SoundActuator::sPySetFilename, METH_VARARGS,NULL}, @@ -340,25 +331,13 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, stopSound, } /* Atribute setting and getting -------------------------------------------- */ -PyObject* KX_SoundActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_SoundActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_SoundActuator::py_setattro(PyObject *attr, PyObject* value) { - py_setattro_up(SCA_IActuator); -} PyObject* KX_SoundActuator::pyattr_get_filename(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SoundActuator * actuator = static_cast (self); if (!actuator->m_soundObject) { - return PyString_FromString(""); + return PyUnicode_FromString(""); } STR_String objectname = actuator->m_soundObject->GetObjectName(); char* name = objectname.Ptr(); @@ -367,7 +346,7 @@ PyObject* KX_SoundActuator::pyattr_get_filename(void *self, const struct KX_PYAT PyErr_SetString(PyExc_RuntimeError, "value = actuator.fileName: KX_SoundActuator, unable to get sound fileName"); return NULL; } else - return PyString_FromString(name); + return PyUnicode_FromString(name); } PyObject* KX_SoundActuator::pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) @@ -402,7 +381,7 @@ PyObject* KX_SoundActuator::pyattr_get_looping(void *self, const struct KX_PYATT { KX_SoundActuator * actuator = static_cast (self); int looping = (actuator->m_soundObject) ? actuator->m_soundObject->GetLoopMode() : (int)SND_LOOP_OFF; - PyObject* result = PyInt_FromLong(looping); + PyObject* result = PyLong_FromSsize_t(looping); return result; } @@ -580,7 +559,7 @@ PyObject* KX_SoundActuator::PyGetFilename() ShowDeprecationWarning("getFilename()", "the fileName property"); if (!m_soundObject) { - return PyString_FromString(""); + return PyUnicode_FromString(""); } STR_String objectname = m_soundObject->GetObjectName(); char* name = objectname.Ptr(); @@ -589,7 +568,7 @@ PyObject* KX_SoundActuator::PyGetFilename() PyErr_SetString(PyExc_RuntimeError, "Unable to get sound fileName"); return NULL; } else - return PyString_FromString(name); + return PyUnicode_FromString(name); } PyObject* KX_SoundActuator::PySetGain(PyObject* args) @@ -689,7 +668,7 @@ PyObject* KX_SoundActuator::PyGetLooping() { ShowDeprecationWarning("getLooping()", "the looping property"); int looping = (m_soundObject) ? m_soundObject->GetLoopMode() : (int)SND_LOOP_OFF; - PyObject* result = PyInt_FromLong(looping); + PyObject* result = PyLong_FromSsize_t(looping); return result; } @@ -777,7 +756,7 @@ PyObject* KX_SoundActuator::PySetType(PyObject* args) PyObject* KX_SoundActuator::PyGetType() { ShowDeprecationWarning("getType()", "the mode property"); - return PyInt_FromLong(m_type); + return PyLong_FromSsize_t(m_type); } // <----- diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h index a7491355667..adafee0a30b 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.h +++ b/source/gameengine/Ketsji/KX_SoundActuator.h @@ -66,8 +66,7 @@ public: class SND_Scene* sndscene, KX_SOUNDACT_TYPE type, short start, - short end, - PyTypeObject* T=&Type); + short end); ~KX_SoundActuator(); @@ -81,10 +80,6 @@ public: /* Python interface --------------------------------------------------- */ /* -------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); - KX_PYMETHOD_DOC_NOARGS(KX_SoundActuator, startSound); KX_PYMETHOD_DOC_NOARGS(KX_SoundActuator, pauseSound); KX_PYMETHOD_DOC_NOARGS(KX_SoundActuator, stopSound); diff --git a/source/gameengine/Ketsji/KX_StateActuator.cpp b/source/gameengine/Ketsji/KX_StateActuator.cpp index f6979eee0f4..9815d6274aa 100644 --- a/source/gameengine/Ketsji/KX_StateActuator.cpp +++ b/source/gameengine/Ketsji/KX_StateActuator.cpp @@ -38,10 +38,9 @@ KX_StateActuator::KX_StateActuator( SCA_IObject* gameobj, int operation, - unsigned int mask, - PyTypeObject* T + unsigned int mask ) - : SCA_IActuator(gameobj,T), + : SCA_IActuator(gameobj), m_operation(operation), m_mask(mask) { @@ -154,24 +153,18 @@ PyTypeObject KX_StateActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject -KX_StateActuator::Parents[] = { - &KX_StateActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; -PyMethodDef -KX_StateActuator::Methods[] = { +PyMethodDef KX_StateActuator::Methods[] = { // deprecated --> {"setOperation", (PyCFunction) KX_StateActuator::sPySetOperation, METH_VARARGS, (PY_METHODCHAR)SetOperation_doc}, @@ -187,20 +180,6 @@ PyAttributeDef KX_StateActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_StateActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_StateActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_StateActuator::py_setattro(PyObject *attr, PyObject* value) -{ - py_setattro_up(SCA_IActuator); -} - /* set operation ---------------------------------------------------------- */ const char diff --git a/source/gameengine/Ketsji/KX_StateActuator.h b/source/gameengine/Ketsji/KX_StateActuator.h index a4191a4c5fd..ce86c4b44fe 100644 --- a/source/gameengine/Ketsji/KX_StateActuator.h +++ b/source/gameengine/Ketsji/KX_StateActuator.h @@ -66,9 +66,8 @@ class KX_StateActuator : public SCA_IActuator KX_StateActuator( SCA_IObject* gameobj, int operation, - unsigned int mask, - PyTypeObject* T=&Type - ); + unsigned int mask + ); virtual ~KX_StateActuator( @@ -89,10 +88,6 @@ class KX_StateActuator : public SCA_IActuator /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); //KX_PYMETHOD_DOC KX_PYMETHOD_DOC_VARARGS(KX_StateActuator,SetOperation); KX_PYMETHOD_DOC_VARARGS(KX_StateActuator,SetMask); diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp deleted file mode 100644 index fc053f05e63..00000000000 --- a/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp +++ /dev/null @@ -1,244 +0,0 @@ -#include "KX_ConvertPhysicsObject.h" - -#ifdef USE_SUMO_SOLID - -#ifdef WIN32 -#pragma warning (disable : 4786) -#endif - -#include "KX_SumoPhysicsController.h" -#include "SG_Spatial.h" -#include "SM_Scene.h" -#include "KX_GameObject.h" -#include "KX_MotionState.h" -#include "KX_ClientObjectInfo.h" - -#include "PHY_IPhysicsEnvironment.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -void KX_SumoPhysicsController::applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse) -{ - SumoPhysicsController::applyImpulse(attach[0],attach[1],attach[2],impulse[0],impulse[1],impulse[2]); -} -void KX_SumoPhysicsController::RelativeTranslate(const MT_Vector3& dloc,bool local) -{ - SumoPhysicsController::RelativeTranslate(dloc[0],dloc[1],dloc[2],local); - -} -void KX_SumoPhysicsController::RelativeRotate(const MT_Matrix3x3& drot,bool local) -{ - float oldmat[12]; - drot.getValue(oldmat); -/* float newmat[9]; - float *m = &newmat[0]; - double *orgm = &oldmat[0]; - - *m++ = *orgm++;*m++ = *orgm++;*m++ = *orgm++;orgm++; - *m++ = *orgm++;*m++ = *orgm++;*m++ = *orgm++;orgm++; - *m++ = *orgm++;*m++ = *orgm++;*m++ = *orgm++;orgm++; */ - - SumoPhysicsController::RelativeRotate(oldmat,local); -} - -void KX_SumoPhysicsController::SetLinearVelocity(const MT_Vector3& lin_vel,bool local) -{ - SumoPhysicsController::SetLinearVelocity(lin_vel[0],lin_vel[1],lin_vel[2],local); - -} - -void KX_SumoPhysicsController::SetAngularVelocity(const MT_Vector3& ang_vel,bool local) -{ - SumoPhysicsController::SetAngularVelocity(ang_vel[0],ang_vel[1],ang_vel[2],local); -} - -MT_Vector3 KX_SumoPhysicsController::GetVelocity(const MT_Point3& pos) -{ - - float linvel[3]; - SumoPhysicsController::GetVelocity(pos[0],pos[1],pos[2],linvel[0],linvel[1],linvel[2]); - - return MT_Vector3 (linvel); -} - -MT_Vector3 KX_SumoPhysicsController::GetLinearVelocity() -{ - return GetVelocity(MT_Point3(0,0,0)); - -} - -void KX_SumoPhysicsController::resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ) -{ - SumoPhysicsController::resolveCombinedVelocities(linvelX,linvelY,linvelZ,angVelX,angVelY,angVelZ); -} - -void KX_SumoPhysicsController::ApplyTorque(const MT_Vector3& torque,bool local) -{ - SumoPhysicsController::ApplyTorque(torque[0],torque[1],torque[2],local); - -} - -void KX_SumoPhysicsController::ApplyForce(const MT_Vector3& force,bool local) -{ - SumoPhysicsController::ApplyForce(force[0],force[1],force[2],local); -} - -bool KX_SumoPhysicsController::Update(double time) -{ - return SynchronizeMotionStates(time); -} - -void KX_SumoPhysicsController::SetSimulatedTime(double time) -{ - -} - -void KX_SumoPhysicsController::SetSumoTransform(bool nondynaonly) -{ - SumoPhysicsController::setSumoTransform(nondynaonly); - -} - -void KX_SumoPhysicsController::SuspendDynamics(bool) -{ - SumoPhysicsController::SuspendDynamics(); -} - -void KX_SumoPhysicsController::RestoreDynamics() -{ - SumoPhysicsController::RestoreDynamics(); -} - -SG_Controller* KX_SumoPhysicsController::GetReplica(SG_Node* destnode) -{ - - PHY_IMotionState* motionstate = new KX_MotionState(destnode); - - KX_SumoPhysicsController* physicsreplica = new KX_SumoPhysicsController(*this); - - //parentcontroller is here be able to avoid collisions between parent/child - - PHY_IPhysicsController* parentctrl = NULL; - - if (destnode != destnode->GetRootSGParent()) - { - KX_GameObject* clientgameobj = (KX_GameObject*) destnode->GetRootSGParent()->GetSGClientObject(); - if (clientgameobj) - { - parentctrl = (KX_SumoPhysicsController*)clientgameobj->GetPhysicsController(); - } else - { - // it could be a false node, try the children - NodeList::const_iterator childit; - for ( - childit = destnode->GetSGChildren().begin(); - childit!= destnode->GetSGChildren().end(); - ++childit - ) { - KX_GameObject *clientgameobj = static_cast( (*childit)->GetSGClientObject()); - if (clientgameobj) - { - parentctrl = (KX_SumoPhysicsController*)clientgameobj->GetPhysicsController(); - } - } - } - } - - physicsreplica->PostProcessReplica(motionstate,parentctrl); - - return physicsreplica; -} - - -void KX_SumoPhysicsController::SetObject (SG_IObject* object) -{ - SG_Controller::SetObject(object); - - // cheating here... -//should not be necessary, is it for duplicates ? - -KX_GameObject* gameobj = (KX_GameObject*) object->GetSGClientObject(); -gameobj->SetPhysicsController(this,gameobj->IsDynamic()); -GetSumoObject()->setClientObject(gameobj->getClientInfo()); -} - -void KX_SumoPhysicsController::setMargin(float collisionMargin) -{ - SumoPhysicsController::SetMargin(collisionMargin); -} - - -void KX_SumoPhysicsController::setOrientation(const MT_Matrix3x3& rot) -{ - MT_Quaternion orn = rot.getRotation(); - SumoPhysicsController::setOrientation( - orn[0],orn[1],orn[2],orn[3]); - -} -void KX_SumoPhysicsController::getOrientation(MT_Quaternion& orn) -{ - - float quat[4]; - - SumoPhysicsController::getOrientation(quat[0],quat[1],quat[2],quat[3]); - - orn = MT_Quaternion(quat); - -} - -void KX_SumoPhysicsController::setPosition(const MT_Point3& pos) -{ - SumoPhysicsController::setPosition(pos[0],pos[1],pos[2]); - -} - -void KX_SumoPhysicsController::setScaling(const MT_Vector3& scaling) -{ - SumoPhysicsController::setScaling(scaling[0],scaling[1],scaling[2]); - -} - -MT_Scalar KX_SumoPhysicsController::GetMass() -{ - return SumoPhysicsController::getMass(); -} - -void KX_SumoPhysicsController::SetMass(MT_Scalar newmass) -{ -} - -MT_Vector3 KX_SumoPhysicsController::GetLocalInertia() -{ - return MT_Vector3(0.f, 0.f, 0.f); // \todo -} - -MT_Scalar KX_SumoPhysicsController::GetRadius() -{ - return SumoPhysicsController::GetRadius(); -} - -MT_Vector3 KX_SumoPhysicsController::getReactionForce() -{ - float force[3]; - SumoPhysicsController::getReactionForce(force[0],force[1],force[2]); - return MT_Vector3(force); - -} - -void KX_SumoPhysicsController::setRigidBody(bool rigid) -{ - SumoPhysicsController::setRigidBody(rigid); - -} - - -KX_SumoPhysicsController::~KX_SumoPhysicsController() -{ - - -} - - -#endif//USE_SUMO_SOLID diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.h b/source/gameengine/Ketsji/KX_SumoPhysicsController.h deleted file mode 100644 index 278994c6ae7..00000000000 --- a/source/gameengine/Ketsji/KX_SumoPhysicsController.h +++ /dev/null @@ -1,122 +0,0 @@ -/** - * $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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef __KX_SUMOPHYSICSCONTROLLER_H -#define __KX_SUMOPHYSICSCONTROLLER_H - -#include "PHY_IPhysicsController.h" - -/** - Physics Controller, a special kind of Scene Graph Transformation Controller. - It get's callbacks from Sumo in case a transformation change took place. - Each time the scene graph get's updated, the controller get's a chance - in the 'Update' method to reflect changed. -*/ - -#include "SumoPhysicsController.h" -#include "KX_IPhysicsController.h" - -class KX_SumoPhysicsController : public KX_IPhysicsController, - public SumoPhysicsController - -{ - - -public: - KX_SumoPhysicsController( - class SM_Scene* sumoScene, - class SM_Object* sumoObj, - class PHY_IMotionState* motionstate - ,bool dyna) - : KX_IPhysicsController(dyna,false,false,NULL) , - SumoPhysicsController(sumoScene,/*solidscene,*/sumoObj,motionstate,dyna) - { - }; - virtual ~KX_SumoPhysicsController(); - - void applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse); - virtual void SetObject (SG_IObject* object); - virtual void setMargin (float collisionMargin); - - void RelativeTranslate(const MT_Vector3& dloc,bool local); - void RelativeRotate(const MT_Matrix3x3& drot,bool local); - void ApplyTorque(const MT_Vector3& torque,bool local); - void ApplyForce(const MT_Vector3& force,bool local); - MT_Vector3 GetLinearVelocity(); - MT_Vector3 GetAngularVelocity() // to keep compiler happy - { return MT_Vector3(0.0,0.0,0.0); } - MT_Vector3 GetVelocity(const MT_Point3& pos); - void SetAngularVelocity(const MT_Vector3& ang_vel,bool local); - void SetLinearVelocity(const MT_Vector3& lin_vel,bool local); - void resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ); - - - void SuspendDynamics(bool); - void RestoreDynamics(); - virtual void AddCompoundChild(KX_IPhysicsController* child) { } - virtual void RemoveCompoundChild(KX_IPhysicsController* child) { } - - virtual void getOrientation(MT_Quaternion& orn); - virtual void setOrientation(const MT_Matrix3x3& orn); - virtual void SetTransform() {} - - virtual void setPosition(const MT_Point3& pos); - virtual void setScaling(const MT_Vector3& scaling); - virtual MT_Scalar GetMass(); - virtual void SetMass(MT_Scalar newmass); - virtual MT_Vector3 GetLocalInertia(); - virtual MT_Scalar GetRadius(); - virtual MT_Vector3 getReactionForce(); - virtual void setRigidBody(bool rigid); - - virtual float GetLinVelocityMin() { return SumoPhysicsController::GetLinVelocityMin(); } - virtual void SetLinVelocityMin(float val) { SumoPhysicsController::SetLinVelocityMin(val); } - virtual float GetLinVelocityMax() { return SumoPhysicsController::GetLinVelocityMax(); } - virtual void SetLinVelocityMax(float val) { SumoPhysicsController::SetLinVelocityMax(val); } - - virtual SG_Controller* GetReplica(class SG_Node* destnode); - - - void SetSumoTransform(bool nondynaonly); - // todo: remove next line ! - virtual void SetSimulatedTime(double time); - - // call from scene graph to update - virtual bool Update(double time); - - void - SetOption( - int option, - int value - ){ - // intentionally empty - }; -}; - -#endif //__KX_SUMOPHYSICSCONTROLLER_H - diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index c06acd4a873..b0cf172c27a 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -97,8 +97,8 @@ bool KX_TouchSensor::Evaluate() return result; } -KX_TouchSensor::KX_TouchSensor(SCA_EventManager* eventmgr,KX_GameObject* gameobj,bool bFindMaterial,bool bTouchPulse,const STR_String& touchedpropname,PyTypeObject* T) -:SCA_ISensor(gameobj,eventmgr,T), +KX_TouchSensor::KX_TouchSensor(SCA_EventManager* eventmgr,KX_GameObject* gameobj,bool bFindMaterial,bool bTouchPulse,const STR_String& touchedpropname) +:SCA_ISensor(gameobj,eventmgr), m_touchedpropname(touchedpropname), m_bFindMaterial(bFindMaterial), m_bTouchPulse(bTouchPulse), @@ -310,19 +310,15 @@ PyTypeObject KX_TouchSensor::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_TouchSensor::Parents[] = { - &KX_TouchSensor::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_ISensor::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_TouchSensor::Methods[] = { @@ -348,20 +344,6 @@ PyAttributeDef KX_TouchSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_TouchSensor::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_ISensor); -} - -PyObject* KX_TouchSensor::py_getattro_dict() { - py_getattro_dict_up(SCA_ISensor); -} - -int KX_TouchSensor::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_ISensor); -} - /* Python API */ /* 1. setProperty */ @@ -374,7 +356,7 @@ const char KX_TouchSensor::SetProperty_doc[] = PyObject* KX_TouchSensor::PySetProperty(PyObject* value) { ShowDeprecationWarning("setProperty()", "the propName property"); - char *nameArg= PyString_AsString(value); + char *nameArg= _PyUnicode_AsString(value); if (nameArg==NULL) { PyErr_SetString(PyExc_ValueError, "expected a "); return NULL; @@ -392,7 +374,7 @@ const char KX_TouchSensor::GetProperty_doc[] = PyObject* KX_TouchSensor::PyGetProperty() { ShowDeprecationWarning("getProperty()", "the propName property"); - return PyString_FromString(m_touchedpropname); + return PyUnicode_FromString(m_touchedpropname); } const char KX_TouchSensor::GetHitObject_doc[] = @@ -433,7 +415,7 @@ const char KX_TouchSensor::GetTouchMaterial_doc[] = PyObject* KX_TouchSensor::PyGetTouchMaterial() { ShowDeprecationWarning("getTouchMaterial()", "the useMaterial property"); - return PyInt_FromLong(m_bFindMaterial); + return PyLong_FromSsize_t(m_bFindMaterial); } /* 6. setTouchMaterial */ @@ -446,7 +428,7 @@ const char KX_TouchSensor::SetTouchMaterial_doc[] = PyObject* KX_TouchSensor::PySetTouchMaterial(PyObject *value) { ShowDeprecationWarning("setTouchMaterial()", "the useMaterial property"); - int pulseArg = PyInt_AsLong(value); + int pulseArg = PyLong_AsSsize_t(value); if(pulseArg ==-1 && PyErr_Occurred()) { PyErr_SetString(PyExc_ValueError, "expected a bool"); diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h index 476c63e89db..6cbf5b15e3b 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.h +++ b/source/gameengine/Ketsji/KX_TouchSensor.h @@ -79,8 +79,7 @@ public: class KX_GameObject* gameobj, bool bFindMaterial, bool bTouchPulse, - const STR_String& touchedpropname, - PyTypeObject* T=&Type) ; + const STR_String& touchedpropname) ; virtual ~KX_TouchSensor(); virtual CValue* GetReplica(); @@ -121,10 +120,6 @@ public: /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); //Deprecated -----> /* 1. setProperty */ diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index 5a50d0fb944..e8a06d8d619 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -59,10 +59,8 @@ KX_TrackToActuator::KX_TrackToActuator(SCA_IObject *gameobj, int time, bool allow3D, int trackflag, - int upflag, - PyTypeObject* T) - : - SCA_IActuator(gameobj, T) + int upflag) + : SCA_IActuator(gameobj) { m_time = time; m_allow3D = allow3D; @@ -74,7 +72,6 @@ KX_TrackToActuator::KX_TrackToActuator(SCA_IObject *gameobj, if (m_object) m_object->RegisterActuator(this); - if (gameobj->isA(&KX_GameObject::Type)) { // if the object is vertex parented, don't check parent orientation as the link is broken if (!((KX_GameObject*)gameobj)->IsVertexParent()){ @@ -450,25 +447,17 @@ PyTypeObject KX_TrackToActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &SCA_IActuator::Type, + 0,0,0,0,0,0, + py_base_new }; - - -PyParentObject KX_TrackToActuator::Parents[] = { - &KX_TrackToActuator::Type, - &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL -}; - - - PyMethodDef KX_TrackToActuator::Methods[] = { // ---> deprecated {"setTime", (PyCFunction) KX_TrackToActuator::sPySetTime, METH_VARARGS, (PY_METHODCHAR)SetTime_doc}, @@ -518,20 +507,6 @@ int KX_TrackToActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUT } -PyObject* KX_TrackToActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_TrackToActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_TrackToActuator::py_setattro(PyObject *attr, PyObject* value) -{ - py_setattro_up(SCA_IActuator); -} - /* 1. setObject */ const char KX_TrackToActuator::SetObject_doc[] = "setObject(object)\n" @@ -576,7 +551,7 @@ PyObject* KX_TrackToActuator::PyGetObject(PyObject* args) Py_RETURN_NONE; if (ret_name_only) - return PyString_FromString(m_object->GetName()); + return PyUnicode_FromString(m_object->GetName()); else return m_object->GetProxy(); } @@ -613,7 +588,7 @@ const char KX_TrackToActuator::GetTime_doc[] = PyObject* KX_TrackToActuator::PyGetTime() { ShowDeprecationWarning("getTime()", "the timer property"); - return PyInt_FromLong(m_time); + return PyLong_FromSsize_t(m_time); } @@ -625,7 +600,7 @@ const char KX_TrackToActuator::GetUse3D_doc[] = PyObject* KX_TrackToActuator::PyGetUse3D() { ShowDeprecationWarning("setTime()", "the use3D property"); - return PyInt_FromLong(!(m_allow3D == 0)); + return PyLong_FromSsize_t(!(m_allow3D == 0)); } diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.h b/source/gameengine/Ketsji/KX_TrackToActuator.h index c4cc2b1f062..801e695bb9b 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.h +++ b/source/gameengine/Ketsji/KX_TrackToActuator.h @@ -56,7 +56,7 @@ class KX_TrackToActuator : public SCA_IActuator public: KX_TrackToActuator(SCA_IObject* gameobj, SCA_IObject *ob, int time, - bool threedee,int trackflag,int upflag, PyTypeObject* T=&Type); + bool threedee,int trackflag,int upflag); virtual ~KX_TrackToActuator(); virtual CValue* GetReplica() { KX_TrackToActuator* replica = new KX_TrackToActuator(*this); @@ -70,9 +70,6 @@ class KX_TrackToActuator : public SCA_IActuator virtual bool Update(double curtime, bool frame); /* Python part */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject* value); /* These are used to get and set m_ob */ static PyObject* pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index 8146d04a878..7001bfc8b7e 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -16,8 +16,8 @@ KX_VehicleWrapper::KX_VehicleWrapper( PHY_IVehicle* vehicle, - PHY_IPhysicsEnvironment* physenv,PyTypeObject *T) : - PyObjectPlus(T), + PHY_IPhysicsEnvironment* physenv) : + PyObjectPlus(), m_vehicle(vehicle), m_physenv(physenv) { @@ -127,13 +127,13 @@ PyObject* KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject* args) PyObject* KX_VehicleWrapper::PyGetNumWheels(PyObject* args) { - return PyInt_FromLong(m_vehicle->GetNumWheels()); + return PyLong_FromSsize_t(m_vehicle->GetNumWheels()); } PyObject* KX_VehicleWrapper::PyGetConstraintId(PyObject* args) { - return PyInt_FromLong(m_vehicle->GetUserConstraintId()); + return PyLong_FromSsize_t(m_vehicle->GetUserConstraintId()); } @@ -264,7 +264,7 @@ PyObject* KX_VehicleWrapper::PySetSteeringValue(PyObject* args) PyObject* KX_VehicleWrapper::PyGetConstraintType(PyObject* args) { - return PyInt_FromLong(m_vehicle->GetUserConstraintType()); + return PyLong_FromSsize_t(m_vehicle->GetUserConstraintType()); } @@ -289,35 +289,17 @@ PyTypeObject KX_VehicleWrapper::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new }; -PyParentObject KX_VehicleWrapper::Parents[] = { - &KX_VehicleWrapper::Type, - &PyObjectPlus::Type, - NULL -}; - -PyObject* KX_VehicleWrapper::py_getattro(PyObject *attr) -{ - //here you can search for existing data members (like mass,friction etc.) - py_getattro_up(PyObjectPlus); -} - -PyObject* KX_VehicleWrapper::py_getattro_dict() { - py_getattro_dict_up(PyObjectPlus); -} - -int KX_VehicleWrapper::py_setattro(PyObject *attr,PyObject* value) -{ - py_setattro_up(PyObjectPlus); -}; - - PyMethodDef KX_VehicleWrapper::Methods[] = { {"addWheel",(PyCFunction) KX_VehicleWrapper::sPyAddWheel, METH_VARARGS}, {"getNumWheels",(PyCFunction) KX_VehicleWrapper::sPyGetNumWheels, METH_VARARGS}, diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.h b/source/gameengine/Ketsji/KX_VehicleWrapper.h index c2b5e3d9251..d7f2da5cd7c 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.h +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.h @@ -12,14 +12,11 @@ class PHY_IMotionState; class KX_VehicleWrapper : public PyObjectPlus { Py_Header; - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); std::vector m_motionStates; public: - KX_VehicleWrapper(PHY_IVehicle* vehicle,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type); + KX_VehicleWrapper(PHY_IVehicle* vehicle,class PHY_IPhysicsEnvironment* physenv); virtual ~KX_VehicleWrapper (); int getConstraintId(); diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index 4b0ad083473..cb8c891969d 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -53,18 +53,15 @@ PyTypeObject KX_VertexProxy::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods -}; - -PyParentObject KX_VertexProxy::Parents[] = { - &KX_VertexProxy::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &CValue::Type, - &PyObjectPlus::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; PyMethodDef KX_VertexProxy::Methods[] = { @@ -85,37 +82,38 @@ PyMethodDef KX_VertexProxy::Methods[] = { PyAttributeDef KX_VertexProxy::Attributes[] = { //KX_PYATTRIBUTE_TODO("DummyProps"), - + KX_PYATTRIBUTE_DUMMY("x"), KX_PYATTRIBUTE_DUMMY("y"), KX_PYATTRIBUTE_DUMMY("z"), - + KX_PYATTRIBUTE_DUMMY("r"), KX_PYATTRIBUTE_DUMMY("g"), KX_PYATTRIBUTE_DUMMY("b"), KX_PYATTRIBUTE_DUMMY("a"), - + KX_PYATTRIBUTE_DUMMY("u"), KX_PYATTRIBUTE_DUMMY("v"), - + KX_PYATTRIBUTE_DUMMY("u2"), KX_PYATTRIBUTE_DUMMY("v2"), - + KX_PYATTRIBUTE_DUMMY("XYZ"), KX_PYATTRIBUTE_DUMMY("UV"), - + KX_PYATTRIBUTE_DUMMY("color"), KX_PYATTRIBUTE_DUMMY("colour"), - + KX_PYATTRIBUTE_DUMMY("normal"), - + { NULL } //Sentinel }; +#if 0 PyObject* KX_VertexProxy::py_getattro(PyObject *attr) { - char *attr_str= PyString_AsString(attr); + char *attr_str= _PyUnicode_AsString(attr); if (attr_str[1]=='\0') { // Group single letters // pos if (attr_str[0]=='x') @@ -141,8 +139,8 @@ KX_VertexProxy::py_getattro(PyObject *attr) if (attr_str[0]=='v') return PyFloat_FromDouble(m_vertex->getUV1()[1]); } - - + + if (!strcmp(attr_str, "XYZ")) return PyObjectFrom(MT_Vector3(m_vertex->getXYZ())); @@ -156,22 +154,21 @@ KX_VertexProxy::py_getattro(PyObject *attr) color /= 255.0; return PyObjectFrom(color); } - + if (!strcmp(attr_str, "normal")) { return PyObjectFrom(MT_Vector3(m_vertex->getNormal())); } - + py_getattro_up(CValue); } +#endif -PyObject* KX_VertexProxy::py_getattro_dict() { - py_getattro_dict_up(CValue); -} +#if 0 int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) { - char *attr_str= PyString_AsString(attr); + char *attr_str= _PyUnicode_AsString(attr); if (PySequence_Check(pyvalue)) { if (!strcmp(attr_str, "XYZ")) @@ -185,7 +182,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) } return PY_SET_ATTR_FAIL; } - + if (!strcmp(attr_str, "UV")) { MT_Point2 vec; @@ -197,7 +194,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) } return PY_SET_ATTR_FAIL; } - + if (!strcmp(attr_str, "color") || !strcmp(attr_str, "colour")) { MT_Vector4 vec; @@ -209,7 +206,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) } return PY_SET_ATTR_FAIL; } - + if (!strcmp(attr_str, "normal")) { MT_Vector3 vec; @@ -222,7 +219,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) return PY_SET_ATTR_FAIL; } } - + if (PyFloat_Check(pyvalue)) { float val = PyFloat_AsDouble(pyvalue); @@ -235,7 +232,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } - + if (!strcmp(attr_str, "y")) { pos.y() = val; @@ -243,7 +240,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } - + if (!strcmp(attr_str, "z")) { pos.z() = val; @@ -251,7 +248,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } - + // uv MT_Point2 uv = m_vertex->getUV1(); if (!strcmp(attr_str, "u")) @@ -287,7 +284,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } - + // col unsigned int icol = *((const unsigned int *)m_vertex->getRGBA()); unsigned char *cp = (unsigned char*) &icol; @@ -321,9 +318,10 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) return PY_SET_ATTR_SUCCESS; } } - + return CValue::py_setattro(attr, pyvalue); } +#endif KX_VertexProxy::KX_VertexProxy(KX_MeshProxy*mesh, RAS_TexVert* vertex) : m_vertex(vertex), @@ -339,7 +337,7 @@ KX_VertexProxy::~KX_VertexProxy() // stuff for cvalue related things CValue* KX_VertexProxy::Calc(VALUE_OPERATOR, CValue *) { return NULL;} -CValue* KX_VertexProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;} +CValue* KX_VertexProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;} STR_String sVertexName="vertex"; const STR_String & KX_VertexProxy::GetText() {return sVertexName;}; double KX_VertexProxy::GetNumber() { return -1;} @@ -348,7 +346,7 @@ void KX_VertexProxy::SetName(const char *) { }; CValue* KX_VertexProxy::GetReplica() { return NULL;} // stuff for python integration - + PyObject* KX_VertexProxy::PyGetXYZ() { return PyObjectFrom(MT_Point3(m_vertex->getXYZ())); @@ -359,7 +357,7 @@ PyObject* KX_VertexProxy::PySetXYZ(PyObject* value) MT_Point3 vec; if (!PyVecTo(value, vec)) return NULL; - + m_vertex->SetXYZ(vec); m_mesh->SetMeshModified(true); Py_RETURN_NONE; @@ -375,7 +373,7 @@ PyObject* KX_VertexProxy::PySetNormal(PyObject* value) MT_Vector3 vec; if (!PyVecTo(value, vec)) return NULL; - + m_vertex->SetNormal(vec); m_mesh->SetMeshModified(true); Py_RETURN_NONE; @@ -385,18 +383,18 @@ PyObject* KX_VertexProxy::PySetNormal(PyObject* value) PyObject* KX_VertexProxy::PyGetRGBA() { int *rgba = (int *) m_vertex->getRGBA(); - return PyInt_FromLong(*rgba); + return PyLong_FromSsize_t(*rgba); } PyObject* KX_VertexProxy::PySetRGBA(PyObject* value) { - if PyInt_Check(value) { - int rgba = PyInt_AsLong(value); + if PyLong_Check(value) { + int rgba = PyLong_AsSsize_t(value); m_vertex->SetRGBA(rgba); m_mesh->SetMeshModified(true); Py_RETURN_NONE; } - else { + else { MT_Vector4 vec; if (PyVecTo(value, vec)) { @@ -405,7 +403,7 @@ PyObject* KX_VertexProxy::PySetRGBA(PyObject* value) Py_RETURN_NONE; } } - + PyErr_SetString(PyExc_TypeError, "vert.setRGBA(value): KX_VertexProxy, expected a 4D vector or an int"); return NULL; } @@ -421,7 +419,7 @@ PyObject* KX_VertexProxy::PySetUV(PyObject* value) MT_Point2 vec; if (!PyVecTo(value, vec)) return NULL; - + m_vertex->SetUV(vec); m_mesh->SetMeshModified(true); Py_RETURN_NONE; @@ -436,14 +434,14 @@ PyObject* KX_VertexProxy::PySetUV2(PyObject* args) { MT_Point2 vec; unsigned int unit= RAS_TexVert::SECOND_UV; - + PyObject* list= NULL; if(!PyArg_ParseTuple(args, "O|i:setUV2", &list, &unit)) return NULL; - + if (!PyVecTo(list, vec)) return NULL; - + m_vertex->SetFlag((m_vertex->getFlag()|RAS_TexVert::SECOND_UV)); m_vertex->SetUnit(unit); m_vertex->SetUV2(vec); diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h index 42db5fbc322..13c57e9f556 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.h +++ b/source/gameengine/Ketsji/KX_VertexProxy.h @@ -53,9 +53,6 @@ public: // stuff for python integration - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *pyvalue); KX_PYMETHOD_NOARGS(KX_VertexProxy,GetXYZ); KX_PYMETHOD_O(KX_VertexProxy,SetXYZ); diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp index d848065ad73..3561ccde9d9 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp @@ -39,10 +39,9 @@ KX_VisibilityActuator::KX_VisibilityActuator( SCA_IObject* gameobj, bool visible, bool occlusion, - bool recursive, - PyTypeObject* T + bool recursive ) - : SCA_IActuator(gameobj,T), + : SCA_IActuator(gameobj), m_visible(visible), m_occlusion(occlusion), m_recursive(recursive) @@ -108,25 +107,18 @@ PyTypeObject KX_VisibilityActuator::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, - py_base_getattro, - py_base_setattro, 0,0,0,0,0,0,0,0,0, - Methods - -}; - -PyParentObject -KX_VisibilityActuator::Parents[] = { - &KX_VisibilityActuator::Type, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, &SCA_IActuator::Type, - &SCA_ILogicBrick::Type, - &CValue::Type, - NULL + 0,0,0,0,0,0, + py_base_new }; -PyMethodDef -KX_VisibilityActuator::Methods[] = { +PyMethodDef KX_VisibilityActuator::Methods[] = { // Deprecated -----> {"set", (PyCFunction) KX_VisibilityActuator::sPySetVisible, METH_VARARGS, (PY_METHODCHAR) SetVisible_doc}, @@ -141,21 +133,6 @@ PyAttributeDef KX_VisibilityActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_VisibilityActuator::py_getattro(PyObject *attr) -{ - py_getattro_up(SCA_IActuator); -} - -PyObject* KX_VisibilityActuator::py_getattro_dict() { - py_getattro_dict_up(SCA_IActuator); -} - -int KX_VisibilityActuator::py_setattro(PyObject *attr, PyObject *value) -{ - py_setattro_up(SCA_IActuator); -} - - /* set visibility ---------------------------------------------------------- */ const char KX_VisibilityActuator::SetVisible_doc[] = diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.h b/source/gameengine/Ketsji/KX_VisibilityActuator.h index 45aba50f645..3ad50c6cea2 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.h +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.h @@ -48,9 +48,7 @@ class KX_VisibilityActuator : public SCA_IActuator SCA_IObject* gameobj, bool visible, bool occlusion, - bool recursive, - PyTypeObject* T=&Type - ); + bool recursive); virtual ~KX_VisibilityActuator( @@ -69,10 +67,6 @@ class KX_VisibilityActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); - virtual PyObject* py_getattro_dict(); - virtual int py_setattro(PyObject *attr, PyObject *value); - // Deprecated -----> KX_PYMETHOD_DOC_VARARGS(KX_VisibilityActuator,SetVisible); // <----- diff --git a/source/gameengine/Ketsji/Makefile b/source/gameengine/Ketsji/Makefile index 59b3ff178fb..8e91eb6ff9a 100644 --- a/source/gameengine/Ketsji/Makefile +++ b/source/gameengine/Ketsji/Makefile @@ -44,7 +44,7 @@ CPPFLAGS += -I../../blender/python CPPFLAGS += -I../../blender/python/generic CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include -CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO) -I$(NAN_MOTO)/include +CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_MOTO)/include CPPFLAGS += -I$(NAN_SOLID)/include CPPFLAGS += -I$(NAN_BULLET2)/include CPPFLAGS += -I../Rasterizer/RAS_OpenGLRasterizer @@ -54,14 +54,11 @@ CPPFLAGS += -I../../kernel/gen_system CPPFLAGS += -I../Network -IKXNetwork CPPFLAGS += -I../Physics/common CPPFLAGS += -I../Physics/Dummy -CPPFLAGS += -I../Physics/Sumo -CPPFLAGS += -I../Physics/BlOde CPPFLAGS += -I../Physics/Bullet CPPFLAGS += -I. CPPFLAGS += -I../Converter CPPFLAGS += -I../../blender/blenkernel CPPFLAGS += -I../../blender/blenlib -CPPFLAGS += -I../../blender/editors/include CPPFLAGS += -I../../blender/makesdna CPPFLAGS += -I../../blender/imbuf CPPFLAGS += -I../../blender/gpu diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript index 49dbacc8916..b09267b79ff 100644 --- a/source/gameengine/Ketsji/SConscript +++ b/source/gameengine/Ketsji/SConscript @@ -18,16 +18,9 @@ incs += ' #source/blender/blenkernel #source/blender #source/blender/editors/inc incs += ' #source/blender/makesdna #source/blender/python #source/gameengine/Rasterizer' incs += ' #source/gameengine/GameLogic #source/gameengine/Expressions #source/gameengine/Network' incs += ' #source/gameengine/SceneGraph #source/gameengine/Physics/common #source/gameengine/Physics/Bullet' -incs += ' #source/gameengine/Physics/BlOde #source/gameengine/Physics/Dummy' +incs += ' #source/gameengine/Physics/Dummy' incs += ' #source/blender/misc #source/blender/blenloader #extern/glew/include #source/blender/gpu' -if env['WITH_BF_SOLID']: - incs += ' #source/gameengine/Physics/Sumo #source/gameengine/Physics/Sumo/include' - incs += ' #source/gameengine/Physics/Sumo/Fuzzics/include #source/gameengine/Network/LoopBackNetwork' - incs += ' ' + env['BF_SOLID_INC'] - defs += ' USE_SUMO_SOLID' - - incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_BULLET_INC'] incs += ' ' + env['BF_OPENGL_INC'] diff --git a/source/gameengine/Physics/BlOde/Makefile b/source/gameengine/Physics/BlOde/Makefile deleted file mode 100644 index 1fbbf198377..00000000000 --- a/source/gameengine/Physics/BlOde/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -# -# $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. -# -# The Original Code is: all of this file. -# -# Contributor(s): none yet. -# -# ***** END GPL LICENSE BLOCK ***** -# -# - -LIBNAME = blode -DIR = $(OCGDIR)/gameengine/blphys/$(LIBNAME) - -include nan_compile.mk - -CCFLAGS += $(LEVEL_1_CPP_WARNINGS) - -CPPFLAGS += -I$(OPENGL_HEADERS) -CPPFLAGS += -I$(NAN_STRING)/include -CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) - -CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO)/include -I$(NAN_MOTO)/include -CPPFLAGS += -I$(NAN_ODE)/include -CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include -CPPFLAGS += -I../../Physics/common -CPPFLAGS += -I../../Physics/Dummy -# nlin: fix this, should put in NAN_ODE dir -#CPPFLAGS += -I./ode/ode/include diff --git a/source/gameengine/Physics/BlOde/OdePhysicsController.cpp b/source/gameengine/Physics/BlOde/OdePhysicsController.cpp deleted file mode 100644 index 5efd0994311..00000000000 --- a/source/gameengine/Physics/BlOde/OdePhysicsController.cpp +++ /dev/null @@ -1,625 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * The contents of this file may be used under the terms of either the GNU - * General Public License Version 2 or later (the "GPL", see - * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or - * later (the "BL", see http://www.blender.org/BL/ ) which has to be - * bought from the Blender Foundation to become active, in which case the - * above mentioned GPL option does not apply. - * - * The Original Code is Copyright (C) 2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#define USE_ODE -#ifdef USE_ODE - -#include "OdePhysicsController.h" -#include "PHY_IMotionState.h" - -#include - -#ifdef HAVE_CONFIG_H -#include -#endif - -/////////////////////////////////////////////////////////////////////////// -// -// general to-do list for ODE physics. This is maintained in doxygen format. -// -/// \todo determine assignment time for bounding spheres. -/// -/// it appears you have to select "sphere" for bounding volume AND "draw bounds" -/// in order for a bounding sphere to be generated. otherwise a box is generated. -/// determine exactly when and how the bounding volumes are generated and make -/// this consistent. -/// } -/// -/// \todo bounding sphere size incorrect -/// -/// it appears NOT to use the size of the shown bounding sphere (button "draw bounds"). -/// it appears instead to use the size of the "size" dynamic parameter in the -/// gamebuttons but this "size" draws an incorrectly-sized circle on screen for the -/// bounding sphere (leftover skewed size calculation from sumo?) so figure out WHERE -/// its getting the radius from. -/// -/// \todo ODE collisions must fire collision actuator -/// -/// See OdePhysicsEnvironment::OdeNearCallback. If a sensor was created to check -/// for the presence of this collision, then in the NearCallback you need to -/// take appropriate action regarding the sensor - something like checking its -/// controller and if needed firing its actuator. Need to find similar code in -/// Fuzzics which fires collision controllers/actuators. -/// -/// \todo Are ghost collisions possible? -/// -/// How do ghost collisions work? Do they require collision detection through ODE -/// and NON-CREATION of contact-joint in OdeNearCallback? Currently OdeNearCallback -/// creates joints ALWAYS for collisions. -/// -/// \todo Why is KX_GameObject::addLinearVelocity commented out? -/// -/// Try putting this code back in. -/// -/// \todo Too many non-dynamic actors bogs down ODE physics -/// -/// Lots of "geoms" (ODE static geometry) probably slows down ode. Try a test file -/// with lots of static geometry - the game performance in Blender says it is -/// spending all its time in physics, and I bet all that time is in collision -/// detection. It's ode's non-hierarchical collision detection. -/// try making a separate ode test program (not within blender) with 1000 geoms and -/// see how fast it is. if it is really slow, there is the culprit. -/// isnt someone working on an improved ODE collision detector? check -/// ode mailing list. -/// -/// -/// \todo support collision of dynas with non-dynamic triangle meshes -/// -/// ODE has trimesh-collision support but only for trimeshes without a transform -/// matrix. update ODE tricollider to support a transform matrix. this will allow -/// moving trimeshes non-dynamically (e.g. through Ipos). then collide trimeshes -/// with dynas. this allows dynamic primitives (spheres, boxes) to collide with -/// non-dynamic or kinematically controlled tri-meshes. full dynamic trimesh to -/// dynamic trimesh support is hard because it requires (a) collision and penetration -/// depth for trimesh to trimesh and (hard to compute) (b) an intertia tensor -/// (easy to compute). -/// -/// a triangle mesh collision geometry should be created when the blender -/// bounding volume (F9, EDITBUTTONS) is set to "polyheder", since this is -/// currently the place where sphere/box selection is made -/// -/// \todo specify ODE ERP+CFM in blender interface -/// -/// when ODE physics selected, have to be able to set global cfm and erp. -/// per-joint erp/cfm could be handled in constraint window. -/// -/// \todo moving infinite mass objects should impart extra impulse to objects they collide with -/// -/// currently ODE's ERP pushes them apart but doesn't account for their motion. -/// you have to detect if one body in a collision is a non-dyna. This -/// requires adding a new accessor method to -/// KX_IPhysicsInterfaceController to access the hidden m_isDyna variable, -/// currently it can only be written, not read). If one of the bodies in a -/// collision is a non-dyna, then impart an extra impulse based on the -/// motion of the static object (using its last 2 frames as an approximation -/// of its linear and angular velocity). Linear velocity is easy to -/// approximate, but angular? you have orientation at this frame and -/// orientation at previous frame. The question is what is the angular -/// velocity which would have taken you from the previous frame's orientation -/// to this frame's orientation? -/// -/// \todo allow tweaking bounding volume size -/// -/// the scene converter currently uses the blender bounding volume of the selected -/// object as the geometry for ODE collision purposes. this is good and automatic -/// intuitive - lets you choose between cube, sphere, mesh. but you need to be able -/// to tweak this size for physics. -/// -/// \todo off center meshes totally wrong for ode -/// -/// ode uses x, y, z extents regradless of center. then places geom at center of object. -/// but visual geom is not necessarily at center. need to detect off-center situations. -/// then do what? treat it as an encapsulated off-center mass, or recenter it? -/// -/// i.o.w. recalculate center, or recalculate mass distribution (using encapsulation)? -/// -/// \todo allow off-center mass -/// -/// using ode geometry encapsulators -/// -/// \todo allow entering compound geoms for complex collision shapes specified as a union of simpler shapes -/// -/// The collision shape for arbitrary triangle meshes can probably in general be -///well approximated by a compound ODE geometry object, which is merely a combination -///of many primitives (capsule, sphere, box). I eventually want to add the ability -///to associate compound geometry objects with Blender gameobjects. I think one -///way of doing this would be to add a new button in the GameButtons, "RigidBodyCompound". -///If the object is "Dynamic" + "RigidBody", then the object's bounding volume (sphere, -///box) is created. If an object is "Dynamic" + "RigidBodyCompound", then the object itself -///will merely create a "wrapper" compound object, with the actual geometry objects -///being created from the object's children in Blender. E.g. if I wanted to make a -///compound collision object consisting of a sphere and 2 boxes, I would create a -///parent gameobject with the actual triangle mesh, and set its GameButtons to -///"RigidBodyCompound". I would then create 3 children of this object, 1 sphere and -///2 boxes, and set the GameButtons for the children to be "RigidBody". Then at -///scene conversion time, the scene converter sees "RigidBodyCompound" for the -///top-level object, then appropriately traverses the children and creates the compound -///collision geometry consisting of 2 boxes and a sphere. In this way, arbitrary -///mesh-mesh collision becomes much less necessary - the artist can (or must, -///depending on your point of view!) approximate the collision shape for arbitrary -///meshes with a combination of one or more primitive shapes. I think using the -///parent/child relationship in Blender and a new button "RigidBodyCompound" for the -///parent object of a compound is a feasible way of doing this in Blender. -/// -///See ODE demo test_boxstack and look at the code when you drop a compound object -///with the "X" key. -/// -/// \todo add visual specification of constraints -/// -/// extend the armature constraint system. by using empties and constraining one empty -/// to "copy location" of another, you can get a p2p constraint between the two empties. -/// by making the two empties each a parent of a blender object, you effectively have -/// a p2p constraint between 2 blender bodies. the scene converter can detect these -/// empties, detect the constraint, and generate an ODE constraint. -/// -/// then add a new constraint type "hinge" and "slider" to correspond to ODE joints. -/// e.g. a slider would be a constraint which restricts the axis of its object to lie -/// along the same line as another axis of a different object. e.g. you constrain x-axis -/// of one empty to lie along the same line as the z-axis of another empty; this gives -/// a slider joint. -/// -/// open questions: how to handle powered joints? to what extent should/must constraints -/// be enforced during modeling? use CCD-style algorithm in modeler to enforce constraints? -/// how about ODE powered constraints e.g. motors? -/// -/// \todo enable suspension of bodies -/// ODE offers native support for suspending dynas. but what about suspending non-dynas -/// (e.g. geoms)? suspending geoms is also necessary to ease the load of ODE's (simple?) -/// collision detector. suspending dynas and geoms is important for the activity culling, -/// which apparently works at a simple level. perhaps suspension should actually -/// remove or insert geoms/dynas into the ODE space/world? is this operation (insertion/ -/// removal) fast enough at run-time? test it. if fast enough, then suspension=remove from -/// ODE simulation, awakening=insertion into ODE simulation. -/// -/// \todo python interface for tweaking constraints via python -/// -/// \todo raytesting to support gameengine sensors that need it -/// -/// \todo investigate compatibility issues with old Blender 2.25 physics engine (sumo/fuzzics) -/// is it possible to have compatibility? how hard is it? how important is it? - - -ODEPhysicsController::ODEPhysicsController(bool dyna, bool fullRigidBody, - bool phantom, class PHY_IMotionState* motionstate, struct dxSpace* space, - struct dxWorld* world, float mass,float friction,float restitution, - bool implicitsphere,float center[3],float extents[3],float radius) - : - m_OdeDyna(dyna), - m_firstTime(true), - m_bFullRigidBody(fullRigidBody), - m_bPhantom(phantom), - m_bKinematic(false), - m_bPrevKinematic(false), - m_MotionState(motionstate), - m_OdeSuspendDynamics(false), - m_space(space), - m_world(world), - m_mass(mass), - m_friction(friction), - m_restitution(restitution), - m_bodyId(0), - m_geomId(0), - m_implicitsphere(implicitsphere), - m_radius(radius) -{ - m_center[0] = center[0]; - m_center[1] = center[1]; - m_center[2] = center[2]; - m_extends[0] = extents[0]; - m_extends[1] = extents[1]; - m_extends[2] = extents[2]; -}; - - -ODEPhysicsController::~ODEPhysicsController() -{ - if (m_geomId) - { - dGeomDestroy (m_geomId); - } -} - -float ODEPhysicsController::getMass() -{ - dMass mass; - dBodyGetMass(m_bodyId,&mass); - return mass.mass; -} - -////////////////////////////////////////////////////////////////////// -/// \todo Impart some extra impulse to dynamic objects when they collide with kinematically controlled "static" objects (ODE geoms), by using last 2 frames as 1st order approximation to the linear/angular velocity, and computing an appropriate impulse. Sumo (old physics engine) did this, see for details. -/// \todo handle scaling of static ODE geoms or fail with error message if Ipo tries to change scale of a static geom object - -bool ODEPhysicsController::SynchronizeMotionStates(float time) -{ - /** - 'Late binding' of the rigidbody, because the World Scaling is not available until the scenegraph is traversed - */ - - - if (m_firstTime) - { - m_firstTime=false; - - m_MotionState->calculateWorldTransformations(); - - dQuaternion worldquat; - float worldpos[3]; - -#ifdef dDOUBLE - m_MotionState->getWorldOrientation((float)worldquat[1], - (float)worldquat[2],(float)worldquat[3],(float)worldquat[0]); -#else - m_MotionState->getWorldOrientation(worldquat[1], - worldquat[2],worldquat[3],worldquat[0]); -#endif - m_MotionState->getWorldPosition(worldpos[0],worldpos[1],worldpos[2]); - - float scaling[3]; - m_MotionState->getWorldScaling(scaling[0],scaling[1],scaling[2]); - - if (!m_bPhantom) - { - if (m_implicitsphere) - { - m_geomId = dCreateSphere (m_space,m_radius*scaling[0]); - } else - { - m_geomId = dCreateBox (m_space, m_extends[0]*scaling[0],m_extends[1]*scaling[1],m_extends[2]*scaling[2]); - } - } else - { - m_geomId=0; - } - - if (m_geomId) - dGeomSetData(m_geomId,this); - - if (!this->m_OdeDyna) - { - if (!m_bPhantom) - { - dGeomSetPosition (this->m_geomId,worldpos[0],worldpos[1],worldpos[2]); - dMatrix3 R; - dQtoR (worldquat, R); - dGeomSetRotation (this->m_geomId,R); - } - } else - { - //it's dynamic, so create a 'model' - m_bodyId = dBodyCreate(this->m_world); - dBodySetPosition (m_bodyId,worldpos[0],worldpos[1],worldpos[2]); - dBodySetQuaternion (this->m_bodyId,worldquat); - //this contains both scalar mass and inertia tensor - dMass m; - float length=1,width=1,height=1; - dMassSetBox (&m,1,m_extends[0]*scaling[0],m_extends[1]*scaling[1],m_extends[2]*scaling[2]); - dMassAdjust (&m,this->m_mass); - dBodySetMass (m_bodyId,&m); - - if (!m_bPhantom) - { - dGeomSetBody (m_geomId,m_bodyId); - } - - - } - - if (this->m_OdeDyna && !m_bFullRigidBody) - { - // ?? huh? what to do here? - } - } - - - - if (m_OdeDyna) - { - if (this->m_OdeSuspendDynamics) - { - return false; - } - - const float* worldPos = (float *)dBodyGetPosition(m_bodyId); - m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]); - - const float* worldquat = (float *)dBodyGetQuaternion(m_bodyId); - m_MotionState->setWorldOrientation(worldquat[1],worldquat[2],worldquat[3],worldquat[0]); - } - else { - // not a dyna, so dynamics (i.e. this controller) has not updated - // anything. BUT! an Ipo or something else might have changed the - // position/orientation of this geometry. - // so update the static geom position - - /// \todo impart some extra impulse to colliding objects! - dQuaternion worldquat; - float worldpos[3]; - -#ifdef dDOUBLE - m_MotionState->getWorldOrientation((float)worldquat[1], - (float)worldquat[2],(float)worldquat[3],(float)worldquat[0]); -#else - m_MotionState->getWorldOrientation(worldquat[1], - worldquat[2],worldquat[3],worldquat[0]); -#endif - m_MotionState->getWorldPosition(worldpos[0],worldpos[1],worldpos[2]); - - float scaling[3]; - m_MotionState->getWorldScaling(scaling[0],scaling[1],scaling[2]); - - /// \todo handle scaling! what if Ipo changes scale of object? - // Must propagate to geom... is scaling geoms possible with ODE? Also - // what about scaling trimeshes, that is certainly difficult... - dGeomSetPosition (this->m_geomId,worldpos[0],worldpos[1],worldpos[2]); - dMatrix3 R; - dQtoR (worldquat, R); - dGeomSetRotation (this->m_geomId,R); - } - - return false; //it update the worldpos -} - -PHY_IMotionState* ODEPhysicsController::GetMotionState() -{ - return m_MotionState; -} - - -// kinematic methods -void ODEPhysicsController::RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local) -{ - -} -void ODEPhysicsController::RelativeRotate(const float drot[9],bool local) -{ -} -void ODEPhysicsController::setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal) -{ - - dQuaternion worldquat; - worldquat[0] = quatReal; - worldquat[1] = quatImag0; - worldquat[2] = quatImag1; - worldquat[3] = quatImag2; - - if (!this->m_OdeDyna) - { - dMatrix3 R; - dQtoR (worldquat, R); - dGeomSetRotation (this->m_geomId,R); - } else - { - dBodySetQuaternion (m_bodyId,worldquat); - this->m_MotionState->setWorldOrientation(quatImag0,quatImag1,quatImag2,quatReal); - } - -} - -void ODEPhysicsController::getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal) -{ - float q[4]; - this->m_MotionState->getWorldOrientation(q[0],q[1],q[2],q[3]); - quatImag0=q[0]; - quatImag1=q[1]; - quatImag2=q[2]; - quatReal=q[3]; -} - -void ODEPhysicsController::getPosition(PHY__Vector3& pos) const -{ - m_MotionState->getWorldPosition(pos[0],pos[1],pos[2]); - -} - -void ODEPhysicsController::setPosition(float posX,float posY,float posZ) -{ - if (!m_bPhantom) - { - if (!this->m_OdeDyna) - { - dGeomSetPosition (m_geomId, posX, posY, posZ); - } else - { - dBodySetPosition (m_bodyId, posX, posY, posZ); - } - } -} -void ODEPhysicsController::setScaling(float scaleX,float scaleY,float scaleZ) -{ -} - -// physics methods -void ODEPhysicsController::ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local) -{ - if (m_OdeDyna) { - if(local) { - dBodyAddRelTorque(m_bodyId, torqueX, torqueY, torqueZ); - } else { - dBodyAddTorque (m_bodyId, torqueX, torqueY, torqueZ); - } - } -} - -void ODEPhysicsController::ApplyForce(float forceX,float forceY,float forceZ,bool local) -{ - if (m_OdeDyna) { - if(local) { - dBodyAddRelForce(m_bodyId, forceX, forceY, forceZ); - } else { - dBodyAddForce (m_bodyId, forceX, forceY, forceZ); - } - } -} - -void ODEPhysicsController::SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local) -{ - if (m_OdeDyna) { - if(local) { - // TODO: translate angular vel into local frame, then apply - } else { - dBodySetAngularVel (m_bodyId, ang_velX,ang_velY,ang_velZ); - } - } -} - -void ODEPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local) -{ - if (m_OdeDyna) - { - dVector3 vel = {lin_velX,lin_velY,lin_velZ, 1.0}; - if (local) - { - dMatrix3 worldmat; - dVector3 localvel; - dQuaternion worldquat; - -#ifdef dDOUBLE - m_MotionState->getWorldOrientation((float)worldquat[1], - (float)worldquat[2], (float)worldquat[3],(float)worldquat[0]); -#else - m_MotionState->getWorldOrientation(worldquat[1],worldquat[2], - worldquat[3],worldquat[0]); -#endif - dQtoR (worldquat, worldmat); - - dMULTIPLY0_331 (localvel,worldmat,vel); - dBodySetLinearVel (m_bodyId, localvel[0],localvel[1],localvel[2]); - - } else - { - dBodySetLinearVel (m_bodyId, lin_velX,lin_velY,lin_velZ); - } - } -} - -void ODEPhysicsController::applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ) -{ - if (m_OdeDyna) - { - //apply linear and angular effect - const dReal* linvel = dBodyGetLinearVel(m_bodyId); - float mass = getMass(); - if (mass >= 0.00001f) - { - float massinv = 1.f/mass; - float newvel[3]; - newvel[0]=linvel[0]+impulseX*massinv; - newvel[1]=linvel[1]+impulseY*massinv; - newvel[2]=linvel[2]+impulseZ*massinv; - dBodySetLinearVel(m_bodyId,newvel[0],newvel[1],newvel[2]); - - const float* worldPos = (float *)dBodyGetPosition(m_bodyId); - - const float* angvelc = (float *)dBodyGetAngularVel(m_bodyId); - float angvel[3]; - angvel[0]=angvelc[0]; - angvel[1]=angvelc[1]; - angvel[2]=angvelc[2]; - - dVector3 impulse; - impulse[0]=impulseX; - impulse[1]=impulseY; - impulse[2]=impulseZ; - - dVector3 ap; - ap[0]=attachX-worldPos[0]; - ap[1]=attachY-worldPos[1]; - ap[2]=attachZ-worldPos[2]; - - dCROSS(angvel,+=,ap,impulse); - dBodySetAngularVel(m_bodyId,angvel[0],angvel[1],angvel[2]); - - } - - } - -} - -void ODEPhysicsController::SuspendDynamics() -{ - -} - -void ODEPhysicsController::RestoreDynamics() -{ - -} - - -/** - reading out information from physics -*/ -void ODEPhysicsController::GetLinearVelocity(float& linvX,float& linvY,float& linvZ) -{ - if (m_OdeDyna) - { - const float* vel = (float *)dBodyGetLinearVel(m_bodyId); - linvX = vel[0]; - linvY = vel[1]; - linvZ = vel[2]; - } else - { - linvX = 0.f; - linvY = 0.f; - linvZ = 0.f; - - } -} -/** - GetVelocity parameters are in geometric coordinates (Origin is not center of mass!). -*/ -void ODEPhysicsController::GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ) -{ - -} - - -void ODEPhysicsController::getReactionForce(float& forceX,float& forceY,float& forceZ) -{ - -} -void ODEPhysicsController::setRigidBody(bool rigid) -{ - -} - - -void ODEPhysicsController::PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl) -{ - m_MotionState = motionstate; - m_bKinematic = false; - m_bPrevKinematic = false; - m_firstTime = true; -} - - -void ODEPhysicsController::SetSimulatedTime(float time) -{ -} - - -void ODEPhysicsController::WriteMotionStateToDynamics(bool nondynaonly) -{ - -} -#endif diff --git a/source/gameengine/Physics/BlOde/OdePhysicsController.h b/source/gameengine/Physics/BlOde/OdePhysicsController.h deleted file mode 100644 index 544d11da2ca..00000000000 --- a/source/gameengine/Physics/BlOde/OdePhysicsController.h +++ /dev/null @@ -1,164 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * The contents of this file may be used under the terms of either the GNU - * General Public License Version 2 or later (the "GPL", see - * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or - * later (the "BL", see http://www.blender.org/BL/ ) which has to be - * bought from the Blender Foundation to become active, in which case the - * above mentioned GPL option does not apply. - * - * The Original Code is Copyright (C) 2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef __ODE_PHYSICSCONTROLLER_H -#define __ODE_PHYSICSCONTROLLER_H - - -#include "PHY_IPhysicsController.h" - -/** - ODE Physics Controller, a special kind of a PhysicsController. - A Physics Controller is a special kind of Scene Graph Transformation Controller. - Each time the scene graph get's updated, the controller get's a chance - in the 'Update' method to reflect changes. -*/ - -class ODEPhysicsController : public PHY_IPhysicsController - -{ - - bool m_OdeDyna; - -public: - ODEPhysicsController( - bool dyna, - bool fullRigidBody, - bool phantom, - class PHY_IMotionState* motionstate, - struct dxSpace* space, - struct dxWorld* world, - float mass, - float friction, - float restitution, - bool implicitsphere, - float center[3], - float extends[3], - float radius); - - virtual ~ODEPhysicsController(); - - // kinematic methods - virtual void RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local); - virtual void RelativeRotate(const float drot[9],bool local); - virtual void getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal); - virtual void setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal); - virtual void setPosition(float posX,float posY,float posZ); - virtual void getPosition(PHY__Vector3& pos) const; - - virtual void setScaling(float scaleX,float scaleY,float scaleZ); - - // physics methods - virtual void ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local); - virtual void ApplyForce(float forceX,float forceY,float forceZ,bool local); - virtual void SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local); - virtual void SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local); - virtual void applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ); - virtual void SetActive(bool active){}; - virtual void SuspendDynamics(); - virtual void RestoreDynamics(); - virtual void resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ) - { - //todo ? - } - - - /** - reading out information from physics - */ - virtual void GetLinearVelocity(float& linvX,float& linvY,float& linvZ); - /** - GetVelocity parameters are in geometric coordinates (Origin is not center of mass!). - */ - virtual void GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ); - virtual float getMass(); - virtual void getReactionForce(float& forceX,float& forceY,float& forceZ); - virtual void setRigidBody(bool rigid); - - - virtual void PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl); - - // \todo remove next line ! - virtual void SetSimulatedTime(float time); - - - virtual void WriteDynamicsToMotionState() {}; - virtual void WriteMotionStateToDynamics(bool nondynaonly); - virtual class PHY_IMotionState* GetMotionState(); - - /** - call from Scene Graph Node to 'update'. - */ - virtual bool SynchronizeMotionStates(float time); - - virtual void calcXform(){} - virtual void SetMargin(float margin) {} - virtual float GetMargin() const {return 0.f;} - virtual float GetRadius() const {return 0.f;} - virtual void SetRadius(float margin) {} - - // clientinfo for raycasts for example - virtual void* getNewClientInfo() { return m_clientInfo;} - virtual void setNewClientInfo(void* clientinfo) {m_clientInfo = clientinfo;}; - void* m_clientInfo; - - struct dxBody* GetOdeBodyId() { return m_bodyId; } - - float getFriction() { return m_friction;} - float getRestitution() { return m_restitution;} - - float GetLinVelocityMin() const { return 0.f; } - void SetLinVelocityMin(float val) { } - float GetLinVelocityMax() const { return 0.f; } - void SetLinVelocityMax(float val) { } - - -private: - - bool m_firstTime; - bool m_bFullRigidBody; - bool m_bPhantom; // special flag for objects that are not affected by physics 'resolver' - - // data to calculate fake velocities for kinematic objects (non-dynas) - bool m_bKinematic; - bool m_bPrevKinematic; - - - float m_lastTime; - bool m_OdeSuspendDynamics; - class PHY_IMotionState* m_MotionState; - - //Ode specific members - struct dxBody* m_bodyId; - struct dxGeom* m_geomId; - struct dxSpace* m_space; - struct dxWorld* m_world; - float m_mass; - float m_friction; - float m_restitution; - bool m_implicitsphere; - float m_center[3]; - float m_extends[3]; - float m_radius; -}; - -#endif //__ODE_PHYSICSCONTROLLER_H - diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp deleted file mode 100644 index 54e97858b7f..00000000000 --- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp +++ /dev/null @@ -1,277 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * The contents of this file may be used under the terms of either the GNU - * General Public License Version 2 or later (the "GPL", see - * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or - * later (the "BL", see http://www.blender.org/BL/ ) which has to be - * bought from the Blender Foundation to become active, in which case the - * above mentioned GPL option does not apply. - * - * The Original Code is Copyright (C) 2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#include "OdePhysicsEnvironment.h" -#include "PHY_IMotionState.h" -#include "OdePhysicsController.h" - -#include -#include <../ode/src/joint.h> -#include - -ODEPhysicsEnvironment::ODEPhysicsEnvironment() -{ - m_OdeWorld = dWorldCreate(); - m_OdeSpace = dHashSpaceCreate(); - m_OdeContactGroup = dJointGroupCreate (0); - dWorldSetCFM (m_OdeWorld,1e-5f); - - m_JointGroup = dJointGroupCreate(0); - - setFixedTimeStep(true,1.f/60.f); -} - - - -ODEPhysicsEnvironment::~ODEPhysicsEnvironment() -{ - dJointGroupDestroy (m_OdeContactGroup); - dJointGroupDestroy (m_JointGroup); - - dSpaceDestroy (m_OdeSpace); - dWorldDestroy (m_OdeWorld); -} - - - -void ODEPhysicsEnvironment::setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep) -{ - m_useFixedTimeStep = useFixedTimeStep; - - if (useFixedTimeStep) - { - m_fixedTimeStep = fixedTimeStep; - } else - { - m_fixedTimeStep = 0.f; - } - m_currentTime = 0.f; - - //todo:implement fixed timestepping - -} -float ODEPhysicsEnvironment::getFixedTimeStep() -{ - return m_fixedTimeStep; -} - - - -bool ODEPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep1,float interval) -{ - - float deltaTime = timeStep1; - int numSteps = 1; - - if (m_useFixedTimeStep) - { - m_currentTime += timeStep1; - // equal to subSampling (might be a little smaller). - numSteps = (int)(m_currentTime / m_fixedTimeStep); - m_currentTime -= m_fixedTimeStep * (float)numSteps; - deltaTime = m_fixedTimeStep; - //todo: experiment by smoothing the remaining time over the substeps - } - - for (int i=0;iClearOdeContactGroup(); - } - return true; -} - -void ODEPhysicsEnvironment::setGravity(float x,float y,float z) -{ - dWorldSetGravity (m_OdeWorld,x,y,z); -} - - - -int ODEPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type, - float pivotX,float pivotY,float pivotZ,float axisX,float axisY,float axisZ) -{ - - int constraintid = 0; - ODEPhysicsController* dynactrl = (ODEPhysicsController*)ctrl; - ODEPhysicsController* dynactrl2 = (ODEPhysicsController*)ctrl2; - - switch (type) - { - case PHY_POINT2POINT_CONSTRAINT: - { - if (dynactrl) - { - dJointID jointid = dJointCreateBall (m_OdeWorld,m_JointGroup); - struct dxBody* bodyid1 = dynactrl->GetOdeBodyId(); - struct dxBody* bodyid2=0; - const dReal* pos = dBodyGetPosition(bodyid1); - const dReal* R = dBodyGetRotation(bodyid1); - dReal offset[3] = {pivotX,pivotY,pivotZ}; - dReal newoffset[3]; - dMULTIPLY0_331 (newoffset,R,offset); - newoffset[0] += pos[0]; - newoffset[1] += pos[1]; - newoffset[2] += pos[2]; - - - if (dynactrl2) - bodyid2 = dynactrl2->GetOdeBodyId(); - - dJointAttach (jointid, bodyid1, bodyid2); - - dJointSetBallAnchor (jointid, newoffset[0], newoffset[1], newoffset[2]); - - constraintid = (int) jointid; - } - break; - } - case PHY_LINEHINGE_CONSTRAINT: - { - if (dynactrl) - { - dJointID jointid = dJointCreateHinge (m_OdeWorld,m_JointGroup); - struct dxBody* bodyid1 = dynactrl->GetOdeBodyId(); - struct dxBody* bodyid2=0; - const dReal* pos = dBodyGetPosition(bodyid1); - const dReal* R = dBodyGetRotation(bodyid1); - dReal offset[3] = {pivotX,pivotY,pivotZ}; - dReal axisset[3] = {axisX,axisY,axisZ}; - - dReal newoffset[3]; - dReal newaxis[3]; - dMULTIPLY0_331 (newaxis,R,axisset); - - dMULTIPLY0_331 (newoffset,R,offset); - newoffset[0] += pos[0]; - newoffset[1] += pos[1]; - newoffset[2] += pos[2]; - - - if (dynactrl2) - bodyid2 = dynactrl2->GetOdeBodyId(); - - dJointAttach (jointid, bodyid1, bodyid2); - - dJointSetHingeAnchor (jointid, newoffset[0], newoffset[1], newoffset[2]); - dJointSetHingeAxis(jointid,newaxis[0],newaxis[1],newaxis[2]); - - constraintid = (int) jointid; - } - break; - } - default: - { - //not yet - } - } - - return constraintid; - -} - -void ODEPhysicsEnvironment::removeConstraint(void *constraintid) -{ - if (constraintid) - { - dJointDestroy((dJointID) constraintid); - } -} - -PHY_IPhysicsController* ODEPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ) -{ - - //m_OdeWorld - //collision detection / raytesting - return NULL; -} - - -void ODEPhysicsEnvironment::OdeNearCallback (void *data, dGeomID o1, dGeomID o2) -{ - // \todo if this is a registered collision sensor - // fire the callback - - int i; - // if (o1->body && o2->body) return; - ODEPhysicsEnvironment* env = (ODEPhysicsEnvironment*) data; - dBodyID b1,b2; - - b1 = dGeomGetBody(o1); - b2 = dGeomGetBody(o2); - // exit without doing anything if the two bodies are connected by a joint - if (b1 && b2 && dAreConnected (b1,b2)) return; - - ODEPhysicsController * ctrl1 =(ODEPhysicsController *)dGeomGetData(o1); - ODEPhysicsController * ctrl2 =(ODEPhysicsController *)dGeomGetData(o2); - float friction=ctrl1->getFriction(); - float restitution = ctrl1->getRestitution(); - //for friction, take minimum - - friction=(friction < ctrl2->getFriction() ? - friction :ctrl2->getFriction()); - - //restitution:take minimum - restitution = restitution < ctrl2->getRestitution()? - restitution : ctrl2->getRestitution(); - - dContact contact[3]; // up to 3 contacts per box - for (i=0; i<3; i++) { - contact[i].surface.mode = dContactBounce; //dContactMu2; - contact[i].surface.mu = friction;//dInfinity; - contact[i].surface.mu2 = 0; - contact[i].surface.bounce = restitution;//0.5; - contact[i].surface.bounce_vel = 0.1f; - contact[i].surface.slip1=0.0; - } - - if (int numc = dCollide (o1,o2,3,&contact[0].geom,sizeof(dContact))) { - // dMatrix3 RI; - // dRSetIdentity (RI); - // const dReal ss[3] = {0.02,0.02,0.02}; - for (i=0; im_OdeWorld,env->m_OdeContactGroup,contact+i); - dJointAttach (c,b1,b2); - } - } -} - - -void ODEPhysicsEnvironment::ClearOdeContactGroup() -{ - dJointGroupEmpty (m_OdeContactGroup); -} - -int ODEPhysicsEnvironment::GetNumOdeContacts() -{ - return m_OdeContactGroup->num; -} - diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h deleted file mode 100644 index 54e4f7f90e1..00000000000 --- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h +++ /dev/null @@ -1,94 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * The contents of this file may be used under the terms of either the GNU - * General Public License Version 2 or later (the "GPL", see - * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or - * later (the "BL", see http://www.blender.org/BL/ ) which has to be - * bought from the Blender Foundation to become active, in which case the - * above mentioned GPL option does not apply. - * - * The Original Code is Copyright (C) 2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef _ODEPHYSICSENVIRONMENT -#define _ODEPHYSICSENVIRONMENT - - -#include "PHY_IPhysicsEnvironment.h" - -/** -* Physics Environment takes care of stepping the simulation and is a container for physics entities (rigidbodies,constraints, materials etc.) -* A derived class may be able to 'construct' entities by loading and/or converting -*/ -class ODEPhysicsEnvironment : public PHY_IPhysicsEnvironment -{ - - bool m_useFixedTimeStep; - float m_fixedTimeStep; - float m_currentTime; - -public: - ODEPhysicsEnvironment(); - virtual ~ODEPhysicsEnvironment(); - virtual void beginFrame() {} - virtual void endFrame() {} - - -// Perform an integration step of duration 'timeStep'. - virtual bool proceedDeltaTime(double curTime,float timeStep,float interval); - virtual void setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep); - virtual float getFixedTimeStep(); - - virtual void setGravity(float x,float y,float z); - virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type, - float pivotX,float pivotY,float pivotZ, - float axisX,float axisY,float axisZ); - - virtual void removeConstraint(void * constraintid); - virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ); - virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes, int occlusionRes) { return false; } - - - //gamelogic callbacks - virtual void addSensor(PHY_IPhysicsController* ctrl) {} - virtual void removeSensor(PHY_IPhysicsController* ctrl) {} - virtual void addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user) - { - } - virtual bool requestCollisionCallback(PHY_IPhysicsController* ctrl) {return false;} - virtual bool removeCollisionCallback(PHY_IPhysicsController* ctrl) {return false;} - virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position) {return 0;} - virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight) { return 0;} - - - - struct dxWorld* GetOdeWorld() { return m_OdeWorld; }; - struct dxSpace* GetOdeSpace() { return m_OdeSpace;}; - -private: - - - // ODE physics response - struct dxWorld* m_OdeWorld; - // ODE collision detection - struct dxSpace* m_OdeSpace; - void ClearOdeContactGroup(); - struct dxJointGroup* m_OdeContactGroup; - struct dxJointGroup* m_JointGroup; - - static void OdeNearCallback(void *data, struct dxGeom* o1, struct dxGeom* o2); - int GetNumOdeContacts(); - -}; - -#endif //_ODEPHYSICSENVIRONMENT - diff --git a/source/gameengine/Physics/BlOde/SConscript b/source/gameengine/Physics/BlOde/SConscript deleted file mode 100644 index 90e949d2d86..00000000000 --- a/source/gameengine/Physics/BlOde/SConscript +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/python -Import ('user_options_dict') -Import ('library_env') - -phy_ode_env = library_env.Copy () - -source_files = ['OdePhysicsController.cpp', - 'OdePhysicsEnvironment.cpp'] - -phy_ode_env.Append (CPPPATH=['.', - '../common', - ]) -phy_ode_env.Append (CPPPATH=user_options_dict['ODE_INCLUDE']) - -phy_ode_env.Library (target='#'+user_options_dict['BUILD_DIR']+'/lib/PHY_Ode', source=source_files) diff --git a/source/gameengine/Physics/Dummy/Makefile b/source/gameengine/Physics/Dummy/Makefile index b0c1b855322..c016a0bebcb 100644 --- a/source/gameengine/Physics/Dummy/Makefile +++ b/source/gameengine/Physics/Dummy/Makefile @@ -39,7 +39,7 @@ CPPFLAGS += -I$(OPENGL_HEADERS) CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) -CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO)/include -I$(NAN_MOTO)/include +CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_MOTO)/include CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include CPPFLAGS += -I../../Physics/common CPPFLAGS += -I../../Physics/Dummy diff --git a/source/gameengine/Physics/Makefile b/source/gameengine/Physics/Makefile index b192e497f35..da0d4cafd2e 100644 --- a/source/gameengine/Physics/Makefile +++ b/source/gameengine/Physics/Makefile @@ -32,7 +32,6 @@ include nan_definitions.mk SOURCEDIR = source/gameengine/Physics DIR = $(OCGDIR)/gameengine/blphys -DIRS = common Sumo Dummy Bullet -#DIRS += BlOde +DIRS = common Dummy Bullet include nan_subdirs.mk diff --git a/source/gameengine/Physics/Sumo/CMakeLists.txt b/source/gameengine/Physics/Sumo/CMakeLists.txt deleted file mode 100644 index c57a4af6706..00000000000 --- a/source/gameengine/Physics/Sumo/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -# $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, Blender Foundation -# All rights reserved. -# -# The Original Code is: all of this file. -# -# Contributor(s): Jacques Beaurain. -# -# ***** END GPL LICENSE BLOCK ***** - -SET(SRC - SumoPHYCallbackBridge.cpp - SumoPhysicsController.cpp - SumoPhysicsEnvironment.cpp - Fuzzics/src/SM_FhObject.cpp - Fuzzics/src/SM_Object.cpp - Fuzzics/src/SM_Scene.cpp - Fuzzics/src/SM_MotionState.cpp -) - -SET(INC - . - ../common - Fuzzics/include - ../../../../intern/moto/include - ../../../../extern/solid -) - -BLENDERLIB(bf_sumo "${SRC}" "${INC}") -#env.BlenderLib ( 'bf_sumo', sources, incs, [], libtype=['game2','player'], priority=[30, 70] , compileflags=cflags) diff --git a/source/gameengine/Physics/Sumo/Fuzzics/Makefile b/source/gameengine/Physics/Sumo/Fuzzics/Makefile deleted file mode 100644 index 5ed2c31a1d0..00000000000 --- a/source/gameengine/Physics/Sumo/Fuzzics/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# -# $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. -# -# The Original Code is: all of this file. -# -# Contributor(s): none yet. -# -# ***** END GPL LICENSE BLOCK ***** -# -# Bounces make to subdirectories. - -SOURCEDIR = source/gameengine/Physics/Sumo/Fuzzics -DIRS = src - -include nan_subdirs.mk diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Callback.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Callback.h deleted file mode 100644 index 42b5ab48ab6..00000000000 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Callback.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef SM_CALLBACK_H -#define SM_CALLBACK_H - -class SM_Callback { -public: - virtual void do_me() = 0; - virtual ~SM_Callback() {} -}; - -#endif - diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_ClientObjectInfo.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_ClientObjectInfo.h deleted file mode 100644 index 6749e7957ec..00000000000 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_ClientObjectInfo.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __SM_CLIENTOBJECT_INFO_H -#define __SM_CLIENTOBJECT_INFO_H - -/** - * Client Type and Additional Info. This structure can be use instead of a bare void* pointer, for safeness, and additional info for callbacks - */ - -struct SM_ClientObjectInfo -{ - int m_type; - void* m_clientobject1; - void* m_auxilary_info; -}; - -#endif //__SM_CLIENTOBJECT_INFO_H - diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Debug.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Debug.h deleted file mode 100644 index 48d5906e53d..00000000000 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Debug.h +++ /dev/null @@ -1,26 +0,0 @@ - - -#ifndef __SM_DEBUG_H__ -#define __SM_DEBUG_H__ - -/* Comment this to disable all SUMO debugging printfs */ - -#define SM_DEBUG - -#ifdef SM_DEBUG - -#include - -/* Uncomment this to printf all ray casts */ -//#define SM_DEBUG_RAYCAST - -/* Uncomment this to printf collision callbacks */ -//#define SM_DEBUG_BOING - -/* Uncomment this to printf Xform matrix calculations */ -//#define SM_DEBUG_XFORM - -#endif /* SM_DEBUG */ - -#endif /* __SM_DEBUG_H__ */ - diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h deleted file mode 100644 index b03612ed15e..00000000000 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * $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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef SM_FHOBJECT_H -#define SM_FHOBJECT_H - -#include "SM_Object.h" - -class SM_FhObject : public SM_Object { -public: - virtual ~SM_FhObject(); - SM_FhObject(DT_ShapeHandle rayshape, MT_Vector3 ray, SM_Object *parent_object); - - const MT_Vector3& getRay() const { return m_ray; } - MT_Point3 getSpot() const { return getPosition() + m_ray; } - const MT_Vector3& getRayDirection() const { return m_ray_direction; } - SM_Object *getParentObject() const { return m_parent_object; } - - static DT_Bool ray_hit(void *client_data, - void *object1, - void *object2, - const DT_CollData *coll_data); - -private: - MT_Vector3 m_ray; - MT_Vector3 m_ray_direction; - SM_Object *m_parent_object; -}; - -#endif - diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h deleted file mode 100644 index fdc45af5225..00000000000 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - * $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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef SM_MOTIONSTATE_H -#define SM_MOTIONSTATE_H - -#include "MT_Transform.h" - -class SM_MotionState { -public: - SM_MotionState() : - m_time(0.0), - m_pos(0.0, 0.0, 0.0), - m_orn(0.0, 0.0, 0.0, 1.0), - m_lin_vel(0.0, 0.0, 0.0), - m_ang_vel(0.0, 0.0, 0.0) - {} - - void setPosition(const MT_Point3& pos) { m_pos = pos; } - void setOrientation(const MT_Quaternion& orn) { m_orn = orn; } - void setLinearVelocity(const MT_Vector3& lin_vel) { m_lin_vel = lin_vel; } - void setAngularVelocity(const MT_Vector3& ang_vel) { m_ang_vel = ang_vel; } - void setTime(MT_Scalar time) { m_time = time; } - - const MT_Point3& getPosition() const { return m_pos; } - const MT_Quaternion& getOrientation() const { return m_orn; } - const MT_Vector3& getLinearVelocity() const { return m_lin_vel; } - const MT_Vector3& getAngularVelocity() const { return m_ang_vel; } - - MT_Scalar getTime() const { return m_time; } - - void integrateMidpoint(MT_Scalar timeStep, const SM_MotionState &prev_state, const MT_Vector3 &velocity, const MT_Quaternion& ang_vel); - void integrateBackward(MT_Scalar timeStep, const MT_Vector3 &velocity, const MT_Quaternion& ang_vel); - void integrateForward(MT_Scalar timeStep, const SM_MotionState &prev_state); - - void lerp(const SM_MotionState &prev, const SM_MotionState &next); - void lerp(MT_Scalar t, const SM_MotionState &other); - - virtual MT_Transform getTransform() const { - return MT_Transform(m_pos, m_orn); - } - -protected: - MT_Scalar m_time; - MT_Point3 m_pos; - MT_Quaternion m_orn; - MT_Vector3 m_lin_vel; - MT_Vector3 m_ang_vel; -}; - -#endif - diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h deleted file mode 100644 index 2d748a0f251..00000000000 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h +++ /dev/null @@ -1,393 +0,0 @@ -/** - * $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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef SM_OBJECT_H -#define SM_OBJECT_H - -#include - -#include - -#include "SM_Callback.h" -#include "SM_MotionState.h" -#include - -class SM_FhObject; - -/** Properties of dynamic objects */ -struct SM_ShapeProps { - MT_Scalar m_mass; ///< Total mass - MT_Scalar m_radius; ///< Bound sphere size - MT_Vector3 m_inertia; ///< Inertia, should be a tensor some time - MT_Scalar m_lin_drag; ///< Linear drag (air, water) 0 = concrete, 1 = vacuum - MT_Scalar m_ang_drag; ///< Angular drag - MT_Scalar m_friction_scaling[3]; ///< Scaling for anisotropic friction. Component in range [0, 1] - bool m_do_anisotropic; ///< Should I do anisotropic friction? - bool m_do_fh; ///< Should the object have a linear Fh spring? - bool m_do_rot_fh; ///< Should the object have an angular Fh spring? -}; - - -/** Properties of collidable objects (non-ghost objects) */ -struct SM_MaterialProps { - MT_Scalar m_restitution; ///< restitution of energy after a collision 0 = inelastic, 1 = elastic - MT_Scalar m_friction; ///< Coulomb friction (= ratio between the normal en maximum friction force) - MT_Scalar m_fh_spring; ///< Spring constant (both linear and angular) - MT_Scalar m_fh_damping; ///< Damping factor (linear and angular) in range [0, 1] - MT_Scalar m_fh_distance; ///< The range above the surface where Fh is active. - bool m_fh_normal; ///< Should the object slide off slopes? -}; - -class SM_ClientObject -{ -public: - SM_ClientObject() {} - virtual ~SM_ClientObject() {} - - virtual bool hasCollisionCallback() = 0; -}; - -/** - * SM_Object is an internal part of the Sumo physics engine. - * - * It encapsulates an object in the physics scene, and is responsible - * for calculating the collision response of objects. - */ -class SM_Object -{ -public: - SM_Object() ; - SM_Object( - DT_ShapeHandle shape, - const SM_MaterialProps *materialProps, - const SM_ShapeProps *shapeProps, - SM_Object *dynamicParent - ); - virtual ~SM_Object(); - - bool isDynamic() const; - - /* nzc experimental. There seem to be two places where kinematics - * are evaluated: proceedKinematic (called from SM_Scene) and - * proceed() in this object. I'll just try and bunge these out for - * now. */ - - void suspend(void); - void resume(void); - - void suspendDynamics(); - - void restoreDynamics(); - - bool isGhost() const; - - void suspendMaterial(); - - void restoreMaterial(); - - SM_FhObject *getFhObject() const; - - void registerCallback(SM_Callback& callback); - - void calcXform(); - void notifyClient(); - void updateInvInertiaTensor(); - - - // Save the current state information for use in the - // velocity computation in the next frame. - - void proceedKinematic(MT_Scalar timeStep); - - void saveReactionForce(MT_Scalar timeStep) ; - - void clearForce() ; - - void clearMomentum() ; - - void setMargin(MT_Scalar margin) ; - - MT_Scalar getMargin() const ; - - const SM_MaterialProps *getMaterialProps() const ; - - const SM_ShapeProps *getShapeProps() const ; - - void setPosition(const MT_Point3& pos); - void setOrientation(const MT_Quaternion& orn); - void setScaling(const MT_Vector3& scaling); - - /** - * set an external velocity. This velocity complements - * the physics velocity. So setting it does not override the - * physics velocity. It is your responsibility to clear - * this external velocity. This velocity is not subject to - * friction or damping. - */ - void setExternalLinearVelocity(const MT_Vector3& lin_vel) ; - void addExternalLinearVelocity(const MT_Vector3& lin_vel) ; - - /** Override the physics velocity */ - void addLinearVelocity(const MT_Vector3& lin_vel); - void setLinearVelocity(const MT_Vector3& lin_vel); - - /** - * Set an external angular velocity. This velocity complemetns - * the physics angular velocity so does not override it. It is - * your responsibility to clear this velocity. This velocity - * is not subject to friction or damping. - */ - void setExternalAngularVelocity(const MT_Vector3& ang_vel) ; - void addExternalAngularVelocity(const MT_Vector3& ang_vel); - - /** Override the physics angular velocity */ - void addAngularVelocity(const MT_Vector3& ang_vel); - void setAngularVelocity(const MT_Vector3& ang_vel); - - /** Clear the external velocities */ - void clearCombinedVelocities(); - - /** - * Tell the physics system to combine the external velocity - * with the physics velocity. - */ - void resolveCombinedVelocities( - const MT_Vector3 & lin_vel, - const MT_Vector3 & ang_vel - ) ; - - - - MT_Scalar getInvMass() const; - - const MT_Vector3& getInvInertia() const ; - - const MT_Matrix3x3& getInvInertiaTensor() const; - - void applyForceField(const MT_Vector3& accel) ; - - void applyCenterForce(const MT_Vector3& force) ; - - void applyTorque(const MT_Vector3& torque) ; - - /** - * Apply an impulse to the object. The impulse will be split into - * angular and linear components. - * @param attach point to apply the impulse to (in world coordinates) - */ - void applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse) ; - - /** - * Applies an impulse through the center of this object. (ie the angular - * velocity will not change. - */ - void applyCenterImpulse(const MT_Vector3& impulse); - /** - * Applies an angular impulse. - */ - void applyAngularImpulse(const MT_Vector3& impulse); - - MT_Point3 getWorldCoord(const MT_Point3& local) const; - MT_Point3 getLocalCoord(const MT_Point3& world) const; - - MT_Vector3 getVelocity(const MT_Point3& local) const; - - - const MT_Vector3& getReactionForce() const ; - - void getMatrix(double *m) const ; - - const double *getMatrix() const ; - - // Still need this??? - const MT_Transform& getScaledTransform() const; - - DT_ObjectHandle getObjectHandle() const ; - DT_ShapeHandle getShapeHandle() const ; - - SM_Object *getDynamicParent() ; - - void integrateForces(MT_Scalar timeStep); - void integrateMomentum(MT_Scalar timeSteo); - - void setRigidBody(bool is_rigid_body) ; - - bool isRigidBody() const ; - - // This is the callback for handling collisions of dynamic objects - static - DT_Bool - boing( - void *client_data, - void *object1, - void *object2, - const DT_CollData *coll_data - ); - - static - DT_Bool - fix( - void *client_data, - void *object1, - void *object2, - const DT_CollData *coll_data - ); - - - SM_ClientObject *getClientObject() { return m_client_object; } - void setClientObject(SM_ClientObject *client_object) { m_client_object = client_object; } - void setPhysicsClientObject(void* physicsClientObject) - { - m_physicsClientObject = physicsClientObject; - } - void* getPhysicsClientObject() { - return m_physicsClientObject; - } - void relax(); - - SM_MotionState &getCurrentFrame(); - SM_MotionState &getPreviousFrame(); - SM_MotionState &getNextFrame(); - - const SM_MotionState &getCurrentFrame() const; - const SM_MotionState &getPreviousFrame() const; - const SM_MotionState &getNextFrame() const; - - // Motion state functions - const MT_Point3& getPosition() const; - const MT_Quaternion& getOrientation() const; - const MT_Vector3& getLinearVelocity() const; - const MT_Vector3& getAngularVelocity() const; - - MT_Scalar getTime() const; - - void setTime(MT_Scalar time); - - void interpolate(MT_Scalar timeStep); - void endFrame(); - -private: - friend class Contact; - // Tweak parameters - static MT_Scalar ImpulseThreshold; - - // return the actual linear_velocity of this object this - // is the addition of m_combined_lin_vel and m_lin_vel. - - const - MT_Vector3 - actualLinVelocity( - ) const ; - - const - MT_Vector3 - actualAngVelocity( - ) const ; - - void dynamicCollision(const MT_Point3 &local2, - const MT_Vector3 &normal, - MT_Scalar dist, - const MT_Vector3 &rel_vel, - MT_Scalar restitution, - MT_Scalar friction_factor, - MT_Scalar invMass - ); - - typedef std::vector T_CallbackList; - - - T_CallbackList m_callbackList; // Each object can have multiple callbacks from the client (=game engine) - SM_Object *m_dynamicParent; // Collisions between parent and children are ignored - - // as the collision callback now has only information - // on an SM_Object, there must be a way that the SM_Object client - // can identify it's clientdata after a collision - SM_ClientObject *m_client_object; - - void* m_physicsClientObject; - - DT_ShapeHandle m_shape; // Shape for collision detection - - // Material and shape properties are not owned by this class. - - const SM_MaterialProps *m_materialProps; - const SM_MaterialProps *m_materialPropsBackup; // Backup in case the object temporarily becomes a ghost. - const SM_ShapeProps *m_shapeProps; - const SM_ShapeProps *m_shapePropsBackup; // Backup in case the object's dynamics is temporarily suspended - DT_ObjectHandle m_object; // A handle to the corresponding object in SOLID. - MT_Scalar m_margin; // Offset for the object's shape (also for collision detection) - MT_Vector3 m_scaling; // Non-uniform scaling of the object's shape - - double m_ogl_matrix[16]; // An OpenGL-type 4x4 matrix - MT_Transform m_xform; // The object's local coordinate system - MT_Transform m_prev_xform; // The object's local coordinate system in the previous frame - SM_MotionState m_prev_state; // The object's motion state in the previous frame - MT_Scalar m_timeStep; // The duration of the last frame - - MT_Vector3 m_reaction_impulse; // The accumulated impulse resulting from collisions - MT_Vector3 m_reaction_force; // The reaction force derived from the reaction impulse - - MT_Vector3 m_lin_mom; // Linear momentum (linear velocity times mass) - MT_Vector3 m_ang_mom; // Angular momentum (angualr velocity times inertia) - MT_Vector3 m_force; // Force on center of mass (afffects linear momentum) - MT_Vector3 m_torque; // Torque around center of mass (affects angular momentum) - - SM_MotionState m_frames[3]; - - MT_Vector3 m_error; // Error in position:- amount object must be moved to prevent intersection with scene - - // Here are the values of externally set linear and angular - // velocity. These are updated from the outside - // (actuators and python) each frame and combined with the - // physics values. At the end of each frame (at the end of a - // call to proceed) they are set to zero. This allows the - // outside world to contribute to the velocity of an object - // but still have it react to physics. - - MT_Vector3 m_combined_lin_vel; - MT_Vector3 m_combined_ang_vel; - - // The force and torque are the accumulated forces and torques applied by the client (game logic, python). - - SM_FhObject *m_fh_object; // The ray object used for Fh - bool m_suspended; // Is this object frozen? - - // Mass properties - MT_Scalar m_inv_mass; // 1/mass - MT_Vector3 m_inv_inertia; // [1/inertia_x, 1/inertia_y, 1/inertia_z] - MT_Matrix3x3 m_inv_inertia_tensor; // Inverse Inertia Tensor - - bool m_kinematic; // Have I been displaced (translated, rotated, scaled) in this frame? - bool m_prev_kinematic; // Have I been displaced (translated, rotated, scaled) in the previous frame? - bool m_is_rigid_body; // Should friction give me a change in angular momentum? - int m_static; // temporarily static. - -}; - -#endif - diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Props.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Props.h deleted file mode 100644 index 81b4cb55b45..00000000000 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Props.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * $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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef SM_PROPSH -#define SM_PROPSH - -#include - -// Properties of dynamic objects -struct SM_ShapeProps { - MT_Scalar m_mass; // Total mass - MT_Scalar m_inertia; // Inertia, should be a tensor some time - MT_Scalar m_lin_drag; // Linear drag (air, water) 0 = concrete, 1 = vacuum - MT_Scalar m_ang_drag; // Angular drag - MT_Scalar m_friction_scaling[3]; // Scaling for anisotropic friction. Component in range [0, 1] - bool m_do_anisotropic; // Should I do anisotropic friction? - bool m_do_fh; // Should the object have a linear Fh spring? - bool m_do_rot_fh; // Should the object have an angular Fh spring? -}; - - -// Properties of collidable objects (non-ghost objects) -struct SM_MaterialProps { - MT_Scalar m_restitution; // restitution of energie after a collision 0 = inelastic, 1 = elastic - MT_Scalar m_friction; // Coulomb friction (= ratio between the normal en maximum friction force) - MT_Scalar m_fh_spring; // Spring constant (both linear and angular) - MT_Scalar m_fh_damping; // Damping factor (linear and angular) in range [0, 1] - MT_Scalar m_fh_distance; // The range above the surface where Fh is active. - bool m_fh_normal; // Should the object slide off slopes? -}; - -#endif //SM_PROPSH - diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h deleted file mode 100644 index 3d8eef2bae0..00000000000 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h +++ /dev/null @@ -1,172 +0,0 @@ -/** - * $Id$ - * Copyright (C) 2001 NaN Technologies B.V. - * The physics scene. - * - * ***** 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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef SM_SCENE_H -#define SM_SCENE_H - -#ifdef WIN32 -#pragma warning (disable : 4786) -#endif - -#include -#include -#include //needed for pair - -#include - -#include "MT_Vector3.h" -#include "MT_Point3.h" - -#include "SM_Object.h" - -enum -{ - FH_RESPONSE, - SENSOR_RESPONSE, /* Touch Sensors */ - CAMERA_RESPONSE, /* Visibility Culling */ - OBJECT_RESPONSE, /* Object Dynamic Geometry Response */ - STATIC_RESPONSE, /* Static Geometry Response */ - - NUM_RESPONSE -}; - -class SM_Scene { -public: - SM_Scene(); - - ~SM_Scene(); - - DT_RespTableHandle getRespTableHandle() const { - return m_respTable; - } - - const MT_Vector3& getForceField() const { - return m_forceField; - } - - MT_Vector3& getForceField() { - return m_forceField; - } - - void setForceField(const MT_Vector3& forceField) { - m_forceField = forceField; - } - - void addTouchCallback(int response_class, DT_ResponseCallback callback, void *user); - - void addSensor(SM_Object& object); - void add(SM_Object& object); - void remove(SM_Object& object); - - void notifyCollision(SM_Object *obj1, SM_Object *obj2); - - void setSecondaryRespTable(DT_RespTableHandle secondaryRespTable); - DT_RespTableHandle getSecondaryRespTable() { return m_secondaryRespTable; } - - void requestCollisionCallback(SM_Object &object); - - void beginFrame(); - void endFrame(); - - // Perform an integration step of duration 'timeStep'. - // 'subSampling' is the maximum duration of a substep, i.e., - // The maximum time interval between two collision checks. - // 'subSampling' can be used to control aliasing effects - // (fast moving objects traversing through walls and such). - bool proceed(MT_Scalar curtime, MT_Scalar ticrate); - void proceed(MT_Scalar subStep); - - /** - * Test whether any objects lie on the line defined by from and - * to. The search returns the first such bject starting at from, - * or NULL if there was none. - * @returns A reference to the object, or NULL if there was none. - * @param ignore_client Do not look for collisions with this - * object. This can be useful to avoid self-hits if - * starting from the location of an object. - * @param from The start point, in world coordinates, of the search. - * @param to The end point, in world coordinates, of the search. - * @param result A store to return the point where intersection - * took place (if there was an intersection). - * @param normal A store to return the normal of the hit object on - * the location of the intersection, if it took place. - */ - SM_Object *rayTest(void *ignore_client, - const MT_Point3& from, const MT_Point3& to, - MT_Point3& result, MT_Vector3& normal) const; - -private: - - // Clear the user set velocities. - void clearObjectCombinedVelocities(); - // This is the callback for handling collisions of dynamic objects - static - DT_Bool - boing( - void *client_data, - void *object1, - void *object2, - const DT_CollData *coll_data - ); - - /** internal type */ - typedef std::vector T_ObjectList; - - /** Handle to the scene in SOLID */ - DT_SceneHandle m_scene; - /** Following response table contains the callbacks for the dynmics */ - DT_RespTableHandle m_respTable; - DT_ResponseClass m_ResponseClass[NUM_RESPONSE]; - /** - * Following response table contains callbacks for the client (= - * game engine) */ - DT_RespTableHandle m_secondaryRespTable; // Handle - DT_ResponseClass m_secondaryResponseClass[NUM_RESPONSE]; - - /** - * Following resposne table contains callbacks for fixing the simulation - * ie making sure colliding objects do not intersect. - */ - DT_RespTableHandle m_fixRespTable; - DT_ResponseClass m_fixResponseClass[NUM_RESPONSE]; - - /** The acceleration from the force field */ - MT_Vector3 m_forceField; - - /** - * The list of objects that receive motion updates and do - * collision tests. */ - T_ObjectList m_objectList; - - unsigned int m_frames; -}; - -#endif - diff --git a/source/gameengine/Physics/Sumo/Fuzzics/sample/Makefile b/source/gameengine/Physics/Sumo/Fuzzics/sample/Makefile deleted file mode 100644 index 672dff39028..00000000000 --- a/source/gameengine/Physics/Sumo/Fuzzics/sample/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# -# $Id$ -# Copyright (C) 2001 NaN Technologies B.V. - -DIR = $(OCGDIR)/sumo -ALLTARGETS = $(OBJS) $(DIR)/$(DEBUG_DIR)particle $(DIR)/$(DEBUG_DIR)particle0 - -include nan_compile.mk - -CPPFLAGS = -I../../include -I../include -I$(NAN_MOTO)/include -CPPFLAGS += -I$(OPENGL_HEADERS) - -clean:: - @$(RM) $(DIR)/particle $(DIR)/particle0 - @$(RM) $(DIR)/debug/particle $(DIR)/debug/particle0 - -LDFLAGS = -L$(DIR) -L/usr/X11R6/lib -OGL_LDLIBS = -lglut -lGLU -lGL -pthread -LDLIBS = -lfuzzics -lsolid $(NAN_MOTO)/lib/libmoto.a $(OGL_LDLIBS) - -$(DIR)/$(DEBUG_DIR)particle: particle.o $(DIR)/$(DEBUG_DIR)libfuzzics.a $(DIR)/$(DEBUG_DIR)libsolid.a - $(CCC) $(CCFLAGS) $(CPPFLAGS) $(LDFLAGS) $< -o $@ $(LDLIBS) - -$(DIR)/$(DEBUG_DIR)particle0: particle0.o $(DIR)/$(DEBUG_DIR)libfuzzics.a $(DIR)/$(DEBUG_DIR)libsolid.a - $(CCC) $(CCFLAGS) $(CPPFLAGS) $(LDFLAGS) $< -o $@ $(LDLIBS) diff --git a/source/gameengine/Physics/Sumo/Fuzzics/sample/particle.cpp b/source/gameengine/Physics/Sumo/Fuzzics/sample/particle.cpp deleted file mode 100644 index d7aca326b42..00000000000 --- a/source/gameengine/Physics/Sumo/Fuzzics/sample/particle.cpp +++ /dev/null @@ -1,709 +0,0 @@ -//#define FAKE_IT -#define USE_COMPLEX -#define QUADS - -#include -#include -#include - -#include "MT_MinMax.h" -#include "MT_Point3.h" -#include "MT_Vector3.h" -#include "MT_Quaternion.h" -#include "MT_Matrix3x3.h" -#include "MT_Transform.h" - -#include "SM_Object.h" -#include "SM_FhObject.h" -#include "SM_Scene.h" - -#include - -#ifdef HAVE_CONFIG_H -#include -#endif - -const MT_Scalar bowl_curv = 0.10; -const MT_Scalar timeStep = 0.02; -const MT_Scalar ground_margin = 0.0; -const MT_Scalar sphere_radius = 0.5; - -const MT_Vector3 gravity(0, -9.8, 0); - -static MT_Scalar DISTANCE = 5; - -static MT_Scalar ele = 0, azi = 0; -static MT_Point3 eye(0, 0, DISTANCE); -static MT_Point3 center(0, 0, 0); - -inline double irnd() { return 2 * MT_random() - 1; } - -static const double SCALE_BOTTOM = 0.5; -static const double SCALE_FACTOR = 2.0; - -SM_ShapeProps g_shapeProps = { - 1.0, // mass - 1.0, // inertia - 0.1, // linear drag - 0.1, // angular drag - { 1.0, 0.0, 0.0 }, // anisotropic friction - false, // do anisotropic friction? - true, // do fh? - true // do rot fh? -}; - -SM_MaterialProps g_materialProps = { - 0.7, // restitution - 0.0, // friction - 10.0, // Fh spring constant - 1.0, // Fh damping - 0.5, // Fh distance - true // Fh leveling -}; - - -void toggleIdle(); - - -void newRandom(); - -void coordSystem() { - glDisable(GL_LIGHTING); - glBegin(GL_LINES); - glColor3f(1, 0, 0); - glVertex3d(0, 0, 0); - glVertex3d(10, 0, 0); - glColor3f(0, 1, 0); - glVertex3d(0, 0, 0); - glVertex3d(0, 10, 0); - glColor3f(0, 0, 1); - glVertex3d(0, 0, 0); - glVertex3d(0, 0, 10); - glEnd(); - glEnable(GL_LIGHTING); -} - - -void display_bbox(const MT_Point3& min, const MT_Point3& max) { - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glColor3f(0, 1, 1); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glBegin(GL_QUAD_STRIP); - glVertex3d(min[0], min[1], min[2]); - glVertex3d(min[0], min[1], max[2]); - glVertex3d(max[0], min[1], min[2]); - glVertex3d(max[0], min[1], max[2]); - glVertex3d(max[0], max[1], min[2]); - glVertex3d(max[0], max[1], max[2]); - glVertex3d(min[0], max[1], min[2]); - glVertex3d(min[0], max[1], max[2]); - glVertex3d(min[0], min[1], min[2]); - glVertex3d(min[0], min[1], max[2]); - glEnd(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glEnable(GL_LIGHTING); - glEnable(GL_DEPTH_TEST); -} - - - - -class GLShape { -public: - virtual void paint(GLdouble *m) const = 0; -}; - - -class GLSphere : public GLShape { - MT_Scalar radius; -public: - GLSphere(MT_Scalar r) : radius(r) {} - - void paint(GLdouble *m) const { - glPushMatrix(); - glLoadMatrixd(m); - coordSystem(); - glutSolidSphere(radius, 20, 20); - glPopMatrix(); - } -}; - - -class GLBox : public GLShape { - MT_Vector3 extent; -public: - GLBox(MT_Scalar x, MT_Scalar y, MT_Scalar z) : - extent(x, y, z) {} - - void paint(GLdouble *m) const { - glPushMatrix(); - glLoadMatrixd(m); - coordSystem(); - glPushMatrix(); - glScaled(extent[0], extent[1], extent[2]); - glutSolidCube(1.0); - glPopMatrix(); - glPopMatrix(); - } -}; - - -class GLCone : public GLShape { - MT_Scalar bottomRadius; - MT_Scalar height; - mutable GLuint displayList; - -public: - GLCone(MT_Scalar r, MT_Scalar h) : - bottomRadius(r), - height(h), - displayList(0) {} - - void paint(GLdouble *m) const { - glPushMatrix(); - glLoadMatrixd(m); - coordSystem(); - if (displayList) glCallList(displayList); - else { - GLUquadricObj *quadObj = gluNewQuadric(); - displayList = glGenLists(1); - glNewList(displayList, GL_COMPILE_AND_EXECUTE); - glPushMatrix(); - glRotatef(-90.0, 1.0, 0.0, 0.0); - glTranslatef(0.0, 0.0, -1.0); - gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL); - gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH); - gluCylinder(quadObj, bottomRadius, 0, height, 15, 10); - glPopMatrix(); - glEndList(); - } - glPopMatrix(); - } -}; - -class GLCylinder : public GLShape { - MT_Scalar radius; - MT_Scalar height; - mutable GLuint displayList; - -public: - GLCylinder(MT_Scalar r, MT_Scalar h) : - radius(r), - height(h), - displayList(0) {} - - void paint(GLdouble *m) const { - glPushMatrix(); - glLoadMatrixd(m); - coordSystem(); - if (displayList) glCallList(displayList); - else { - GLUquadricObj *quadObj = gluNewQuadric(); - displayList = glGenLists(1); - glNewList(displayList, GL_COMPILE_AND_EXECUTE); - glPushMatrix(); - glRotatef(-90.0, 1.0, 0.0, 0.0); - glTranslatef(0.0, 0.0, -1.0); - gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL); - gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH); - gluCylinder(quadObj, radius, radius, height, 15, 10); - glPopMatrix (); - glEndList(); - } - glPopMatrix(); - } -}; - -class Object; - -class Callback : public SM_Callback { -public: - Callback(Object& object) : m_object(object) {} - - virtual void do_me(); - -private: - Object& m_object; -}; - - -class Object { -public: - Object(GLShape *gl_shape, SM_Object& object) : - m_gl_shape(gl_shape), - m_object(object), - m_callback(*this) - { - m_object.registerCallback(m_callback); - } - - ~Object() {} - - void paint() { - if (m_gl_shape) { - m_gl_shape->paint(m); - // display_bbox(m_bbox.lower(), m_bbox.upper()); - } - } - - void print_reaction_force() const { - std::cout << m_object.getReactionForce() << std::endl; - } - - MT_Vector3 getAhead() { - return MT_Vector3(&m[4]); - } - - MT_Vector3 getUp() { - return MT_Vector3(&m[8]); - } - - void clearMomentum() { - m_object.clearMomentum(); - } - - void setMargin(MT_Scalar margin) { - m_object.setMargin(margin); - } - - void setScaling(const MT_Vector3& scaling) { - m_object.setScaling(scaling); - } - - const MT_Point3& getPosition() { - return m_object.getPosition(); - } - - void setPosition(const MT_Point3& pos) { - m_object.setPosition(pos); - } - - void setOrientation(const MT_Quaternion& orn) { - m_object.setOrientation(orn); - } - - void applyCenterForce(const MT_Vector3& force) { - m_object.applyCenterForce(force); - } - - void applyTorque(const MT_Vector3& torque) { - m_object.applyTorque(torque); - } - - MT_Point3 getWorldCoord(const MT_Point3& local) const { - return m_object.getWorldCoord(local); - } - - MT_Vector3 getLinearVelocity() const { - return m_object.getLinearVelocity(); - } - - MT_Vector3 getAngularVelocity() const { - return m_object.getAngularVelocity(); - } - - void setMatrix() { - m_object.calcXform(); - m_object.getMatrix(m); - } - - const double *getMatrix() { - m_object.calcXform(); - return m_object.getMatrix(); - } - -private: - GLShape *m_gl_shape; - SM_Object& m_object; - DT_Scalar m[16]; - Callback m_callback; -}; - - - -const MT_Scalar SPACE_SIZE = 2; - -static GLSphere gl_sphere(sphere_radius); -static GLBox gl_ground(50.0, 0.0, 50.0); - - - -#ifdef USE_COMPLEX - -const int GRID_SCALE = 10; -const MT_Scalar GRID_UNIT = 25.0 / GRID_SCALE; - -DT_ShapeHandle createComplex() { - DT_ShapeHandle shape = DT_NewComplexShape(); - for (int i0 = -GRID_SCALE; i0 != GRID_SCALE; ++i0) { - for (int j0 = -GRID_SCALE; j0 != GRID_SCALE; ++j0) { - int i1 = i0 + 1; - int j1 = j0 + 1; -#ifdef QUADS - DT_Begin(); - DT_Vertex(GRID_UNIT * i0, bowl_curv * i0*i0, GRID_UNIT * j0); - DT_Vertex(GRID_UNIT * i0, bowl_curv * i0*i0, GRID_UNIT * j1); - DT_Vertex(GRID_UNIT * i1, bowl_curv * i1*i1, GRID_UNIT * j1); - DT_Vertex(GRID_UNIT * i1, bowl_curv * i1*i1, GRID_UNIT * j0); - DT_End(); -#else - DT_Begin(); - DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j0); - DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j1); - DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j1); - DT_End(); - - DT_Begin(); - DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j1); - DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j1); - DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j0); - DT_End(); -#endif - - } - } - DT_EndComplexShape(); - return shape; -} - - -static DT_ShapeHandle ground_shape = createComplex(); - -#else - -static DT_ShapeHandle ground_shape = DT_Box(50, 0, 50); - -#endif - -static SM_Object sm_ground(ground_shape, &g_materialProps, 0, 0); -static Object ground(&gl_ground, sm_ground); - -static SM_Object sm_sphere(DT_Sphere(0.0), &g_materialProps, &g_shapeProps, 0); -static Object object(&gl_sphere, sm_sphere); - - -static SM_Scene g_scene; - - -bool g_hit = false; -MT_Point3 g_spot; -MT_Vector3 g_normal; - - -void Callback::do_me() -{ - m_object.setMatrix(); - m_object.print_reaction_force(); -} - -void myinit(void) { - - GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 }; - GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; - GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }; - - /* light_position is NOT default value */ - GLfloat light_position0[] = { 1.0, 1.0, 1.0, 0.0 }; - GLfloat light_position1[] = { -1.0, -1.0, -1.0, 0.0 }; - - glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); - glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); - glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); - glLightfv(GL_LIGHT0, GL_POSITION, light_position0); - - glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient); - glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); - glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular); - glLightfv(GL_LIGHT1, GL_POSITION, light_position1); - - - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); - glEnable(GL_LIGHT1); - - glShadeModel(GL_SMOOTH); - - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - - // glEnable(GL_CULL_FACE); - // glCullFace(GL_BACK); - - ground.setPosition(MT_Point3(0, -10, 0)); - ground.setOrientation(MT_Quaternion(0, 0, 0, 1)); - ground.setMatrix(); - center.setValue(0.0, 0.0, 0.0); - sm_ground.setMargin(ground_margin); - - g_scene.setForceField(gravity); - g_scene.add(sm_ground); - - object.setMargin(sphere_radius); - - g_scene.add(sm_sphere); - - - newRandom(); -} - - -//MT_Point3 cp1, cp2; -//bool intersection; - -void display(void) { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - ground.paint(); - object.paint(); - - if (g_hit) { - glDisable(GL_LIGHTING); - glColor3f(1, 0, 0); - - glPointSize(5); - glBegin(GL_POINTS); - glVertex3d(g_spot[0], g_spot[1], g_spot[2]); - glEnd(); - glPointSize(1); - - glColor3f(1, 1, 0); - glBegin(GL_LINES); - glVertex3d(g_spot[0], g_spot[1], g_spot[2]); - glVertex3d(g_spot[0] + g_normal[0], - g_spot[1] + g_normal[1], - g_spot[2] + g_normal[2]); - glEnd(); - glEnable(GL_LIGHTING); - } - - - -#ifdef COLLISION - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glColor3f(1, 1, 0); - if (intersection) { - glPointSize(5); - glBegin(GL_POINTS); - glVertex3d(cp1[0], cp1[1], cp1[2]); - glEnd(); - glPointSize(1); - } - else { - glBegin(GL_LINES); - glVertex3d(cp1[0], cp1[1], cp1[2]); - glVertex3d(cp2[0], cp2[1], cp2[2]); - glEnd(); - } - glEnable(GL_LIGHTING); - glEnable(GL_DEPTH_TEST); -#endif - - glFlush(); - glutSwapBuffers(); -} - - - - - -void newRandom() { - object.setPosition(MT_Point3(0, 0, 0)); - object.setOrientation(MT_Quaternion::random()); - object.clearMomentum(); - object.setMatrix(); - - display(); -} - -void moveAndDisplay() { - g_scene.proceed(timeStep, 0.01); - - display(); - g_hit = false; -} - - -void turn_left() { - object.applyTorque(5.0 * object.getUp()); -} - -void turn_right() { - object.applyTorque(-5.0 * object.getUp()); -} - -void forward() { - object.applyCenterForce(10.0 * object.getAhead()); -} - -void backward() { - object.applyCenterForce(-10.0 * object.getAhead()); -} - -void jump() { - object.applyCenterForce(MT_Vector3(0.0, 200.0, 0.0)); -} - - -void toggleIdle() { - static bool idle = true; - if (idle) { - glutIdleFunc(moveAndDisplay); - idle = false; - } - else { - glutIdleFunc(NULL); - idle = true; - } -} - - -void setCamera() { - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 200.0); - MT_Scalar rele = MT_radians(ele); - MT_Scalar razi = MT_radians(azi); - eye.setValue(DISTANCE * sin(razi) * cos(rele), - DISTANCE * sin(rele), - DISTANCE * cos(razi) * cos(rele)); - gluLookAt(eye[0], eye[1], eye[2], - center[0], center[1], center[2], - 0, 1, 0); - glMatrixMode(GL_MODELVIEW); - display(); -} - -const MT_Scalar STEPSIZE = 5; - -void stepLeft() { azi -= STEPSIZE; if (azi < 0) azi += 360; setCamera(); } -void stepRight() { azi += STEPSIZE; if (azi >= 360) azi -= 360; setCamera(); } -void stepFront() { ele += STEPSIZE; if (azi >= 360) azi -= 360; setCamera(); } -void stepBack() { ele -= STEPSIZE; if (azi < 0) azi += 360; setCamera(); } -void zoomIn() { DISTANCE -= 1; setCamera(); } -void zoomOut() { DISTANCE += 1; setCamera(); } - - -void myReshape(int w, int h) { - glViewport(0, 0, w, h); - setCamera(); -} - -void myKeyboard(unsigned char key, int x, int y) -{ - switch (key) - { - case 'w': forward(); break; - case 's': backward(); break; - case 'a': turn_left(); break; - case 'd': turn_right(); break; - case 'e': jump(); break; - case 'l' : stepLeft(); break; - case 'r' : stepRight(); break; - case 'f' : stepFront(); break; - case 'b' : stepBack(); break; - case 'z' : zoomIn(); break; - case 'x' : zoomOut(); break; - case 'i' : toggleIdle(); break; - case ' ' : newRandom(); break; - default: -// std::cout << "unused key : " << key << std::endl; - break; - } -} - -void mySpecial(int key, int x, int y) -{ - switch (key) - { - case GLUT_KEY_LEFT : stepLeft(); break; - case GLUT_KEY_RIGHT : stepRight(); break; - case GLUT_KEY_UP : stepFront(); break; - case GLUT_KEY_DOWN : stepBack(); break; - case GLUT_KEY_PAGE_UP : zoomIn(); break; - case GLUT_KEY_PAGE_DOWN : zoomOut(); break; - case GLUT_KEY_HOME : toggleIdle(); break; - default: -// std::cout << "unused (special) key : " << key << std::endl; - break; - } -} - -void goodbye( void) -{ - g_scene.remove(sm_ground); - g_scene.remove(sm_sphere); - - std::cout << "goodbye ..." << std::endl; - exit(0); -} - -void menu(int choice) -{ - - static int fullScreen = 0; - static int px, py, sx, sy; - - switch(choice) { - case 1: - if (fullScreen == 1) { - glutPositionWindow(px,py); - glutReshapeWindow(sx,sy); - glutChangeToMenuEntry(1,"Full Screen",1); - fullScreen = 0; - } else { - px=glutGet((GLenum)GLUT_WINDOW_X); - py=glutGet((GLenum)GLUT_WINDOW_Y); - sx=glutGet((GLenum)GLUT_WINDOW_WIDTH); - sy=glutGet((GLenum)GLUT_WINDOW_HEIGHT); - glutFullScreen(); - glutChangeToMenuEntry(1,"Close Full Screen",1); - fullScreen = 1; - } - break; - case 2: - toggleIdle(); - break; - case 3: - goodbye(); - break; - default: - break; - } -} - -void createMenu() -{ - glutCreateMenu(menu); - glutAddMenuEntry("Full Screen", 1); - glutAddMenuEntry("Toggle Idle (Start/Stop)", 2); - glutAddMenuEntry("Quit", 3); - glutAttachMenu(GLUT_RIGHT_BUTTON); -} - -int main(int argc, char **argv) { - glutInit(&argc, argv); - glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); - glutInitWindowPosition(0, 0); - glutInitWindowSize(500, 500); - glutCreateWindow("Physics demo"); - - myinit(); - glutKeyboardFunc(myKeyboard); - glutSpecialFunc(mySpecial); - glutReshapeFunc(myReshape); - createMenu(); - glutIdleFunc(NULL); - - glutDisplayFunc(display); - glutMainLoop(); - return 0; -} - - - - - - - diff --git a/source/gameengine/Physics/Sumo/Fuzzics/sample/particle0.cpp b/source/gameengine/Physics/Sumo/Fuzzics/sample/particle0.cpp deleted file mode 100644 index cdf0a2d8f64..00000000000 --- a/source/gameengine/Physics/Sumo/Fuzzics/sample/particle0.cpp +++ /dev/null @@ -1,695 +0,0 @@ -//#define FAKE_IT -#define USE_COMPLEX -#define QUADS - -#include -#include -#include - -#include "MT_MinMax.h" -#include "MT_Point3.h" -#include "MT_Vector3.h" -#include "MT_Quaternion.h" -#include "MT_Matrix3x3.h" -#include "MT_Transform.h" - -#include "SM_Object.h" -#include "SM_Scene.h" - -#include "solid.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -const MT_Scalar bowl_curv = 0.10; -const MT_Scalar timeStep = 0.04; -const MT_Scalar ground_margin = 0.0; -const MT_Scalar sphere_radius = 0.5; - -const MT_Vector3 gravity(0, -9.8, 0); - -static MT_Scalar DISTANCE = 5; - -static MT_Scalar ele = 0, azi = 0; -static MT_Point3 eye(0, 0, DISTANCE); -static MT_Point3 center(0, 0, 0); - -inline double irnd() { return 2 * MT_random() - 1; } - -static const double SCALE_BOTTOM = 0.5; -static const double SCALE_FACTOR = 2.0; - -SM_ShapeProps g_shapeProps = { - 1.0, // mass - 1.0, // inertia - 0.9, // linear drag - 0.9 // angular drag -}; - -SM_MaterialProps g_materialProps = { - 0.7, // restitution - 0.0, // friction - 0.0, // spring constant - 0.0 // damping -}; - - -void toggleIdle(); - - -void newRandom(); - -void coordSystem() { - glDisable(GL_LIGHTING); - glBegin(GL_LINES); - glColor3f(1, 0, 0); - glVertex3d(0, 0, 0); - glVertex3d(10, 0, 0); - glColor3f(0, 1, 0); - glVertex3d(0, 0, 0); - glVertex3d(0, 10, 0); - glColor3f(0, 0, 1); - glVertex3d(0, 0, 0); - glVertex3d(0, 0, 10); - glEnd(); - glEnable(GL_LIGHTING); -} - - -void display_bbox(const MT_Point3& min, const MT_Point3& max) { - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glColor3f(0, 1, 1); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glBegin(GL_QUAD_STRIP); - glVertex3d(min[0], min[1], min[2]); - glVertex3d(min[0], min[1], max[2]); - glVertex3d(max[0], min[1], min[2]); - glVertex3d(max[0], min[1], max[2]); - glVertex3d(max[0], max[1], min[2]); - glVertex3d(max[0], max[1], max[2]); - glVertex3d(min[0], max[1], min[2]); - glVertex3d(min[0], max[1], max[2]); - glVertex3d(min[0], min[1], min[2]); - glVertex3d(min[0], min[1], max[2]); - glEnd(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glEnable(GL_LIGHTING); - glEnable(GL_DEPTH_TEST); -} - - - - -class GLShape { -public: - virtual void paint(GLdouble *m) const = 0; -}; - - -class GLSphere : public GLShape { - MT_Scalar radius; -public: - GLSphere(MT_Scalar r) : radius(r) {} - - void paint(GLdouble *m) const { - glPushMatrix(); - glLoadMatrixd(m); - coordSystem(); - glutSolidSphere(radius, 20, 20); - glPopMatrix(); - } -}; - - -class GLBox : public GLShape { - MT_Vector3 extent; -public: - GLBox(MT_Scalar x, MT_Scalar y, MT_Scalar z) : - extent(x, y, z) {} - - void paint(GLdouble *m) const { - glPushMatrix(); - glLoadMatrixd(m); - coordSystem(); - glPushMatrix(); - glScaled(extent[0], extent[1], extent[2]); - glutSolidCube(1.0); - glPopMatrix(); - glPopMatrix(); - } -}; - - -class GLCone : public GLShape { - MT_Scalar bottomRadius; - MT_Scalar height; - mutable GLuint displayList; - -public: - GLCone(MT_Scalar r, MT_Scalar h) : - bottomRadius(r), - height(h), - displayList(0) {} - - void paint(GLdouble *m) const { - glPushMatrix(); - glLoadMatrixd(m); - coordSystem(); - if (displayList) glCallList(displayList); - else { - GLUquadricObj *quadObj = gluNewQuadric(); - displayList = glGenLists(1); - glNewList(displayList, GL_COMPILE_AND_EXECUTE); - glPushMatrix(); - glRotatef(-90.0, 1.0, 0.0, 0.0); - glTranslatef(0.0, 0.0, -1.0); - gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL); - gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH); - gluCylinder(quadObj, bottomRadius, 0, height, 15, 10); - glPopMatrix(); - glEndList(); - } - glPopMatrix(); - } -}; - -class GLCylinder : public GLShape { - MT_Scalar radius; - MT_Scalar height; - mutable GLuint displayList; - -public: - GLCylinder(MT_Scalar r, MT_Scalar h) : - radius(r), - height(h), - displayList(0) {} - - void paint(GLdouble *m) const { - glPushMatrix(); - glLoadMatrixd(m); - coordSystem(); - if (displayList) glCallList(displayList); - else { - GLUquadricObj *quadObj = gluNewQuadric(); - displayList = glGenLists(1); - glNewList(displayList, GL_COMPILE_AND_EXECUTE); - glPushMatrix(); - glRotatef(-90.0, 1.0, 0.0, 0.0); - glTranslatef(0.0, 0.0, -1.0); - gluQuadricDrawStyle(quadObj, (GLenum)GLU_FILL); - gluQuadricNormals(quadObj, (GLenum)GLU_SMOOTH); - gluCylinder(quadObj, radius, radius, height, 15, 10); - glPopMatrix (); - glEndList(); - } - glPopMatrix(); - } -}; - -class Object; - -class Callback : public SM_Callback { -public: - Callback(Object& object) : m_object(object) {} - - virtual void do_me(); - -private: - Object& m_object; -}; - - -class Object { -public: - Object(GLShape *gl_shape, SM_Object& object) : - m_gl_shape(gl_shape), - m_object(object), - m_callback(*this) - { - m_object.registerCallback(m_callback); - } - - ~Object() {} - - void paint() { - m_gl_shape->paint(m); - // display_bbox(m_bbox.lower(), m_bbox.upper()); - } - - MT_Vector3 getAhead() { - return MT_Vector3(-m[8], -m[9], -m[10]); - } - - void clearMomentum() { - m_object.clearMomentum(); - } - - void setMargin(MT_Scalar margin) { - m_object.setMargin(margin); - } - - void setScaling(const MT_Vector3& scaling) { - m_object.setScaling(scaling); - } - - void setPosition(const MT_Point3& pos) { - m_object.setPosition(pos); - } - - void setOrientation(const MT_Quaternion& orn) { - m_object.setOrientation(orn); - } - - void applyCenterForce(const MT_Vector3& force) { - m_object.applyCenterForce(force); - } - - void applyTorque(const MT_Vector3& torque) { - m_object.applyTorque(torque); - } - - MT_Point3 getWorldCoord(const MT_Point3& local) const { - return m_object.getWorldCoord(local); - } - - MT_Vector3 getLinearVelocity() const { - return m_object.getLinearVelocity(); - } - - void setMatrix() { - m_object.getMatrix(m); - } - -private: - GLShape *m_gl_shape; - SM_Object& m_object; - DT_Scalar m[16]; - Callback m_callback; -}; - - -void Callback::do_me() -{ - m_object.setMatrix(); -} - - -const MT_Scalar SPACE_SIZE = 2; - -static GLSphere gl_sphere(sphere_radius); -static GLBox gl_ground(50.0, 0.0, 50.0); - - - -#ifdef USE_COMPLEX - -const int GRID_SCALE = 10; -const MT_Scalar GRID_UNIT = 25.0 / GRID_SCALE; - -DT_ShapeHandle createComplex() { - DT_ShapeHandle shape = DT_NewComplexShape(); - for (int i0 = -GRID_SCALE; i0 != GRID_SCALE; ++i0) { - for (int j0 = -GRID_SCALE; j0 != GRID_SCALE; ++j0) { - int i1 = i0 + 1; - int j1 = j0 + 1; -#ifdef QUADS - DT_Begin(); - DT_Vertex(GRID_UNIT * i0, bowl_curv * i0*i0, GRID_UNIT * j0); - DT_Vertex(GRID_UNIT * i0, bowl_curv * i0*i0, GRID_UNIT * j1); - DT_Vertex(GRID_UNIT * i1, bowl_curv * i1*i1, GRID_UNIT * j1); - DT_Vertex(GRID_UNIT * i1, bowl_curv * i1*i1, GRID_UNIT * j0); - DT_End(); -#else - DT_Begin(); - DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j0); - DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j1); - DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j1); - DT_End(); - - DT_Begin(); - DT_Vertex(GRID_UNIT * i0, 0, GRID_UNIT * j1); - DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j1); - DT_Vertex(GRID_UNIT * i1, 0, GRID_UNIT * j0); - DT_End(); -#endif - - } - } - DT_EndComplexShape(); - return shape; -} - - -static DT_ShapeHandle ground_shape = createComplex(); - -#else - -static DT_ShapeHandle ground_shape = DT_Box(50, 0, 50); - -#endif - -static SM_Object sm_ground(ground_shape, &g_materialProps, 0, 0); -static Object ground(&gl_ground, sm_ground); - -static SM_Object sm_sphere(DT_Sphere(0.0), &g_materialProps, &g_shapeProps, 0); -static Object object(&gl_sphere, sm_sphere); - - -static SM_Object sm_ray(DT_Ray(0.0, -1.0, 0.0), 0, 0, 0); - -static SM_Scene g_scene; - - -void myinit(void) { - - GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 }; - GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; - GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }; - - /* light_position is NOT default value */ - GLfloat light_position0[] = { 1.0, 1.0, 1.0, 0.0 }; - GLfloat light_position1[] = { -1.0, -1.0, -1.0, 0.0 }; - - glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); - glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); - glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); - glLightfv(GL_LIGHT0, GL_POSITION, light_position0); - - glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient); - glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); - glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular); - glLightfv(GL_LIGHT1, GL_POSITION, light_position1); - - - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); - glEnable(GL_LIGHT1); - - glShadeModel(GL_SMOOTH); - - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - - // glEnable(GL_CULL_FACE); - // glCullFace(GL_BACK); - - g_scene.setForceField(gravity); - g_scene.add(sm_ground); - sm_ground.setMargin(ground_margin); - - new(&object) Object(&gl_sphere, sm_sphere); - - - object.setMargin(sphere_radius); - - g_scene.add(sm_sphere); - - ground.setPosition(MT_Point3(0, -10, 0)); - ground.setOrientation(MT_Quaternion(0, 0, 0, 1)); - ground.setMatrix(); - center.setValue(0.0, 0.0, 0.0); - - newRandom(); -} - - -//MT_Point3 cp1, cp2; -//bool intersection; - -bool g_hit = false; -MT_Point3 g_spot; -MT_Vector3 g_normal; - - -void display(void) { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - ground.paint(); - object.paint(); - - if (g_hit) { - glPointSize(5); - glBegin(GL_POINTS); - glVertex3d(g_spot[0], g_spot[1], g_spot[2]); - glEnd(); - glPointSize(1); - } - - - -#ifdef COLLISION - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glColor3f(1, 1, 0); - if (intersection) { - glPointSize(5); - glBegin(GL_POINTS); - glVertex3d(cp1[0], cp1[1], cp1[2]); - glEnd(); - glPointSize(1); - } - else { - glBegin(GL_LINES); - glVertex3d(cp1[0], cp1[1], cp1[2]); - glVertex3d(cp2[0], cp2[1], cp2[2]); - glEnd(); - } - glEnable(GL_LIGHTING); - glEnable(GL_DEPTH_TEST); -#endif - - glFlush(); - glutSwapBuffers(); -} - - - - - -void newRandom() { - object.setPosition(MT_Point3(0, 0, 0)); - object.clearMomentum(); - object.setMatrix(); - - display(); -} - -void moveAndDisplay() { - g_scene.proceed(timeStep, 0.01); - - MT_Vector3 normal(0, 1, 0); - - MT_Point3 from = object.getWorldCoord(MT_Point3(0, 0, 0)); - MT_Point3 to = from - normal * 10.0; - - g_hit = DT_ObjectRayTest(sm_ground.getObjectHandle(), - from.getValue(), - to.getValue(), g_spot.getValue(), - g_normal.getValue()); - - // Scrap -#define DO_FH -#ifdef DO_FH - MT_Scalar dist = MT_distance(from, g_spot); - if (dist < 5.0) { - MT_Vector3 lin_vel = object.getLinearVelocity(); - MT_Scalar lin_vel_normal = lin_vel.dot(normal); - - MT_Scalar spring_extent = dist + lin_vel_normal * (timeStep * 0.5); - - MT_Scalar f_spring = (5.0 - spring_extent) * 3.0; - object.applyCenterForce(normal * f_spring); - object.applyCenterForce(-lin_vel_normal * normal); - } - -#endif - - - display(); -} - - -void turn_left() { - object.applyTorque(MT_Vector3(0.0, 10.0, 0.0)); -} - -void turn_right() { - object.applyTorque(MT_Vector3(0.0, -10.0, 0.0)); -} - -void forward() { - object.applyCenterForce(20.0 * object.getAhead()); -} - -void backward() { - object.applyCenterForce(-20.0 * object.getAhead()); -} - -void jump() { - object.applyCenterForce(MT_Vector3(0.0, 200.0, 0.0)); -} - - -void toggleIdle() { - static bool idle = true; - if (idle) { - glutIdleFunc(moveAndDisplay); - idle = false; - } - else { - glutIdleFunc(NULL); - idle = true; - } -} - - -void setCamera() { - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 200.0); - MT_Scalar rele = MT_radians(ele); - MT_Scalar razi = MT_radians(azi); - eye.setValue(DISTANCE * sin(razi) * cos(rele), - DISTANCE * sin(rele), - DISTANCE * cos(razi) * cos(rele)); - gluLookAt(eye[0], eye[1], eye[2], - center[0], center[1], center[2], - 0, 1, 0); - glMatrixMode(GL_MODELVIEW); - display(); -} - -const MT_Scalar STEPSIZE = 5; - -void stepLeft() { azi -= STEPSIZE; if (azi < 0) azi += 360; setCamera(); } -void stepRight() { azi += STEPSIZE; if (azi >= 360) azi -= 360; setCamera(); } -void stepFront() { ele += STEPSIZE; if (azi >= 360) azi -= 360; setCamera(); } -void stepBack() { ele -= STEPSIZE; if (azi < 0) azi += 360; setCamera(); } -void zoomIn() { DISTANCE -= 1; setCamera(); } -void zoomOut() { DISTANCE += 1; setCamera(); } - - -void myReshape(int w, int h) { - glViewport(0, 0, w, h); - setCamera(); -} - -void myKeyboard(unsigned char key, int x, int y) -{ - switch (key) - { - case 'w': forward(); break; - case 's': backward(); break; - case 'a': turn_left(); break; - case 'd': turn_right(); break; - case 'e': jump(); break; - case 'l' : stepLeft(); break; - case 'r' : stepRight(); break; - case 'f' : stepFront(); break; - case 'b' : stepBack(); break; - case 'z' : zoomIn(); break; - case 'x' : zoomOut(); break; - case 'i' : toggleIdle(); break; - case ' ' : newRandom(); break; - default: -// std::cout << "unused key : " << key << std::endl; - break; - } -} - -void mySpecial(int key, int x, int y) -{ - switch (key) - { - case GLUT_KEY_LEFT : stepLeft(); break; - case GLUT_KEY_RIGHT : stepRight(); break; - case GLUT_KEY_UP : stepFront(); break; - case GLUT_KEY_DOWN : stepBack(); break; - case GLUT_KEY_PAGE_UP : zoomIn(); break; - case GLUT_KEY_PAGE_DOWN : zoomOut(); break; - case GLUT_KEY_HOME : toggleIdle(); break; - default: -// std::cout << "unused (special) key : " << key << std::endl; - break; - } -} - -void goodbye( void) -{ - g_scene.remove(sm_ground); - g_scene.remove(sm_sphere); - - std::cout << "goodbye ..." << std::endl; - exit(0); -} - -void menu(int choice) -{ - - static int fullScreen = 0; - static int px, py, sx, sy; - - switch(choice) { - case 1: - if (fullScreen == 1) { - glutPositionWindow(px,py); - glutReshapeWindow(sx,sy); - glutChangeToMenuEntry(1,"Full Screen",1); - fullScreen = 0; - } else { - px=glutGet((GLenum)GLUT_WINDOW_X); - py=glutGet((GLenum)GLUT_WINDOW_Y); - sx=glutGet((GLenum)GLUT_WINDOW_WIDTH); - sy=glutGet((GLenum)GLUT_WINDOW_HEIGHT); - glutFullScreen(); - glutChangeToMenuEntry(1,"Close Full Screen",1); - fullScreen = 1; - } - break; - case 2: - toggleIdle(); - break; - case 3: - goodbye(); - break; - default: - break; - } -} - -void createMenu() -{ - glutCreateMenu(menu); - glutAddMenuEntry("Full Screen", 1); - glutAddMenuEntry("Toggle Idle (Start/Stop)", 2); - glutAddMenuEntry("Quit", 3); - glutAttachMenu(GLUT_RIGHT_BUTTON); -} - -int main(int argc, char **argv) { - glutInit(&argc, argv); - glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); - glutInitWindowPosition(0, 0); - glutInitWindowSize(500, 500); - glutCreateWindow("Physics demo"); - - myinit(); - glutKeyboardFunc(myKeyboard); - glutSpecialFunc(mySpecial); - glutReshapeFunc(myReshape); - createMenu(); - glutIdleFunc(NULL); - - glutDisplayFunc(display); - glutMainLoop(); - return 0; -} - - - - - - - diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/Makefile b/source/gameengine/Physics/Sumo/Fuzzics/src/Makefile deleted file mode 100644 index b2744c5496a..00000000000 --- a/source/gameengine/Physics/Sumo/Fuzzics/src/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# $Id$ -# Copyright (C) 2001 NaN Technologies B.V. - -LIBNAME = fuzzics -DIR = $(OCGDIR)/gameengine/blphys/$(LIBNAME) - -include nan_compile.mk - -CCFLAGS += $(LEVEL_1_CPP_WARNINGS) - -CPPFLAGS += -I../include -I$(NAN_MOTO)/include -I../../include -CPPFLAGS += -I$(NAN_SOLID)/include - diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_FhObject.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_FhObject.cpp deleted file mode 100644 index d866cdb4922..00000000000 --- a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_FhObject.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/** - * $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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#include "SM_FhObject.h" -#include "MT_MinMax.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -SM_FhObject::SM_FhObject(DT_ShapeHandle rayshape, MT_Vector3 ray, SM_Object *parent_object) : - SM_Object(rayshape, NULL, NULL, NULL), - m_ray(ray), - m_ray_direction(ray.normalized()), - m_parent_object(parent_object) -{ -} - -SM_FhObject::~SM_FhObject() -{ - DT_DeleteShape(getShapeHandle()); -} - -DT_Bool SM_FhObject::ray_hit(void *client_data, - void *client_object1, - void *client_object2, - const DT_CollData *coll_data) -{ - - SM_FhObject *fh_object = dynamic_cast((SM_Object *)client_object2); - if (!fh_object) - { - std::swap(client_object1, client_object2); - fh_object = dynamic_cast((SM_Object *)client_object2); - } - - SM_Object *hit_object = (SM_Object *)client_object1; - const SM_MaterialProps *matProps = hit_object->getMaterialProps(); - - if ((matProps == 0) || (matProps->m_fh_distance < MT_EPSILON)) { - return DT_CONTINUE; - } - - SM_Object *cl_object = fh_object->getParentObject(); - - assert(fh_object); - - if (hit_object == cl_object) { - // Shot myself in the foot... - return DT_CONTINUE; - } - - const SM_ShapeProps *shapeProps = cl_object->getShapeProps(); - - // Exit if the client object is not dynamic. - if (shapeProps == 0) { - return DT_CONTINUE; - } - - MT_Point3 lspot; - MT_Vector3 normal; - - DT_Vector3 from, to, dnormal; - DT_Scalar dlspot; - fh_object->getPosition().getValue(from); - fh_object->getSpot().getValue(to); - - - if (DT_ObjectRayCast(hit_object->getObjectHandle(), - from, - to, - 1., - &dlspot, - dnormal)) { - - lspot = fh_object->getPosition() + (fh_object->getSpot() - fh_object->getPosition()) * dlspot; - const MT_Vector3& ray_dir = fh_object->getRayDirection(); - MT_Scalar dist = MT_distance(fh_object->getPosition(), lspot) - - cl_object->getMargin() - shapeProps->m_radius; - - normal = MT_Vector3(dnormal).safe_normalized(); - - if (dist < matProps->m_fh_distance) { - - if (shapeProps->m_do_fh) { - lspot -= hit_object->getPosition(); - MT_Vector3 rel_vel = cl_object->getLinearVelocity() - hit_object->getVelocity(lspot); - MT_Scalar rel_vel_ray = ray_dir.dot(rel_vel); - MT_Scalar spring_extent = 1.0 - dist / matProps->m_fh_distance; - - MT_Scalar i_spring = spring_extent * matProps->m_fh_spring; - MT_Scalar i_damp = rel_vel_ray * matProps->m_fh_damping; - - cl_object->addLinearVelocity(-(i_spring + i_damp) * ray_dir); - if (matProps->m_fh_normal) { - cl_object->addLinearVelocity( - (i_spring + i_damp) * - (normal - normal.dot(ray_dir) * ray_dir)); - } - - MT_Vector3 lateral = rel_vel - rel_vel_ray * ray_dir; - const SM_ShapeProps *shapeProps = cl_object->getShapeProps(); - - if (shapeProps->m_do_anisotropic) { - MT_Matrix3x3 lcs(cl_object->getOrientation()); - MT_Vector3 loc_lateral = lateral * lcs; - const MT_Vector3& friction_scaling = - shapeProps->m_friction_scaling; - - loc_lateral.scale(friction_scaling[0], - friction_scaling[1], - friction_scaling[2]); - lateral = lcs * loc_lateral; - } - - - MT_Scalar rel_vel_lateral = lateral.length(); - - if (rel_vel_lateral > MT_EPSILON) { - MT_Scalar friction_factor = matProps->m_friction; - MT_Scalar max_friction = friction_factor * MT_max(MT_Scalar(0.0), i_spring); - - MT_Scalar rel_mom_lateral = rel_vel_lateral / - cl_object->getInvMass(); - - MT_Vector3 friction = - (rel_mom_lateral > max_friction) ? - -lateral * (max_friction / rel_vel_lateral) : - -lateral; - - cl_object->applyCenterImpulse(friction); - } - } - - if (shapeProps->m_do_rot_fh) { - const double *ogl_mat = cl_object->getMatrix(); - MT_Vector3 up(&ogl_mat[8]); - MT_Vector3 t_spring = up.cross(normal) * matProps->m_fh_spring; - MT_Vector3 ang_vel = cl_object->getAngularVelocity(); - - // only rotations that tilt relative to the normal are damped - ang_vel -= ang_vel.dot(normal) * normal; - - MT_Vector3 t_damp = ang_vel * matProps->m_fh_damping; - - cl_object->addAngularVelocity(t_spring - t_damp); - } - } - } - - return DT_CONTINUE; -} - - - diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_MotionState.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_MotionState.cpp deleted file mode 100644 index b8f4e0c591c..00000000000 --- a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_MotionState.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/** - * $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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#include -#include -#include - -#include "SM_MotionState.h" - -void SM_MotionState::integrateMidpoint(MT_Scalar timeStep, const SM_MotionState &prev_state, const MT_Vector3 &velocity, const MT_Quaternion& ang_vel) -{ - m_pos += (prev_state.getLinearVelocity() + velocity) * (timeStep * 0.5); - m_orn += (prev_state.getAngularVelocity() * prev_state.getOrientation() + ang_vel * m_orn) * (timeStep * 0.25); - m_orn.normalize(); -} - -void SM_MotionState::integrateBackward(MT_Scalar timeStep, const MT_Vector3 &velocity, const MT_Quaternion& ang_vel) -{ - m_pos += velocity * timeStep; - m_orn += ang_vel * m_orn * (timeStep * 0.5); - m_orn.normalize(); -} - -void SM_MotionState::integrateForward(MT_Scalar timeStep, const SM_MotionState &prev_state) -{ - m_pos += prev_state.getLinearVelocity() * timeStep; - m_orn += prev_state.getAngularVelocity() * m_orn * (timeStep * 0.5); - m_orn.normalize(); -} - -/* -// Newtonian lerp: interpolate based on Newtonian motion -void SM_MotionState::nlerp(const SM_MotionState &prev, const SM_MotionState &next) -{ - MT_Scalar dt = next.getTime() - prev.getTime(); - MT_Scalar t = getTime() - prev.getTime(); - MT_Vector3 dx = next.getPosition() - prev.getPosition(); - MT_Vector3 a = dx/(dt*dt) - prev.getLinearVelocity()/dt; - - m_pos = prev.getPosition() + prev.getLinearVelocity()*t + a*t*t; -} -*/ - -void SM_MotionState::lerp(const SM_MotionState &prev, const SM_MotionState &next) -{ - MT_Scalar dt = next.getTime() - prev.getTime(); - if (MT_fuzzyZero(dt)) - { - *this = next; - return; - } - - MT_Scalar x = (getTime() - prev.getTime())/dt; - - m_pos = x*next.getPosition() + (1-x)*prev.getPosition(); - - m_orn = prev.getOrientation().slerp(next.getOrientation(), 1-x); - - m_lin_vel = x*next.getLinearVelocity() + (1-x)*prev.getLinearVelocity(); - m_ang_vel = x*next.getAngularVelocity() + (1-x)*prev.getAngularVelocity(); -} - -void SM_MotionState::lerp(MT_Scalar t, const SM_MotionState &other) -{ - MT_Scalar x = (t - getTime())/(other.getTime() - getTime()); - m_pos = (1-x)*m_pos + x*other.getPosition(); - - m_orn = other.getOrientation().slerp(m_orn, x); - - m_lin_vel = (1-x)*m_lin_vel + x*other.getLinearVelocity(); - m_ang_vel = (1-x)*m_ang_vel + x*other.getAngularVelocity(); - - m_time = t; -} - diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp deleted file mode 100644 index 4b2c7cae008..00000000000 --- a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp +++ /dev/null @@ -1,1298 +0,0 @@ -/** - * $Id$ - * Copyright (C) 2001 NaN Technologies B.V. - * The basic physics object. - * - * ***** 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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef WIN32 -// This warning tells us about truncation of __long__ stl-generated names. -// It can occasionally cause DevStudio to have internal compiler warnings. -#pragma warning( disable : 4786 ) -#endif - -#include "MT_assert.h" - -#include "SM_Object.h" -#include "SM_Scene.h" -#include "SM_FhObject.h" -#include "SM_Debug.h" - -#include "MT_MinMax.h" - -MT_Scalar SM_Object::ImpulseThreshold = -1.0; - -struct Contact -{ - SM_Object *obj1; - SM_Object *obj2; - MT_Vector3 normal; - MT_Point3 pos; - - // Sort objects by height - bool operator()(const Contact *a, const Contact *b) - { - return a->pos[2] < b->pos[2]; - } - - Contact(SM_Object *o1, SM_Object *o2, const MT_Vector3 nor, const MT_Point3 p) - : obj1(o1), - obj2(o2), - normal(nor), - pos(p) - { - } - - Contact() - { - } - - void resolve() - { - if (obj1->m_static || obj2->m_static) - { - if (obj1->isDynamic()) - { - if (obj1->m_static && obj2->m_static) - { - if (obj1->m_static < obj2->m_static) - { - obj2->m_error -= normal; - obj2->m_static = obj1->m_static + 1; - } - else - { - obj1->m_error += normal; - obj1->m_static = obj2->m_static + 1; - } - } - else - { - if (obj1->m_static) - { - obj2->m_error -= normal; - obj2->m_static = obj1->m_static + 1; - } - else - { - obj1->m_error += normal; - obj1->m_static = obj2->m_static + 1; - } - } - } - else - { - obj2->m_error -= normal; - obj2->m_static = 1; - } - } - else - { - // This distinction between dynamic and non-dynamic objects should not be - // necessary. Non-dynamic objects are assumed to have infinite mass. - if (obj1->isDynamic()) { - MT_Vector3 error = normal * 0.5f; - obj1->m_error += error; - obj2->m_error -= error; - } - else { - // Same again but now obj1 is non-dynamic - obj2->m_error -= normal; - obj2->m_static = obj1->m_static + 1; - } - } - - } - - - typedef std::set Set; -}; - -static Contact::Set contacts; - -SM_Object::SM_Object( - DT_ShapeHandle shape, - const SM_MaterialProps *materialProps, - const SM_ShapeProps *shapeProps, - SM_Object *dynamicParent) : - - m_dynamicParent(dynamicParent), - m_client_object(0), - m_physicsClientObject(0), - m_shape(shape), - m_materialProps(materialProps), - m_materialPropsBackup(0), - m_shapeProps(shapeProps), - m_shapePropsBackup(0), - m_margin(0.0), - m_scaling(1.0, 1.0, 1.0), - m_reaction_impulse(0.0, 0.0, 0.0), - m_reaction_force(0.0, 0.0, 0.0), - m_lin_mom(0.0, 0.0, 0.0), - m_ang_mom(0.0, 0.0, 0.0), - m_force(0.0, 0.0, 0.0), - m_torque(0.0, 0.0, 0.0), - m_error(0.0, 0.0, 0.0), - m_combined_lin_vel (0.0, 0.0, 0.0), - m_combined_ang_vel (0.0, 0.0, 0.0), - m_fh_object(0), - m_inv_mass(0.0), - m_inv_inertia(0., 0., 0.), - m_kinematic(false), - m_prev_kinematic(false), - m_is_rigid_body(false), - m_static(0) -{ - m_object = DT_CreateObject(this, shape); - m_xform.setIdentity(); - m_xform.getValue(m_ogl_matrix); - if (shapeProps) - { - if (shapeProps->m_do_fh || shapeProps->m_do_rot_fh) - { - DT_Vector3 zero = {0., 0., 0.}, ray = {0.0, 0.0, -10.0}; - m_fh_object = new SM_FhObject(DT_NewLineSegment(zero, ray), MT_Vector3(ray), this); - //printf("SM_Object:: WARNING! fh disabled.\n"); - } - m_inv_mass = 1. / shapeProps->m_mass; - m_inv_inertia = MT_Vector3(1./shapeProps->m_inertia[0], 1./shapeProps->m_inertia[1], 1./shapeProps->m_inertia[2]); - } - updateInvInertiaTensor(); - m_suspended = false; -} - - - void -SM_Object:: -integrateForces( - MT_Scalar timeStep -){ - if (!m_suspended) { - m_prev_state = getNextFrame(); - m_prev_state.setLinearVelocity(actualLinVelocity()); - m_prev_state.setAngularVelocity(actualAngVelocity()); - if (isDynamic()) { - // Integrate momentum (forward Euler) - m_lin_mom += m_force * timeStep; - m_ang_mom += m_torque * timeStep; - // Drain momentum because of air/water resistance - m_lin_mom *= pow(m_shapeProps->m_lin_drag, timeStep); - m_ang_mom *= pow(m_shapeProps->m_ang_drag, timeStep); - // Set velocities according momentum - getNextFrame().setLinearVelocity(m_lin_mom * m_inv_mass); - getNextFrame().setAngularVelocity(m_inv_inertia_tensor * m_ang_mom); - } - } - -}; - - void -SM_Object:: -integrateMomentum( - MT_Scalar timeStep -){ - // Integrate position and orientation - - // only do it for objects with linear and/or angular velocity - // else clients with hierarchies may get into trouble - if (!actualLinVelocity().fuzzyZero() || !actualAngVelocity().fuzzyZero()) - { - - // those MIDPOINT and BACKWARD integration methods are - // in this form not ok with some testfiles ! - // For a release build please use forward euler unless completely tested - -//#define MIDPOINT -//#define BACKWARD -#ifdef MIDPOINT -// Midpoint rule - getNextFrame().integrateMidpoint(timeStep, m_prev_state, actualLinVelocity(), actualAngVelocity()); -#elif defined BACKWARD -// Backward Euler - getNextFrame().integrateBackward(timeStep, actualLinVelocity(), actualAngVelocity()); -#else -// Forward Euler - getNextFrame().integrateForward(timeStep, m_prev_state); -#endif - - calcXform(); - notifyClient(); - - } -} - -/** - * dynamicCollision computes the response to a collision. - * - * @param local2 the contact point in local coordinates. - * @param normal the contact normal. - * @param dist the penetration depth of the contact. (unused) - * @param rel_vel the relative velocity of the objects - * @param restitution the amount of momentum conserved in the collision. Range: 0.0 - 1.0 - * @param friction_factor the amount of friction between the two surfaces. - * @param invMass the inverse mass of the collision objects (1.0 / mass) - */ -void SM_Object::dynamicCollision(const MT_Point3 &local2, - const MT_Vector3 &normal, - MT_Scalar dist, - const MT_Vector3 &rel_vel, - MT_Scalar restitution, - MT_Scalar friction_factor, - MT_Scalar invMass -) -{ - /** - * rel_vel_normal is the relative velocity in the contact normal direction. - */ - MT_Scalar rel_vel_normal = normal.dot(rel_vel); - - /** - * if rel_vel_normal > 0, the objects are moving apart! - */ - if (rel_vel_normal < -MT_EPSILON) { - /** - * if rel_vel_normal < ImpulseThreshold, scale the restitution down. - * This should improve the simulation where the object is stacked. - */ - restitution *= MT_min(MT_Scalar(1.0), rel_vel_normal/ImpulseThreshold); - - MT_Scalar impulse = -(1.0 + restitution) * rel_vel_normal; - - if (isRigidBody()) - { - MT_Vector3 temp = getInvInertiaTensor() * local2.cross(normal); - impulse /= invMass + normal.dot(temp.cross(local2)); - - /** - * Apply impulse at the collision point. - * Take rotational inertia into account. - */ - applyImpulse(local2 + getNextFrame().getPosition(), impulse * normal); - } else { - /** - * Apply impulse through object center. (no rotation.) - */ - impulse /= invMass; - applyCenterImpulse( impulse * normal ); - } - - MT_Vector3 external = m_combined_lin_vel + m_combined_ang_vel.cross(local2); - MT_Vector3 lateral = rel_vel - external - normal * (rel_vel_normal - external.dot(normal)); -#if 0 - // test - only do friction on the physics part of the - // velocity. - vel1 -= obj1->m_combined_lin_vel; - vel2 -= obj2->m_combined_lin_vel; - - // This should look familiar.... - rel_vel = vel2 - vel1; - rel_vel_normal = normal.dot(rel_vel); -#endif - /** - * The friction part starts here!!!!!!!! - * - * Compute the lateral component of the relative velocity - * lateral actually points in the opposite direction, i.e., - * into the direction of the friction force. - */ - if (m_shapeProps->m_do_anisotropic) { - - /** - * For anisotropic friction we scale the lateral component, - * rather than compute a direction-dependent fricition - * factor. For this the lateral component is transformed to - * local coordinates. - */ - - MT_Matrix3x3 lcs(getNextFrame().getOrientation()); - - /** - * We cannot use m_xform.getBasis() for the matrix, since - * it might contain a non-uniform scaling. - * OPT: it's a bit daft to compute the matrix since the - * quaternion itself can be used to do the transformation. - */ - MT_Vector3 loc_lateral = lateral * lcs; - - /** - * lcs is orthogonal so lcs.inversed() == lcs.transposed(), - * and lcs.transposed() * lateral == lateral * lcs. - */ - const MT_Vector3& friction_scaling = - m_shapeProps->m_friction_scaling; - - // Scale the local lateral... - loc_lateral.scale(friction_scaling[0], - friction_scaling[1], - friction_scaling[2]); - // ... and transform it back to global coordinates - lateral = lcs * loc_lateral; - } - - /** - * A tiny Coulomb friction primer: - * The Coulomb friction law states that the magnitude of the - * maximum possible friction force depends linearly on the - * magnitude of the normal force. - * - * \f[ - F_max_friction = friction_factor * F_normal - \f] - * - * (NB: independent of the contact area!!) - * - * The friction factor depends on the material. - * We use impulses rather than forces but let us not be - * bothered by this. - */ - MT_Scalar rel_vel_lateral = lateral.length(); - - if (rel_vel_lateral > MT_EPSILON) { - lateral /= rel_vel_lateral; - - // Compute the maximum friction impulse - MT_Scalar max_friction = - friction_factor * MT_max(MT_Scalar(0.0), impulse); - - // I guess the GEN_max is not necessary, so let's check it - - MT_assert(impulse >= 0.0); - - /** - * Here's the trick. We compute the impulse to make the - * lateral velocity zero. (Make the objects stick together - * at the contact point. If this impulse is larger than - * the maximum possible friction impulse, then shrink its - * magnitude to the maximum friction. - */ - - if (isRigidBody()) { - - /** - * For rigid bodies we take the inertia into account, - * since the friction impulse is going to change the - * angular momentum as well. - */ - MT_Vector3 temp = getInvInertiaTensor() * local2.cross(lateral); - MT_Scalar impulse_lateral = rel_vel_lateral / - (invMass + lateral.dot(temp.cross(local2))); - - MT_Scalar friction = MT_min(impulse_lateral, max_friction); - applyImpulse(local2 + getNextFrame().getPosition(), -lateral * friction); - } - else { - MT_Scalar impulse_lateral = rel_vel_lateral / invMass; - - MT_Scalar friction = MT_min(impulse_lateral, max_friction); - applyCenterImpulse( -friction * lateral); - } - - - } - - //calcXform(); - //notifyClient(); - - } -} - -static void AddCallback(SM_Scene *scene, SM_Object *obj1, SM_Object *obj2) -{ - // If we have callbacks on either of the client objects, do a collision test - // and add a callback if they intersect. - DT_Vector3 v; - if ((obj1->getClientObject() && obj1->getClientObject()->hasCollisionCallback()) || - (obj2->getClientObject() && obj2->getClientObject()->hasCollisionCallback()) && - DT_GetIntersect(obj1->getObjectHandle(), obj2->getObjectHandle(), v)) - scene->notifyCollision(obj1, obj2); -} - -DT_Bool SM_Object::boing( - void *client_data, - void *object1, - void *object2, - const DT_CollData *coll_data -){ - SM_Scene *scene = (SM_Scene *)client_data; - SM_Object *obj1 = (SM_Object *)object1; - SM_Object *obj2 = (SM_Object *)object2; - - // at this point it is unknown whether we are really intersecting (broad phase) - - DT_Vector3 p1, p2; - if (!obj2->isDynamic()) { - std::swap(obj1, obj2); - } - - // If one of the objects is a ghost then ignore it for the dynamics - if (obj1->isGhost() || obj2->isGhost()) { - AddCallback(scene, obj1, obj2); - return DT_CONTINUE; - } - - // Objects do not collide with parent objects - if (obj1->getDynamicParent() == obj2 || obj2->getDynamicParent() == obj1) { - AddCallback(scene, obj1, obj2); - return DT_CONTINUE; - } - - if (!obj2->isDynamic()) { - AddCallback(scene, obj1, obj2); - return DT_CONTINUE; - } - - // Get collision data from SOLID - if (!DT_GetPenDepth(obj1->getObjectHandle(), obj2->getObjectHandle(), p1, p2)) - return DT_CONTINUE; - - MT_Point3 local1(p1), local2(p2); - MT_Vector3 normal(local2 - local1); - MT_Scalar dist = normal.length(); - - if (dist < MT_EPSILON) - return DT_CONTINUE; - - // Now we are definitely intersecting. - - // Set callbacks for game engine. - if ((obj1->getClientObject() && obj1->getClientObject()->hasCollisionCallback()) || - (obj2->getClientObject() && obj2->getClientObject()->hasCollisionCallback())) - scene->notifyCollision(obj1, obj2); - - local1 -= obj1->getNextFrame().getPosition(); - local2 -= obj2->getNextFrame().getPosition(); - - // Calculate collision parameters - MT_Vector3 rel_vel = obj1->getVelocity(local1) - obj2->getVelocity(local2); - - MT_Scalar restitution = - MT_min(obj1->getMaterialProps()->m_restitution, - obj2->getMaterialProps()->m_restitution); - - MT_Scalar friction_factor = - MT_min(obj1->getMaterialProps()->m_friction, - obj2->getMaterialProps()->m_friction); - - MT_Scalar invMass = obj1->getInvMass() + obj2->getInvMass(); - - normal /= dist; - - // Calculate reactions - if (obj1->isDynamic()) - obj1->dynamicCollision(local1, normal, dist, rel_vel, restitution, friction_factor, invMass); - - if (obj2->isDynamic()) - { - obj2->dynamicCollision(local2, -normal, dist, -rel_vel, restitution, friction_factor, invMass); - if (!obj1->isDynamic() || obj1->m_static) - obj2->m_static = obj1->m_static + 1; - } - - return DT_CONTINUE; -} - -DT_Bool SM_Object::fix( - void *client_data, - void *object1, - void *object2, - const DT_CollData *coll_data -){ - SM_Object *obj1 = (SM_Object *)object1; - SM_Object *obj2 = (SM_Object *)object2; - - // If one of the objects is a ghost then ignore it for the dynamics - if (obj1->isGhost() || obj2->isGhost()) { - return DT_CONTINUE; - } - - if (obj1->getDynamicParent() == obj2 || obj2->getDynamicParent() == obj1) { - return DT_CONTINUE; - } - - if (!obj2->isDynamic()) { - std::swap(obj1, obj2); - } - - if (!obj2->isDynamic()) { - return DT_CONTINUE; - } - - // obj1 points to a dynamic object - DT_Vector3 p1, p2; - if (!DT_GetPenDepth(obj1->getObjectHandle(), obj2->getObjectHandle(), p1, p2)) - return DT_CONTINUE; - MT_Point3 local1(p1), local2(p2); - // Get collision data from SOLID - MT_Vector3 normal(local2 - local1); - - MT_Scalar dist = normal.dot(normal); - if (dist < MT_EPSILON || dist > obj2->m_shapeProps->m_radius*obj2->m_shapeProps->m_radius) - return DT_CONTINUE; - - - if ((obj1->m_static || !obj1->isDynamic()) && obj1->m_static < obj2->m_static) - { - obj2->m_static = obj1->m_static + 1; - } else if (obj2->m_static && obj2->m_static < obj1->m_static) - { - obj1->m_static = obj2->m_static + 1; - } - - contacts.insert(new Contact(obj1, obj2, normal, MT_Point3(local1 + 0.5*(local2 - local1)))); - - - return DT_CONTINUE; -} - -void SM_Object::relax(void) -{ - for (Contact::Set::iterator csit = contacts.begin() ; csit != contacts.end(); ++csit) - { - (*csit)->resolve(); - delete (*csit); - } - - contacts.clear(); - if (m_error.fuzzyZero()) - return; - //std::cout << "SM_Object::relax: { " << m_error << " }" << std::endl; - - getNextFrame().setPosition(getNextFrame().getPosition() + m_error); - m_error.setValue(0., 0., 0.); - //calcXform(); - //notifyClient(); -} - -SM_Object::SM_Object() : - m_dynamicParent(0), - m_client_object(0), - m_physicsClientObject(0), - m_shape(0), - m_materialProps(0), - m_materialPropsBackup(0), - m_shapeProps(0), - m_shapePropsBackup(0), - m_object(0), - m_margin(0.0), - m_scaling(1.0, 1.0, 1.0), - m_reaction_impulse(0.0, 0.0, 0.0), - m_reaction_force(0.0, 0.0, 0.0), - m_lin_mom(0.0, 0.0, 0.0), - m_ang_mom(0.0, 0.0, 0.0), - m_force(0.0, 0.0, 0.0), - m_torque(0.0, 0.0, 0.0), - m_error(0.0, 0.0, 0.0), - m_combined_lin_vel (0.0, 0.0, 0.0), - m_combined_ang_vel (0.0, 0.0, 0.0), - m_fh_object(0), - m_kinematic(false), - m_prev_kinematic(false), - m_is_rigid_body(false) -{ - // warning no initialization of variables done by moto. -} - -SM_Object:: -~SM_Object() { - if (m_fh_object) - delete m_fh_object; - - DT_DestroyObject(m_object); - m_object = NULL; -} - - bool -SM_Object:: -isDynamic( -) const { - return m_shapeProps != 0; -} - -/* nzc experimental. There seem to be two places where kinematics - * are evaluated: proceedKinematic (called from SM_Scene) and - * proceed() in this object. I'll just try and bunge these out for - * now. */ - void -SM_Object:: -suspend( -){ - if (!m_suspended) { - m_suspended = true; - suspendDynamics(); - } -} - - void -SM_Object:: -resume( -) { - if (m_suspended) { - m_suspended = false; - restoreDynamics(); - } -} - - void -SM_Object:: -suspendDynamics( -) { - if (m_shapeProps) { - m_shapePropsBackup = m_shapeProps; - m_shapeProps = 0; - } -} - - void -SM_Object:: -restoreDynamics( -) { - if (m_shapePropsBackup) { - m_shapeProps = m_shapePropsBackup; - m_shapePropsBackup = 0; - } -} - - bool -SM_Object:: -isGhost( -) const { - return m_materialProps == 0; -} - - void -SM_Object:: -suspendMaterial( -) { - if (m_materialProps) { - m_materialPropsBackup = m_materialProps; - m_materialProps = 0; - } -} - - void -SM_Object:: -restoreMaterial( -) { - if (m_materialPropsBackup) { - m_materialProps = m_materialPropsBackup; - m_materialPropsBackup = 0; - } -} - - SM_FhObject * -SM_Object:: -getFhObject( -) const { - return m_fh_object; -} - - void -SM_Object:: -registerCallback( - SM_Callback& callback -) { - m_callbackList.push_back(&callback); -} - -// Set the local coordinate system according to the current state - void -SM_Object:: -calcXform() { -#ifdef SM_DEBUG_XFORM - printf("SM_Object::calcXform m_pos = { %-0.5f, %-0.5f, %-0.5f }\n", - m_pos[0], m_pos[1], m_pos[2]); - printf(" m_orn = { %-0.5f, %-0.5f, %-0.5f, %-0.5f }\n", - m_orn[0], m_orn[1], m_orn[2], m_orn[3]); - printf(" m_scaling = { %-0.5f, %-0.5f, %-0.5f }\n", - m_scaling[0], m_scaling[1], m_scaling[2]); -#endif - m_xform.setOrigin(getNextFrame().getPosition()); - m_xform.setBasis(MT_Matrix3x3(getNextFrame().getOrientation(), m_scaling)); - m_xform.getValue(m_ogl_matrix); - - /* Blender has been known to crash here. - This usually means SM_Object *this has been deleted more than once. */ - DT_SetMatrixd(m_object, m_ogl_matrix); - if (m_fh_object) { - m_fh_object->setPosition(getNextFrame().getPosition()); - m_fh_object->calcXform(); - } - updateInvInertiaTensor(); -#ifdef SM_DEBUG_XFORM - printf("\n | %-0.5f %-0.5f %-0.5f %-0.5f |\n", - m_ogl_matrix[0], m_ogl_matrix[4], m_ogl_matrix[ 8], m_ogl_matrix[12]); - printf( " | %-0.5f %-0.5f %-0.5f %-0.5f |\n", - m_ogl_matrix[1], m_ogl_matrix[5], m_ogl_matrix[ 9], m_ogl_matrix[13]); - printf( "m_ogl_matrix = | %-0.5f %-0.5f %-0.5f %-0.5f |\n", - m_ogl_matrix[2], m_ogl_matrix[6], m_ogl_matrix[10], m_ogl_matrix[14]); - printf( " | %-0.5f %-0.5f %-0.5f %-0.5f |\n\n", - m_ogl_matrix[3], m_ogl_matrix[7], m_ogl_matrix[11], m_ogl_matrix[15]); -#endif -} - - void -SM_Object::updateInvInertiaTensor() -{ - m_inv_inertia_tensor = m_xform.getBasis().scaled(m_inv_inertia[0], m_inv_inertia[1], m_inv_inertia[2]) * m_xform.getBasis().transposed(); -} - -// Call callbacks to notify the client of a change of placement - void -SM_Object:: -notifyClient() { - T_CallbackList::iterator i; - for (i = m_callbackList.begin(); i != m_callbackList.end(); ++i) { - (*i)->do_me(); - } -} - - -// Save the current state information for use in the velocity computation in the next frame. - void -SM_Object:: -proceedKinematic( - MT_Scalar timeStep -) { - /* nzc: need to bunge this for the logic bubbling as well? */ - if (!m_suspended) { - m_prev_kinematic = m_kinematic; - if (m_kinematic) { - m_prev_xform = m_xform; - m_timeStep = timeStep; - calcXform(); - m_kinematic = false; - } - } -} - - void -SM_Object:: -saveReactionForce( - MT_Scalar timeStep -) { - if (isDynamic()) { - m_reaction_force = m_reaction_impulse / timeStep; - m_reaction_impulse.setValue(0.0, 0.0, 0.0); - } -} - - void -SM_Object:: -clearForce( -) { - m_force.setValue(0.0, 0.0, 0.0); - m_torque.setValue(0.0, 0.0, 0.0); -} - - void -SM_Object:: -clearMomentum( -) { - m_lin_mom.setValue(0.0, 0.0, 0.0); - m_ang_mom.setValue(0.0, 0.0, 0.0); -} - - void -SM_Object:: -setMargin( - MT_Scalar margin -) { - m_margin = margin; - DT_SetMargin(m_object, margin); -} - - MT_Scalar -SM_Object:: -getMargin( -) const { - return m_margin; -} - -const - SM_MaterialProps * -SM_Object:: -getMaterialProps( -) const { - return m_materialProps; -} - -const - SM_ShapeProps * -SM_Object:: -getShapeProps( -) const { - return m_shapeProps; -} - - void -SM_Object:: -setPosition( - const MT_Point3& pos -){ - m_kinematic = true; - getNextFrame().setPosition(pos); - endFrame(); -} - - void -SM_Object:: -setOrientation( - const MT_Quaternion& orn -){ - MT_assert(!orn.fuzzyZero()); - m_kinematic = true; - getNextFrame().setOrientation(orn); - endFrame(); -} - - void -SM_Object:: -setScaling( - const MT_Vector3& scaling -){ - m_kinematic = true; - m_scaling = scaling; -} - -/** - * Functions to handle linear velocity - */ - - void -SM_Object:: -setExternalLinearVelocity( - const MT_Vector3& lin_vel -) { - m_combined_lin_vel=lin_vel; -} - - void -SM_Object:: -addExternalLinearVelocity( - const MT_Vector3& lin_vel -) { - m_combined_lin_vel+=lin_vel; -} - - void -SM_Object:: -addLinearVelocity( - const MT_Vector3& lin_vel -){ - setLinearVelocity(getNextFrame().getLinearVelocity() + lin_vel); -} - - void -SM_Object:: -setLinearVelocity( - const MT_Vector3& lin_vel -){ - getNextFrame().setLinearVelocity(lin_vel); - if (m_shapeProps) { - m_lin_mom = getNextFrame().getLinearVelocity() * m_shapeProps->m_mass; - } -} - -/** - * Functions to handle angular velocity - */ - - void -SM_Object:: -setExternalAngularVelocity( - const MT_Vector3& ang_vel -) { - m_combined_ang_vel = ang_vel; -} - - void -SM_Object:: -addExternalAngularVelocity( - const MT_Vector3& ang_vel -) { - m_combined_ang_vel += ang_vel; -} - - void -SM_Object:: -setAngularVelocity( - const MT_Vector3& ang_vel -) { - getNextFrame().setAngularVelocity(ang_vel); - if (m_shapeProps) { - m_ang_mom = getNextFrame().getAngularVelocity() * m_shapeProps->m_inertia; - } -} - - void -SM_Object:: -addAngularVelocity( - const MT_Vector3& ang_vel -) { - setAngularVelocity(getNextFrame().getAngularVelocity() + ang_vel); -} - - - void -SM_Object:: -clearCombinedVelocities( -) { - m_combined_lin_vel = MT_Vector3(0,0,0); - m_combined_ang_vel = MT_Vector3(0,0,0); -} - - void -SM_Object:: -resolveCombinedVelocities( - const MT_Vector3 & lin_vel, - const MT_Vector3 & ang_vel -) { - - // Different behaviours for dynamic and non-dynamic - // objects. For non-dynamic we just set the velocity to - // zero. For dynmic the physics velocity has to be - // taken into account. We must make an arbitrary decision - // on how to resolve the 2 velocities. Choices are - // Add the physics velocity to the linear velocity. Objects - // will just keep on moving in the direction they were - // last set in - untill external forces affect them. - // Set the combinbed linear and physics velocity to zero. - // Set the physics velocity in the direction of the set velocity - // zero. - if (isDynamic()) { - -#if 1 - getNextFrame().setLinearVelocity(getNextFrame().getLinearVelocity() + lin_vel); - getNextFrame().setAngularVelocity(getNextFrame().getAngularVelocity() + ang_vel); -#else - - //compute the component of the physics velocity in the - // direction of the set velocity and set it to zero. - MT_Vector3 lin_vel_norm = lin_vel.normalized(); - - setLinearVelocity(getNextFrame().getLinearVelocity() - (getNextFrame().getLinearVelocity().dot(lin_vel_norm) * lin_vel_norm)); -#endif - m_lin_mom = getNextFrame().getLinearVelocity() * m_shapeProps->m_mass; - m_ang_mom = getNextFrame().getAngularVelocity() * m_shapeProps->m_inertia; - clearCombinedVelocities(); - - } - -} - - - MT_Scalar -SM_Object:: -getInvMass( -) const { - return m_inv_mass; - // OPT: cache the result of this division rather than compute it each call -} - - const MT_Vector3& -SM_Object:: -getInvInertia( -) const { - return m_inv_inertia; - // OPT: cache the result of this division rather than compute it each call -} - - const MT_Matrix3x3& -SM_Object:: -getInvInertiaTensor( -) const { - return m_inv_inertia_tensor; -} - - void -SM_Object:: -applyForceField( - const MT_Vector3& accel -) { - if (m_shapeProps) { - m_force += m_shapeProps->m_mass * accel; // F = m * a - } -} - - void -SM_Object:: -applyCenterForce( - const MT_Vector3& force -) { - m_force += force; -} - - void -SM_Object:: -applyTorque( - const MT_Vector3& torque -) { - m_torque += torque; -} - - void -SM_Object:: -applyImpulse( - const MT_Point3& attach, const MT_Vector3& impulse -) { - applyCenterImpulse(impulse); // Change in linear momentum - applyAngularImpulse((attach - getNextFrame().getPosition()).cross(impulse)); // Change in angular momentump -} - - void -SM_Object:: -applyCenterImpulse( - const MT_Vector3& impulse -) { - if (m_shapeProps) { - m_lin_mom += impulse; - m_reaction_impulse += impulse; - getNextFrame().setLinearVelocity(m_lin_mom * m_inv_mass); - - // The linear velocity is immedialtely updated since otherwise - // simultaneous collisions will get a double impulse. - } -} - - void -SM_Object:: -applyAngularImpulse( - const MT_Vector3& impulse -) { - if (m_shapeProps) { - m_ang_mom += impulse; - getNextFrame().setAngularVelocity( m_inv_inertia_tensor * m_ang_mom); - } -} - - MT_Point3 -SM_Object:: -getWorldCoord( - const MT_Point3& local -) const { - return m_xform(local); -} - - MT_Vector3 -SM_Object:: -getVelocity( - const MT_Point3& local -) const { - if (m_prev_kinematic && !isDynamic()) - { - // For displaced objects the velocity is faked using the previous state. - // Dynamic objects get their own velocity, not the faked velocity. - // (Dynamic objects shouldn't be displaced in the first place!!) - return (m_xform(local) - m_prev_xform(local)) / m_timeStep; - } - - // NB: m_xform.getBasis() * local == m_xform(local) - m_xform.getOrigin() - return actualLinVelocity() + actualAngVelocity().cross(local); -} - - -const - MT_Vector3& -SM_Object:: -getReactionForce( -) const { - return m_reaction_force; -} - - void -SM_Object:: -getMatrix( - double *m -) const { - std::copy(&m_ogl_matrix[0], &m_ogl_matrix[16], &m[0]); -} - -const - double * -SM_Object:: -getMatrix( -) const { - return m_ogl_matrix; -} - -// Still need this??? -const - MT_Transform& -SM_Object:: -getScaledTransform( -) const { - return m_xform; -} - - DT_ObjectHandle -SM_Object:: -getObjectHandle( -) const { - return m_object; -} - - DT_ShapeHandle -SM_Object:: -getShapeHandle( -) const { - return m_shape; -} - - SM_Object * -SM_Object:: -getDynamicParent( -) { - return m_dynamicParent; -} - - void -SM_Object:: -setRigidBody( - bool is_rigid_body -) { - m_is_rigid_body = is_rigid_body; -} - - bool -SM_Object:: -isRigidBody( -) const { - return m_is_rigid_body; -} - -const - MT_Vector3 -SM_Object:: -actualLinVelocity( -) const { - return m_combined_lin_vel + getNextFrame().getLinearVelocity(); -}; - -const - MT_Vector3 -SM_Object:: -actualAngVelocity( -) const { - return m_combined_ang_vel + getNextFrame().getAngularVelocity(); -} - - -SM_MotionState& -SM_Object:: -getCurrentFrame() -{ - return m_frames[1]; -} - -SM_MotionState& -SM_Object:: -getPreviousFrame() -{ - return m_frames[0]; -} - -SM_MotionState & -SM_Object:: -getNextFrame() -{ - return m_frames[2]; -} - -const SM_MotionState & -SM_Object:: -getCurrentFrame() const -{ - return m_frames[1]; -} - -const SM_MotionState & -SM_Object:: -getPreviousFrame() const -{ - return m_frames[0]; -} - -const SM_MotionState & -SM_Object:: -getNextFrame() const -{ - return m_frames[2]; -} - - -const MT_Point3& -SM_Object:: -getPosition() const -{ - return m_frames[1].getPosition(); -} - -const MT_Quaternion& -SM_Object:: -getOrientation() const -{ - return m_frames[1].getOrientation(); -} - -const MT_Vector3& -SM_Object:: -getLinearVelocity() const -{ - return m_frames[1].getLinearVelocity(); -} - -const MT_Vector3& -SM_Object:: -getAngularVelocity() const -{ - return m_frames[1].getAngularVelocity(); -} - -void -SM_Object:: -interpolate(MT_Scalar timeStep) -{ - if (!actualLinVelocity().fuzzyZero() || !actualAngVelocity().fuzzyZero()) - { - getCurrentFrame().setTime(timeStep); - getCurrentFrame().lerp(getPreviousFrame(), getNextFrame()); - notifyClient(); - } -} - -void -SM_Object:: -endFrame() -{ - getPreviousFrame() = getNextFrame(); - getCurrentFrame() = getNextFrame(); - m_static = 0; -} diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp deleted file mode 100644 index f0791bbf89f..00000000000 --- a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp +++ /dev/null @@ -1,378 +0,0 @@ -/** - * $Id$ - * Copyright (C) 2001 NaN Technologies B.V. - * The physics scene. - * - * ***** 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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef WIN32 -#pragma warning(disable : 4786) // shut off 255 char limit debug template warning -#endif - -#include "SM_Scene.h" -#include "SM_Object.h" -#include "SM_FhObject.h" - -#include "SM_Debug.h" - -#include - -SM_Scene::SM_Scene() : - m_scene(DT_CreateScene()), - m_respTable(DT_CreateRespTable()), - m_secondaryRespTable(DT_CreateRespTable()), - m_fixRespTable(DT_CreateRespTable()), - m_forceField(0.0, 0.0, 0.0), - m_frames(0) -{ - for (int i = 0 ; i < NUM_RESPONSE; i++) - { - m_ResponseClass[i] = DT_GenResponseClass(m_respTable); - m_secondaryResponseClass[i] = DT_GenResponseClass(m_secondaryRespTable); - m_fixResponseClass[i] = DT_GenResponseClass(m_fixRespTable); - } - - /* Sensor */ - DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], 0, DT_NO_RESPONSE, this); - DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this); - DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this); - DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[FH_RESPONSE], 0, DT_NO_RESPONSE, this); - - /* Static */ - DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this); - DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[STATIC_RESPONSE], 0, DT_NO_RESPONSE, this); - DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Object::boing, DT_BROAD_RESPONSE, this); - DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[FH_RESPONSE], SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this); - - /* Object */ - DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this); - DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_Object::boing, DT_BROAD_RESPONSE, this); - DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Object::boing, DT_BROAD_RESPONSE, this); - DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[FH_RESPONSE], SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this); - - /* Fh Object */ - DT_AddPairResponse(m_respTable, m_ResponseClass[FH_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], 0, DT_NO_RESPONSE, this); - DT_AddPairResponse(m_respTable, m_ResponseClass[FH_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this); - DT_AddPairResponse(m_respTable, m_ResponseClass[FH_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this); - DT_AddPairResponse(m_respTable, m_ResponseClass[FH_RESPONSE], m_ResponseClass[FH_RESPONSE], 0, DT_NO_RESPONSE, this); - - /* Object (Fix Pass) */ - DT_AddPairResponse(m_fixRespTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], 0, DT_NO_RESPONSE, this); - DT_AddPairResponse(m_fixRespTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_Object::fix, DT_BROAD_RESPONSE, this); - DT_AddPairResponse(m_fixRespTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Object::fix, DT_BROAD_RESPONSE, this); - DT_AddPairResponse(m_fixRespTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[FH_RESPONSE], 0, DT_NO_RESPONSE, this); -} - -void SM_Scene::addTouchCallback(int response_class, DT_ResponseCallback callback, void *user) -{ - DT_AddClassResponse(m_secondaryRespTable, m_secondaryResponseClass[response_class], callback, DT_BROAD_RESPONSE, user); -} - -void SM_Scene::addSensor(SM_Object& object) -{ - T_ObjectList::iterator i = - std::find(m_objectList.begin(), m_objectList.end(), &object); - if (i == m_objectList.end()) - { - object.calcXform(); - m_objectList.push_back(&object); - DT_AddObject(m_scene, object.getObjectHandle()); - DT_SetResponseClass(m_respTable, object.getObjectHandle(), m_ResponseClass[SENSOR_RESPONSE]); - DT_SetResponseClass(m_secondaryRespTable, object.getObjectHandle(), m_secondaryResponseClass [SENSOR_RESPONSE]); - DT_SetResponseClass(m_fixRespTable, object.getObjectHandle(), m_fixResponseClass[SENSOR_RESPONSE]); - } -} - -void SM_Scene::add(SM_Object& object) { - object.calcXform(); - m_objectList.push_back(&object); - DT_AddObject(m_scene, object.getObjectHandle()); - if (object.isDynamic()) { - DT_SetResponseClass(m_respTable, object.getObjectHandle(), m_ResponseClass[OBJECT_RESPONSE]); - DT_SetResponseClass(m_secondaryRespTable, object.getObjectHandle(), m_secondaryResponseClass[OBJECT_RESPONSE]); - DT_SetResponseClass(m_fixRespTable, object.getObjectHandle(), m_fixResponseClass[OBJECT_RESPONSE]); - } else { - DT_SetResponseClass(m_respTable, object.getObjectHandle(), m_ResponseClass[STATIC_RESPONSE]); - DT_SetResponseClass(m_secondaryRespTable, object.getObjectHandle(), m_secondaryResponseClass[STATIC_RESPONSE]); - DT_SetResponseClass(m_fixRespTable, object.getObjectHandle(), m_fixResponseClass[STATIC_RESPONSE]); - } - - SM_FhObject *fh_object = object.getFhObject(); - - if (fh_object) { - DT_AddObject(m_scene, fh_object->getObjectHandle()); - DT_SetResponseClass(m_respTable, fh_object->getObjectHandle(), m_ResponseClass[FH_RESPONSE]); - DT_SetResponseClass(m_secondaryRespTable, fh_object->getObjectHandle(), m_secondaryResponseClass[FH_RESPONSE]); - DT_SetResponseClass(m_fixRespTable, fh_object->getObjectHandle(), m_fixResponseClass[FH_RESPONSE]); - } -} - -void SM_Scene::requestCollisionCallback(SM_Object &object) -{ - DT_SetResponseClass(m_respTable, object.getObjectHandle(), m_ResponseClass[OBJECT_RESPONSE]); - DT_SetResponseClass(m_secondaryRespTable, object.getObjectHandle(), m_secondaryResponseClass[OBJECT_RESPONSE]); -// DT_SetResponseClass(m_fixRespTable, object.getObjectHandle(), m_fixResponseClass[OBJECT_RESPONSE]); -} - -void SM_Scene::remove(SM_Object& object) { - //std::cout << "SM_Scene::remove this =" << this << "object = " << &object << std::endl; - T_ObjectList::iterator i = - std::find(m_objectList.begin(), m_objectList.end(), &object); - if (!(i == m_objectList.end())) - { - std::swap(*i, m_objectList.back()); - m_objectList.pop_back(); - DT_RemoveObject(m_scene, object.getObjectHandle()); - - SM_FhObject *fh_object = object.getFhObject(); - - if (fh_object) { - DT_RemoveObject(m_scene, fh_object->getObjectHandle()); - } - } - else { - // tried to remove an object that is not in the scene - //assert(false); - } -} - -void SM_Scene::beginFrame() -{ - T_ObjectList::iterator i; - // Apply a forcefield (such as gravity) - for (i = m_objectList.begin(); i != m_objectList.end(); ++i) - (*i)->applyForceField(m_forceField); - -} - -void SM_Scene::endFrame() -{ - T_ObjectList::iterator i; - for (i = m_objectList.begin(); i != m_objectList.end(); ++i) - (*i)->clearForce(); -} - -bool SM_Scene::proceed(MT_Scalar curtime, MT_Scalar ticrate) -{ - if (!m_frames) - { - if (ticrate > 0.) - m_frames = (unsigned int)(curtime*ticrate) + 1.0; - else - m_frames = (unsigned int)(curtime*65536.0); - } - - // Divide the timeStep into a number of subsamples of size roughly - // equal to subS (might be a little smaller). - MT_Scalar subStep; - int num_samples; - int frames = m_frames; - - // Compute the number of steps to do this update. - if (ticrate > 0.0) - { - // Fixed time step - subStep = 1.0/ticrate; - num_samples = (unsigned int)(curtime*ticrate + 1.0) - m_frames; - - if (num_samples > 4) - { - std::cout << "Dropping physics frames! frames:" << num_samples << " substep: " << subStep << std::endl; - MT_Scalar tr = ticrate; - do - { - frames = frames / 2; - tr = tr / 2.0; - num_samples = (unsigned int)(curtime*tr + 1.0) - frames; - subStep *= 2.0; - } while (num_samples > 8); - std::cout << " frames:" << num_samples << " substep: " << subStep << std::endl; - } - } - else - { - // Variable time step. (old update) - // Integrate at least 100 Hz - MT_Scalar timeStep = curtime - m_frames/65536.0; - subStep = timeStep > 0.01 ? 0.01 : timeStep; - num_samples = int(timeStep * 0.01); - if (num_samples < 1) - num_samples = 1; - } - - // Do a physics timestep. - T_ObjectList::iterator i; - if (num_samples > 0) - { - // Do the integration steps per object. - for (int step = 0; step != num_samples; ++step) - { - MT_Scalar time; - if (ticrate > 0.) - time = MT_Scalar(frames + step + 1) * subStep; - else - time = MT_Scalar(m_frames)/65536.0 + MT_Scalar(step + 1)*subStep; - - for (i = m_objectList.begin(); i != m_objectList.end(); ++i) { - (*i)->endFrame(); - // Apply a forcefield (such as gravity) - (*i)->integrateForces(subStep); - // And second we update the object positions by performing - // an integration step for each object - (*i)->integrateMomentum(subStep); - } - - // So now first we let the physics scene respond to - // new forces, velocities set externally. - // The collsion and friction impulses are computed here. - // Collision phase - DT_Test(m_scene, m_respTable); - - // Contact phase - DT_Test(m_scene, m_fixRespTable); - - // Finish this timestep by saving al state information for the next - // timestep and clearing the accumulated forces. - for (i = m_objectList.begin(); i != m_objectList.end(); ++i) { - (*i)->relax(); - (*i)->proceedKinematic(subStep); - (*i)->saveReactionForce(subStep); - (*i)->getNextFrame().setTime(time); - //(*i)->clearForce(); - } - } - } - - if (ticrate > 0) - { - // Interpolate between time steps. - for (i = m_objectList.begin(); i != m_objectList.end(); ++i) - (*i)->interpolate(curtime); - - //only update the m_frames after an actual physics timestep - if (num_samples) - { - m_frames = (unsigned int)(curtime*ticrate) + 1.0; - } - } - else - { - m_frames = (unsigned int)(curtime*65536.0); - } - - return num_samples != 0; -} - -void SM_Scene::notifyCollision(SM_Object *obj1, SM_Object *obj2) -{ - // For each pair of object that collided, call the corresponding callback. - if (m_secondaryRespTable) - DT_CallResponse(m_secondaryRespTable, obj1->getObjectHandle(), obj2->getObjectHandle(), 0); -} - - -SM_Object *SM_Scene::rayTest(void *ignore_client, - const MT_Point3& from, const MT_Point3& to, - MT_Point3& result, MT_Vector3& normal) const { -#ifdef SM_DEBUG_RAYCAST - std::cout << "ray: { " << from << " } - { " << to << " }" << std::endl; -#endif - - DT_Vector3 n, dfrom, dto; - DT_Scalar param; - from.getValue(dfrom); - to.getValue(dto); - SM_Object *hit_object = (SM_Object *) - DT_RayCast(m_scene, ignore_client, dfrom, dto, 1., ¶m, n); - - if (hit_object) { - //result = hit_object->getWorldCoord(from + (to - from)*param); - result = from + (to - from) * param; - normal.setValue(n); -#ifdef SM_DEBUG_RAYCAST - std::cout << "ray: { " << from << " } -> { " << to << " }: { " << result - << " } (" << param << "), normal = { " << normal << " }" << std::endl; -#endif - } - - return hit_object; -} - -void SM_Scene::clearObjectCombinedVelocities() { - - T_ObjectList::iterator i; - - for (i = m_objectList.begin(); i != m_objectList.end(); ++i) { - - (*i)->clearCombinedVelocities(); - - } - -} - - -void SM_Scene::setSecondaryRespTable(DT_RespTableHandle secondaryRespTable) { - m_secondaryRespTable = secondaryRespTable; -} - - -DT_Bool SM_Scene::boing( - void *client_data, - void *object1, - void *object2, - const DT_CollData * -){ - SM_Scene *scene = (SM_Scene *)client_data; - SM_Object *obj1 = (SM_Object *)object1; - SM_Object *obj2 = (SM_Object *)object2; - - scene->notifyCollision(obj1, obj2); // Record this collision for client callbacks - -#ifdef SM_DEBUG_BOING - printf("SM_Scene::boing\n"); -#endif - - return DT_CONTINUE; -} - -SM_Scene::~SM_Scene() -{ - //std::cout << "SM_Scene::~ SM_Scene(): destroy " << this << std::endl; -// if (m_objectList.begin() != m_objectList.end()) -// std::cout << "SM_Scene::~SM_Scene: There are still objects in the Sumo scene!" << std::endl; - for (T_ObjectList::iterator it = m_objectList.begin() ; it != m_objectList.end() ; it++) - delete *it; - - DT_DestroyRespTable(m_respTable); - DT_DestroyRespTable(m_secondaryRespTable); - DT_DestroyRespTable(m_fixRespTable); - DT_DestroyScene(m_scene); -} diff --git a/source/gameengine/Physics/Sumo/Makefile b/source/gameengine/Physics/Sumo/Makefile deleted file mode 100644 index 69efc4d84eb..00000000000 --- a/source/gameengine/Physics/Sumo/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -# -# $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. -# -# The Original Code is: all of this file. -# -# Contributor(s): none yet. -# -# ***** END GPL LICENSE BLOCK ***** -# -# - -SOURCEDIR = source/gameengine/Physics/Sumo -LIBNAME = sumo -DIR = $(OCGDIR)/gameengine/blphys/$(LIBNAME) -DIRS = Fuzzics - -include nan_compile.mk - -CCFLAGS += $(LEVEL_1_CPP_WARNINGS) - -CPPFLAGS += -I$(OPENGL_HEADERS) -CPPFLAGS += -I$(NAN_STRING)/include -CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) - -CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO) -I$(NAN_MOTO)/include -CPPFLAGS += -I$(NAN_SOLID)/include -CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include -CPPFLAGS += -I../../Physics/common -CPPFLAGS += -I../../Physics/Dummy - -include nan_subdirs.mk diff --git a/source/gameengine/Physics/Sumo/SConscript b/source/gameengine/Physics/Sumo/SConscript deleted file mode 100644 index a228a986af2..00000000000 --- a/source/gameengine/Physics/Sumo/SConscript +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/python -Import ('env') - -sources = ['SumoPHYCallbackBridge.cpp', - 'SumoPhysicsController.cpp', - 'SumoPhysicsEnvironment.cpp', - 'Fuzzics/src/SM_FhObject.cpp', - 'Fuzzics/src/SM_Object.cpp', - 'Fuzzics/src/SM_Scene.cpp', - 'Fuzzics/src/SM_MotionState.cpp' - ] - -incs =['.', - '../common', - 'Fuzzics/include', - '#/intern/moto/include' - ] -incs += [env['BF_SOLID_INC']] - -cflags = [] -if env['OURPLATFORM']=='win32-vc': - cflags.append('/GR') - cflags.append('/O1') - -env.BlenderLib ( 'bf_sumo', sources, incs, [], libtype=['core','player'], priority=[400, 55] , compileflags=cflags) diff --git a/source/gameengine/Physics/Sumo/SumoPHYCallbackBridge.cpp b/source/gameengine/Physics/Sumo/SumoPHYCallbackBridge.cpp deleted file mode 100644 index 1992bbe3421..00000000000 --- a/source/gameengine/Physics/Sumo/SumoPHYCallbackBridge.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "SumoPHYCallbackBridge.h" -#include "PHY_IPhysicsController.h" -#include "SM_Object.h" - - -SumoPHYCallbackBridge::SumoPHYCallbackBridge(void* clientData,PHY_ResponseCallback phyCallback) -:m_orgClientData(clientData), -m_phyCallback(phyCallback) -{ - -} -DT_Bool SumoPHYCallbackBridge::StaticSolidToPHYCallback(void *client_data, - void *client_object1, - void *client_object2, - const DT_CollData *coll_data) -{ - SumoPHYCallbackBridge* bridge = static_cast(client_data); - bridge->SolidToPHY(client_object1,client_object2,coll_data); - return false; -} - -DT_Bool SumoPHYCallbackBridge::SolidToPHY(void *client_object1, - void *client_object2, - const DT_CollData *coll_data) -{ - - SM_Object* smObject1 = static_cast(client_object1); - SM_Object* smObject2 = static_cast(client_object2); - - PHY_IPhysicsController* ctrl1 = static_cast(smObject1->getPhysicsClientObject()); - PHY_IPhysicsController* ctrl2 = static_cast(smObject2->getPhysicsClientObject()); - - if (!ctrl1 || !ctrl2) - { - //todo: check which objects are not linked up properly - return false; - } - if (coll_data) - { - PHY_CollData phyCollData; - - phyCollData.m_point1[0] = coll_data->point1[0]; - phyCollData.m_point1[1] = coll_data->point1[1]; - phyCollData.m_point1[2] = coll_data->point1[2]; - phyCollData.m_point1[3] = 0.f; - - phyCollData.m_point2[0] = coll_data->point2[0]; - phyCollData.m_point2[1] = coll_data->point2[1]; - phyCollData.m_point2[2] = coll_data->point2[2]; - phyCollData.m_point2[3] = 0.f; - - phyCollData.m_normal[0] = coll_data->normal[0]; - phyCollData.m_normal[1] = coll_data->normal[1]; - phyCollData.m_normal[2] = coll_data->normal[2]; - phyCollData.m_normal[3] = 0.f; - - - return m_phyCallback(m_orgClientData, - ctrl1,ctrl2,&phyCollData); - } - - return m_phyCallback(m_orgClientData, - ctrl1,ctrl2,0); - -} - diff --git a/source/gameengine/Physics/Sumo/SumoPHYCallbackBridge.h b/source/gameengine/Physics/Sumo/SumoPHYCallbackBridge.h deleted file mode 100644 index cc980f3961d..00000000000 --- a/source/gameengine/Physics/Sumo/SumoPHYCallbackBridge.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SUMO_PHY_CALLBACK_BRIDGE_H -#define SUMO_PHY_CALLBACK_BRIDGE_H - -#include -#include "PHY_DynamicTypes.h" - -class SumoPHYCallbackBridge -{ - void* m_orgClientData; - PHY_ResponseCallback m_phyCallback; - -public: - - SumoPHYCallbackBridge(void* clientData,PHY_ResponseCallback phyCallback); - - static DT_Bool StaticSolidToPHYCallback(void *client_data, - void *client_object1, - void *client_object2, - const DT_CollData *coll_data); - - DT_Bool SolidToPHY(void *client_object1, - void *client_object2, - const DT_CollData *coll_data); - - -}; - -#endif //SUMO_PHY_CALLBACK_BRIDGE_H diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsController.cpp b/source/gameengine/Physics/Sumo/SumoPhysicsController.cpp deleted file mode 100644 index 56caa9236bf..00000000000 --- a/source/gameengine/Physics/Sumo/SumoPhysicsController.cpp +++ /dev/null @@ -1,495 +0,0 @@ -/** - * @file $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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include "SumoPhysicsController.h" -#include "PHY_IMotionState.h" -#include "SM_Object.h" -#include "MT_Quaternion.h" - - -SumoPhysicsController::SumoPhysicsController( - class SM_Scene* sumoScene, - class SM_Object* sumoObj, - class PHY_IMotionState* motionstate, - - bool dyna) - : - m_sumoObj(sumoObj) , - m_sumoScene(sumoScene), - m_bFirstTime(true), - m_bDyna(dyna), - m_MotionState(motionstate) -{ - if (m_sumoObj) - { - - PHY__Vector3 pos1; - getPosition(pos1); - MT_Point3 pos(pos1); - - //temp debugging check - //assert(pos.length() < 100000.f); - - //need this to do the upcast after the solid/sumo collision callback - m_sumoObj->setPhysicsClientObject(this); - //if it is a dyna, register for a callback - m_sumoObj->registerCallback(*this); - } -}; - - - -SumoPhysicsController::~SumoPhysicsController() -{ - if (m_sumoObj) - { - m_sumoScene->remove(*m_sumoObj); - - delete m_sumoObj; - m_sumoObj = NULL; - } -} - -float SumoPhysicsController::getMass() -{ - if (m_sumoObj) - { - const SM_ShapeProps *shapeprops = m_sumoObj->getShapeProps(); - if(shapeprops!=NULL) return shapeprops->m_mass; - } - return 0.f; -} - -bool SumoPhysicsController::SynchronizeMotionStates(float) -{ - if (m_bFirstTime) - { - setSumoTransform(!m_bFirstTime); - m_bFirstTime = false; - } - return false; -} - - - - -void SumoPhysicsController::GetWorldOrientation(MT_Matrix3x3& mat) -{ - float orn[4]; - m_MotionState->getWorldOrientation(orn[0],orn[1],orn[2],orn[3]); - MT_Quaternion quat(orn); - mat.setRotation(quat); - -} - -void SumoPhysicsController::getPosition(PHY__Vector3& pos) const -{ - assert(m_sumoObj); - - pos[0] = m_sumoObj->getPosition()[0]; - pos[1] = m_sumoObj->getPosition()[0]; - pos[2] = m_sumoObj->getPosition()[0]; - - //m_MotionState->getWorldPosition(pos[0],pos[1],pos[2]); -} - -void SumoPhysicsController::GetWorldPosition(MT_Point3& pos) -{ -// assert(m_sumoObj); - -// pos[0] = m_sumoObj->getPosition()[0]; -// pos[1] = m_sumoObj->getPosition()[0]; -// pos[2] = m_sumoObj->getPosition()[0]; - - float worldpos[3]; - m_MotionState->getWorldPosition(worldpos[0],worldpos[1],worldpos[2]); - pos[0]=worldpos[0]; - pos[1]=worldpos[1]; - pos[2]=worldpos[2]; -} - -void SumoPhysicsController::GetWorldScaling(MT_Vector3& scale) -{ - float worldscale[3]; - m_MotionState->getWorldScaling(worldscale[0],worldscale[1],worldscale[2]); - scale[0]=worldscale[0]; - scale[1]=worldscale[1]; - scale[2]=worldscale[2]; -} - - - // kinematic methods -void SumoPhysicsController::RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local) -{ - if (m_sumoObj) - { - MT_Matrix3x3 mat; - GetWorldOrientation(mat); - MT_Vector3 dloc(dlocX,dlocY,dlocZ); - - MT_Point3 newpos = m_sumoObj->getPosition(); - - newpos += (local ? mat * dloc : dloc); - m_sumoObj->setPosition(newpos); - } - -} -void SumoPhysicsController::RelativeRotate(const float drot[12],bool local) -{ - if (m_sumoObj ) - { - MT_Matrix3x3 drotmat(drot); - MT_Matrix3x3 currentOrn; - GetWorldOrientation(currentOrn); - - m_sumoObj->setOrientation(m_sumoObj->getOrientation()*(local ? - drotmat : (currentOrn.inverse() * drotmat * currentOrn)).getRotation()); - } - -} -void SumoPhysicsController::setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal) -{ - m_sumoObj->setOrientation(MT_Quaternion(quatImag0,quatImag1,quatImag2,quatReal)); -} - -void SumoPhysicsController::getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal) -{ - const MT_Quaternion& q = m_sumoObj->getOrientation(); - quatImag0 = q[0]; - quatImag1 = q[1]; - quatImag2 = q[2]; - quatReal = q[3]; -} - -void SumoPhysicsController::setPosition(float posX,float posY,float posZ) -{ - m_sumoObj->setPosition(MT_Point3(posX,posY,posZ)); -} - -void SumoPhysicsController::setScaling(float scaleX,float scaleY,float scaleZ) -{ - if (!m_bDyna) - m_sumoObj->setScaling(MT_Vector3(scaleX,scaleY,scaleZ)); -} - - // physics methods -void SumoPhysicsController::ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local) -{ - if (m_sumoObj) - { - MT_Vector3 torque(torqueX,torqueY,torqueZ); - - MT_Matrix3x3 orn; - GetWorldOrientation(orn); - m_sumoObj->applyTorque(local ? - orn * torque : - torque); - } -} - -void SumoPhysicsController::ApplyForce(float forceX,float forceY,float forceZ,bool local) -{ - if (m_sumoObj) - { - MT_Vector3 force(forceX,forceY,forceZ); - - MT_Matrix3x3 orn; - GetWorldOrientation(orn); - - m_sumoObj->applyCenterForce(local ? - orn * force : - force); - } -} - -void SumoPhysicsController::SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local) -{ - if (m_sumoObj) - { - MT_Vector3 ang_vel(ang_velX,ang_velY,ang_velZ); - - MT_Matrix3x3 orn; - GetWorldOrientation(orn); - - m_sumoObj->setExternalAngularVelocity(local ? - orn * ang_vel : - ang_vel); - } -} - -void SumoPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local) -{ - if (m_sumoObj ) - { - MT_Matrix3x3 orn; - GetWorldOrientation(orn); - - MT_Vector3 lin_vel(lin_velX,lin_velY,lin_velZ); - m_sumoObj->setExternalLinearVelocity(local ? - orn * lin_vel : - lin_vel); - } -} - -void SumoPhysicsController::resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ) -{ - if (m_sumoObj) - m_sumoObj->resolveCombinedVelocities(MT_Vector3(linvelX,linvelY,linvelZ),MT_Vector3(angVelX,angVelY,angVelZ)); -} - - - - -void SumoPhysicsController::applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ) -{ - if (m_sumoObj) - { - MT_Point3 attach(attachX,attachY,attachZ); - MT_Vector3 impulse(impulseX,impulseY,impulseZ); - m_sumoObj->applyImpulse(attach,impulse); - } - -} - -void SumoPhysicsController::SuspendDynamics() -{ - m_suspendDynamics=true; - - if (m_sumoObj) - { - m_sumoObj->suspendDynamics(); - m_sumoObj->setLinearVelocity(MT_Vector3(0,0,0)); - m_sumoObj->setAngularVelocity(MT_Vector3(0,0,0)); - m_sumoObj->calcXform(); - } -} - -void SumoPhysicsController::RestoreDynamics() -{ - m_suspendDynamics=false; - - if (m_sumoObj) - { - m_sumoObj->restoreDynamics(); - } -} - - -/** - reading out information from physics -*/ -void SumoPhysicsController::GetLinearVelocity(float& linvX,float& linvY,float& linvZ) -{ - if (m_sumoObj) - { - // get velocity from the physics object (m_sumoObj) - const MT_Vector3& vel = m_sumoObj->getLinearVelocity(); - linvX = vel[0]; - linvY = vel[1]; - linvZ = vel[2]; - } - else - { - linvX = 0.f; - linvY = 0.f; - linvZ = 0.f; - } -} - -/** - GetVelocity parameters are in geometric coordinates (Origin is not center of mass!). -*/ -void SumoPhysicsController::GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ) -{ - if (m_sumoObj) - { - MT_Point3 pos(posX,posY,posZ); - // get velocity from the physics object (m_sumoObj) - const MT_Vector3& vel = m_sumoObj->getVelocity(pos); - linvX = vel[0]; - linvY = vel[1]; - linvZ = vel[2]; - } - else - { - linvX = 0.f; - linvY = 0.f; - linvZ = 0.f; - - } -} - -void SumoPhysicsController::getReactionForce(float& forceX,float& forceY,float& forceZ) -{ - const MT_Vector3& force = m_sumoObj->getReactionForce(); - forceX = force[0]; - forceY = force[1]; - forceZ = force[2]; -} - -void SumoPhysicsController::setRigidBody(bool rigid) -{ - m_sumoObj->setRigidBody(rigid); -} - -void SumoPhysicsController::PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl) -{ - m_MotionState = motionstate; - - SM_Object* dynaparent=0; - SumoPhysicsController* sumoparentctrl = (SumoPhysicsController* )parentctrl; - - if (sumoparentctrl) - { - dynaparent = sumoparentctrl->GetSumoObject(); - } - - SM_Object* orgsumoobject = m_sumoObj; - - - m_sumoObj = new SM_Object( - orgsumoobject->getShapeHandle(), - orgsumoobject->getMaterialProps(), - orgsumoobject->getShapeProps(), - dynaparent); - - m_sumoObj->setRigidBody(orgsumoobject->isRigidBody()); - - m_sumoObj->setMargin(orgsumoobject->getMargin()); - m_sumoObj->setPosition(orgsumoobject->getPosition()); - m_sumoObj->setOrientation(orgsumoobject->getOrientation()); - //if it is a dyna, register for a callback - m_sumoObj->registerCallback(*this); - - m_sumoScene->add(* (m_sumoObj)); -} - -PHY_IMotionState* SumoPhysicsController::GetMotionState() -{ - return m_MotionState; -} - -void SumoPhysicsController::SetSimulatedTime(float) -{ -} - - -void SumoPhysicsController::WriteMotionStateToDynamics(bool) -{ - -} -// this is the actual callback from sumo, and the position/orientation -//is written to the scenegraph, using the motionstate abstraction - -void SumoPhysicsController::do_me() -{ - MT_assert(m_sumoObj); - const MT_Point3& pos = m_sumoObj->getPosition(); - const MT_Quaternion& orn = m_sumoObj->getOrientation(); - - MT_assert(m_MotionState); - m_MotionState->setWorldPosition(pos[0],pos[1],pos[2]); - m_MotionState->setWorldOrientation(orn[0],orn[1],orn[2],orn[3]); -} - - -void SumoPhysicsController::setSumoTransform(bool nondynaonly) -{ - if (!nondynaonly || !m_bDyna) - { - if (m_sumoObj) - { - MT_Point3 pos; - GetWorldPosition(pos); - - m_sumoObj->setPosition(pos); - if (m_bDyna) - { - m_sumoObj->setScaling(MT_Vector3(1,1,1)); - } else - { - MT_Vector3 scale; - GetWorldScaling(scale); - m_sumoObj->setScaling(scale); - } - MT_Matrix3x3 orn; - GetWorldOrientation(orn); - m_sumoObj->setOrientation(orn.getRotation()); - m_sumoObj->calcXform(); - } - } -} - - - // clientinfo for raycasts for example -void* SumoPhysicsController::getNewClientInfo() -{ - if (m_sumoObj) - return m_sumoObj->getClientObject(); - return 0; - -} -void SumoPhysicsController::setNewClientInfo(void* clientinfo) -{ - if (m_sumoObj) - { - SM_ClientObject* clOb = static_cast (clientinfo); - m_sumoObj->setClientObject(clOb); - } - -} - -void SumoPhysicsController::calcXform() -{ - if (m_sumoObj) - m_sumoObj->calcXform(); -} - -void SumoPhysicsController::SetMargin(float margin) -{ - if (m_sumoObj) - m_sumoObj->setMargin(margin); -} - -float SumoPhysicsController::GetMargin() const -{ - if (m_sumoObj) - m_sumoObj->getMargin(); - return 0.f; -} - -float SumoPhysicsController::GetRadius() const -{ - if (m_sumoObj && m_sumoObj->getShapeProps()) - { - return m_sumoObj->getShapeProps()->m_radius; - } - return 0.f; - -} diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsController.h b/source/gameengine/Physics/Sumo/SumoPhysicsController.h deleted file mode 100644 index adf29649f18..00000000000 --- a/source/gameengine/Physics/Sumo/SumoPhysicsController.h +++ /dev/null @@ -1,192 +0,0 @@ -/** - * @file $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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef __SUMO_PHYSICSCONTROLLER_H -#define __SUMO_PHYSICSCONTROLLER_H - -#include "PHY_IPhysicsController.h" -#include "SM_Scene.h" -#include "SM_Callback.h" - -/** - * Sumo Physics Controller, a special kind of a PhysicsController. - * A Physics Controller is a special kind of Scene Graph Transformation Controller. - * Each time the scene graph get's updated, the controller get's a chance - * in the 'Update' method to reflect changes. - * - * Sumo uses the SOLID library for collision detection. - */ -class SumoPhysicsController : public PHY_IPhysicsController , public SM_Callback - - -{ - - -public: - SumoPhysicsController( - class SM_Scene* sumoScene, - class SM_Object* sumoObj, - class PHY_IMotionState* motionstate, - bool dyna); - - virtual ~SumoPhysicsController(); - - /** - * @name Kinematic Methods. - */ - /*@{*/ - virtual void RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local); - /** - * @param drot a 3x4 matrix. This will treated as a 3x3 rotation matrix. - * @warning RelativeRotate expects a 3x4 matrix. The fourth column is padding. - */ - virtual void RelativeRotate(const float drot[12],bool local); - virtual void getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal); - virtual void setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal); - virtual void setPosition(float posX,float posY,float posZ); - virtual void getPosition(PHY__Vector3& pos) const; - - virtual void setScaling(float scaleX,float scaleY,float scaleZ); - /*@}*/ - - /** - * @name Physics Methods - */ - /*@{*/ - virtual void ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local); - virtual void ApplyForce(float forceX,float forceY,float forceZ,bool local); - virtual void SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local); - virtual void SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local); - virtual void resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ); - virtual void applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ); - virtual void SetActive(bool active){}; - virtual void SuspendDynamics(); - virtual void RestoreDynamics(); - /*@}*/ - - - /** - * reading out information from physics - */ - virtual void GetLinearVelocity(float& linvX,float& linvY,float& linvZ); - /** - * GetVelocity parameters are in geometric coordinates (Origin is not center of mass!). - */ - virtual void GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ); - virtual float getMass(); - virtual void getReactionForce(float& forceX,float& forceY,float& forceZ); - virtual void setRigidBody(bool rigid); - - - virtual void PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl); - - // TODO: remove next line ! - virtual void SetSimulatedTime(float time); - - virtual void WriteDynamicsToMotionState() {}; - virtual void WriteMotionStateToDynamics(bool nondynaonly); - virtual class PHY_IMotionState* GetMotionState(); - - /** - * call from Scene Graph Node to 'update'. - */ - virtual bool SynchronizeMotionStates(float time); - - virtual void calcXform(); - virtual void SetMargin(float margin) ; - virtual float GetMargin() const; - virtual float GetRadius() const ; - virtual void SetRadius(float margin) { SetMargin(margin); } - - - // clientinfo for raycasts for example - virtual void* getNewClientInfo(); - virtual void setNewClientInfo(void* clientinfo); - - float getFriction() { return m_friction;} - float getRestitution() { return m_restitution;} - - /** - * Sumo callback - */ - virtual void do_me(); - - class SM_Object* GetSumoObject () - { - return m_sumoObj; - }; - - void GetWorldOrientation(class MT_Matrix3x3& mat); - void GetWorldPosition(MT_Point3& pos); - void GetWorldScaling(MT_Vector3& scale); - - float GetLinVelocityMin() const { return 0.f; } - void SetLinVelocityMin(float val) { } - float GetLinVelocityMax() const { return 0.f; } - void SetLinVelocityMax(float val) { } - - -// void SetSumoObject(class SM_Object* sumoObj) { -// m_sumoObj = sumoObj; -// } -// void SetSumoScene(class SM_Scene* sumoScene) { -// m_sumoScene = sumoScene; -// } - - void setSumoTransform(bool nondynaonly); - - -private: - class SM_Object* m_sumoObj; - class SM_Scene* m_sumoScene; // needed for replication - bool m_bFirstTime; - bool m_bDyna; - - float m_friction; - float m_restitution; - - - bool m_suspendDynamics; - - bool m_firstTime; - bool m_bFullRigidBody; - bool m_bPhantom; // special flag for objects that are not affected by physics 'resolver' - - // data to calculate fake velocities for kinematic objects (non-dynas) - bool m_bKinematic; - bool m_bPrevKinematic; - - float m_lastTime; - - class PHY_IMotionState* m_MotionState; - - -}; - -#endif //__SUMO_PHYSICSCONTROLLER_H - diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp deleted file mode 100644 index b4daf0a3f80..00000000000 --- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/** - * $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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#include // memset -#include "SumoPhysicsEnvironment.h" -#include "PHY_IMotionState.h" -#include "SumoPhysicsController.h" -#include "SM_Scene.h" -#include "SumoPHYCallbackBridge.h" -#include - -SumoPhysicsEnvironment::SumoPhysicsEnvironment() -{ - m_fixedTimeStep = 1.f/60.f; - m_useFixedTimeStep = true; - m_currentTime = 0.f; - - m_sumoScene = new SM_Scene(); -} - - - -SumoPhysicsEnvironment::~SumoPhysicsEnvironment() -{ - delete m_sumoScene; -} - - - -void SumoPhysicsEnvironment::beginFrame() -{ - m_sumoScene->beginFrame(); -} - -void SumoPhysicsEnvironment::endFrame() -{ - m_sumoScene->endFrame(); -} - -void SumoPhysicsEnvironment::setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep) -{ - m_useFixedTimeStep = useFixedTimeStep; - if (m_useFixedTimeStep) - { - m_fixedTimeStep = fixedTimeStep; - } else - { - m_fixedTimeStep = 0.f; - } - //reset current time ? - m_currentTime = 0.f; -} -float SumoPhysicsEnvironment::getFixedTimeStep() -{ - return m_fixedTimeStep; -} - - -bool SumoPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep,float interval) -{ - - bool result = false; - if (m_useFixedTimeStep) - { - m_currentTime += timeStep; - float ticrate = 1.f/m_fixedTimeStep; - - result = m_sumoScene->proceed(curTime, ticrate); - } else - { - m_currentTime += timeStep; - result = m_sumoScene->proceed(m_currentTime, timeStep); - } - return result; -} - -void SumoPhysicsEnvironment::setGravity(float x,float y,float z) -{ - m_sumoScene->setForceField(MT_Vector3(x,y,z)); -} - -int SumoPhysicsEnvironment::createConstraint( - class PHY_IPhysicsController* ctrl, - class PHY_IPhysicsController* ctrl2, - PHY_ConstraintType type, - float pivotX,float pivotY,float pivotZ, - float axisX,float axisY,float axisZ, - float axis1X,float axis1Y,float axis1Z, - float axis2X,float axis2Y,float axis2Z, - int flag - ) -{ - int constraintid = 0; - return constraintid; -} - -void SumoPhysicsEnvironment::removeConstraint(int constraintid) -{ - if (constraintid) - { - } -} - -PHY_IPhysicsController* SumoPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback, - float fromX,float fromY,float fromZ, - float toX,float toY,float toZ) -{ - SumoPhysicsController* ignoreCtr = static_cast (filterCallback.m_ignoreController); - - //collision detection / raytesting - MT_Point3 hit, normal; - PHY_RayCastResult result; - - SM_Object* sm_ignore = 0; - if (ignoreCtr) - sm_ignore = ignoreCtr->GetSumoObject(); - - memset(&result, 0, sizeof(result)); - - SM_Object* smOb = m_sumoScene->rayTest(sm_ignore,MT_Point3(fromX, fromY, fromZ),MT_Point3(toX, toY, toZ), hit, normal); - if (smOb) - { - result.m_controller = (PHY_IPhysicsController *) smOb->getPhysicsClientObject(); - result.m_hitPoint[0] = hit[0]; - result.m_hitPoint[1] = hit[1]; - result.m_hitPoint[2] = hit[2]; - result.m_hitNormal[0] = normal[0]; - result.m_hitNormal[1] = normal[1]; - result.m_hitNormal[2] = normal[2]; - filterCallback.reportHit(&result); - } - return result.m_controller; -} -//gamelogic callbacks -void SumoPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl) -{ - SumoPhysicsController* smctrl = dynamic_cast(ctrl); - SM_Object* smObject = smctrl->GetSumoObject(); - assert(smObject); - if (smObject) - { - m_sumoScene->addSensor(*smObject); - } -} -void SumoPhysicsEnvironment::removeSensor(PHY_IPhysicsController* ctrl) -{ - SumoPhysicsController* smctrl = dynamic_cast(ctrl); - SM_Object* smObject = smctrl->GetSumoObject(); - assert(smObject); - if (smObject) - { - m_sumoScene->remove(*smObject); - } -} - - -void SumoPhysicsEnvironment::addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user) -{ - - int sumoRespClass = 0; - - //map PHY_ convention into SM_ convention - switch (response_class) - { - case PHY_FH_RESPONSE: - sumoRespClass = FH_RESPONSE; - break; - case PHY_SENSOR_RESPONSE: - sumoRespClass = SENSOR_RESPONSE; - break; - case PHY_CAMERA_RESPONSE: - sumoRespClass =CAMERA_RESPONSE; - break; - case PHY_OBJECT_RESPONSE: - sumoRespClass = OBJECT_RESPONSE; - break; - case PHY_STATIC_RESPONSE: - sumoRespClass = PHY_STATIC_RESPONSE; - break; - case PHY_BROADPH_RESPONSE: - return; - default: - assert(0); - return; - } - - SumoPHYCallbackBridge* bridge = new SumoPHYCallbackBridge(user,callback); - - m_sumoScene->addTouchCallback(sumoRespClass,SumoPHYCallbackBridge::StaticSolidToPHYCallback,bridge); -} -bool SumoPhysicsEnvironment::requestCollisionCallback(PHY_IPhysicsController* ctrl) -{ - SumoPhysicsController* smctrl = dynamic_cast(ctrl); - MT_assert(smctrl); - SM_Object* smObject = smctrl->GetSumoObject(); - MT_assert(smObject); - if (smObject) - { - //assert(smObject->getPhysicsClientObject() == ctrl); - smObject->setPhysicsClientObject(ctrl); - - m_sumoScene->requestCollisionCallback(*smObject); - return true; - } - return false; -} - -bool SumoPhysicsEnvironment::removeCollisionCallback(PHY_IPhysicsController* ctrl) -{ - // intentionally empty - return false; -} - -PHY_IPhysicsController* SumoPhysicsEnvironment::CreateSphereController(float radius,const PHY__Vector3& position) -{ - DT_ShapeHandle shape = DT_NewSphere(0.0); - SM_Object* ob = new SM_Object(shape,0,0,0); - ob->setPosition(MT_Point3(position)); - //testing - MT_Quaternion rotquatje(MT_Vector3(0,0,1),MT_radians(90)); - ob->setOrientation(rotquatje); - - PHY_IPhysicsController* ctrl = new SumoPhysicsController(m_sumoScene,ob,0,false); - ctrl->SetMargin(radius); - return ctrl; -} -PHY_IPhysicsController* SumoPhysicsEnvironment::CreateConeController(float coneradius,float coneheight) -{ - DT_ShapeHandle shape = DT_NewCone(coneradius,coneheight); - SM_Object* ob = new SM_Object(shape,0,0,0); - ob->setPosition(MT_Point3(0.f,0.f,0.f)); - MT_Quaternion rotquatje(MT_Vector3(0,0,1),MT_radians(90)); - ob->setOrientation(rotquatje); - - PHY_IPhysicsController* ctrl = new SumoPhysicsController(m_sumoScene,ob,0,false); - - return ctrl; -} - diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h deleted file mode 100644 index 5ae33eb4b0e..00000000000 --- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h +++ /dev/null @@ -1,110 +0,0 @@ -/** - * $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. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef _SUMOPhysicsEnvironment -#define _SUMOPhysicsEnvironment - -#include "MT_Scalar.h" - -#include "PHY_IPhysicsEnvironment.h" -class SumoPHYCallbackBridge; -#include -/** -* Physics Environment takes care of stepping the simulation and is a container for physics entities (rigidbodies,constraints, materials etc.) -* A derived class may be able to 'construct' entities by loading and/or converting -*/ -class SumoPhysicsEnvironment : public PHY_IPhysicsEnvironment -{ - - class SM_Scene* m_sumoScene; - float m_currentTime; - float m_fixedTimeStep; - bool m_useFixedTimeStep; - - std::vector m_callbacks; - -public: - SumoPhysicsEnvironment(); - virtual ~SumoPhysicsEnvironment(); - virtual void beginFrame(); - virtual void endFrame(); -// Perform an integration step of duration 'timeStep'. - virtual bool proceedDeltaTime(double curTime,float timeStep,float interval); - virtual void setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep); - virtual float getFixedTimeStep(); - - virtual void setGravity(float x,float y,float z); - virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type, - float pivotX,float pivotY,float pivotZ, - float axisX,float axisY,float axisZ, - float axis1X=0,float axis1Y=0,float axis1Z=0, - float axis2X=0,float axis2Y=0,float axis2Z=0,int flag=0 - - ); - - virtual void removeConstraint(int constraintid); - - //complex constraint for vehicles - virtual PHY_IVehicle* getVehicleConstraint(int constraintId) - { - return 0; - } - - virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ); - virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4 *planes, int nplanes, int occlusionRes) { return false; } - - - //gamelogic callbacks - virtual void addSensor(PHY_IPhysicsController* ctrl); - virtual void removeSensor(PHY_IPhysicsController* ctrl); - virtual void addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user); - virtual bool requestCollisionCallback(PHY_IPhysicsController* ctrl); - virtual bool removeCollisionCallback(PHY_IPhysicsController* ctrl); - virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position); - virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight); - - virtual float getConstraintParam(int constraintId,int param) - { - return 0.f; - } - virtual void setConstraintParam(int constraintId,int param,float value,float value1) - { - } - SM_Scene* GetSumoScene() - { - return m_sumoScene; - } - -protected: - // 60Hz (Default) - static MT_Scalar PhysicsTicRate; - -}; - -#endif //_SUMOPhysicsEnvironment - diff --git a/source/gameengine/Physics/Sumo/convert.txt b/source/gameengine/Physics/Sumo/convert.txt deleted file mode 100644 index 81f8f602cde..00000000000 --- a/source/gameengine/Physics/Sumo/convert.txt +++ /dev/null @@ -1,35 +0,0 @@ -static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj) -{ - DT_ShapeHandle shape = DT_NewComplexShape(); - int numpolys = meshobj->NumPolygons(); - int numvalidpolys = 0; - - for (int p=0; pGetPolygon(p); - - // only add polygons that have the collisionflag set - if (poly->IsCollider()) - { - DT_Begin(); - for (int v=0; vVertexCount(); v++) { - MT_Point3 pt = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[v], - poly->GetMaterial()->GetPolyMaterial())->xyz(); - DT_Vertex(pt[0],pt[1],pt[2]); - } - DT_End(); - - numvalidpolys++; - } - } - - DT_EndComplexShape(); - - if (numvalidpolys==0) { - delete shape; - return NULL; - } else { - return shape; - } -} diff --git a/source/gameengine/Physics/Sumo/include/interpolator.h b/source/gameengine/Physics/Sumo/include/interpolator.h deleted file mode 100644 index 055c242edc7..00000000000 --- a/source/gameengine/Physics/Sumo/include/interpolator.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef INTERPOLATOR_H -#define INTERPOLATOR_H - -#include "solid_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -DT_DECLARE_HANDLE(IP_IpoHandle); - -typedef struct IP_ControlPoint { - DT_Scalar m_key; - DT_Scalar m_keyValue; -} IP_ControlPoint; - -IP_IpoHandle IP_CreateLinear(const IP_ControlPoint *cpoints, int num_cpoints); - -void IP_DeleteInterpolator(IP_IpoHandle ipo); - -DT_Scalar IP_GetValue(IP_IpoHandle ipo, DT_Scalar key); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/source/gameengine/Physics/common/Makefile b/source/gameengine/Physics/common/Makefile index e3edd426c36..f2dd0134b71 100644 --- a/source/gameengine/Physics/common/Makefile +++ b/source/gameengine/Physics/common/Makefile @@ -40,7 +40,7 @@ CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) -CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO)/include -I$(NAN_MOTO)/include +CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_MOTO)/include CPPFLAGS += -I../../blender # these two needed because of blenkernel CPPFLAGS += -I../../blender/makesdna diff --git a/source/gameengine/SConscript b/source/gameengine/SConscript index 864e4c3ebee..592b138583f 100644 --- a/source/gameengine/SConscript +++ b/source/gameengine/SConscript @@ -18,13 +18,5 @@ SConscript(['BlenderRoutines/SConscript', 'VideoTexture/SConscript' ]) -if env['WITH_BF_SOLID']: - SConscript(['Physics/Sumo/SConscript']) - if env['WITH_BF_PLAYER']: SConscript(['GamePlayer/SConscript']) - -#if user_options_dict['USE_PHYSICS'] == 'solid': -# SConscript(['Physics/Sumo/SConscript']) -#elif user_options_dict['USE_PHYSICS'] == 'ode': -# SConscript(['Physics/BlOde/SConscript']) diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.cpp b/source/gameengine/VideoTexture/FilterBlueScreen.cpp index 6b23105a278..6d26e5b6d35 100644 --- a/source/gameengine/VideoTexture/FilterBlueScreen.cpp +++ b/source/gameengine/VideoTexture/FilterBlueScreen.cpp @@ -81,17 +81,17 @@ static int setColor (PyFilter * self, PyObject * value, void * closure) { // check validity of parameter if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 3 - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1)) - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 2))) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1)) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 2))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 3 ints"); return -1; } // set color - getFilter(self)->setColor((unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))), - (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))), - (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2)))); + getFilter(self)->setColor((unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), + (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))), + (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)))); // success return 0; } @@ -108,15 +108,15 @@ static int setLimits (PyFilter * self, PyObject * value, void * closure) { // check validity of parameter if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 2 - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1))) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints"); return -1; } // set limits - getFilter(self)->setLimits((unsigned short)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))), - (unsigned short)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1)))); + getFilter(self)->setLimits((unsigned short)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), + (unsigned short)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1)))); // success return 0; } diff --git a/source/gameengine/VideoTexture/FilterColor.cpp b/source/gameengine/VideoTexture/FilterColor.cpp index 5ff1f7f11ce..eb86f520e02 100644 --- a/source/gameengine/VideoTexture/FilterColor.cpp +++ b/source/gameengine/VideoTexture/FilterColor.cpp @@ -147,10 +147,10 @@ static int setMatrix (PyFilter * self, PyObject * value, void * closure) for (int c = 0; valid && c < 5; ++c) { // item must be int - valid = PyInt_Check(PySequence_Fast_GET_ITEM(row, c)); + valid = PyLong_Check(PySequence_Fast_GET_ITEM(row, c)); // if it is valid, save it in matrix if (valid) - mat[r][c] = short(PyInt_AsLong(PySequence_Fast_GET_ITEM(row, c))); + mat[r][c] = short(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(row, c))); } } // if parameter is not valid, report error @@ -286,10 +286,10 @@ static int setLevels (PyFilter * self, PyObject * value, void * closure) for (int c = 0; valid && c < 2; ++c) { // item must be int - valid = PyInt_Check(PySequence_Fast_GET_ITEM(row, c)); + valid = PyLong_Check(PySequence_Fast_GET_ITEM(row, c)); // if it is valid, save it in matrix if (valid) - lev[r][c] = (unsigned short)(PyInt_AsLong(PySequence_Fast_GET_ITEM(row, c))); + lev[r][c] = (unsigned short)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(row, c))); } } // if parameter is not valid, report error diff --git a/source/gameengine/VideoTexture/FilterNormal.cpp b/source/gameengine/VideoTexture/FilterNormal.cpp index 9a2b1e90d5a..002be6c3189 100644 --- a/source/gameengine/VideoTexture/FilterNormal.cpp +++ b/source/gameengine/VideoTexture/FilterNormal.cpp @@ -72,13 +72,13 @@ static PyObject * getColor (PyFilter * self, void * closure) static int setColor (PyFilter * self, PyObject * value, void * closure) { // check validity of parameter - if (value == NULL || !PyInt_Check(value)) + if (value == NULL || !PyLong_Check(value)) { PyErr_SetString(PyExc_TypeError, "filt.colorIdx = int: VideoTexture.FilterNormal, expected the value must be a int"); return -1; } // set color index - getFilter(self)->setColor((unsigned short)(PyInt_AsLong(value))); + getFilter(self)->setColor((unsigned short)(PyLong_AsSsize_t(value))); // success return 0; } diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index c4fb1fefd9c..d8be08e0eb5 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -331,19 +331,19 @@ static int setBackground (PyImage * self, PyObject * value, void * closure) { // check validity of parameter if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 4 - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1)) - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 2)) - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 3))) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1)) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 2)) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 3))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 4 integer between 0 and 255"); return -1; } // set background color - getImageRender(self)->setBackground((unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))), - (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))), - (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2))), - (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 3)))); + getImageRender(self)->setBackground((unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), + (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))), + (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2))), + (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 3)))); // success return 0; } diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp index d2c23e758f6..55b14396280 100644 --- a/source/gameengine/VideoTexture/ImageViewport.cpp +++ b/source/gameengine/VideoTexture/ImageViewport.cpp @@ -218,16 +218,16 @@ static int ImageViewport_setPosition (PyImage * self, PyObject * value, void * c { // check validity of parameter if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 2 - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1))) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints"); return -1; } // set position GLint pos [] = { - GLint(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))), - GLint(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))) + GLint(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), + GLint(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))) }; getImageViewport(self)->setPosition(pos); // success @@ -246,16 +246,16 @@ int ImageViewport_setCaptureSize (PyImage * self, PyObject * value, void * closu { // check validity of parameter if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 2 - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1))) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) + || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints"); return -1; } // set capture size short size [] = { - short(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))), - short(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))) + short(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), + short(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))) }; getImageViewport(self)->setCaptureSize(size); // success diff --git a/source/gameengine/VideoTexture/VideoBase.cpp b/source/gameengine/VideoTexture/VideoBase.cpp index 5d449a158d8..5de7a9e80a9 100644 --- a/source/gameengine/VideoTexture/VideoBase.cpp +++ b/source/gameengine/VideoTexture/VideoBase.cpp @@ -167,13 +167,13 @@ PyObject * Video_getRepeat (PyImage * self, void * closure) int Video_setRepeat (PyImage * self, PyObject * value, void * closure) { // check validity of parameter - if (value == NULL || !PyInt_Check(value)) + if (value == NULL || !PyLong_Check(value)) { PyErr_SetString(PyExc_TypeError, "The value must be an int"); return -1; } // set repeat - getVideo(self)->setRepeat(int(PyInt_AsLong(value))); + getVideo(self)->setRepeat(int(PyLong_AsSsize_t(value))); // success return 0; } diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp index 1a5481488c0..cf4ea88c1b5 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp +++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp @@ -1095,13 +1095,13 @@ PyObject * VideoFFmpeg_getPreseek (PyImage *self, void * closure) int VideoFFmpeg_setPreseek (PyImage * self, PyObject * value, void * closure) { // check validity of parameter - if (value == NULL || !PyInt_Check(value)) + if (value == NULL || !PyLong_Check(value)) { PyErr_SetString(PyExc_TypeError, "The value must be an integer"); return -1; } // set preseek - getFFmpeg(self)->setPreseek(PyInt_AsLong(value)); + getFFmpeg(self)->setPreseek(PyLong_AsSsize_t(value)); // success return 0; } diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp index dad52a426b6..22171f69321 100644 --- a/source/gameengine/VideoTexture/blendVideoTex.cpp +++ b/source/gameengine/VideoTexture/blendVideoTex.cpp @@ -67,7 +67,7 @@ static PyObject * getMaterialID (PyObject *self, PyObject *args) // get last error description static PyObject * getLastError (PyObject *self, PyObject *args) { - return PyString_FromString(Exception::m_lastError.c_str()); + return PyUnicode_FromString(Exception::m_lastError.c_str()); } // set log file diff --git a/source/nan_compile.mk b/source/nan_compile.mk index bd6dd6e1baa..bc264fe5c1d 100644 --- a/source/nan_compile.mk +++ b/source/nan_compile.mk @@ -71,21 +71,6 @@ DBG_CCFLAGS += -g # OS dependent parts --------------------------------------------------- -ifeq ($(OS),beos) - CC = gcc - CCC = g++ - CFLAGS += -pipe -fPIC -funsigned-char -fno-strict-aliasing - CCFLAGS += -pipe -fPIC -funsigned-char -fno-strict-aliasing - REL_CFLAGS += -O2 - REL_CCFLAGS += -O2 - NAN_DEPEND = true - OPENGL_HEADERS = . - CPPFLAGS += -D__BeOS - AR = ar - ARFLAGS = ruv - ARFLAGSQUIET = ru -endif - ifeq ($(OS),darwin) CC = gcc CCC = g++ diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk index b9e623ed4e4..91f90525c1e 100644 --- a/source/nan_definitions.mk +++ b/source/nan_definitions.mk @@ -91,7 +91,6 @@ endif export BF_PROFILE ?= false export NAN_USE_BULLET ?= true export NAN_BULLET2 ?= $(LCGDIR)/bullet2 - export NAN_SUMO ?= $(SRCHOME)/gameengine/Physics/Sumo export NAN_FUZZICS ?= $(SRCHOME)/gameengine/Physics/Sumo/Fuzzics export NAN_BLENKEY ?= $(LCGDIR)/blenkey export NAN_DECIMATION ?= $(LCGDIR)/decimation @@ -131,45 +130,6 @@ endif endif # Platform Dependent settings go below: - ifeq ($(OS),beos) - - export ID = $(USER) - export HOST = $(HOSTNAME) - export NAN_PYTHON ?= $(LCGDIR)/python - export NAN_PYTHON_VERSION ?= 2.3 - export NAN_PYTHON_BINARY ?= $(NAN_PYTHON)/bin/python$(NAN_PYTHON_VERSION) - export NAN_PYTHON_LIB ?= $(NAN_PYTHON)/lib/python$(NAN_PYTHON_VERSION)/config/libpython$(NAN_PYTHON_VERSION).a - export NAN_OPENAL ?= $(LCGDIR)/openal - export NAN_JPEG ?= $(LCGDIR)/jpeg - export NAN_PNG ?= $(LCGDIR)/png - export NAN_TIFF ?= $(LCGDIR)/tiff - export NAN_ODE ?= $(LCGDIR)/ode - export NAN_TERRAPLAY ?= $(LCGDIR)/terraplay - export NAN_MESA ?= /usr/src/Mesa-3.1 - export NAN_ZLIB ?= $(LCGDIR)/zlib - export NAN_NSPR ?= $(LCGDIR)/nspr - export NAN_FREETYPE ?= $(LCGDIR)/freetype - export NAN_GETTEXT ?= $(LCGDIR)/gettext - export NAN_SDL ?= $(shell sdl-config --prefix) - export NAN_SDLLIBS ?= $(shell sdl-config --libs) - export NAN_SDLCFLAGS ?= $(shell sdl-config --cflags) - - # Uncomment the following line to use Mozilla inplace of netscape - # CPPFLAGS +=-DMOZ_NOT_NET - # Location of MOZILLA/Netscape header files... - export NAN_MOZILLA_INC ?= $(LCGDIR)/mozilla/include - export NAN_MOZILLA_LIB ?= $(LCGDIR)/mozilla/lib/ - # Will fall back to look in NAN_MOZILLA_INC/nspr and NAN_MOZILLA_LIB - # if this is not set. - - export NAN_BUILDINFO ?= true - # Be paranoid regarding library creation (do not update archives) - export NAN_PARANOID ?= true - - # l10n - #export INTERNATIONAL ?= true - - else ifeq ($(OS),darwin) export ID = $(shell whoami) @@ -589,7 +549,6 @@ endif endif # irix endif # freebsd endif # darwin - endif # beos endif # CONFIG_GUESS diff --git a/source/nan_link.mk b/source/nan_link.mk index 42b17b425b3..63c9a578498 100644 --- a/source/nan_link.mk +++ b/source/nan_link.mk @@ -49,10 +49,6 @@ endif # default (overriden by windows) SOEXT = .so -ifeq ($(OS),beos) - LLIBS = -L/boot/develop/lib/x86/ -lGL -lbe -L/boot/home/config/lib/ -endif - ifeq ($(OS),darwin) LLIBS += -lGLU -lGL LLIBS += -lz -lstdc++ diff --git a/tools/btools.py b/tools/btools.py index 377a389941f..9603022deaa 100755 --- a/tools/btools.py +++ b/tools/btools.py @@ -44,9 +44,8 @@ def validate_arguments(args, bc): 'WITH_BF_INTERNATIONAL', 'BF_GETTEXT', 'BF_GETTEXT_INC', 'BF_GETTEXT_LIB', 'BF_GETTEXT_LIBPATH', 'WITH_BF_ICONV', 'BF_ICONV', 'BF_ICONV_INC', 'BF_ICONV_LIB', 'BF_ICONV_LIBPATH', - 'WITH_BF_ODE', 'BF_ODE', 'BF_ODE_INC', 'BF_ODE_LIB', - 'WITH_BF_GAMEENGINE', 'WITH_BF_SOLID', 'WITH_BF_BULLET', 'BF_BULLET', 'BF_BULLET_INC', 'BF_BULLET_LIB', - 'BF_SOLID', 'BF_SOLID_INC', 'BF_WINTAB', 'BF_WINTAB_INC', + 'WITH_BF_GAMEENGINE', 'WITH_BF_BULLET', 'BF_BULLET', 'BF_BULLET_INC', 'BF_BULLET_LIB', + 'BF_WINTAB', 'BF_WINTAB_INC', 'WITH_BF_FREETYPE', 'BF_FREETYPE', 'BF_FREETYPE_INC', 'BF_FREETYPE_LIB', 'BF_FREETYPE_LIBPATH', 'WITH_BF_QUICKTIME', 'BF_QUICKTIME', 'BF_QUICKTIME_INC', 'BF_QUICKTIME_LIB', 'BF_QUICKTIME_LIBPATH', 'WITH_BF_STATICOPENGL', 'BF_OPENGL', 'BF_OPENGL_INC', 'BF_OPENGL_LIB', 'BF_OPENGL_LIBPATH', 'BF_OPENGL_LIB_STATIC', @@ -251,19 +250,11 @@ def read_opts(cfg, args): (BoolVariable('WITH_BF_GAMEENGINE', 'Build with gameengine' , False)), - (BoolVariable('WITH_BF_ODE', 'Use ODE if true', True)), - ('BF_ODE', 'ODE base path', ''), - ('BF_ODE_INC', 'ODE include path' , ''), - ('BF_ODE_LIB', 'ODE library', ''), - (BoolVariable('WITH_BF_BULLET', 'Use Bullet if true', True)), ('BF_BULLET', 'Bullet base dir', ''), ('BF_BULLET_INC', 'Bullet include path', ''), ('BF_BULLET_LIB', 'Bullet library', ''), - (BoolVariable('WITH_BF_SOLID', 'Use Sumo/Solid deprecated physics system if true', True)), - ('BF_SOLID', 'Solid base dir', '#/extern/solid'), - ('BF_SOLID_INC', 'Solid include path', ''), ('BF_WINTAB', 'WinTab base dir', ''), ('BF_WINTAB_INC', 'WinTab include dir', ''), ('BF_CXX', 'c++ base path for libstdc++, only used when static linking', ''), From 5c207a61f3defc4c25dab1bc0f13c100b8bc4fca Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Thu, 2 Jul 2009 15:45:15 +0000 Subject: [PATCH 027/138] *RTBuilder now supports splitting leafs in N leafs something is wrong on rayobject_bvh as it looks slower than BLI_bvh and code is based on it --- .../render/intern/include/rayobject_rtbuild.h | 5 +- .../blender/render/intern/source/rayobject.c | 1 + .../render/intern/source/rayobject_bvh.c | 97 +++++++++++++++---- .../render/intern/source/rayobject_rtbuild.c | 49 +++++++--- 4 files changed, 116 insertions(+), 36 deletions(-) diff --git a/source/blender/render/intern/include/rayobject_rtbuild.h b/source/blender/render/intern/include/rayobject_rtbuild.h index fbe3930149c..af0a11508e8 100644 --- a/source/blender/render/intern/include/rayobject_rtbuild.h +++ b/source/blender/render/intern/include/rayobject_rtbuild.h @@ -41,7 +41,7 @@ * generate with simple calls, and then convert to the theirs * specific structure on the fly. */ -#define MAX_CHILDS 32 +#define RTBUILD_MAX_CHILDS 32 typedef struct RTBuilder { /* list to all primitives in this tree */ @@ -51,7 +51,7 @@ typedef struct RTBuilder int split_axis; /* child partitions calculated during splitting */ - int child_offset[MAX_CHILDS+1]; + int child_offset[RTBUILD_MAX_CHILDS+1]; } RTBuilder; @@ -67,5 +67,6 @@ RTBuilder* rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp); /* Calculates child partitions and returns number of efectively needed partitions */ int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis); int rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds); +int rtbuild_get_largest_axis(RTBuilder *b); #endif diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index 7779c2aee82..a8564721422 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -296,6 +296,7 @@ int RE_rayobject_raycast(RayObject *r, Isect *isec) RE_RC_COUNT(isec->count->raycast.test); /* Setup vars used on raycast */ + isec->labda *= Normalize(isec->vec); isec->dist = VecLength(isec->vec); for(i=0; i<3; i++) diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index 4be57543a77..a67def00220 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -35,7 +35,7 @@ #include "rayobject_rtbuild.h" #include "rayobject.h" -#define BVH_NCHILDS 2 +#define BVH_NCHILDS 4 typedef struct BVHTree BVHTree; static int bvh_intersect(BVHTree *obj, Isect *isec); @@ -57,7 +57,7 @@ typedef struct BVHNode BVHNode; struct BVHNode { BVHNode *child[BVH_NCHILDS]; - float bb[2][3]; + float *bb; //[6]; //[2][3]; }; struct BVHTree @@ -65,6 +65,7 @@ struct BVHTree RayObject rayobj; BVHNode *alloc, *next_node, *root; + float *bb_alloc, *bb_next; RTBuilder *builder; }; @@ -90,6 +91,9 @@ static void bvh_free(BVHTree *obj) if(obj->alloc) MEM_freeN(obj->alloc); + if(obj->bb_alloc) + MEM_freeN(obj->bb_alloc); + MEM_freeN(obj); } @@ -99,8 +103,8 @@ static void bvh_merge_bb(BVHNode *node, float *min, float *max) if(RayObject_isAligned(node)) { //TODO only half operations needed - DO_MINMAX(node->bb[0], min, max); - DO_MINMAX(node->bb[1], min, max); + DO_MINMAX(node->bb , min, max); + DO_MINMAX(node->bb+3, min, max); } else { @@ -121,18 +125,40 @@ static int dfs_raycast(BVHNode *node, Isect *isec) int hit = 0; if(RE_rayobject_bb_intersect(isec, (const float*)node->bb) != FLT_MAX) { - int i; - for(i=0; ichild[i])) - { - hit |= dfs_raycast(node->child[i], isec); - if(hit && isec->mode == RE_RAY_SHADOW) return hit; - } - else - { - hit |= RE_rayobject_intersect( (RayObject*)node->child[i], isec); - if(hit && isec->mode == RE_RAY_SHADOW) return hit; - } +// if(isec->idot_axis[node->split_axis] > 0.0f) + { + int i; + for(i=0; ichild[i])) + { + if(node->child[i] == 0) break; + + hit |= dfs_raycast(node->child[i], isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + else + { + hit |= RE_rayobject_intersect( (RayObject*)node->child[i], isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + } +/* + else + { + int i; + for(i=BVH_NCHILDS-1; i>=0; i--) + if(RayObject_isAligned(node->child[i])) + { + hit |= dfs_raycast(node->child[i], isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + else + { + hit |= RE_rayobject_intersect( (RayObject*)node->child[i], isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + } +*/ } return hit; } @@ -154,11 +180,36 @@ static void bvh_add(BVHTree *obj, RayObject *ob) rtbuild_add( obj->builder, ob ); } +static BVHNode *bvh_new_node(BVHTree *tree) +{ + BVHNode *node = tree->next_node++; + node->bb = tree->bb_next; + tree->bb_next += 6; + + return node; +} + static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder) { if(rtbuild_size(builder) == 1) { - return (BVHNode*)builder->begin[0]; +// return (BVHNode*)builder->begin[0]; +// +// + int i; + BVHNode *parent = bvh_new_node(tree); + + INIT_MINMAX(parent->bb, parent->bb+3); + + for(i=0; i<1; i++) + { + parent->child[i] = (BVHNode*)builder->begin[i]; + bvh_merge_bb(parent->child[i], parent->bb, parent->bb+3); + } + for(; ichild[i] = 0; + + return parent; } else { @@ -166,15 +217,17 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder) int nc = rtbuild_mean_split_largest_axis(builder, BVH_NCHILDS); RTBuilder tmp; - BVHNode *parent = tree->next_node++; + BVHNode *parent = bvh_new_node(tree); - INIT_MINMAX(parent->bb[0], parent->bb[1]); + INIT_MINMAX(parent->bb, parent->bb+3); // bvh->split_axis = tmp->split_axis; for(i=0; ichild[i] = bvh_rearrange( tree, rtbuild_get_child(builder, i, &tmp) ); - bvh_merge_bb(parent->child[i], parent->bb[0], parent->bb[1]); + bvh_merge_bb(parent->child[i], parent->bb, parent->bb+3); } + for(; ichild[i] = 0; return parent; } @@ -189,6 +242,10 @@ static void bvh_done(BVHTree *obj) assert(needed_nodes > 0); obj->alloc = (BVHNode*)MEM_mallocN( sizeof(BVHNode)*needed_nodes, "BVHTree.Nodes"); obj->next_node = obj->alloc; + + obj->bb_alloc = (float*)MEM_mallocN( sizeof(float)*6*needed_nodes, "BVHTree.Nodes"); + obj->bb_next = obj->bb_alloc; + obj->root = bvh_rearrange( obj, obj->builder ); assert(obj->alloc+needed_nodes >= obj->next_node); diff --git a/source/blender/render/intern/source/rayobject_rtbuild.c b/source/blender/render/intern/source/rayobject_rtbuild.c index 46833b8c15d..391aaeb10c2 100644 --- a/source/blender/render/intern/source/rayobject_rtbuild.c +++ b/source/blender/render/intern/source/rayobject_rtbuild.c @@ -1,8 +1,10 @@ +#include +#include + #include "rayobject_rtbuild.h" #include "MEM_guardedalloc.h" #include "BLI_arithb.h" #include "BKE_utildefines.h" -#include static int partition_nth_element(RTBuilder *b, int _begin, int _end, int n); static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis); @@ -16,7 +18,7 @@ static void rtbuild_init(RTBuilder *b, RayObject **begin, RayObject **end) b->end = end; b->split_axis = 0; - for(i=0; ichild_offset[i] = 0; } @@ -59,7 +61,7 @@ static void merge_bb(RTBuilder *b, float *min, float *max) RE_rayobject_merge_bb(*index, min, max); } -static int calc_largest_axis(RTBuilder *b) +int rtbuild_get_largest_axis(RTBuilder *b) { float min[3], max[3], sub[3]; @@ -84,25 +86,44 @@ static int calc_largest_axis(RTBuilder *b) } -//Unballanced mean -//TODO better balance nodes -//TODO suport for variable number of partitions (its hardcoded in 2) +//Left balanced tree int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis) { - b->child_offset[0] = 0; - b->child_offset[1] = (b->end - b->begin) / 2; - b->child_offset[2] = (b->end - b->begin); - - assert( b->child_offset[0] != b->child_offset[1] && b->child_offset[1] != b->child_offset[2]); + int i; + int leafs_per_child; + int tot_leafs = rtbuild_size(b); - split_leafs(b, b->child_offset, 2, axis); - return 2; + long long s; + + assert(nchilds <= RTBUILD_MAX_CHILDS); + + //TODO optimize calc of leafs_per_child + for(s=nchilds; s= tot_leafs); + + b->child_offset[0] = 0; + for(i=1; ; i++) + { + assert(i <= nchilds); + + b->child_offset[i] = b->child_offset[i-1] + leafs_per_child; + if(b->child_offset[i] >= tot_leafs) + { + b->child_offset[i] = tot_leafs; + split_leafs(b, b->child_offset, i, axis); + + assert(i > 1); + return i; + } + } } int rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds) { - int axis = calc_largest_axis(b); + int axis = rtbuild_get_largest_axis(b); return rtbuild_mean_split(b, nchilds, axis); } From 686a426cf010d3de627dbb44082bc3b9371f77f8 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Thu, 2 Jul 2009 21:57:50 +0000 Subject: [PATCH 028/138] *fixed rtbuild (there was a sorting bug introduced while adapting code from BLI_bvh) This bvh should be at least as fast as BLI_kdopbvh now --- .../blender/render/intern/source/rayobject.c | 3 +- .../render/intern/source/rayobject_bvh.c | 35 ++++++--- .../render/intern/source/rayobject_rtbuild.c | 78 +++++++++++-------- 3 files changed, 71 insertions(+), 45 deletions(-) diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index a8564721422..ffe1bba52c9 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -42,8 +42,9 @@ * Based on Tactical Optimization of Ray/Box Intersection, by Graham Fyffe * [http://tog.acm.org/resources/RTNews/html/rtnv21n1.html#art9] */ -float RE_rayobject_bb_intersect(const Isect *isec, const float *bb) +float RE_rayobject_bb_intersect(const Isect *isec, const float *_bb) { + const float *bb = _bb; float dist; float t1x = (bb[isec->bv_index[0]] - isec->start[0]) * isec->idot_axis[0]; diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index a67def00220..8bf0a72bbb5 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -27,6 +27,7 @@ * ***** END GPL LICENSE BLOCK ***** */ #include +#include #include "MEM_guardedalloc.h" #include "BKE_utildefines.h" @@ -58,6 +59,7 @@ struct BVHNode { BVHNode *child[BVH_NCHILDS]; float *bb; //[6]; //[2][3]; + char split_axis; }; struct BVHTree @@ -125,7 +127,7 @@ static int dfs_raycast(BVHNode *node, Isect *isec) int hit = 0; if(RE_rayobject_bb_intersect(isec, (const float*)node->bb) != FLT_MAX) { -// if(isec->idot_axis[node->split_axis] > 0.0f) + if(isec->idot_axis[node->split_axis] > 0.0f) { int i; for(i=0; imode == RE_RAY_SHADOW) return hit; } } -/* else { int i; @@ -158,7 +159,6 @@ static int dfs_raycast(BVHNode *node, Isect *isec) if(hit && isec->mode == RE_RAY_SHADOW) return hit; } } -*/ } return hit; } @@ -180,16 +180,25 @@ static void bvh_add(BVHTree *obj, RayObject *ob) rtbuild_add( obj->builder, ob ); } -static BVHNode *bvh_new_node(BVHTree *tree) +static BVHNode *bvh_new_node(BVHTree *tree, int nid) { - BVHNode *node = tree->next_node++; + BVHNode *node = tree->alloc + nid - 1; + if(node+1 > tree->next_node) + tree->next_node = node+1; + node->bb = tree->bb_next; tree->bb_next += 6; return node; } -static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder) +static int child_id(int pid, int nchild) +{ + //N child of node A = A * K + (2 - K) + N, (0 <= N < K) + return pid*BVH_NCHILDS+(2-BVH_NCHILDS)+nchild; +} + +static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid) { if(rtbuild_size(builder) == 1) { @@ -197,7 +206,7 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder) // // int i; - BVHNode *parent = bvh_new_node(tree); + BVHNode *parent = bvh_new_node(tree, nid); INIT_MINMAX(parent->bb, parent->bb+3); @@ -217,13 +226,13 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder) int nc = rtbuild_mean_split_largest_axis(builder, BVH_NCHILDS); RTBuilder tmp; - BVHNode *parent = bvh_new_node(tree); + BVHNode *parent = bvh_new_node(tree, nid); INIT_MINMAX(parent->bb, parent->bb+3); -// bvh->split_axis = tmp->split_axis; + parent->split_axis = builder->split_axis; for(i=0; ichild[i] = bvh_rearrange( tree, rtbuild_get_child(builder, i, &tmp) ); + parent->child[i] = bvh_rearrange( tree, rtbuild_get_child(builder, i, &tmp), child_id(nid,i) ); bvh_merge_bb(parent->child[i], parent->bb, parent->bb+3); } for(; ialloc = (BVHNode*)MEM_mallocN( sizeof(BVHNode)*needed_nodes, "BVHTree.Nodes"); obj->next_node = obj->alloc; - obj->bb_alloc = (float*)MEM_mallocN( sizeof(float)*6*needed_nodes, "BVHTree.Nodes"); + obj->bb_alloc = (float*)MEM_mallocN( sizeof(float)*6*needed_nodes, "BVHTree.NodesBB"); obj->bb_next = obj->bb_alloc; - obj->root = bvh_rearrange( obj, obj->builder ); + obj->root = bvh_rearrange( obj, obj->builder, 1 ); assert(obj->alloc+needed_nodes >= obj->next_node); + printf("BVH: Used %d nodes\n", obj->next_node-obj->alloc); + rtbuild_free( obj->builder ); obj->builder = NULL; diff --git a/source/blender/render/intern/source/rayobject_rtbuild.c b/source/blender/render/intern/source/rayobject_rtbuild.c index 391aaeb10c2..7be17312a52 100644 --- a/source/blender/render/intern/source/rayobject_rtbuild.c +++ b/source/blender/render/intern/source/rayobject_rtbuild.c @@ -67,8 +67,10 @@ int rtbuild_get_largest_axis(RTBuilder *b) INIT_MINMAX(min, max); merge_bb( b, min, max); - - VECSUB(sub, max, min); + + sub[0] = max[0]-min[0]; + sub[1] = max[1]-min[1]; + sub[2] = max[2]-min[2]; if(sub[0] > sub[1]) { if(sub[0] > sub[2]) @@ -90,8 +92,9 @@ int rtbuild_get_largest_axis(RTBuilder *b) int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis) { int i; - int leafs_per_child; + int mleafs_per_child, Mleafs_per_child; int tot_leafs = rtbuild_size(b); + int missing_leafs; long long s; @@ -99,25 +102,41 @@ int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis) //TODO optimize calc of leafs_per_child for(s=nchilds; s= tot_leafs); + Mleafs_per_child = s/nchilds; + mleafs_per_child = Mleafs_per_child/nchilds; + //split min leafs per child b->child_offset[0] = 0; - for(i=1; ; i++) + for(i=1; i<=nchilds; i++) + b->child_offset[i] = mleafs_per_child; + + //split remaining leafs + missing_leafs = tot_leafs - mleafs_per_child*nchilds; + for(i=1; i<=nchilds; i++) { - assert(i <= nchilds); - - b->child_offset[i] = b->child_offset[i-1] + leafs_per_child; - if(b->child_offset[i] >= tot_leafs) + if(missing_leafs > Mleafs_per_child - mleafs_per_child) { - b->child_offset[i] = tot_leafs; - split_leafs(b, b->child_offset, i, axis); - - assert(i > 1); - return i; + b->child_offset[i] += Mleafs_per_child - mleafs_per_child; + missing_leafs -= Mleafs_per_child - mleafs_per_child; + } + else + { + b->child_offset[i] += missing_leafs; + missing_leafs = 0; + break; } } + + //adjust for accumulative offsets + for(i=1; i<=nchilds; i++) + b->child_offset[i] += b->child_offset[i-1]; + + //Count created childs + for(i=nchilds; b->child_offset[i] == b->child_offset[i-1]; i--); + split_leafs(b, b->child_offset, i, axis); + + assert( b->child_offset[0] == 0 && b->child_offset[i] == tot_leafs ); + return i; } @@ -166,15 +185,15 @@ static int medianof3(RTBuilder *d, int a, int b, int c) } else { - if(fc > fb) - return b; - else + if(fc < fb) { - if(fc > fa) - return c; - else + if(fc < fa) return a; + else + return c; } + else + return b; } } @@ -203,14 +222,9 @@ static int partition(RTBuilder *b, int lo, int mid, int hi) int i=lo, j=hi; while (1) { - while(sort_get_value(b,i) < x) - i++; - + while(sort_get_value(b,i) < x) i++; j--; - - while(x < sort_get_value(b,j)) - j--; - + while(x < sort_get_value(b,j)) j--; if(!(i < j)) return i; @@ -226,7 +240,7 @@ static int partition(RTBuilder *b, int lo, int mid, int hi) // after a call to this function you can expect one of: // every node to left of a[n] are smaller or equal to it // every node to the right of a[n] are greater or equal to it -static int partition_nth_element(RTBuilder *b, int _begin, int _end, int n) +static int partition_nth_element(RTBuilder *b, int _begin, int n, int _end) { int begin = _begin, end = _end, cut; while(end-begin > 3) @@ -246,10 +260,10 @@ static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis) { int i; b->split_axis = split_axis; + for(i=0; i < partitions-1; i++) { - if(nth[i] >= nth[partitions]) - break; + assert(nth[i] < nth[i+1] && nth[i+1] < nth[partitions]); partition_nth_element(b, nth[i], nth[i+1], nth[partitions] ); } From 4b81d44282f214f5e208f24ae79ce966e0a105d2 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Thu, 2 Jul 2009 22:12:26 +0000 Subject: [PATCH 029/138] *fixed crash --- source/blender/render/intern/source/rayobject_bvh.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index 8bf0a72bbb5..8e9484d14b8 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -150,8 +150,11 @@ static int dfs_raycast(BVHNode *node, Isect *isec) for(i=BVH_NCHILDS-1; i>=0; i--) if(RayObject_isAligned(node->child[i])) { - hit |= dfs_raycast(node->child[i], isec); - if(hit && isec->mode == RE_RAY_SHADOW) return hit; + if(node->child[i]) + { + hit |= dfs_raycast(node->child[i], isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } } else { @@ -259,7 +262,7 @@ static void bvh_done(BVHTree *obj) assert(obj->alloc+needed_nodes >= obj->next_node); - printf("BVH: Used %d nodes\n", obj->next_node-obj->alloc); +// printf("BVH: Used %d nodes\n", obj->next_node-obj->alloc); rtbuild_free( obj->builder ); From 8394653ebd0f62615d8a4b71e5ff6bd905684dd9 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 3 Jul 2009 02:26:40 +0000 Subject: [PATCH 030/138] *No need of a BB if the underlying structure already has a BB --- .../render/intern/source/rayobject_bvh.c | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index 8e9484d14b8..f5805fc1a02 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -59,7 +59,7 @@ struct BVHNode { BVHNode *child[BVH_NCHILDS]; float *bb; //[6]; //[2][3]; - char split_axis; + int split_axis; }; struct BVHTree @@ -205,23 +205,31 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid) { if(rtbuild_size(builder) == 1) { -// return (BVHNode*)builder->begin[0]; -// -// - int i; - BVHNode *parent = bvh_new_node(tree, nid); - - INIT_MINMAX(parent->bb, parent->bb+3); + RayObject *child = builder->begin[0]; - for(i=0; i<1; i++) + if(RayObject_isRayFace(child)) { - parent->child[i] = (BVHNode*)builder->begin[i]; - bvh_merge_bb(parent->child[i], parent->bb, parent->bb+3); - } - for(; ichild[i] = 0; + int i; + BVHNode *parent = bvh_new_node(tree, nid); + + INIT_MINMAX(parent->bb, parent->bb+3); - return parent; + for(i=0; i<1; i++) + { + parent->child[i] = (BVHNode*)builder->begin[i]; + bvh_merge_bb(parent->child[i], parent->bb, parent->bb+3); + } + for(; ichild[i] = 0; + + return parent; + } + else + { + //Its a sub-raytrace structure, assume it has it own raycast + //methods and adding a Bounding Box arround is unnecessary + return (BVHNode*)child; + } } else { From 44ef6c1eac75a5076d459500323e0e4467509f56 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 3 Jul 2009 02:56:54 +0000 Subject: [PATCH 031/138] *little fix --- source/blender/render/intern/source/rayobject_bvh.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index f5805fc1a02..88f673cbcb1 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -186,6 +186,7 @@ static void bvh_add(BVHTree *obj, RayObject *ob) static BVHNode *bvh_new_node(BVHTree *tree, int nid) { BVHNode *node = tree->alloc + nid - 1; + assert(RayObject_isAligned(node)); if(node+1 > tree->next_node) tree->next_node = node+1; @@ -211,7 +212,8 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid) { int i; BVHNode *parent = bvh_new_node(tree, nid); - + parent->split_axis = 0; + INIT_MINMAX(parent->bb, parent->bb+3); for(i=0; i<1; i++) @@ -226,6 +228,7 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid) } else { + assert(!RayObject_isAligned(child)); //Its a sub-raytrace structure, assume it has it own raycast //methods and adding a Bounding Box arround is unnecessary return (BVHNode*)child; From 4a72557e6b3a4b2594ca0a3b971d7f7acf59072a Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 3 Jul 2009 17:10:54 +0000 Subject: [PATCH 032/138] Fixed memory aligns for 64bits --- source/blender/render/intern/include/rayobject.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index 3b77341f229..c611e2ceca2 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -102,14 +102,13 @@ typedef struct RayObjectAPI } RayObjectAPI; -//TODO use intptr_t -#define RayObject_align(o) ((RayObject*)(((int)o)&(~3))) -#define RayObject_unalignRayFace(o) ((RayObject*)(((int)o)|1)) -#define RayObject_unalignRayAPI(o) ((RayObject*)(((int)o)|2)) +#define RayObject_align(o) ((RayObject*)(((intptr_t)o)&(~3))) +#define RayObject_unalignRayFace(o) ((RayObject*)(((intptr_t)o)|1)) +#define RayObject_unalignRayAPI(o) ((RayObject*)(((intptr_t)o)|2)) -#define RayObject_isAligned(o) ((((int)o)&3) == 0) -#define RayObject_isRayFace(o) ((((int)o)&3) == 1) -#define RayObject_isRayAPI(o) ((((int)o)&3) == 2) +#define RayObject_isAligned(o) ((((intptr_t)o)&3) == 0) +#define RayObject_isRayFace(o) ((((intptr_t)o)&3) == 1) +#define RayObject_isRayAPI(o) ((((intptr_t)o)&3) == 2) /* * Extend min/max coords so that the rayobject is inside them From 3d06a104a42355f094dcdf5bb6922f685f3e98d2 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 3 Jul 2009 18:16:59 +0000 Subject: [PATCH 033/138] rayobject_octree fixed --- .../render/intern/source/rayobject_octree.c | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/source/blender/render/intern/source/rayobject_octree.c b/source/blender/render/intern/source/rayobject_octree.c index b7850c05104..88ea2bb38ed 100644 --- a/source/blender/render/intern/source/rayobject_octree.c +++ b/source/blender/render/intern/source/rayobject_octree.c @@ -60,7 +60,7 @@ typedef struct OcVal typedef struct Node { - struct RayObject *v[8]; + struct RayFace *v[8]; struct OcVal ov[8]; struct Node *next; } Node; @@ -79,7 +79,7 @@ typedef struct Octree { /* during building only */ char *ocface; - RayObject **ro_nodes; + RayFace **ro_nodes; int ro_nodes_size, ro_nodes_used; } Octree; @@ -294,7 +294,7 @@ static void ocwrite(Octree *oc, RayFace *face, int quad, short x, short y, short while(no->v[a]!=NULL) a++; } - no->v[a]= (RayObject*)face; + no->v[a]= (RayFace*) RayObject_align(face); if(quad) calc_ocval_face(rtf[0], rtf[1], rtf[2], rtf[3], x>>2, y>>1, z, &no->ov[a]); @@ -456,7 +456,7 @@ RayObject *RE_rayobject_octree_create(int ocres, int size) oc->ocres = ocres; - oc->ro_nodes = MEM_callocN(sizeof(RayObject*)*size, "octree rayobject nodes"); + oc->ro_nodes = (RayFace**)MEM_callocN(sizeof(RayFace*)*size, "octree rayobject nodes"); oc->ro_nodes_size = size; oc->ro_nodes_used = 0; @@ -469,8 +469,9 @@ static void RayObject_octree_add(RayObject *tree, RayObject *node) { Octree *oc = (Octree*)tree; + assert( RayObject_isRayFace(node) ); assert( oc->ro_nodes_used < oc->ro_nodes_size ); - oc->ro_nodes[ oc->ro_nodes_used++ ] = node; + oc->ro_nodes[ oc->ro_nodes_used++ ] = (RayFace*)RayObject_align(node); } static void octree_fill_rayface(Octree *oc, RayFace *face) @@ -601,7 +602,7 @@ static void RayObject_octree_done(RayObject *tree) /* Calculate Bounding Box */ for(c=0; cro_nodes_used; c++) - RE_rayobject_merge_bb(oc->ro_nodes[c], oc->min, oc->max); + RE_rayobject_merge_bb( RayObject_unalignRayFace(oc->ro_nodes[c]), oc->min, oc->max); /* Alloc memory */ oc->adrbranch= MEM_callocN(sizeof(void *)*BRANCH_ARRAY, "octree branches"); @@ -631,8 +632,7 @@ static void RayObject_octree_done(RayObject *tree) for(c=0; cro_nodes_used; c++) { - assert( RayObject_isRayFace(oc->ro_nodes[c]) ); - octree_fill_rayface(oc, (RayFace*)oc->ro_nodes[c]); + octree_fill_rayface(oc, oc->ro_nodes[c]); } MEM_freeN(oc->ocface); @@ -663,14 +663,14 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval) for(; no; no = no->next) for(nr=0; nr<8; nr++) { - RayObject *face = no->v[nr]; + RayFace *face = no->v[nr]; OcVal *ov = no->ov+nr; if(!face) break; if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { - if( RE_rayobject_intersect(face,is) ) + if( RE_rayobject_intersect( RayObject_unalignRayFace(face),is) ) return 1; } } @@ -682,14 +682,14 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval) for(; no; no = no->next) for(nr=0; nr<8; nr++) { - RayObject *face = no->v[nr]; + RayFace *face = no->v[nr]; OcVal *ov = no->ov+nr; if(!face) break; if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { - if( RE_rayobject_intersect(face,is) ) + if( RE_rayobject_intersect( RayObject_unalignRayFace(face),is) ) found= 1; } } From 621b37bed6528af2192539295b3a604271f29cdc Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 5 Jul 2009 00:38:53 +0000 Subject: [PATCH 034/138] *Added BIH --- .../render/extern/include/RE_raytrace.h | 3 +- .../render/intern/source/rayobject_bih.c | 254 ++++++++++++++++++ .../render/intern/source/rayobject_bvh.c | 39 +-- 3 files changed, 280 insertions(+), 16 deletions(-) create mode 100644 source/blender/render/intern/source/rayobject_bih.c diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index e1d03c996a4..ca21433f229 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -50,9 +50,10 @@ void RE_rayobject_free(RayObject *r); RayObject* RE_rayobject_octree_create(int ocres, int size); RayObject* RE_rayobject_instance_create(RayObject *target, float transform[][4], void *ob, void *target_ob); -#define RE_rayobject_tree_create RE_rayobject_bvh_create +#define RE_rayobject_tree_create RE_rayobject_bih_create RayObject* RE_rayobject_blibvh_create(int size); /* BLI_kdopbvh.c */ RayObject* RE_rayobject_bvh_create(int size); /* rayobject_bvh.c */ +RayObject* RE_rayobject_bih_create(int size); /* rayobject_bih.c */ /* Ray Intersection */ diff --git a/source/blender/render/intern/source/rayobject_bih.c b/source/blender/render/intern/source/rayobject_bih.c new file mode 100644 index 00000000000..fb755e2c7e6 --- /dev/null +++ b/source/blender/render/intern/source/rayobject_bih.c @@ -0,0 +1,254 @@ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#include +#include + +#include "MEM_guardedalloc.h" +#include "BKE_utildefines.h" +#include "BLI_arithb.h" +#include "RE_raytrace.h" +#include "rayobject_rtbuild.h" +#include "rayobject.h" + +#define BIH_NCHILDS 4 +typedef struct BIHTree BIHTree; + +static int bih_intersect(BIHTree *obj, Isect *isec); +static void bih_add(BIHTree *o, RayObject *ob); +static void bih_done(BIHTree *o); +static void bih_free(BIHTree *o); +static void bih_bb(BIHTree *o, float *min, float *max); + +static RayObjectAPI bih_api = +{ + (RE_rayobject_raycast_callback) bih_intersect, + (RE_rayobject_add_callback) bih_add, + (RE_rayobject_done_callback) bih_done, + (RE_rayobject_free_callback) bih_free, + (RE_rayobject_merge_bb_callback)bih_bb +}; + +typedef struct BIHNode BIHNode; +struct BIHNode +{ + BIHNode *child[BIH_NCHILDS]; + float bi[BIH_NCHILDS][2]; + int split_axis; +}; + +struct BIHTree +{ + RayObject rayobj; + + BIHNode *root; + + BIHNode *node_alloc, *node_next; + RTBuilder *builder; + + float bb[2][3]; +}; + + +RayObject *RE_rayobject_bih_create(int size) +{ + BIHTree *obj= (BIHTree*)MEM_callocN(sizeof(BIHTree), "BIHTree"); + assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ + + obj->rayobj.api = &bih_api; + obj->root = NULL; + + obj->node_alloc = obj->node_next = NULL; + obj->builder = rtbuild_create( size ); + + return RayObject_unalignRayAPI((RayObject*) obj); +} + +static void bih_free(BIHTree *obj) +{ + if(obj->builder) + rtbuild_free(obj->builder); + + if(obj->node_alloc) + MEM_freeN(obj->node_alloc); + + MEM_freeN(obj); +} + +static void bih_bb(BIHTree *obj, float *min, float *max) +{ + //TODO only half operations needed + DO_MINMAX(obj->bb[0], min, max); + DO_MINMAX(obj->bb[1], min, max); +} + +/* + * Tree transverse + */ +static int dfs_raycast(const BIHNode *const node, Isect *isec, float tmin, float tmax) +{ + int i; + int hit = 0; + + const int *const offset = isec->bv_index + node->split_axis*2; + + //TODO diving heuristic + for(i=0; ibi[i][offset[0]] - isec->start[node->split_axis]) * isec->idot_axis[node->split_axis]; + float t2 = (node->bi[i][offset[1]] - isec->start[node->split_axis]) * isec->idot_axis[node->split_axis]; + + if(t1 < tmin) t1 = tmin; //t1 = MAX2(t1, tmin); + if(t2 > tmax) t2 = tmax; //t2 = MIN2(t2, tmax); + + if(t1 <= t2) + { + if(RayObject_isAligned(node->child[i])) + { + if(node->child[i] == 0) break; + + hit |= dfs_raycast(node->child[i], isec, t1, t2); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + else + { + hit |= RE_rayobject_intersect( (RayObject*)node->child[i], isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + + if(tmax > isec->labda) + tmax = isec->labda; + } + } + + return hit; +} + +static int bih_intersect(BIHTree *obj, Isect *isec) +{ + if(RayObject_isAligned(obj->root)) + return dfs_raycast(obj->root, isec, 0, isec->labda); + else + return RE_rayobject_intersect( (RayObject*)obj->root, isec); +} + + +/* + * Builds a BIH tree from builder object + */ +static void bih_add(BIHTree *obj, RayObject *ob) +{ + rtbuild_add( obj->builder, ob ); +} + +static BIHNode *bih_new_node(BIHTree *tree, int nid) +{ + BIHNode *node = tree->node_alloc + nid - 1; + assert(RayObject_isAligned(node)); + if(node+1 > tree->node_next) + tree->node_next = node+1; + + return node; +} + +static int child_id(int pid, int nchild) +{ + //N child of node A = A * K + (2 - K) + N, (0 <= N < K) + return pid*BIH_NCHILDS+(2-BIH_NCHILDS)+nchild; +} + +static BIHNode *bih_rearrange(BIHTree *tree, RTBuilder *builder, int nid, float *bb) +{ + if(rtbuild_size(builder) == 1) + { + RayObject *child = builder->begin[0]; + assert(!RayObject_isAligned(child)); + + INIT_MINMAX(bb, bb+3); + RE_rayobject_merge_bb( (RayObject*)child, bb, bb+3); + + return (BIHNode*)child; + } + else + { + int i; + int nc = rtbuild_mean_split_largest_axis(builder, BIH_NCHILDS); + RTBuilder tmp; + + BIHNode *parent = bih_new_node(tree, nid); + + INIT_MINMAX(bb, bb+3); + parent->split_axis = builder->split_axis; + for(i=0; ichild[i] = bih_rearrange( tree, rtbuild_get_child(builder, i, &tmp), child_id(nid,i), cbb ); + + parent->bi[i][0] = cbb[parent->split_axis]; + parent->bi[i][1] = cbb[parent->split_axis+3]; + + DO_MINMAX(cbb , bb, bb+3); + DO_MINMAX(cbb+3, bb, bb+3); + } + for(; ibi[i][0] = 1.0; + parent->bi[i][1] = -1.0; + parent->child[i] = 0; + } + + return parent; + } +} + +static void bih_info(BIHTree *obj) +{ + printf("BIH: Used %d nodes\n", obj->node_next - obj->node_alloc); +} + +static void bih_done(BIHTree *obj) +{ + int needed_nodes; + assert(obj->root == NULL && obj->node_alloc == NULL && obj->builder); + + //TODO exact calculate needed nodes + needed_nodes = (rtbuild_size(obj->builder)+1)*2; + assert(needed_nodes > 0); + + obj->node_alloc = (BIHNode*)MEM_mallocN( sizeof(BIHNode)*needed_nodes, "BIHTree.Nodes"); + obj->node_next = obj->node_alloc; + + obj->root = bih_rearrange( obj, obj->builder, 1, (float*)obj->bb ); + + rtbuild_free( obj->builder ); + obj->builder = NULL; + + assert(obj->node_alloc+needed_nodes >= obj->node_next); +} + diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index 88f673cbcb1..d9d3832830a 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -66,7 +66,9 @@ struct BVHTree { RayObject rayobj; - BVHNode *alloc, *next_node, *root; + BVHNode *root; + + BVHNode *node_alloc, *node_next; float *bb_alloc, *bb_next; RTBuilder *builder; @@ -79,9 +81,12 @@ RayObject *RE_rayobject_bvh_create(int size) assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ obj->rayobj.api = &bvh_api; - obj->builder = rtbuild_create( size ); obj->root = NULL; + obj->node_alloc = obj->node_next = NULL; + obj->bb_alloc = obj->bb_next = NULL; + obj->builder = rtbuild_create( size ); + return RayObject_unalignRayAPI((RayObject*) obj); } @@ -90,8 +95,8 @@ static void bvh_free(BVHTree *obj) if(obj->builder) rtbuild_free(obj->builder); - if(obj->alloc) - MEM_freeN(obj->alloc); + if(obj->node_alloc) + MEM_freeN(obj->node_alloc); if(obj->bb_alloc) MEM_freeN(obj->bb_alloc); @@ -185,10 +190,10 @@ static void bvh_add(BVHTree *obj, RayObject *ob) static BVHNode *bvh_new_node(BVHTree *tree, int nid) { - BVHNode *node = tree->alloc + nid - 1; + BVHNode *node = tree->node_alloc + nid - 1; assert(RayObject_isAligned(node)); - if(node+1 > tree->next_node) - tree->next_node = node+1; + if(node+1 > tree->node_next) + tree->node_next = node+1; node->bb = tree->bb_next; tree->bb_next += 6; @@ -255,28 +260,32 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid) return parent; } } + +static void bvh_info(BVHTree *obj) +{ + printf("BVH: Used %d nodes\n", obj->node_next - obj->node_alloc); +} static void bvh_done(BVHTree *obj) { int needed_nodes; - assert(obj->root == NULL && obj->next_node == NULL && obj->builder); + assert(obj->root == NULL && obj->node_alloc == NULL && obj->bb_alloc == NULL && obj->builder); + //TODO exact calculate needed nodes needed_nodes = (rtbuild_size(obj->builder)+1)*2; assert(needed_nodes > 0); - obj->alloc = (BVHNode*)MEM_mallocN( sizeof(BVHNode)*needed_nodes, "BVHTree.Nodes"); - obj->next_node = obj->alloc; + + obj->node_alloc = (BVHNode*)MEM_mallocN( sizeof(BVHNode)*needed_nodes, "BVHTree.Nodes"); + obj->node_next = obj->node_alloc; obj->bb_alloc = (float*)MEM_mallocN( sizeof(float)*6*needed_nodes, "BVHTree.NodesBB"); obj->bb_next = obj->bb_alloc; obj->root = bvh_rearrange( obj, obj->builder, 1 ); - assert(obj->alloc+needed_nodes >= obj->next_node); - -// printf("BVH: Used %d nodes\n", obj->next_node-obj->alloc); - - rtbuild_free( obj->builder ); obj->builder = NULL; + + assert(obj->node_alloc+needed_nodes >= obj->node_next); } From abc44f720ac3d463fcdf051ffd680373c4a43b2a Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 5 Jul 2009 18:46:23 +0000 Subject: [PATCH 035/138] Set BVH (rayobject_bvh.c) as default tree type --- source/blender/render/extern/include/RE_raytrace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index f2fb8c5277a..b3c128c3019 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -50,7 +50,7 @@ void RE_rayobject_free(RayObject *r); RayObject* RE_rayobject_octree_create(int ocres, int size); RayObject* RE_rayobject_instance_create(RayObject *target, float transform[][4], void *ob, void *target_ob); -#define RE_rayobject_tree_create RE_rayobject_blibvh_create +#define RE_rayobject_tree_create RE_rayobject_bvh_create RayObject* RE_rayobject_blibvh_create(int size); /* BLI_kdopbvh.c */ RayObject* RE_rayobject_bvh_create(int size); /* rayobject_bvh.c */ RayObject* RE_rayobject_bih_create(int size); /* rayobject_bih.c */ From ba1f3323bf21929d74504f3e9ada296d7df85290 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 6 Jul 2009 13:27:40 +0000 Subject: [PATCH 036/138] *Added output of BB/primitves test/hits *"Added" SCE_PASS_RAYHITS to visually see each pixel primitive and BB tests (not-completed for UI) *Added runtime exchange of tree structure *Removed FLOAT_EPSILON from BLI_bvhkdop BB's --- release/ui/buttons_scene.py | 1 + source/blender/makesdna/DNA_scene_types.h | 10 ++- source/blender/makesrna/intern/rna_scene.c | 12 ++++ .../render/extern/include/RE_raytrace.h | 69 ++++++++++--------- .../render/extern/include/RE_shader_ext.h | 6 ++ .../blender/render/intern/source/pipeline.c | 13 +++- .../blender/render/intern/source/rayobject.c | 60 +++++++++++----- .../render/intern/source/rayobject_blibvh.c | 2 +- .../blender/render/intern/source/rayshade.c | 50 ++++++++++++-- .../blender/render/intern/source/rendercore.c | 10 +++ .../blender/render/intern/source/shadeinput.c | 11 +++ 11 files changed, 188 insertions(+), 56 deletions(-) diff --git a/release/ui/buttons_scene.py b/release/ui/buttons_scene.py index 25ff12de306..c5ce455669f 100644 --- a/release/ui/buttons_scene.py +++ b/release/ui/buttons_scene.py @@ -26,6 +26,7 @@ class RENDER_PT_shading(RenderButtonsPanel): colsub = col.column() colsub.active = rd.render_raytracing colsub.itemR(rd, "raytrace_structure", text="Structure") + colsub.itemR(rd, "raytrace_tree_type", text="Tree Type") colsub.itemR(rd, "octree_resolution", text="Octree") col.itemR(rd, "dither_intensity", text="Dither", slider=True) diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 1199bd1e2b1..bcbccecbb55 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -161,6 +161,8 @@ typedef struct SceneRenderLayer { #define SCE_PASS_RADIO 8192 /* Radio removed, can use for new GI? */ #define SCE_PASS_MIST 16384 +#define SCE_PASS_RAYHITS 32768 + /* note, srl->passflag is treestore element 'nr' in outliner, short still... */ @@ -233,7 +235,8 @@ typedef struct RenderData { /* render engine, octree resolution */ short renderer, ocres; short raystructure; - short pad4[3]; + short raytrace_tree_type; + short pad4[2]; /** * What to do with the sky/background. Picks sky/premul/key @@ -675,6 +678,11 @@ typedef struct Scene { #define R_RAYSTRUCTURE_SINGLE_OCTREE 2 #define R_RAYSTRUCTURE_SINGLE_BVH 3 +/* raytrace tree type */ +#define R_RAYTRACE_TREE_BVH 0 +#define R_RAYTRACE_TREE_BLIBVH 1 +#define R_RAYTRACE_TREE_BIH 2 + /* scemode (int now) */ #define R_DOSEQ 0x0001 #define R_BG_RENDER 0x0002 diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 59d036a84dc..dfee6a9eb83 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -293,6 +293,12 @@ void rna_def_scene_render_data(BlenderRNA *brna) {R_RAYSTRUCTURE_SINGLE_BVH, "{R_RAYSTRUCTURE_SINGLE_BVH", 0, "Single BVH", "BVH of all primitives (no instance support)"}, {R_RAYSTRUCTURE_SINGLE_OCTREE, "{R_RAYSTRUCTURE_SINGLE_OCTREE", 0, "Octree", "Octree of all primitives (no instance support)"}, {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem raytrace_tree_type_items[] = { + {R_RAYTRACE_TREE_BVH, "{R_RAYTRACE_TREE_BVH", 0, "BVH", "rayobject_bvh.c"}, + {R_RAYTRACE_TREE_BLIBVH, "{R_RAYTRACE_TREE_BLIBVH", 0, "BLIbvh", "rayobject_blibvh.c"}, + {R_RAYTRACE_TREE_BIH, "{R_RAYSTRUCTURE_SINGLE_BVH", 0, "BIH", "rayobject_bih.c"}, + {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem fixed_oversample_items[] = { {5, "OVERSAMPLE_5", 0, "5", ""}, @@ -694,6 +700,12 @@ void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_enum_items(prop, raytrace_structure_items); RNA_def_property_ui_text(prop, "Raytrace Acceleration Structure", "Type of raytrace accelerator structure."); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + + prop= RNA_def_property(srna, "raytrace_tree_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "raytrace_tree_type"); + RNA_def_property_enum_items(prop, raytrace_tree_type_items); + RNA_def_property_ui_text(prop, "Raytrace tree type", "Type of raytrace accelerator structure."); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); prop= RNA_def_property(srna, "antialiasing", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_OSA); diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index b3c128c3019..fdd49cf1216 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -31,12 +31,43 @@ #ifndef RE_RAYTRACE_H #define RE_RAYTRACE_H -#define RE_RAY_COUNTER +#define RE_RAYCOUNTER +#ifdef RE_RAYCOUNTER + +typedef struct RayCounter RayCounter; +struct RayCounter +{ + + struct + { + unsigned long long test, hit; + + } faces, bb, raycast; + + unsigned long long rayshadow_last_hit_optimization; +}; + +/* #define RE_RC_INIT(isec, shi) (isec).count = re_rc_counter+(shi).thread */ +#define RE_RC_INIT(isec, shi) (isec).raycounter = &((shi).raycounter) +void RE_RC_INFO (RayCounter *rc); +void RE_RC_MERGE(RayCounter *rc, RayCounter *tmp); +#define RE_RC_COUNT(var) (var)++ + +extern RayCounter re_rc_counter[]; + +#else + +#define RE_RC_INIT(isec,shi) +#define RE_RC_INFO(rc) +#define RE_RC_MERGE(dest,src) +#define RE_RC_COUNT(var) + +#endif + /* Internals about raycasting structures can be found on intern/raytree.h */ typedef struct RayObject RayObject; typedef struct Isect Isect; -typedef struct RayCounter RayCounter; struct DerivedMesh; struct Mesh; @@ -50,7 +81,6 @@ void RE_rayobject_free(RayObject *r); RayObject* RE_rayobject_octree_create(int ocres, int size); RayObject* RE_rayobject_instance_create(RayObject *target, float transform[][4], void *ob, void *target_ob); -#define RE_rayobject_tree_create RE_rayobject_bvh_create RayObject* RE_rayobject_blibvh_create(int size); /* BLI_kdopbvh.c */ RayObject* RE_rayobject_bvh_create(int size); /* rayobject_bvh.c */ RayObject* RE_rayobject_bih_create(int size); /* rayobject_bih.c */ @@ -93,38 +123,11 @@ struct Isect void *userdata; -#ifdef RE_RAY_COUNTER - RayCounter *count; -#endif - -}; - #ifdef RE_RAYCOUNTER - -struct RayCounter -{ - - struct - { - unsigned long long test, hit; - - } intersect_rayface, raycast; - - unsigned long long rayshadow_last_hit_optimization; -}; - -void RE_RC_INIT (RayCounter *rc); -void RE_RC_MERGE(RayCounter *rc, RayCounter *tmp); -#define RE_RC_COUNT(var) (var)++ - -#else - -#define RE_RC_INIT(rc) -#define RE_RC_MERGE(dest,src) -#define RE_RC_COUNT(var) - + RayCounter *raycounter; #endif - + +}; /* ray types */ #define RE_RAY_SHADOW 0 diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 0ad48fe97a9..980ff59b86a 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -30,6 +30,7 @@ #ifndef RE_SHADER_EXT_H #define RE_SHADER_EXT_H +#include "RE_raytrace.h" /* For RE_RAYCOUNTER */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* this include is for shading and texture exports */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -57,6 +58,7 @@ typedef struct ShadeResult float nor[3]; float rad[3]; float winspeed[4]; + float rayhits[4]; } ShadeResult; /* only here for quick copy */ @@ -178,6 +180,10 @@ typedef struct ShadeInput struct Group *light_override; struct Material *mat_override; +#ifdef RE_RAYCOUNTER + RayCounter raycounter; +#endif + } ShadeInput; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index ec2660566f5..65ef85a04ca 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -347,6 +347,13 @@ static char *get_pass_name(int passtype, int channel) if(channel==-1) return "Mist"; return "Mist.Z"; } + if(passtype == SCE_PASS_RAYHITS) + { + if(channel==-1) return "Rayhits"; + if(channel==0) return "Rayhits.R"; + if(channel==1) return "Rayhits.G"; + return "Rayhits.B"; + } return "Unknown"; } @@ -398,6 +405,8 @@ static int passtype_from_name(char *str) if(strcmp(str, "Mist")==0) return SCE_PASS_MIST; + if(strcmp(str, "RAYHITS")==0) + return SCE_PASS_RAYHITS; return 0; } @@ -523,7 +532,7 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int rl->lay= srl->lay; rl->lay_zmask= srl->lay_zmask; rl->layflag= srl->layflag; - rl->passflag= srl->passflag; + rl->passflag= srl->passflag | SCE_PASS_RAYHITS; rl->pass_xor= srl->pass_xor; rl->light_override= srl->light_override; rl->mat_override= srl->mat_override; @@ -565,6 +574,8 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB); if(srl->passflag & SCE_PASS_MIST) render_layer_add_pass(rr, rl, 1, SCE_PASS_MIST); + if(rl->passflag & SCE_PASS_RAYHITS) + render_layer_add_pass(rr, rl, 4, SCE_PASS_RAYHITS); } /* sss, previewrender and envmap don't do layers, so we make a default one */ diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index ffe1bba52c9..e9cf46d0734 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -54,10 +54,14 @@ float RE_rayobject_bb_intersect(const Isect *isec, const float *_bb) float t1z = (bb[isec->bv_index[4]] - isec->start[2]) * isec->idot_axis[2]; float t2z = (bb[isec->bv_index[5]] - isec->start[2]) * isec->idot_axis[2]; + RE_RC_COUNT(isec->raycounter->bb.test); + if(t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) return FLT_MAX; if(t2x < 0.0 || t2y < 0.0 || t2z < 0.0) return FLT_MAX; if(t1x > isec->labda || t1y > isec->labda || t1z > isec->labda) return FLT_MAX; + RE_RC_COUNT(isec->raycounter->bb.hit); + dist = t1x; if (t1y > dist) dist = t1y; if (t1z > dist) dist = t1z; @@ -157,7 +161,7 @@ static int intersect_rayface(RayFace *face, Isect *is) if(is->orig.ob == face->ob && is->orig.face == face->face) return 0; - RE_RC_COUNT(is->count->intersect_rayface.test); + RE_RC_COUNT(is->raycounter->faces.test); VECCOPY(co1, face->v1); VECCOPY(co2, face->v2); @@ -276,7 +280,7 @@ static int intersect_rayface(RayFace *face, Isect *is) } #endif - RE_RC_COUNT(is->count->intersect_rayface.hit); + RE_RC_COUNT(is->raycounter->faces.hit); is->isect= ok; // wich half of the quad is->labda= labda; @@ -294,7 +298,7 @@ static int intersect_rayface(RayFace *face, Isect *is) int RE_rayobject_raycast(RayObject *r, Isect *isec) { int i; - RE_RC_COUNT(isec->count->raycast.test); + RE_RC_COUNT(isec->raycounter->raycast.test); /* Setup vars used on raycast */ isec->labda *= Normalize(isec->vec); @@ -315,15 +319,15 @@ int RE_rayobject_raycast(RayObject *r, Isect *isec) /* Last hit heuristic */ if(isec->mode==RE_RAY_SHADOW && isec->last_hit && RE_rayobject_intersect(isec->last_hit, isec)) { - RE_RC_COUNT(isec->count->raycast.hit); - RE_RC_COUNT(isec->count->rayshadow_last_hit_optimization ); + RE_RC_COUNT(isec->raycounter->raycast.hit); + RE_RC_COUNT(isec->raycounter->rayshadow_last_hit_optimization ); return 1; } #ifdef RE_RAYCOUNTER if(RE_rayobject_intersect(r, isec)) { - RE_RC_COUNT(isec->count->raycast.hit); + RE_RC_COUNT(isec->raycounter->raycast.hit); return 1; } return 0; @@ -383,16 +387,40 @@ void RE_rayobject_merge_bb(RayObject *r, float *min, float *max) } #ifdef RE_RAYCOUNTER -void RE_merge_raycounter(RayCounter *dest, RayCounter *tmp) +void RE_RC_INFO(RayCounter *info) { - int i; - for(i=0; i<3; i++) dest->casted[i] += tmp->casted[i]; - for(i=0; i<3; i++) dest->hit [i] += tmp->hit [i]; - - dest->test_primitives += tmp->test_primitives; - dest->hit_primitives += tmp->hit_primitives; - - dest->test_bb += tmp->test_bb; - dest->hit_bb += tmp->hit_bb; + printf("----------- Raycast counter --------\n"); + printf("Rays total: %llu\n", info->raycast.test ); + printf("Rays hit: %llu\n", info->raycast.hit ); + printf("\n"); + printf("BB tests: %llu\n", info->bb.test ); + printf("BB hits: %llu\n", info->bb.hit ); + printf("\n"); + printf("Primitives tests: %llu\n", info->faces.test ); + printf("Primitives hits: %llu\n", info->faces.hit ); + printf("\n"); + printf("Shadow Last hit reuse: %llu\n", info->rayshadow_last_hit_optimization); + printf("\n"); + printf("Primitives tests per ray: %f\n", info->faces.test / ((float)info->raycast.test) ); + printf("Primitives hits per ray: %f\n", info->faces.hit / ((float)info->raycast.test) ); + printf("\n"); + printf("BB tests per ray: %f\n", info->bb.test / ((float)info->raycast.test) ); + printf("BB hits per ray: %f\n", info->bb.hit / ((float)info->raycast.test) ); + printf("\n"); } + +void RE_RC_MERGE(RayCounter *dest, RayCounter *tmp) +{ + dest->faces.test += tmp->faces.test; + dest->faces.hit += tmp->faces.hit; + + dest->bb.test += tmp->bb.test; + dest->bb.hit += tmp->bb.hit; + + dest->raycast.test += tmp->raycast.test; + dest->raycast.hit += tmp->raycast.hit; + + dest->rayshadow_last_hit_optimization += tmp->rayshadow_last_hit_optimization; +} + #endif \ No newline at end of file diff --git a/source/blender/render/intern/source/rayobject_blibvh.c b/source/blender/render/intern/source/rayobject_blibvh.c index 41da4679b6a..ab8d7f1236e 100644 --- a/source/blender/render/intern/source/rayobject_blibvh.c +++ b/source/blender/render/intern/source/rayobject_blibvh.c @@ -66,7 +66,7 @@ RayObject *RE_rayobject_blibvh_create(int size) assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ obj->rayobj.api = &bvh_api; - obj->bvh = BLI_bvhtree_new(size, FLT_EPSILON, 4, 6); + obj->bvh = BLI_bvhtree_new(size, 0.0, 4, 6); INIT_MINMAX(obj->bb[0], obj->bb[1]); return RayObject_unalignRayAPI((RayObject*) obj); diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 4c16ac05ec2..09bf0842734 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -70,6 +70,22 @@ extern struct Render R; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +RayObject *RE_rayobject_tree_create(int type, int size) +{ + if(type == R_RAYTRACE_TREE_BVH) + return RE_rayobject_bvh_create(size); + if(type == R_RAYTRACE_TREE_BIH) + return RE_rayobject_bih_create(size); + if(type == R_RAYTRACE_TREE_BLIBVH) + return RE_rayobject_blibvh_create(size); + + return RE_rayobject_bvh_create(size); +} + +#ifdef RE_RAYCOUNTER +RayCounter re_rc_counter[BLENDER_MAX_THREADS] = {}; +#endif + #if 0 static int vlr_check_intersect(Isect *is, int ob, RayFace *face) { @@ -123,6 +139,16 @@ void freeraytree(Render *re) obi->raytree = NULL; } } + +#ifdef RE_RAYCOUNTER + { + RayCounter sum = {}; + int i; + for(i=0; ir.raystructure == R_RAYSTRUCTURE_HIER_BVH_OCTREE) raytree = obr->raytree = RE_rayobject_octree_create( re->r.ocres, faces ); else //if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_BVH) - raytree = obr->raytree = RE_rayobject_tree_create( faces ); + raytree = obr->raytree = RE_rayobject_tree_create( re->r.raytrace_tree_type, faces ); face = obr->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "ObjectRen faces"); obr->rayobi = obi; @@ -240,7 +266,7 @@ static void makeraytree_hier(Render *re) num_objects++; //Create raytree - re->raytree = RE_rayobject_tree_create( num_objects ); + re->raytree = RE_rayobject_tree_create( re->r.raytrace_tree_type, num_objects ); for(obi=re->instancetable.first; obi; obi=obi->next) if(is_raytraceable(re, obi)) @@ -292,7 +318,7 @@ static void makeraytree_single(Render *re) if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_OCTREE) raytree = re->raytree = RE_rayobject_octree_create( re->r.ocres, faces ); else //if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_BVH) - raytree = re->raytree = RE_rayobject_tree_create( faces ); + raytree = re->raytree = RE_rayobject_tree_create( re->r.raytrace_tree_type, faces ); face = re->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces"); @@ -322,6 +348,17 @@ static void makeraytree_single(Render *re) void makeraytree(Render *re) { +#ifdef RE_RAYCOUNTER + if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_OCTREE) + printf("Building single octree\n"); + else if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_BVH) + printf("Building single tree\n"); + else if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_OCTREE) + printf("Building tree of octrees\n"); + else + printf("Building tree of trees\n"); +#endif + if(ELEM(re->r.raystructure, R_RAYSTRUCTURE_SINGLE_BVH, R_RAYSTRUCTURE_SINGLE_OCTREE)) BENCH(makeraytree_single(re), tree_build); else @@ -563,6 +600,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo isec.orig.ob = obi; isec.orig.face = vlr; + RE_RC_INIT(isec, shi); if(RE_rayobject_raycast(R.raytree, &isec)) { float d= 1.0f; @@ -1306,7 +1344,6 @@ void ray_trace(ShadeInput *shi, ShadeResult *shr) do_tra= ((shi->mat->mode & (MA_RAYTRANSP)) && shr->alpha!=1.0f); do_mir= ((shi->mat->mode & MA_RAYMIRROR) && shi->ray_mirror!=0.0f); - /* raytrace mirror amd refract like to separate the spec color */ if(shi->combinedflag & SCE_PASS_SPEC) @@ -1465,6 +1502,7 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr) isec.mode= RE_RAY_MIRROR; isec.orig.ob = ship->obi; isec.orig.face = ship->vlr; + RE_RC_INIT(isec, shi); for(a=0; a<8*8; a++) { @@ -1669,6 +1707,7 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) float dxyview[3], skyadded=0, div; int aocolor; + RE_RC_INIT(isec, *shi); isec.orig.ob = shi->obi; isec.orig.face = shi->vlr; isec.skip = RE_SKIP_VLR_NEIGHBOUR; @@ -1802,6 +1841,7 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) float dxyview[3]; int j= -1, tot, actual=0, skyadded=0, aocolor, resol= R.wrld.aosamp; + RE_RC_INIT(isec, *shi); isec.orig.ob = shi->obi; isec.orig.face = shi->vlr; isec.skip = RE_SKIP_VLR_NEIGHBOUR; @@ -2238,6 +2278,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) int lampvec; /* indicates if lampco is a vector lamp */ /* setup isec */ + RE_RC_INIT(isec, *shi); if(shi->mat->mode & MA_SHADOW_TRA) isec.mode= RE_RAY_SHADOW_TRA; else isec.mode= RE_RAY_SHADOW; @@ -2323,6 +2364,7 @@ static void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float assert(0); /* setup isec */ + RE_RC_INIT(isec, *shi); isec.mode= RE_RAY_SHADOW_TRA; if(lar->mode & LA_LAYER) isec.lay= lar->lay; else isec.lay= -1; diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 89eb5e28598..507e1460d4c 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -521,6 +521,12 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, } } break; + + case SCE_PASS_RAYHITS: + /* */ + col= &shr->rayhits; + pixsize= 4; + break; } if(col) { fp= rpass->rect + pixsize*offset; @@ -597,6 +603,10 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult fp= rpass->rect + offset; *fp= shr->mist; break; + case SCE_PASS_RAYHITS: + col= shr->rayhits; + pixsize= 4; + break; } if(col) { fp= rpass->rect + pixsize*offset; diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index 1cd8ec110f9..08c3ba07372 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -142,6 +142,7 @@ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr) float alpha; /* ------ main shading loop -------- */ + memset(&shi->raycounter, 0, sizeof(shi->raycounter)); if(shi->mat->nodetree && shi->mat->use_nodes) { ntreeShaderExecTree(shi->mat->nodetree, shi, shr); @@ -188,6 +189,16 @@ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr) /* add z */ shr->z= -shi->co[2]; + + /* RAYHITS */ + if(1 || shi->passflag & SCE_PASS_RAYHITS) + { + shr->rayhits[0] = (float)shi->raycounter.faces.test; + shr->rayhits[1] = (float)shi->raycounter.bb.hit; + shr->rayhits[2] = 0.0; + shr->rayhits[3] = 1.0; + RE_RC_MERGE(&re_rc_counter[shi->thread], &shi->raycounter); + } } /* **************************************************************************** */ From e0e66f6b74d988d8af59f8ee9235dc251577efc3 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 6 Jul 2009 14:36:26 +0000 Subject: [PATCH 037/138] *"Fixed" rayobject_bvh memory organization of BB's until now rayobject_bvh should be at least as fast as BLIBVH, this seemed to be the missing piece --- .../blender/render/intern/source/rayobject_bvh.c | 2 +- source/blender/render/intern/source/rayshade.c | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index d9d3832830a..9a6292d33e5 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -195,7 +195,7 @@ static BVHNode *bvh_new_node(BVHTree *tree, int nid) if(node+1 > tree->node_next) tree->node_next = node+1; - node->bb = tree->bb_next; + node->bb = tree->bb_alloc + nid - 1; tree->bb_next += 6; return node; diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 09bf0842734..b70e4bf5000 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -348,15 +348,24 @@ static void makeraytree_single(Render *re) void makeraytree(Render *re) { + const char *tree_type = "Tree(unknown)"; + #ifdef RE_RAYCOUNTER + if(re->r.raytrace_tree_type == R_RAYTRACE_TREE_BVH) + tree_type = "BVH"; + if(re->r.raytrace_tree_type == R_RAYTRACE_TREE_BIH) + tree_type = "BIH"; + if(re->r.raytrace_tree_type == R_RAYTRACE_TREE_BLIBVH) + tree_type = "BLIBVH"; + if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_OCTREE) printf("Building single octree\n"); else if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_BVH) - printf("Building single tree\n"); + printf("Building single tree(%s)\n", tree_type); else if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_OCTREE) - printf("Building tree of octrees\n"); + printf("Building tree(%s) of octrees\n", tree_type); else - printf("Building tree of trees\n"); + printf("Building tree(%s) of trees(%s)\n", tree_type, tree_type); #endif if(ELEM(re->r.raystructure, R_RAYSTRUCTURE_SINGLE_BVH, R_RAYSTRUCTURE_SINGLE_OCTREE)) From aa12d2153fbc80d0bd4fb3e9cc1278e15bce6376 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 6 Jul 2009 15:35:46 +0000 Subject: [PATCH 038/138] *fix (forgot to multiply by BB size) --- source/blender/render/intern/source/rayobject_bvh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index 9a6292d33e5..1798af6465f 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -195,7 +195,7 @@ static BVHNode *bvh_new_node(BVHTree *tree, int nid) if(node+1 > tree->node_next) tree->node_next = node+1; - node->bb = tree->bb_alloc + nid - 1; + node->bb = tree->bb_alloc + (nid - 1)*6; tree->bb_next += 6; return node; From c65a3e3166397928f8b276db7dd4d5445671574e Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 6 Jul 2009 19:45:00 +0000 Subject: [PATCH 039/138] *Added BLI_memarena on bvh *Median split support on rtbuild --- .../render/intern/include/rayobject_rtbuild.h | 8 +- .../render/intern/source/rayobject_bvh.c | 65 +++++++- .../render/intern/source/rayobject_rtbuild.c | 155 +++++++++++++++++- 3 files changed, 216 insertions(+), 12 deletions(-) diff --git a/source/blender/render/intern/include/rayobject_rtbuild.h b/source/blender/render/intern/include/rayobject_rtbuild.h index af0a11508e8..ed0b03ec03e 100644 --- a/source/blender/render/intern/include/rayobject_rtbuild.h +++ b/source/blender/render/intern/include/rayobject_rtbuild.h @@ -65,8 +65,12 @@ int rtbuild_size(RTBuilder *b); RTBuilder* rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp); /* Calculates child partitions and returns number of efectively needed partitions */ -int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis); -int rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds); int rtbuild_get_largest_axis(RTBuilder *b); +int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis); +int rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds); + +int rtbuild_median_split(RTBuilder *b, float *separators, int nchilds, int axis); +int rtbuild_median_split_largest_axis(RTBuilder *b, int nchilds); + #endif diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index 1798af6465f..15c0d70b248 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -32,10 +32,16 @@ #include "MEM_guardedalloc.h" #include "BKE_utildefines.h" #include "BLI_arithb.h" +#include "BLI_memarena.h" #include "RE_raytrace.h" #include "rayobject_rtbuild.h" #include "rayobject.h" +#define DYNAMIC_ALLOC + +#define SPLIT_OVERLAP_MEAN_LONGEST_AXIS /* objects mean split on the longest axis, childs BB are allowed to overlap */ +//#define SPLIT_OVERLAP_MEDIAN_LONGEST_AXIS /* space median split on the longest axis, childs BB are allowed to overlap */ + #define BVH_NCHILDS 4 typedef struct BVHTree BVHTree; @@ -58,7 +64,11 @@ typedef struct BVHNode BVHNode; struct BVHNode { BVHNode *child[BVH_NCHILDS]; +#ifdef DYNAMIC_ALLOC + float bb[6]; +#else float *bb; //[6]; //[2][3]; +#endif int split_axis; }; @@ -68,8 +78,12 @@ struct BVHTree BVHNode *root; +#ifdef DYNAMIC_ALLOC + MemArena *node_arena; +#else BVHNode *node_alloc, *node_next; float *bb_alloc, *bb_next; +#endif RTBuilder *builder; }; @@ -83,8 +97,12 @@ RayObject *RE_rayobject_bvh_create(int size) obj->rayobj.api = &bvh_api; obj->root = NULL; +#ifdef DYNAMIC_ALLOC + obj->node_arena = NULL; +#else obj->node_alloc = obj->node_next = NULL; obj->bb_alloc = obj->bb_next = NULL; +#endif obj->builder = rtbuild_create( size ); return RayObject_unalignRayAPI((RayObject*) obj); @@ -95,11 +113,16 @@ static void bvh_free(BVHTree *obj) if(obj->builder) rtbuild_free(obj->builder); +#ifdef DYNAMIC_ALLOC + if(obj->node_arena) + BLI_memarena_free(obj->node_arena); +#else if(obj->node_alloc) MEM_freeN(obj->node_alloc); if(obj->bb_alloc) MEM_freeN(obj->bb_alloc); +#endif MEM_freeN(obj); } @@ -190,6 +213,10 @@ static void bvh_add(BVHTree *obj, RayObject *ob) static BVHNode *bvh_new_node(BVHTree *tree, int nid) { +#ifdef DYNAMIC_ALLOC + BVHNode *node = BLI_memarena_alloc(tree->node_arena, sizeof(BVHNode)); + return node; +#else BVHNode *node = tree->node_alloc + nid - 1; assert(RayObject_isAligned(node)); if(node+1 > tree->node_next) @@ -199,6 +226,7 @@ static BVHNode *bvh_new_node(BVHTree *tree, int nid) tree->bb_next += 6; return node; +#endif } static int child_id(int pid, int nchild) @@ -209,6 +237,9 @@ static int child_id(int pid, int nchild) static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid) { + if(rtbuild_size(builder) == 0) + return 0; + if(rtbuild_size(builder) == 1) { RayObject *child = builder->begin[0]; @@ -242,10 +273,17 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid) else { int i; - int nc = rtbuild_mean_split_largest_axis(builder, BVH_NCHILDS); RTBuilder tmp; - BVHNode *parent = bvh_new_node(tree, nid); + int nc; + +#ifdef SPLIT_OVERLAP_MEAN_LONGEST_AXIS + nc = rtbuild_mean_split_largest_axis(builder, BVH_NCHILDS); +#elif defined(SPLIT_OVERLAP_MEDIAN_LONGEST_AXIS) + nc = rtbuild_median_split_largest_axis(builder, BVH_NCHILDS); +#else + assert(0); +#endif INIT_MINMAX(parent->bb, parent->bb+3); parent->split_axis = builder->split_axis; @@ -261,31 +299,48 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid) } } +/* static void bvh_info(BVHTree *obj) { printf("BVH: Used %d nodes\n", obj->node_next - obj->node_alloc); } +*/ static void bvh_done(BVHTree *obj) { + + +#ifdef DYNAMIC_ALLOC + int needed_nodes = (rtbuild_size(obj->builder)+1)*2; + if(needed_nodes > BLI_MEMARENA_STD_BUFSIZE) + needed_nodes = BLI_MEMARENA_STD_BUFSIZE; + + obj->node_arena = BLI_memarena_new(needed_nodes); + BLI_memarena_use_malloc(obj->node_arena); + +#else int needed_nodes; - assert(obj->root == NULL && obj->node_alloc == NULL && obj->bb_alloc == NULL && obj->builder); //TODO exact calculate needed nodes needed_nodes = (rtbuild_size(obj->builder)+1)*2; assert(needed_nodes > 0); + BVHNode *node = BLI_memarena_alloc(tree->node_arena, sizeof(BVHNode)); + return node; obj->node_alloc = (BVHNode*)MEM_mallocN( sizeof(BVHNode)*needed_nodes, "BVHTree.Nodes"); obj->node_next = obj->node_alloc; obj->bb_alloc = (float*)MEM_mallocN( sizeof(float)*6*needed_nodes, "BVHTree.NodesBB"); obj->bb_next = obj->bb_alloc; +#endif obj->root = bvh_rearrange( obj, obj->builder, 1 ); + +#ifndef DYNAMIC_ALLOC + assert(obj->node_alloc+needed_nodes >= obj->node_next); +#endif rtbuild_free( obj->builder ); obj->builder = NULL; - - assert(obj->node_alloc+needed_nodes >= obj->node_next); } diff --git a/source/blender/render/intern/source/rayobject_rtbuild.c b/source/blender/render/intern/source/rayobject_rtbuild.c index 7be17312a52..0c378dc5948 100644 --- a/source/blender/render/intern/source/rayobject_rtbuild.c +++ b/source/blender/render/intern/source/rayobject_rtbuild.c @@ -1,5 +1,6 @@ #include #include +#include #include "rayobject_rtbuild.h" #include "MEM_guardedalloc.h" @@ -8,6 +9,7 @@ static int partition_nth_element(RTBuilder *b, int _begin, int _end, int n); static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis); +static int split_leafs_by_plane(RTBuilder *b, int begin, int end, float plane); static void rtbuild_init(RTBuilder *b, RayObject **begin, RayObject **end) @@ -61,12 +63,9 @@ static void merge_bb(RTBuilder *b, float *min, float *max) RE_rayobject_merge_bb(*index, min, max); } -int rtbuild_get_largest_axis(RTBuilder *b) +static int largest_axis(float *min, float *max) { - float min[3], max[3], sub[3]; - - INIT_MINMAX(min, max); - merge_bb( b, min, max); + float sub[3]; sub[0] = max[0]-min[0]; sub[1] = max[1]-min[1]; @@ -87,7 +86,22 @@ int rtbuild_get_largest_axis(RTBuilder *b) } } +int rtbuild_get_largest_axis(RTBuilder *b) +{ + float min[3], max[3]; + INIT_MINMAX(min, max); + merge_bb( b, min, max); + + return largest_axis(min,max); +} + + +/* +int rtbuild_median_split(RTBuilder *b, int nchilds, int axis) +{ +} +*/ //Left balanced tree int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis) { @@ -146,6 +160,123 @@ int rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds) return rtbuild_mean_split(b, nchilds, axis); } +/* + * "separators" is an array of dim NCHILDS-1 + * and indicates where to cut the childs + */ +int rtbuild_median_split(RTBuilder *b, float *separators, int nchilds, int axis) +{ + int size = rtbuild_size(b); + + assert(nchilds <= RTBUILD_MAX_CHILDS); + if(size <= nchilds) + { + return rtbuild_mean_split(b, nchilds, axis); + } + else + { + int i; + + b->split_axis = axis; + + //Calculate child offsets + b->child_offset[0] = 0; + for(i=0; ichild_offset[i+1] = split_leafs_by_plane(b, b->child_offset[i], size, separators[i]); + b->child_offset[nchilds] = size; + + for(i=0; ichild_offset[i+1] - b->child_offset[i] == size) + return rtbuild_mean_split(b, nchilds, axis); + + return nchilds; + } +} + +int rtbuild_median_split_largest_axis(RTBuilder *b, int nchilds) +{ + int la, i; + float separators[RTBUILD_MAX_CHILDS]; + float min[3], max[3]; + + INIT_MINMAX(min, max); + merge_bb( b, min, max); + + la = largest_axis(min,max); + for(i=1; ikey < b->key) return -1; + if(a->key > b->key) return 1; + if(a->value < b->value) return -1; + if(a->value > b->value) return 1; + return 0; +} + +void costevent_sort(CostEvent *begin, CostEvent *end) +{ + //TODO introsort + qsort(begin, sizeof(*begin), end-begin, (int(*)(const void *, const void *)) costevent_cmp); +} + +/* +int rtbuild_heuristic_split(RTBuilder *b, int nchilds) +{ + int size = rtbuild_size(b); + + if(size <= nchilds) + { + return rtbuild_mean_split_largest_axis(b, nchilds); + } + else + { + CostEvent *events[3], *ev[3]; + RayObject *index; + int a = 0; + + for(a = 0; a<3; a++) + ev[a] = events[a] = MEM_malloc( sizeof(CostEvent)*2*size, "RTBuilder.SweepSplitCostEvent" ); + + for(index = b->begin; b != b->end; b++) + { + float min[3], max[3]; + INIT_MINMAX(min, max); + RE_rayobject_merge_bb(index, min, max); + for(a = 0; a<3; a++) + { + ev[a]->key = min[a]; + ev[a]->value = 1; + ev[a]++; + + ev[a]->key = max[a]; + ev[a]->value = -1; + ev[a]++; + } + } + for(a = 0; a<3; a++) + costevent_sort(events[a], ev[a]); + + + + for(a = 0; a<3; a++) + MEM_freeN(ev[a]); + } +} +*/ /* * Helper code @@ -268,3 +399,17 @@ static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis) partition_nth_element(b, nth[i], nth[i+1], nth[partitions] ); } } + +static int split_leafs_by_plane(RTBuilder *b, int begin, int end, float plane) +{ + int i; + for(i = begin; i != end; i++) + { + if(sort_get_value(b, i) < plane) + { + sort_swap(b, i, begin); + begin++; + } + } + return begin; +} From 08fa7862510e755b9112a64754ca4401138d957b Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 7 Jul 2009 15:42:08 +0000 Subject: [PATCH 040/138] *added Object SAH support to rtbuild: only for 2childs splits with "worse case heuristic" means each child is considered to have a cost linear on the number of leafs no termination criteria number of BB test/hits expected to "reduced" by some factor tree building is also expected to be slower as previous split was "object mean", which is quite fast to evaluate --- .../render/intern/include/rayobject_rtbuild.h | 5 + .../render/intern/source/rayobject_bvh.c | 7 +- .../render/intern/source/rayobject_rtbuild.c | 142 +++++++++++++++++- 3 files changed, 146 insertions(+), 8 deletions(-) diff --git a/source/blender/render/intern/include/rayobject_rtbuild.h b/source/blender/render/intern/include/rayobject_rtbuild.h index ed0b03ec03e..0ead47eefca 100644 --- a/source/blender/render/intern/include/rayobject_rtbuild.h +++ b/source/blender/render/intern/include/rayobject_rtbuild.h @@ -67,10 +67,15 @@ RTBuilder* rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp); /* Calculates child partitions and returns number of efectively needed partitions */ int rtbuild_get_largest_axis(RTBuilder *b); +//Object partition int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis); int rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds); +int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds); + +//Space partition int rtbuild_median_split(RTBuilder *b, float *separators, int nchilds, int axis); int rtbuild_median_split_largest_axis(RTBuilder *b, int nchilds); + #endif diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index 15c0d70b248..82aa4c57ccb 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -39,10 +39,11 @@ #define DYNAMIC_ALLOC -#define SPLIT_OVERLAP_MEAN_LONGEST_AXIS /* objects mean split on the longest axis, childs BB are allowed to overlap */ +//#define SPLIT_OVERLAP_MEAN_LONGEST_AXIS /* objects mean split on the longest axis, childs BB are allowed to overlap */ //#define SPLIT_OVERLAP_MEDIAN_LONGEST_AXIS /* space median split on the longest axis, childs BB are allowed to overlap */ +#define SPLIT_OBJECTS_SAH /* split objects using heuristic */ -#define BVH_NCHILDS 4 +#define BVH_NCHILDS 2 typedef struct BVHTree BVHTree; static int bvh_intersect(BVHTree *obj, Isect *isec); @@ -281,6 +282,8 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid) nc = rtbuild_mean_split_largest_axis(builder, BVH_NCHILDS); #elif defined(SPLIT_OVERLAP_MEDIAN_LONGEST_AXIS) nc = rtbuild_median_split_largest_axis(builder, BVH_NCHILDS); +#elif defined(SPLIT_OBJECTS_SAH) + nc = rtbuild_heuristic_object_split(builder, BVH_NCHILDS); #else assert(0); #endif diff --git a/source/blender/render/intern/source/rayobject_rtbuild.c b/source/blender/render/intern/source/rayobject_rtbuild.c index 0c378dc5948..5ed03a08f6a 100644 --- a/source/blender/render/intern/source/rayobject_rtbuild.c +++ b/source/blender/render/intern/source/rayobject_rtbuild.c @@ -209,7 +209,135 @@ int rtbuild_median_split_largest_axis(RTBuilder *b, int nchilds) return rtbuild_median_split(b, separators, nchilds, la); } -//Heuristics Splitter +//Heuristics Object Splitter +typedef struct CostObject CostObject; +struct CostObject +{ + RayObject *obj; + float bb[6]; +}; + +//Ugly.. but using qsort and no globals its the cleaner I can get +#define costobject_cmp(axis) costobject_cmp##axis +#define define_costobject_cmp(axis) \ +int costobject_cmp(axis)(const CostObject *a, const CostObject *b) \ +{ \ + if(a->bb[axis] < b->bb[axis]) return -1; \ + if(a->bb[axis] > b->bb[axis]) return 1; \ + if(a->obj < b->obj) return -1; \ + if(a->obj > b->obj) return 1; \ + return 0; \ +} + +define_costobject_cmp(0) +define_costobject_cmp(1) +define_costobject_cmp(2) +define_costobject_cmp(3) +define_costobject_cmp(4) +define_costobject_cmp(5) + +void costobject_sort(CostObject *begin, CostObject *end, int axis) +{ + //TODO introsort + if(axis == 0) qsort(begin, end-begin, sizeof(*begin), (int(*)(const void *, const void *)) costobject_cmp(0)); + else if(axis == 1) qsort(begin, end-begin, sizeof(*begin), (int(*)(const void *, const void *)) costobject_cmp(1)); + else if(axis == 2) qsort(begin, end-begin, sizeof(*begin), (int(*)(const void *, const void *)) costobject_cmp(2)); + else if(axis == 3) qsort(begin, end-begin, sizeof(*begin), (int(*)(const void *, const void *)) costobject_cmp(3)); + else if(axis == 4) qsort(begin, end-begin, sizeof(*begin), (int(*)(const void *, const void *)) costobject_cmp(4)); + else if(axis == 5) qsort(begin, end-begin, sizeof(*begin), (int(*)(const void *, const void *)) costobject_cmp(5)); +} + +float bb_volume(float *min, float *max) +{ + return (max[0]-min[0])*(max[1]-min[1])*(max[2]-min[2]); +} + +float bb_area(float *min, float *max) +{ + float sub[3]; + sub[0] = max[0]-min[0]; + sub[1] = max[1]-min[1]; + sub[2] = max[2]-min[2]; + + return (sub[0]*sub[1] + sub[0]*sub[2] + sub[1]*sub[2])*2; +} + +int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) +{ + int size = rtbuild_size(b); + assert(nchilds == 2); + + if(size <= nchilds) + { + return rtbuild_mean_split_largest_axis(b, nchilds); + } + else + { + float bcost = FLT_MAX; + int i, axis, baxis, boffset; + CostObject *cost = MEM_mallocN( sizeof(CostObject)*size, "RTBuilder.HeuristicObjectSplitter" ); + float *acc_bb = MEM_mallocN( sizeof(float)*6*size, "RTBuilder.HeuristicObjectSplitterBB" ); + + for(i=0; ibegin[i]; + INIT_MINMAX(cost[i].bb, cost[i].bb+3); + RE_rayobject_merge_bb(b->begin[i], cost[i].bb, cost[i].bb+3); + } + + for(axis=0; axis<3; axis++) + { + float other_bb[6]; + + costobject_sort(cost, cost+size, axis); + for(i=size-1; i>=0; i--) + { + float *bb = acc_bb+i*6; + if(i == size-1) + { + INIT_MINMAX( bb, bb+3 ); + } + else + { + VECCOPY( bb, bb+6 ); + VECCOPY( bb+3, bb+6+3 ); + } + RE_rayobject_merge_bb( cost[i].obj, bb, bb+3 ); + } + + INIT_MINMAX(other_bb, other_bb+3); + DO_MINMAX( cost[0].bb, other_bb, other_bb+3 ); + DO_MINMAX( cost[0].bb+3, other_bb, other_bb+3 ); + + for(i=1; ibegin[i] = cost[i].obj; + + b->child_offset[0] = 0; + b->child_offset[1] = boffset; + b->child_offset[2] = size; + + MEM_freeN(acc_bb); + MEM_freeN(cost); + return nchilds; + } +} + +//Heuristic Area Splitter typedef struct CostEvent CostEvent; struct CostEvent @@ -232,24 +360,26 @@ void costevent_sort(CostEvent *begin, CostEvent *end) //TODO introsort qsort(begin, sizeof(*begin), end-begin, (int(*)(const void *, const void *)) costevent_cmp); } - /* int rtbuild_heuristic_split(RTBuilder *b, int nchilds) { - int size = rtbuild_size(b); - + int size = rtbuild_size(b); + + assert(nchilds == 2); + if(size <= nchilds) { return rtbuild_mean_split_largest_axis(b, nchilds); } else { - CostEvent *events[3], *ev[3]; + CostEvent *events, *ev; RayObject *index; int a = 0; + events = MEM_malloc( sizeof(CostEvent)*2*size, "RTBuilder.SweepSplitCostEvent" ); for(a = 0; a<3; a++) - ev[a] = events[a] = MEM_malloc( sizeof(CostEvent)*2*size, "RTBuilder.SweepSplitCostEvent" ); + for(index = b->begin; b != b->end; b++) { From 5b75ea38ff034d40a67b331b161d0ce870848ebb Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 7 Jul 2009 19:07:53 +0000 Subject: [PATCH 041/138] made rtbuild object_heuristic_spliter faster I think its something like: old was: 4*nlogn + 3*(n*6) new is: (2*nlogn + 3*(n*6)) * f, with f<1 Still missing changing the sorting function to an introsort instead of qsort Other options like bucketing sort may be worth trying (for very large trees) --- source/blender/blenkernel/BKE_utildefines.h | 8 +++ .../render/intern/include/rayobject_rtbuild.h | 2 + .../render/intern/source/rayobject_bih.c | 9 ++- .../render/intern/source/rayobject_blibvh.c | 8 +-- .../render/intern/source/rayobject_bvh.c | 5 +- .../render/intern/source/rayobject_rtbuild.c | 68 ++++++++++++++----- 6 files changed, 71 insertions(+), 29 deletions(-) diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index 419f0f5beeb..1c88b94df85 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -80,6 +80,14 @@ #define INIT_MINMAX2(min, max) { (min)[0]= (min)[1]= 1.0e30f; (max)[0]= (max)[1]= -1.0e30f; } +#define DO_MIN(vec, min) { if( (min)[0]>(vec)[0] ) (min)[0]= (vec)[0]; \ + if( (min)[1]>(vec)[1] ) (min)[1]= (vec)[1]; \ + if( (min)[2]>(vec)[2] ) (min)[2]= (vec)[2]; } \ + +#define DO_MAX(vec, max) { if( (max)[0]<(vec)[0] ) (max)[0]= (vec)[0]; \ + if( (max)[1]<(vec)[1] ) (max)[1]= (vec)[1]; \ + if( (max)[2]<(vec)[2] ) (max)[2]= (vec)[2]; } \ + #define DO_MINMAX(vec, min, max) { if( (min)[0]>(vec)[0] ) (min)[0]= (vec)[0]; \ if( (min)[1]>(vec)[1] ) (min)[1]= (vec)[1]; \ if( (min)[2]>(vec)[2] ) (min)[2]= (vec)[2]; \ diff --git a/source/blender/render/intern/include/rayobject_rtbuild.h b/source/blender/render/intern/include/rayobject_rtbuild.h index 0ead47eefca..f27005a2fa7 100644 --- a/source/blender/render/intern/include/rayobject_rtbuild.h +++ b/source/blender/render/intern/include/rayobject_rtbuild.h @@ -52,6 +52,8 @@ typedef struct RTBuilder /* child partitions calculated during splitting */ int child_offset[RTBUILD_MAX_CHILDS+1]; + + int child_sorted_axis; /* -1 if not sorted */ } RTBuilder; diff --git a/source/blender/render/intern/source/rayobject_bih.c b/source/blender/render/intern/source/rayobject_bih.c index fb755e2c7e6..e2cb9bad302 100644 --- a/source/blender/render/intern/source/rayobject_bih.c +++ b/source/blender/render/intern/source/rayobject_bih.c @@ -102,9 +102,8 @@ static void bih_free(BIHTree *obj) static void bih_bb(BIHTree *obj, float *min, float *max) { - //TODO only half operations needed - DO_MINMAX(obj->bb[0], min, max); - DO_MINMAX(obj->bb[1], min, max); + DO_MIN(obj->bb[0], min); + DO_MAX(obj->bb[1], max); } /* @@ -213,8 +212,8 @@ static BIHNode *bih_rearrange(BIHTree *tree, RTBuilder *builder, int nid, float parent->bi[i][0] = cbb[parent->split_axis]; parent->bi[i][1] = cbb[parent->split_axis+3]; - DO_MINMAX(cbb , bb, bb+3); - DO_MINMAX(cbb+3, bb, bb+3); + DO_MIN(cbb , bb); + DO_MAX(cbb+3, bb+3); } for(; ibb[0], obj->bb[1]); - DO_MINMAX(min_max+3, obj->bb[0], obj->bb[1]); + DO_MIN(min_max , obj->bb[0]); + DO_MAX(min_max+3, obj->bb[1]); BLI_bvhtree_insert(obj->bvh, (int)ob, min_max, 2 ); } @@ -135,6 +135,6 @@ static void RayObject_blibvh_free(RayObject *o) static void RayObject_blibvh_bb(RayObject *o, float *min, float *max) { BVHObject *obj = (BVHObject*)o; - DO_MINMAX( obj->bb[0], min, max ); - DO_MINMAX( obj->bb[1], min, max ); + DO_MIN( obj->bb[0], min ); + DO_MAX( obj->bb[1], max ); } diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index 82aa4c57ccb..62adcb75b7c 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -133,9 +133,8 @@ static void bvh_merge_bb(BVHNode *node, float *min, float *max) { if(RayObject_isAligned(node)) { - //TODO only half operations needed - DO_MINMAX(node->bb , min, max); - DO_MINMAX(node->bb+3, min, max); + DO_MIN(node->bb , min); + DO_MAX(node->bb+3, max); } else { diff --git a/source/blender/render/intern/source/rayobject_rtbuild.c b/source/blender/render/intern/source/rayobject_rtbuild.c index 5ed03a08f6a..688b3a920b4 100644 --- a/source/blender/render/intern/source/rayobject_rtbuild.c +++ b/source/blender/render/intern/source/rayobject_rtbuild.c @@ -19,6 +19,7 @@ static void rtbuild_init(RTBuilder *b, RayObject **begin, RayObject **end) b->begin = begin; b->end = end; b->split_axis = 0; + b->child_sorted_axis = -1; for(i=0; ichild_offset[i] = 0; @@ -46,6 +47,7 @@ void rtbuild_add(RTBuilder *b, RayObject *o) RTBuilder* rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp) { rtbuild_init( tmp, b->begin + b->child_offset[child], b->begin + b->child_offset[child+1] ); + tmp->child_sorted_axis = b->child_sorted_axis; return tmp; } @@ -254,12 +256,14 @@ float bb_volume(float *min, float *max) float bb_area(float *min, float *max) { - float sub[3]; + float sub[3], a; sub[0] = max[0]-min[0]; sub[1] = max[1]-min[1]; sub[2] = max[2]-min[2]; - return (sub[0]*sub[1] + sub[0]*sub[2] + sub[1]*sub[2])*2; + a = (sub[0]*sub[1] + sub[0]*sub[2] + sub[1]*sub[2])*2; + assert(a >= 0.0); + return a; } int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) @@ -274,7 +278,7 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) else { float bcost = FLT_MAX; - int i, axis, baxis, boffset; + int i, axis, baxis, boffset, k, try_axis[3]; CostObject *cost = MEM_mallocN( sizeof(CostObject)*size, "RTBuilder.HeuristicObjectSplitter" ); float *acc_bb = MEM_mallocN( sizeof(float)*6*size, "RTBuilder.HeuristicObjectSplitterBB" ); @@ -285,7 +289,20 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) RE_rayobject_merge_bb(b->begin[i], cost[i].bb, cost[i].bb+3); } - for(axis=0; axis<3; axis++) + if(b->child_sorted_axis >= 0 && b->child_sorted_axis < 3) + { + try_axis[0] = b->child_sorted_axis; + try_axis[1] = (b->child_sorted_axis+1)%3; + try_axis[2] = (b->child_sorted_axis+2)%3; + } + else + { + try_axis[0] = 0; + try_axis[1] = 1; + try_axis[2] = 2; + } + + for(axis=try_axis[k=0]; k<3; axis=try_axis[++k]) { float other_bb[6]; @@ -295,37 +312,54 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) float *bb = acc_bb+i*6; if(i == size-1) { - INIT_MINMAX( bb, bb+3 ); + VECCOPY(bb, cost[i].bb); + VECCOPY(bb+3, cost[i].bb+3); } else { - VECCOPY( bb, bb+6 ); - VECCOPY( bb+3, bb+6+3 ); + bb[0] = MIN2(cost[i].bb[0], bb[6+0]); + bb[1] = MIN2(cost[i].bb[1], bb[6+1]); + bb[2] = MIN2(cost[i].bb[2], bb[6+2]); + + bb[3] = MAX2(cost[i].bb[3], bb[6+3]); + bb[4] = MAX2(cost[i].bb[4], bb[6+4]); + bb[5] = MAX2(cost[i].bb[5], bb[6+5]); } - RE_rayobject_merge_bb( cost[i].obj, bb, bb+3 ); } INIT_MINMAX(other_bb, other_bb+3); - DO_MINMAX( cost[0].bb, other_bb, other_bb+3 ); - DO_MINMAX( cost[0].bb+3, other_bb, other_bb+3 ); + DO_MIN( cost[0].bb, other_bb ); + DO_MAX( cost[0].bb+3, other_bb+3 ); for(i=1; i bcost) break; //No way we can find a better heuristic in this axis + + hcost = left_side+right_side; + if( hcost < bcost + || (hcost == bcost && axis < baxis)) //this makes sure the tree built is the same whatever is the order of the sorting axis { bcost = hcost; baxis = axis; boffset = i; } - DO_MINMAX( cost[i].bb, other_bb, other_bb+3 ); - DO_MINMAX( cost[i].bb+3, other_bb, other_bb+3 ); + DO_MIN( cost[i].bb, other_bb ); + DO_MAX( cost[i].bb+3, other_bb+3 ); + } + + if(baxis == axis) + { + for(i=0; ibegin[i] = cost[i].obj; + b->child_sorted_axis = axis; } } - costobject_sort(cost, cost+size, baxis); - for(i=0; ibegin[i] = cost[i].obj; b->child_offset[0] = 0; b->child_offset[1] = boffset; From f90a0b838321cfa11cda2fd65d820a6f39a06e5c Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 8 Jul 2009 10:40:26 +0000 Subject: [PATCH 042/138] Added local stack during bvh transversal --- .../render/intern/source/rayobject_bvh.c | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index 62adcb75b7c..33821db0905 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -37,6 +37,7 @@ #include "rayobject_rtbuild.h" #include "rayobject.h" +#define DFS_STACK_SIZE 64 #define DYNAMIC_ALLOC //#define SPLIT_OVERLAP_MEAN_LONGEST_AXIS /* objects mean split on the longest axis, childs BB are allowed to overlap */ @@ -47,6 +48,7 @@ typedef struct BVHTree BVHTree; static int bvh_intersect(BVHTree *obj, Isect *isec); +static int bvh_intersect_stack(BVHTree *obj, Isect *isec); static void bvh_add(BVHTree *o, RayObject *ob); static void bvh_done(BVHTree *o); static void bvh_free(BVHTree *o); @@ -54,7 +56,11 @@ static void bvh_bb(BVHTree *o, float *min, float *max); static RayObjectAPI bvh_api = { +#ifdef DFS_STACK_SIZE + (RE_rayobject_raycast_callback) bvh_intersect_stack, +#else (RE_rayobject_raycast_callback) bvh_intersect, +#endif (RE_rayobject_add_callback) bvh_add, (RE_rayobject_done_callback) bvh_done, (RE_rayobject_free_callback) bvh_free, @@ -150,6 +156,55 @@ static void bvh_bb(BVHTree *obj, float *min, float *max) /* * Tree transverse */ +static int dfs_raycast_stack(BVHNode *root, Isect *isec) +{ + BVHNode *stack[DFS_STACK_SIZE]; + int hit = 0, stack_pos = 0; + + stack[stack_pos++] = root; + + while(stack_pos) + { + BVHNode *node = stack[--stack_pos]; + if(RayObject_isAligned(node)) + { + if(RE_rayobject_bb_intersect(isec, (const float*)node->bb) != FLT_MAX) + { + //push nodes in reverse visit order + if(isec->idot_axis[node->split_axis] < 0.0f) + { + int i; + for(i=0; ichild[i] == 0) break; + else stack[stack_pos++] = node->child[i]; + } + else + { + int i; + for(i=0; ichild[i] != 0) stack[stack_pos++] = node->child[i]; + else break; + } + assert(stack_pos <= DFS_STACK_SIZE); + } + } + else + { + hit |= RE_rayobject_intersect( (RayObject*)node, isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + } + return hit; +} + +static int bvh_intersect_stack(BVHTree *obj, Isect *isec) +{ + if(RayObject_isAligned(obj->root)) + return dfs_raycast_stack(obj->root, isec); + else + return RE_rayobject_intersect( (RayObject*)obj->root, isec); +} + static int dfs_raycast(BVHNode *node, Isect *isec) { int hit = 0; From f13d11ab712d22dc96dab594775f165eba1260ea Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 8 Jul 2009 15:34:41 +0000 Subject: [PATCH 043/138] Hint support (only for first hiearchic level and shadow rays, lets see if this is useful) That means each shadow ray tests: 1st: last hit face 2nd: last hit object 3rd: tree of all objects --- .../render/extern/include/RE_raytrace.h | 16 ++++-- .../blender/render/intern/source/rayobject.c | 45 ++++++++++++----- .../render/intern/source/rayobject_bvh.c | 50 +++++++++++++++++-- .../blender/render/intern/source/rayshade.c | 6 +++ 4 files changed, 96 insertions(+), 21 deletions(-) diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index fdd49cf1216..ce21bb1c858 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -31,7 +31,10 @@ #ifndef RE_RAYTRACE_H #define RE_RAYTRACE_H +#define RT_USE_HINT /* 1 level hint */ #define RE_RAYCOUNTER + + #ifdef RE_RAYCOUNTER typedef struct RayCounter RayCounter; @@ -42,9 +45,7 @@ struct RayCounter { unsigned long long test, hit; - } faces, bb, raycast; - - unsigned long long rayshadow_last_hit_optimization; + } faces, bb, raycast, raytrace_hint, rayshadow_last_hit; }; /* #define RE_RC_INIT(isec, shi) (isec).count = re_rc_counter+(shi).thread */ @@ -68,6 +69,9 @@ extern RayCounter re_rc_counter[]; /* Internals about raycasting structures can be found on intern/raytree.h */ typedef struct RayObject RayObject; typedef struct Isect Isect; + +typedef struct RayTraceHint RayTraceHint; + struct DerivedMesh; struct Mesh; @@ -97,7 +101,6 @@ struct Isect int bv_index[6]; float idot_axis[3]; float dist; - /* float end[3]; - not used */ @@ -107,11 +110,14 @@ struct Isect { void *ob; void *face; -/* RayObject *obj; */ } hit, orig; RayObject *last_hit; /* last hit optimization */ + +#ifdef RT_USE_HINT + RayTraceHint *hint, *hit_hint; +#endif short isect; /* which half of quad */ short mode; /* RE_RAY_SHADOW, RE_RAY_MIRROR, RE_RAY_SHADOW_TRA */ diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index e9cf46d0734..49d6e7cbefc 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -317,23 +317,34 @@ int RE_rayobject_raycast(RayObject *r, Isect *isec) /* Last hit heuristic */ - if(isec->mode==RE_RAY_SHADOW && isec->last_hit && RE_rayobject_intersect(isec->last_hit, isec)) + if(isec->mode==RE_RAY_SHADOW && isec->last_hit) { - RE_RC_COUNT(isec->raycounter->raycast.hit); - RE_RC_COUNT(isec->raycounter->rayshadow_last_hit_optimization ); - return 1; + RE_RC_COUNT(isec->raycounter->rayshadow_last_hit.test); + + if(RE_rayobject_intersect(isec->last_hit, isec)) + { + RE_RC_COUNT(isec->raycounter->raycast.hit); + RE_RC_COUNT(isec->raycounter->rayshadow_last_hit.hit); + return 1; + } } -#ifdef RE_RAYCOUNTER +#ifdef RT_USE_HINT + isec->hit_hint = 0; +#endif + if(RE_rayobject_intersect(r, isec)) { +#ifdef RE_RAYCOUNTER RE_RC_COUNT(isec->raycounter->raycast.hit); +#endif + +#ifdef RT_USE_HINT + isec->hint = isec->hit_hint; +#endif return 1; } return 0; -#else - return RE_rayobject_intersect(r, isec); -#endif } int RE_rayobject_intersect(RayObject *r, Isect *i) @@ -398,15 +409,19 @@ void RE_RC_INFO(RayCounter *info) printf("\n"); printf("Primitives tests: %llu\n", info->faces.test ); printf("Primitives hits: %llu\n", info->faces.hit ); + printf("------------------------------------\n"); + printf("Shadow last-hit tests per ray: %f\n", info->rayshadow_last_hit.test / ((float)info->raycast.test) ); + printf("Shadow last-hit hits per ray: %f\n", info->rayshadow_last_hit.hit / ((float)info->raycast.test) ); printf("\n"); - printf("Shadow Last hit reuse: %llu\n", info->rayshadow_last_hit_optimization); - printf("\n"); - printf("Primitives tests per ray: %f\n", info->faces.test / ((float)info->raycast.test) ); - printf("Primitives hits per ray: %f\n", info->faces.hit / ((float)info->raycast.test) ); + printf("Hint tests per ray: %f\n", info->raytrace_hint.test / ((float)info->raycast.test) ); + printf("Hint hits per ray: %f\n", info->raytrace_hint.hit / ((float)info->raycast.test) ); printf("\n"); printf("BB tests per ray: %f\n", info->bb.test / ((float)info->raycast.test) ); printf("BB hits per ray: %f\n", info->bb.hit / ((float)info->raycast.test) ); printf("\n"); + printf("Primitives tests per ray: %f\n", info->faces.test / ((float)info->raycast.test) ); + printf("Primitives hits per ray: %f\n", info->faces.hit / ((float)info->raycast.test) ); + printf("------------------------------------\n"); } void RE_RC_MERGE(RayCounter *dest, RayCounter *tmp) @@ -420,7 +435,11 @@ void RE_RC_MERGE(RayCounter *dest, RayCounter *tmp) dest->raycast.test += tmp->raycast.test; dest->raycast.hit += tmp->raycast.hit; - dest->rayshadow_last_hit_optimization += tmp->rayshadow_last_hit_optimization; + dest->rayshadow_last_hit.test += tmp->rayshadow_last_hit.test; + dest->rayshadow_last_hit.hit += tmp->rayshadow_last_hit.hit; + + dest->raytrace_hint.test += tmp->raytrace_hint.test; + dest->raytrace_hint.hit += tmp->raytrace_hint.hit; } #endif \ No newline at end of file diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index 33821db0905..6f3a829ce6e 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -160,6 +160,9 @@ static int dfs_raycast_stack(BVHNode *root, Isect *isec) { BVHNode *stack[DFS_STACK_SIZE]; int hit = 0, stack_pos = 0; +#ifdef RT_USE_HINT + BVHNode *last_processed_node = 0; +#endif stack[stack_pos++] = root; @@ -170,19 +173,29 @@ static int dfs_raycast_stack(BVHNode *root, Isect *isec) { if(RE_rayobject_bb_intersect(isec, (const float*)node->bb) != FLT_MAX) { + last_processed_node = node; //push nodes in reverse visit order if(isec->idot_axis[node->split_axis] < 0.0f) { int i; for(i=0; ichild[i] == 0) break; - else stack[stack_pos++] = node->child[i]; + else +#ifdef RT_USE_HINT + if(node->child[i] != (BVHNode*)isec->hint) +#endif + stack[stack_pos++] = node->child[i]; } else { int i; for(i=0; ichild[i] != 0) stack[stack_pos++] = node->child[i]; + if(node->child[i] != 0 +#ifdef RT_USE_HINT + && node->child[i] != (BVHNode*)isec->hint +#endif + ) + stack[stack_pos++] = node->child[i]; else break; } assert(stack_pos <= DFS_STACK_SIZE); @@ -190,7 +203,19 @@ static int dfs_raycast_stack(BVHNode *root, Isect *isec) } else { - hit |= RE_rayobject_intersect( (RayObject*)node, isec); + int ghit; +#ifdef RT_USE_HINT + RayTraceHint *b_hint = isec->hint; + isec->hint = 0; +#endif + ghit = RE_rayobject_intersect( (RayObject*)node, isec); + +#ifdef RT_USE_HINT + isec->hint = b_hint; + if(ghit) + isec->hit_hint = (RayTraceHint*)last_processed_node; +#endif + hit |= ghit; if(hit && isec->mode == RE_RAY_SHADOW) return hit; } } @@ -200,7 +225,26 @@ static int dfs_raycast_stack(BVHNode *root, Isect *isec) static int bvh_intersect_stack(BVHTree *obj, Isect *isec) { if(RayObject_isAligned(obj->root)) + { +#ifdef RT_USE_HINT + if(isec->hint) + { + int hit; + RE_RC_COUNT(isec->raycounter->raytrace_hint.test); + hit = dfs_raycast_stack((BVHNode*) isec->hint, isec); + if(hit) + { + RE_RC_COUNT(isec->raycounter->raytrace_hint.hit); + + if(isec->mode == RE_RAY_SHADOW) return hit; + } + else isec->hint = 0; //Clear HINT on non-hit?, that sounds good, but no tests where made + + return hit | dfs_raycast_stack(obj->root, isec); + } +#endif return dfs_raycast_stack(obj->root, isec); + } else return RE_rayobject_intersect( (RayObject*)obj->root, isec); } diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index b70e4bf5000..80ff6f6418c 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -606,6 +606,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo isec.labda = dist_mir > 0 ? dist_mir : RE_RAYTRACE_MAXDIST; isec.mode= RE_RAY_MIRROR; isec.skip = RE_SKIP_VLR_NEIGHBOUR; + isec.hint = 0; isec.orig.ob = obi; isec.orig.face = vlr; @@ -1511,6 +1512,7 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr) isec.mode= RE_RAY_MIRROR; isec.orig.ob = ship->obi; isec.orig.face = ship->vlr; + isec.hint = 0; RE_RC_INIT(isec, shi); for(a=0; a<8*8; a++) { @@ -1720,6 +1722,7 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) isec.orig.ob = shi->obi; isec.orig.face = shi->vlr; isec.skip = RE_SKIP_VLR_NEIGHBOUR; + isec.hint = 0; isec.hit.ob = 0; isec.hit.face = 0; @@ -1854,6 +1857,7 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) isec.orig.ob = shi->obi; isec.orig.face = shi->vlr; isec.skip = RE_SKIP_VLR_NEIGHBOUR; + isec.hint = 0; isec.hit.ob = 0; isec.hit.face = 0; @@ -2290,6 +2294,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) RE_RC_INIT(isec, *shi); if(shi->mat->mode & MA_SHADOW_TRA) isec.mode= RE_RAY_SHADOW_TRA; else isec.mode= RE_RAY_SHADOW; + isec.hint = 0; if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) isec.lay= lar->lay; @@ -2375,6 +2380,7 @@ static void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float /* setup isec */ RE_RC_INIT(isec, *shi); isec.mode= RE_RAY_SHADOW_TRA; + isec.hint = 0; if(lar->mode & LA_LAYER) isec.lay= lar->lay; else isec.lay= -1; From 8105454cba0be3405fc0e6fe95c979f429ed0ca4 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 8 Jul 2009 19:39:37 +0000 Subject: [PATCH 044/138] Enabled #ifdefs to test LAST_HIT, LAST_HINT Disable last_hint as it only slow downs --- source/blender/render/extern/include/RE_raytrace.h | 4 +++- source/blender/render/intern/source/rayobject.c | 5 ++++- source/blender/render/intern/source/rayobject_bvh.c | 2 ++ source/blender/render/intern/source/rayshade.c | 12 ++++++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index ce21bb1c858..7624cd09edb 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -31,7 +31,9 @@ #ifndef RE_RAYTRACE_H #define RE_RAYTRACE_H -#define RT_USE_HINT /* 1 level hint */ +#define RT_USE_LAST_HIT /* last shadow hit is reused before raycasting on whole tree */ +//#define RT_USE_HINT /* last hit object is reused before raycasting on whole tree */ + #define RE_RAYCOUNTER diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index 49d6e7cbefc..247eb952429 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -288,7 +288,9 @@ static int intersect_rayface(RayFace *face, Isect *is) is->hit.ob = face->ob; is->hit.face = face->face; +#ifdef RT_USE_LAST_HIT is->last_hit = (RayObject*) RayObject_unalignRayFace(face); +#endif return 1; } @@ -315,7 +317,7 @@ int RE_rayobject_raycast(RayObject *r, Isect *isec) isec->bv_index[2*i+1] = i+3*isec->bv_index[2*i+1]; } - +#ifdef RT_USE_LAST_HIT /* Last hit heuristic */ if(isec->mode==RE_RAY_SHADOW && isec->last_hit) { @@ -328,6 +330,7 @@ int RE_rayobject_raycast(RayObject *r, Isect *isec) return 1; } } +#endif #ifdef RT_USE_HINT isec->hit_hint = 0; diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index 6f3a829ce6e..a5158d96acc 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -173,7 +173,9 @@ static int dfs_raycast_stack(BVHNode *root, Isect *isec) { if(RE_rayobject_bb_intersect(isec, (const float*)node->bb) != FLT_MAX) { +#ifdef RT_USE_HINT last_processed_node = node; +#endif //push nodes in reverse visit order if(isec->idot_axis[node->split_axis] < 0.0f) { diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 80ff6f6418c..977cba75f55 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -606,7 +606,9 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo isec.labda = dist_mir > 0 ? dist_mir : RE_RAYTRACE_MAXDIST; isec.mode= RE_RAY_MIRROR; isec.skip = RE_SKIP_VLR_NEIGHBOUR; +#ifdef RT_USE_HINT isec.hint = 0; +#endif isec.orig.ob = obi; isec.orig.face = vlr; @@ -1512,7 +1514,9 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr) isec.mode= RE_RAY_MIRROR; isec.orig.ob = ship->obi; isec.orig.face = ship->vlr; +#ifdef RT_USE_HINT isec.hint = 0; +#endif RE_RC_INIT(isec, shi); for(a=0; a<8*8; a++) { @@ -1722,7 +1726,9 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) isec.orig.ob = shi->obi; isec.orig.face = shi->vlr; isec.skip = RE_SKIP_VLR_NEIGHBOUR; +#ifdef RT_USE_HINT isec.hint = 0; +#endif isec.hit.ob = 0; isec.hit.face = 0; @@ -1857,7 +1863,9 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) isec.orig.ob = shi->obi; isec.orig.face = shi->vlr; isec.skip = RE_SKIP_VLR_NEIGHBOUR; +#ifdef RT_USE_HINT isec.hint = 0; +#endif isec.hit.ob = 0; isec.hit.face = 0; @@ -2294,7 +2302,9 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) RE_RC_INIT(isec, *shi); if(shi->mat->mode & MA_SHADOW_TRA) isec.mode= RE_RAY_SHADOW_TRA; else isec.mode= RE_RAY_SHADOW; +#ifdef RT_USE_HINT isec.hint = 0; +#endif if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) isec.lay= lar->lay; @@ -2380,7 +2390,9 @@ static void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float /* setup isec */ RE_RC_INIT(isec, *shi); isec.mode= RE_RAY_SHADOW_TRA; +#ifdef RT_USE_HINT isec.hint = 0; +#endif if(lar->mode & LA_LAYER) isec.lay= lar->lay; else isec.lay= -1; From 85f6c108aca9f86fb5e219ade03e15791bb822e8 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 8 Jul 2009 20:04:40 +0000 Subject: [PATCH 045/138] *Added support for variable cost per RayObject Suposedly usefull for creating trees of objects (where objects have very diferent size-NumFaces and shape-BB) Altought the implemented costs maybe not be very correct (for now), as i didnt cared about following a specific "corrected" model --- .../blender/render/intern/include/rayobject.h | 11 +++++++- .../render/intern/include/rayobject_rtbuild.h | 3 +++ .../blender/render/intern/source/rayobject.c | 14 ++++++++++ .../render/intern/source/rayobject_bvh.c | 26 +++++++++++++++---- .../render/intern/source/rayobject_rtbuild.c | 22 +++++++++++++--- 5 files changed, 66 insertions(+), 10 deletions(-) diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index c611e2ceca2..de36a1e4888 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -86,11 +86,13 @@ struct RayObject }; + typedef int (*RE_rayobject_raycast_callback)(RayObject *, Isect *); -typedef void (*RE_rayobject_add_callback)(RayObject *, RayObject *); +typedef void (*RE_rayobject_add_callback)(RayObject *raytree, RayObject *rayobject); typedef void (*RE_rayobject_done_callback)(RayObject *); typedef void (*RE_rayobject_free_callback)(RayObject *); typedef void (*RE_rayobject_merge_bb_callback)(RayObject *, float *min, float *max); +typedef float (*RE_rayobject_cost_callback)(RayObject *); typedef struct RayObjectAPI { @@ -99,6 +101,7 @@ typedef struct RayObjectAPI RE_rayobject_done_callback done; RE_rayobject_free_callback free; RE_rayobject_merge_bb_callback bb; + RE_rayobject_cost_callback cost; } RayObjectAPI; @@ -128,6 +131,12 @@ int RE_rayobject_intersect(RayObject *r, Isect *i); */ float RE_rayobject_bb_intersect(const Isect *i, const float *bb); +/* + * Returns the expected cost of raycast on this node, primitives have a cost of 1 + */ +float RE_rayobject_cost(RayObject *r); + + #define ISECT_EPSILON ((float)FLT_EPSILON) diff --git a/source/blender/render/intern/include/rayobject_rtbuild.h b/source/blender/render/intern/include/rayobject_rtbuild.h index f27005a2fa7..6fef18433b9 100644 --- a/source/blender/render/intern/include/rayobject_rtbuild.h +++ b/source/blender/render/intern/include/rayobject_rtbuild.h @@ -80,4 +80,7 @@ int rtbuild_median_split(RTBuilder *b, float *separators, int nchilds, int axis) int rtbuild_median_split_largest_axis(RTBuilder *b, int nchilds); +/* bb utils */ +float bb_area(float *min, float *max); + #endif diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index 247eb952429..949b7afb5a0 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -400,6 +400,20 @@ void RE_rayobject_merge_bb(RayObject *r, float *min, float *max) else assert(0); } +float RE_rayobject_cost(RayObject *r) +{ + if(RayObject_isRayFace(r)) + { + return 1.0; + } + else if(RayObject_isRayAPI(r)) + { + r = RayObject_align( r ); + return r->api->cost( r ); + } + else assert(0); +} + #ifdef RE_RAYCOUNTER void RE_RC_INFO(RayCounter *info) { diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index a5158d96acc..d0e0e8b6dc5 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -53,6 +53,7 @@ static void bvh_add(BVHTree *o, RayObject *ob); static void bvh_done(BVHTree *o); static void bvh_free(BVHTree *o); static void bvh_bb(BVHTree *o, float *min, float *max); +static float bvh_cost(BVHTree *o); static RayObjectAPI bvh_api = { @@ -64,7 +65,8 @@ static RayObjectAPI bvh_api = (RE_rayobject_add_callback) bvh_add, (RE_rayobject_done_callback) bvh_done, (RE_rayobject_free_callback) bvh_free, - (RE_rayobject_merge_bb_callback)bvh_bb + (RE_rayobject_merge_bb_callback)bvh_bb, + (RE_rayobject_cost_callback) bvh_cost }; typedef struct BVHNode BVHNode; @@ -91,6 +93,7 @@ struct BVHTree BVHNode *node_alloc, *node_next; float *bb_alloc, *bb_next; #endif + float cost; RTBuilder *builder; }; @@ -153,6 +156,12 @@ static void bvh_bb(BVHTree *obj, float *min, float *max) bvh_merge_bb(obj->root, min, max); } +static float bvh_cost(BVHTree *obj) +{ + assert(obj->cost >= 0.0); + return obj->cost; +} + /* * Tree transverse */ @@ -336,8 +345,9 @@ static int child_id(int pid, int nchild) return pid*BVH_NCHILDS+(2-BVH_NCHILDS)+nchild; } -static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid) +static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid, float *cost) { + *cost = 0; if(rtbuild_size(builder) == 0) return 0; @@ -361,6 +371,7 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid) for(; ichild[i] = 0; + *cost = bb_area(parent->bb, parent->bb+3)*RE_rayobject_cost(child); return parent; } else @@ -368,6 +379,8 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid) assert(!RayObject_isAligned(child)); //Its a sub-raytrace structure, assume it has it own raycast //methods and adding a Bounding Box arround is unnecessary + + *cost = RE_rayobject_cost(child); return (BVHNode*)child; } } @@ -392,12 +405,16 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid) parent->split_axis = builder->split_axis; for(i=0; ichild[i] = bvh_rearrange( tree, rtbuild_get_child(builder, i, &tmp), child_id(nid,i) ); + float tcost; + parent->child[i] = bvh_rearrange( tree, rtbuild_get_child(builder, i, &tmp), child_id(nid,i), &tcost ); bvh_merge_bb(parent->child[i], parent->bb, parent->bb+3); + + *cost += tcost; } for(; ichild[i] = 0; + *cost *= bb_area(parent->bb, parent->bb+3); return parent; } } @@ -412,7 +429,6 @@ static void bvh_info(BVHTree *obj) static void bvh_done(BVHTree *obj) { - #ifdef DYNAMIC_ALLOC int needed_nodes = (rtbuild_size(obj->builder)+1)*2; if(needed_nodes > BLI_MEMARENA_STD_BUFSIZE) @@ -437,7 +453,7 @@ static void bvh_done(BVHTree *obj) obj->bb_next = obj->bb_alloc; #endif - obj->root = bvh_rearrange( obj, obj->builder, 1 ); + obj->root = bvh_rearrange( obj, obj->builder, 1, &obj->cost ); #ifndef DYNAMIC_ALLOC assert(obj->node_alloc+needed_nodes >= obj->node_next); diff --git a/source/blender/render/intern/source/rayobject_rtbuild.c b/source/blender/render/intern/source/rayobject_rtbuild.c index 688b3a920b4..2d5afe28600 100644 --- a/source/blender/render/intern/source/rayobject_rtbuild.c +++ b/source/blender/render/intern/source/rayobject_rtbuild.c @@ -216,6 +216,7 @@ typedef struct CostObject CostObject; struct CostObject { RayObject *obj; + float cost; float bb[6]; }; @@ -278,6 +279,7 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) else { float bcost = FLT_MAX; + float childrens_cost = 0; int i, axis, baxis, boffset, k, try_axis[3]; CostObject *cost = MEM_mallocN( sizeof(CostObject)*size, "RTBuilder.HeuristicObjectSplitter" ); float *acc_bb = MEM_mallocN( sizeof(float)*6*size, "RTBuilder.HeuristicObjectSplitterBB" ); @@ -286,12 +288,14 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) { cost[i].obj = b->begin[i]; INIT_MINMAX(cost[i].bb, cost[i].bb+3); - RE_rayobject_merge_bb(b->begin[i], cost[i].bb, cost[i].bb+3); + RE_rayobject_merge_bb(cost[i].obj, cost[i].bb, cost[i].bb+3); + cost[i].cost = RE_rayobject_cost(cost[i].obj); + childrens_cost += cost[i].cost; } if(b->child_sorted_axis >= 0 && b->child_sorted_axis < 3) { - try_axis[0] = b->child_sorted_axis; + try_axis[0] = b->child_sorted_axis; try_axis[1] = (b->child_sorted_axis+1)%3; try_axis[2] = (b->child_sorted_axis+2)%3; } @@ -304,8 +308,11 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) for(axis=try_axis[k=0]; k<3; axis=try_axis[++k]) { + float left_cost, right_cost; float other_bb[6]; + + costobject_sort(cost, cost+size, axis); for(i=size-1; i>=0; i--) { @@ -330,18 +337,22 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) INIT_MINMAX(other_bb, other_bb+3); DO_MIN( cost[0].bb, other_bb ); DO_MAX( cost[0].bb+3, other_bb+3 ); + left_cost = cost[0].cost; + right_cost = childrens_cost-cost[0].cost; + if(right_cost < 0) right_cost = 0; for(i=1; i bcost) break; //No way we can find a better heuristic in this axis hcost = left_side+right_side; + assert(hcost >= 0); if( hcost < bcost || (hcost == bcost && axis < baxis)) //this makes sure the tree built is the same whatever is the order of the sorting axis { @@ -351,6 +362,9 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) } DO_MIN( cost[i].bb, other_bb ); DO_MAX( cost[i].bb+3, other_bb+3 ); + left_cost += cost[i].cost; + right_cost -= cost[i].cost; + if(right_cost < 0.0f) right_cost = 0.0; } if(baxis == axis) From 2e4b9f3be4c362ab6f2bb5135c6479ee8b06817d Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 8 Jul 2009 21:56:24 +0000 Subject: [PATCH 046/138] *set cost of transversing a BVH as log(size) --- source/blender/render/intern/source/rayobject_bvh.c | 9 +++++++-- source/blender/render/intern/source/rayobject_rtbuild.c | 8 +++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index d0e0e8b6dc5..40719a15f0e 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -28,6 +28,7 @@ */ #include #include +#include #include "MEM_guardedalloc.h" #include "BKE_utildefines.h" @@ -37,6 +38,7 @@ #include "rayobject_rtbuild.h" #include "rayobject.h" +#define RAY_BB_TEST_COST (0.2f) #define DFS_STACK_SIZE 64 #define DYNAMIC_ALLOC @@ -371,7 +373,7 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid, float for(; ichild[i] = 0; - *cost = bb_area(parent->bb, parent->bb+3)*RE_rayobject_cost(child); + *cost = RE_rayobject_cost(child)+RAY_BB_TEST_COST; return parent; } else @@ -414,7 +416,8 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid, float for(; ichild[i] = 0; - *cost *= bb_area(parent->bb, parent->bb+3); + *cost /= nc*bb_area(parent->bb, parent->bb+3); + *cost += RAY_BB_TEST_COST; return parent; } } @@ -454,6 +457,8 @@ static void bvh_done(BVHTree *obj) #endif obj->root = bvh_rearrange( obj, obj->builder, 1, &obj->cost ); +// obj->cost = 1.0; + obj->cost = logf( rtbuild_size( obj->builder ) ); #ifndef DYNAMIC_ALLOC assert(obj->node_alloc+needed_nodes >= obj->node_next); diff --git a/source/blender/render/intern/source/rayobject_rtbuild.c b/source/blender/render/intern/source/rayobject_rtbuild.c index 2d5afe28600..46140d3d24d 100644 --- a/source/blender/render/intern/source/rayobject_rtbuild.c +++ b/source/blender/render/intern/source/rayobject_rtbuild.c @@ -280,7 +280,7 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) { float bcost = FLT_MAX; float childrens_cost = 0; - int i, axis, baxis, boffset, k, try_axis[3]; + int i, axis, baxis = -1, boffset = size/2, k, try_axis[3]; CostObject *cost = MEM_mallocN( sizeof(CostObject)*size, "RTBuilder.HeuristicObjectSplitter" ); float *acc_bb = MEM_mallocN( sizeof(float)*6*size, "RTBuilder.HeuristicObjectSplitterBB" ); @@ -346,8 +346,8 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) //Worst case heuristic (cost of each child is linear) float hcost, left_side, right_side; - left_side = bb_area(other_bb, other_bb+3)*left_cost; //(i+logf(i)); - right_side= bb_area(acc_bb+i*6, acc_bb+i*6+3)*right_cost; //(size-i+logf(size-i)); + left_side = bb_area(other_bb, other_bb+3)*(left_cost+logf(i)); + right_side= bb_area(acc_bb+i*6, acc_bb+i*6+3)*(right_cost+logf(i)); if(left_side > bcost) break; //No way we can find a better heuristic in this axis @@ -373,6 +373,8 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) b->begin[i] = cost[i].obj; b->child_sorted_axis = axis; } + + assert(baxis >= 0 && baxis < 3); } b->child_offset[0] = 0; From b60bfd613edfc23de848d0f4c37faeff8c85ad23 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 10 Jul 2009 15:33:35 +0000 Subject: [PATCH 047/138] Cost of a BVH is calculated using SA(child)/SA(parent) Although tests didnt showed this to be clearly superior to: cost(bvh) = log(size) --- .../blender/render/intern/source/rayobject_bvh.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index 40719a15f0e..1622851edfc 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -407,17 +407,22 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid, float parent->split_axis = builder->split_axis; for(i=0; ichild[i] = bvh_rearrange( tree, rtbuild_get_child(builder, i, &tmp), child_id(nid,i), &tcost ); - bvh_merge_bb(parent->child[i], parent->bb, parent->bb+3); - *cost += tcost; + INIT_MINMAX(cbb, cbb+3); + bvh_merge_bb(parent->child[i], cbb, cbb+3); + DO_MIN(cbb, parent->bb); + DO_MAX(cbb+3, parent->bb+3); + + *cost += tcost*bb_area(cbb, cbb+3); } for(; ichild[i] = 0; - *cost /= nc*bb_area(parent->bb, parent->bb+3); - *cost += RAY_BB_TEST_COST; + *cost /= bb_area(parent->bb, parent->bb+3); + *cost += nc*RAY_BB_TEST_COST; return parent; } } @@ -458,7 +463,7 @@ static void bvh_done(BVHTree *obj) obj->root = bvh_rearrange( obj, obj->builder, 1, &obj->cost ); // obj->cost = 1.0; - obj->cost = logf( rtbuild_size( obj->builder ) ); +// obj->cost = logf( rtbuild_size( obj->builder ) ); #ifndef DYNAMIC_ALLOC assert(obj->node_alloc+needed_nodes >= obj->node_next); From c43fe4cca969e4f4755b041d3e1bc6aee322517f Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 10 Jul 2009 15:43:59 +0000 Subject: [PATCH 048/138] Should improve mirror rays (copy past error: was losing dive first heuristic sometimes) --- source/blender/render/intern/source/rayobject_bvh.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c index 1622851edfc..181456c2b4d 100644 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ b/source/blender/render/intern/source/rayobject_bvh.c @@ -202,14 +202,13 @@ static int dfs_raycast_stack(BVHNode *root, Isect *isec) else { int i; - for(i=0; i=0; i--) if(node->child[i] != 0 #ifdef RT_USE_HINT && node->child[i] != (BVHNode*)isec->hint #endif ) stack[stack_pos++] = node->child[i]; - else break; } assert(stack_pos <= DFS_STACK_SIZE); } From 81c356151345e99d7ae0968be1f6242cd3c6fce1 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 10 Jul 2009 16:42:51 +0000 Subject: [PATCH 049/138] *rtbuild now stores BB *fix in ray/bb hit tests inside instances --- .../render/intern/include/rayobject_rtbuild.h | 5 + .../render/intern/source/rayobject_instance.c | 39 ++- .../render/intern/source/rayobject_rtbuild.c | 224 +++++++----------- 3 files changed, 121 insertions(+), 147 deletions(-) diff --git a/source/blender/render/intern/include/rayobject_rtbuild.h b/source/blender/render/intern/include/rayobject_rtbuild.h index 6fef18433b9..a98ed38a581 100644 --- a/source/blender/render/intern/include/rayobject_rtbuild.h +++ b/source/blender/render/intern/include/rayobject_rtbuild.h @@ -54,6 +54,8 @@ typedef struct RTBuilder int child_offset[RTBUILD_MAX_CHILDS+1]; int child_sorted_axis; /* -1 if not sorted */ + + float bb[6]; } RTBuilder; @@ -61,6 +63,7 @@ typedef struct RTBuilder RTBuilder* rtbuild_create(int size); void rtbuild_free(RTBuilder *b); void rtbuild_add(RTBuilder *b, RayObject *o); +void rtbuild_merge_bb(RTBuilder *b, float *min, float *max); int rtbuild_size(RTBuilder *b); /* used during tree reorganization */ @@ -82,5 +85,7 @@ int rtbuild_median_split_largest_axis(RTBuilder *b, int nchilds); /* bb utils */ float bb_area(float *min, float *max); +float bb_volume(float *min, float *max); +int bb_largest_axis(float *min, float *max); #endif diff --git a/source/blender/render/intern/source/rayobject_instance.c b/source/blender/render/intern/source/rayobject_instance.c index 4a67e8108cb..14f333a7f86 100644 --- a/source/blender/render/intern/source/rayobject_instance.c +++ b/source/blender/render/intern/source/rayobject_instance.c @@ -34,9 +34,12 @@ #include "RE_raytrace.h" #include "rayobject.h" +#define RE_COST_INSTANCE (1.0f) + static int RayObject_instance_intersect(RayObject *o, Isect *isec); static void RayObject_instance_free(RayObject *o); static void RayObject_instance_bb(RayObject *o, float *min, float *max); +static float RayObject_instance_cost(RayObject *o); static RayObjectAPI instance_api = { @@ -44,7 +47,8 @@ static RayObjectAPI instance_api = NULL, //static void RayObject_instance_add(RayObject *o, RayObject *ob); NULL, //static void RayObject_instance_done(RayObject *o); RayObject_instance_free, - RayObject_instance_bb + RayObject_instance_bb, + RayObject_instance_cost }; typedef struct InstanceRayObject @@ -85,7 +89,7 @@ static int RayObject_instance_intersect(RayObject *o, Isect *isec) InstanceRayObject *obj = (InstanceRayObject*)o; int res; float start[3], vec[3], labda, dist; - int changed = 0; + int changed = 0, i; //TODO - this is disabling self intersection on instances if(isec->orig.ob == obj->ob && obj->ob) @@ -111,6 +115,18 @@ static int RayObject_instance_intersect(RayObject *o, Isect *isec) isec->labda *= isec->dist / dist; + //Update idot_axis and bv_index + for(i=0; i<3; i++) + { + isec->idot_axis[i] = 1.0f / isec->vec[i]; + + isec->bv_index[2*i] = isec->idot_axis[i] < 0.0 ? 1 : 0; + isec->bv_index[2*i+1] = 1 - isec->bv_index[2*i]; + + isec->bv_index[2*i] = i+3*isec->bv_index[2*i]; + isec->bv_index[2*i+1] = i+3*isec->bv_index[2*i+1]; + } + //Raycast res = RE_rayobject_intersect(obj->target, isec); @@ -118,7 +134,6 @@ static int RayObject_instance_intersect(RayObject *o, Isect *isec) if(res == 0) { isec->labda = labda; - } else { @@ -131,6 +146,18 @@ static int RayObject_instance_intersect(RayObject *o, Isect *isec) if(changed) isec->orig.ob = obj->ob; + + //Update idot_axis and bv_index + for(i=0; i<3; i++) + { + isec->idot_axis[i] = 1.0f / isec->vec[i]; + + isec->bv_index[2*i] = isec->idot_axis[i] < 0.0 ? 1 : 0; + isec->bv_index[2*i+1] = 1 - isec->bv_index[2*i]; + + isec->bv_index[2*i] = i+3*isec->bv_index[2*i]; + isec->bv_index[2*i+1] = i+3*isec->bv_index[2*i+1]; + } return res; } @@ -141,6 +168,12 @@ static void RayObject_instance_free(RayObject *o) MEM_freeN(obj); } +static float RayObject_instance_cost(RayObject *o) +{ + InstanceRayObject *obj = (InstanceRayObject*)o; + return RE_rayobject_cost(obj->target) + RE_COST_INSTANCE; +} + static void RayObject_instance_bb(RayObject *o, float *min, float *max) { //TODO: diff --git a/source/blender/render/intern/source/rayobject_rtbuild.c b/source/blender/render/intern/source/rayobject_rtbuild.c index 46140d3d24d..3c301ce1f9f 100644 --- a/source/blender/render/intern/source/rayobject_rtbuild.c +++ b/source/blender/render/intern/source/rayobject_rtbuild.c @@ -11,7 +11,6 @@ static int partition_nth_element(RTBuilder *b, int _begin, int _end, int n); static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis); static int split_leafs_by_plane(RTBuilder *b, int begin, int end, float plane); - static void rtbuild_init(RTBuilder *b, RayObject **begin, RayObject **end) { int i; @@ -23,6 +22,8 @@ static void rtbuild_init(RTBuilder *b, RayObject **begin, RayObject **end) for(i=0; ichild_offset[i] = 0; + + INIT_MINMAX(b->bb, b->bb+3); } RTBuilder* rtbuild_create(int size) @@ -44,6 +45,36 @@ void rtbuild_add(RTBuilder *b, RayObject *o) *(b->end++) = o; } +void rtbuild_calc_bb(RTBuilder *b) +{ + if(b->bb[0] == 1.0e30f) + { + RayObject **index = b->begin; + for(; index != b->end; index++) + RE_rayobject_merge_bb(*index, b->bb, b->bb+3); + } +} + +void rtbuild_merge_bb(RTBuilder *b, float *min, float *max) +{ + rtbuild_calc_bb(b); + DO_MIN(b->bb, min); + DO_MAX(b->bb+3, max); +} + +int rtbuild_get_largest_axis(RTBuilder *b) +{ + rtbuild_calc_bb(b); + return bb_largest_axis(b->bb, b->bb+3); +} + + +int rtbuild_size(RTBuilder *b) +{ + return b->end - b->begin; +} + + RTBuilder* rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp) { rtbuild_init( tmp, b->begin + b->child_offset[child], b->begin + b->child_offset[child+1] ); @@ -51,59 +82,8 @@ RTBuilder* rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp) return tmp; } -int rtbuild_size(RTBuilder *b) -{ - return b->end - b->begin; -} - -/* Split methods */ -static void merge_bb(RTBuilder *b, float *min, float *max) -{ - RayObject **index = b->begin; - - for(; index != b->end; index++) - RE_rayobject_merge_bb(*index, min, max); -} - -static int largest_axis(float *min, float *max) -{ - float sub[3]; - - sub[0] = max[0]-min[0]; - sub[1] = max[1]-min[1]; - sub[2] = max[2]-min[2]; - if(sub[0] > sub[1]) - { - if(sub[0] > sub[2]) - return 0; - else - return 2; - } - else - { - if(sub[1] > sub[2]) - return 1; - else - return 2; - } -} - -int rtbuild_get_largest_axis(RTBuilder *b) -{ - float min[3], max[3]; - - INIT_MINMAX(min, max); - merge_bb( b, min, max); - - return largest_axis(min,max); -} -/* -int rtbuild_median_split(RTBuilder *b, int nchilds, int axis) -{ -} -*/ //Left balanced tree int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis) { @@ -199,14 +179,12 @@ int rtbuild_median_split_largest_axis(RTBuilder *b, int nchilds) { int la, i; float separators[RTBUILD_MAX_CHILDS]; - float min[3], max[3]; + + rtbuild_calc_bb(b); - INIT_MINMAX(min, max); - merge_bb( b, min, max); - - la = largest_axis(min,max); + la = bb_largest_axis(b->bb,b->bb+3); for(i=1; ibb[la+3]-b->bb[la])*i / nchilds; return rtbuild_median_split(b, separators, nchilds, la); } @@ -250,23 +228,9 @@ void costobject_sort(CostObject *begin, CostObject *end, int axis) else if(axis == 5) qsort(begin, end-begin, sizeof(*begin), (int(*)(const void *, const void *)) costobject_cmp(5)); } -float bb_volume(float *min, float *max) -{ - return (max[0]-min[0])*(max[1]-min[1])*(max[2]-min[2]); -} -float bb_area(float *min, float *max) -{ - float sub[3], a; - sub[0] = max[0]-min[0]; - sub[1] = max[1]-min[1]; - sub[2] = max[2]-min[2]; - - a = (sub[0]*sub[1] + sub[0]*sub[2] + sub[1]*sub[2])*2; - assert(a >= 0.0); - return a; -} +/* Object Surface Area Heuristic splitter */ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) { int size = rtbuild_size(b); @@ -387,77 +351,6 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) } } -//Heuristic Area Splitter -typedef struct CostEvent CostEvent; - -struct CostEvent -{ - float key; - float value; -}; - -int costevent_cmp(const CostEvent *a, const CostEvent *b) -{ - if(a->key < b->key) return -1; - if(a->key > b->key) return 1; - if(a->value < b->value) return -1; - if(a->value > b->value) return 1; - return 0; -} - -void costevent_sort(CostEvent *begin, CostEvent *end) -{ - //TODO introsort - qsort(begin, sizeof(*begin), end-begin, (int(*)(const void *, const void *)) costevent_cmp); -} -/* -int rtbuild_heuristic_split(RTBuilder *b, int nchilds) -{ - int size = rtbuild_size(b); - - assert(nchilds == 2); - - if(size <= nchilds) - { - return rtbuild_mean_split_largest_axis(b, nchilds); - } - else - { - CostEvent *events, *ev; - RayObject *index; - int a = 0; - - events = MEM_malloc( sizeof(CostEvent)*2*size, "RTBuilder.SweepSplitCostEvent" ); - for(a = 0; a<3; a++) - - - for(index = b->begin; b != b->end; b++) - { - float min[3], max[3]; - INIT_MINMAX(min, max); - RE_rayobject_merge_bb(index, min, max); - for(a = 0; a<3; a++) - { - ev[a]->key = min[a]; - ev[a]->value = 1; - ev[a]++; - - ev[a]->key = max[a]; - ev[a]->value = -1; - ev[a]++; - } - } - for(a = 0; a<3; a++) - costevent_sort(events[a], ev[a]); - - - - for(a = 0; a<3; a++) - MEM_freeN(ev[a]); - } -} -*/ - /* * Helper code * PARTITION code / used on mean-split @@ -593,3 +486,46 @@ static int split_leafs_by_plane(RTBuilder *b, int begin, int end, float plane) } return begin; } + +/* + * Bounding Box utils + */ +float bb_volume(float *min, float *max) +{ + return (max[0]-min[0])*(max[1]-min[1])*(max[2]-min[2]); +} + +float bb_area(float *min, float *max) +{ + float sub[3], a; + sub[0] = max[0]-min[0]; + sub[1] = max[1]-min[1]; + sub[2] = max[2]-min[2]; + + a = (sub[0]*sub[1] + sub[0]*sub[2] + sub[1]*sub[2])*2; + assert(a >= 0.0); + return a; +} + +int bb_largest_axis(float *min, float *max) +{ + float sub[3]; + + sub[0] = max[0]-min[0]; + sub[1] = max[1]-min[1]; + sub[2] = max[2]-min[2]; + if(sub[0] > sub[1]) + { + if(sub[0] > sub[2]) + return 0; + else + return 2; + } + else + { + if(sub[1] > sub[2]) + return 1; + else + return 2; + } +} From 9a23287fd8062674ad58829b9e58bb2b3e982f23 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 10 Jul 2009 17:41:49 +0000 Subject: [PATCH 050/138] SUN and HEMI lights back as trunk (i think) --- .../render/intern/include/render_types.h | 1 + .../blender/render/intern/source/rayshade.c | 94 +++++++++---------- 2 files changed, 46 insertions(+), 49 deletions(-) diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 88bf30bd9ef..c412921eb31 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -172,6 +172,7 @@ struct Render /* octree tables and variables for raytrace */ struct RayObject *raytree; struct RayFace *rayfaces; + float maxdist; /* needed for keeping an incorrect behaviour of SUN and HEMI lights (avoid breaking old scenes) */ /* occlusion tree */ void *occlusiontree; diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 977cba75f55..b967f2bd8ce 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -348,6 +348,8 @@ static void makeraytree_single(Render *re) void makeraytree(Render *re) { + float min[3], max[3], sub[3]; + int i; const char *tree_type = "Tree(unknown)"; #ifdef RE_RAYCOUNTER @@ -372,6 +374,18 @@ void makeraytree(Render *re) BENCH(makeraytree_single(re), tree_build); else BENCH(makeraytree_hier(re), tree_build); + + + //Calculate raytree max_size + //This is ONLY needed to kept a bogus behaviour of SUN and HEMI lights + RE_rayobject_merge_bb( re->raytree, min, max ); + for(i=0; i<3; i++) + { + min[i] += 0.01f; + max[i] += 0.01f; + sub[i] = max[i]-min[i]; + } + re->maxdist = sqrt( sub[0]*sub[0] + sub[1]*sub[1] + sub[2]*sub[2] ); } @@ -2029,7 +2043,7 @@ static void ray_shadow_jittered_coords(ShadeInput *shi, int max, float jitco[RE_ } } -static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, int lampvec, float *shadfac, Isect *isec) +static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *shadfac, Isect *isec) { QMCSampler *qsa=NULL; int samples=0; @@ -2135,20 +2149,10 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, int lam } VECCOPY(isec->start, co); - if(lampvec) - { - isec->vec[0] = end[0]; - isec->vec[1] = end[1]; - isec->vec[2] = end[2]; - isec->labda = RE_RAYTRACE_MAXDIST; - } - else - { - isec->vec[0] = end[0]-isec->start[0]; - isec->vec[1] = end[1]-isec->start[1]; - isec->vec[2] = end[2]-isec->start[2]; - isec->labda = 1.0f; // * Normalize(isec->vec); - } + isec->vec[0] = end[0]-isec->start[0]; + isec->vec[1] = end[1]-isec->start[1]; + isec->vec[2] = end[2]-isec->start[2]; + isec->labda = 1.0f; // * Normalize(isec->vec); /* trace the ray */ if(isec->mode==RE_RAY_SHADOW_TRA) { @@ -2201,7 +2205,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, int lam release_thread_qmcsampler(&R, shi->thread, qsa); } -static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, int lampvec, float *shadfac, Isect *isec) +static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, float *shadfac, Isect *isec) { /* area soft shadow */ float *jitlamp; @@ -2243,21 +2247,11 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, int Mat3MulVecfl(lar->mat, vec); /* set start and vec */ - VECCOPY(isec->start, shi->co); - if(lampvec) - { - isec->vec[0] = vec[0]+lampco[0]; - isec->vec[1] = vec[1]+lampco[1]; - isec->vec[2] = vec[2]+lampco[2]; - isec->labda = RE_RAYTRACE_MAXDIST; - } - else - { - isec->vec[0] = vec[0]+lampco[0]-shi->co[0]; - isec->vec[1] = vec[1]+lampco[1]-shi->co[1]; - isec->vec[2] = vec[2]+lampco[2]-shi->co[2]; - isec->labda = 1.0f; - } + VECCOPY(isec->start, shi->co); + isec->vec[0] = vec[0]+lampco[0]-shi->co[0]; + isec->vec[1] = vec[1]+lampco[1]-shi->co[1]; + isec->vec[2] = vec[2]+lampco[2]-shi->co[2]; + isec->labda = 1.0f; isec->skip = RE_SKIP_VLR_NEIGHBOUR; if(isec->mode==RE_RAY_SHADOW_TRA) { @@ -2296,7 +2290,6 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) { Isect isec; float lampco[3]; - int lampvec; /* indicates if lampco is a vector lamp */ /* setup isec */ RE_RC_INIT(isec, *shi); @@ -2320,19 +2313,30 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) } if(lar->type==LA_SUN || lar->type==LA_HEMI) { - lampco[0]= -lar->vec[0]; - lampco[1]= -lar->vec[1]; - lampco[2]= -lar->vec[2]; - lampvec = 1; + /* jitter and QMC sampling add a displace vector to the lamp position + * that's incorrect because a SUN lamp does not has an exact position + * and the displace should be done at the ray vector instead of the + * lamp position. + * This is easily verified by noticing that shadows of SUN lights change + * with the scene BB. + * + * This was detected during SoC 2009 - Raytrace Optimization, but to keep + * consistency with older render code it wasn't removed. + * + * If the render code goes through some recode/serious bug-fix then this + * is something to consider! + */ + lampco[0]= shi->co[0] - R.maxdist*lar->vec[0]; + lampco[1]= shi->co[1] - R.maxdist*lar->vec[1]; + lampco[2]= shi->co[2] - R.maxdist*lar->vec[2]; } else { VECCOPY(lampco, lar->co); - lampvec = 0; } if (ELEM(lar->ray_samp_method, LA_SAMP_HALTON, LA_SAMP_HAMMERSLEY)) { - ray_shadow_qmc(shi, lar, lampco, lampvec, shadfac, &isec); + ray_shadow_qmc(shi, lar, lampco, shadfac, &isec); } else { if(lar->ray_totsamp<2) { @@ -2344,16 +2348,8 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) /* set up isec vec */ VECCOPY(isec.start, shi->co); - if(lampvec) - { - VECCOPY(isec.vec, lampco); - isec.labda = RE_RAYTRACE_MAXDIST; - } - else - { - VECSUB(isec.vec, lampco, isec.start); - isec.labda = 1.0f; - } + VECSUB(isec.vec, lampco, isec.start); + isec.labda = 1.0f; if(isec.mode==RE_RAY_SHADOW_TRA) { /* isec.col is like shadfac, so defines amount of light (0.0 is full shadow) */ @@ -2367,7 +2363,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) shadfac[3]= 0.0f; } else { - ray_shadow_jitter(shi, lar, lampco, lampvec, shadfac, &isec); + ray_shadow_jitter(shi, lar, lampco, shadfac, &isec); } } From d6aefa6abd6d99a0024e7d576a3766f72d115b7f Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sat, 11 Jul 2009 22:13:01 +0000 Subject: [PATCH 051/138] Added module bf_render_raytrace (source/blender/render/intern/raytrace) to be able to use C++ at raytrace code C++ used in here is basicly C with templates and function overloads, to make it easier to reuse code between structures. For now BVH was converted in C++ and moved to this module --- source/blender/render/SConscript | 2 + source/blender/render/intern/raytrace/bvh.h | 288 +++++++++++ .../render/intern/raytrace/rayobject_bvh.cpp | 470 +++++++++++++++++ .../render/intern/source/rayobject_bvh.c | 474 ------------------ 4 files changed, 760 insertions(+), 474 deletions(-) create mode 100644 source/blender/render/intern/raytrace/bvh.h create mode 100644 source/blender/render/intern/raytrace/rayobject_bvh.cpp delete mode 100644 source/blender/render/intern/source/rayobject_bvh.c diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript index 173f5db8482..a52f211e918 100644 --- a/source/blender/render/SConscript +++ b/source/blender/render/SConscript @@ -3,6 +3,7 @@ Import ('env') cflags='' sources = env.Glob('intern/source/*.c') +raysources = env.Glob('intern/raytrace/*.cpp') incs = 'intern/include #/intern/guardedalloc ../blenlib ../makesdna' incs += ' extern/include ../blenkernel ../radiosity/extern/include ../imbuf' @@ -24,3 +25,4 @@ if env['OURPLATFORM']=='linux2': cflags='-pthread' env.BlenderLib ( libname = 'bf_render', sources = sources, includes = Split(incs), defines=defs, libtype='core', priority=145, compileflags=cflags ) +env.BlenderLib ( libname = 'bf_render_raytrace', sources = raysources, includes = Split(incs), defines=defs, libtype='core', priority=145, compileflags=cflags ) diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h new file mode 100644 index 00000000000..d2da2690c49 --- /dev/null +++ b/source/blender/render/intern/raytrace/bvh.h @@ -0,0 +1,288 @@ + +/* bvh tree generics */ +template static int bvh_intersect(Tree *obj, Isect *isec); + +template static void bvh_add(Tree *obj, RayObject *ob) +{ + rtbuild_add( obj->builder, ob ); +} + +template static void bvh_done(Tree *obj); + +template +static void bvh_free(Tree *obj) +{ + if(obj->builder) + rtbuild_free(obj->builder); + + if(obj->node_arena) + BLI_memarena_free(obj->node_arena); + + MEM_freeN(obj); +} + +template +static void bvh_bb(Tree *obj, float *min, float *max) +{ + bvh_node_merge_bb(obj->root, min, max); +} + + +template +static float bvh_cost(Tree *obj) +{ + assert(obj->cost >= 0.0); + return obj->cost; +} + + + +/* bvh tree nodes generics */ +template static inline int bvh_node_hit_test(Node *node, Isect *isec) +{ + return RE_rayobject_bb_intersect(isec, (const float*)node->bb) != FLT_MAX; +} + + +template +static void bvh_node_merge_bb(Node *node, float *min, float *max) +{ + if(RayObject_isAligned(node)) + { + DO_MIN(node->bb , min); + DO_MAX(node->bb+3, max); + } + else + { + RE_rayobject_merge_bb( (RayObject*)node, min, max); + } +} + + + +/* + * recursivly transverse a BVH looking for a rayhit using a local stack + */ +template static inline void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, int &stack_pos); + +template +static int bvh_node_stack_raycast(Node *root, Isect *isec) +{ + Node *stack[MAX_STACK_SIZE]; + int hit = 0, stack_pos = 0; + + stack[stack_pos++] = root; + while(stack_pos) + { + Node *node = stack[--stack_pos]; + if(RayObject_isAligned(node)) + { + if(bvh_node_hit_test(node,isec)) + { + bvh_node_push_childs(node, isec, stack, stack_pos); + assert(stack_pos <= MAX_STACK_SIZE); + } + } + else + { + hit |= RE_rayobject_intersect( (RayObject*)node, isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + } + return hit; + +} + +/* + * recursively transverse a BVH looking for a rayhit using system stack + */ +/* +template +static int bvh_node_raycast(Node *node, Isect *isec) +{ + int hit = 0; + if(bvh_test_node(node, isec)) + { + if(isec->idot_axis[node->split_axis] > 0.0f) + { + int i; + for(i=0; ichild[i])) + { + if(node->child[i] == 0) break; + + hit |= bvh_node_raycast(node->child[i], isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + else + { + hit |= RE_rayobject_intersect( (RayObject*)node->child[i], isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + } + else + { + int i; + for(i=BVH_NCHILDS-1; i>=0; i--) + if(RayObject_isAligned(node->child[i])) + { + if(node->child[i]) + { + hit |= dfs_raycast(node->child[i], isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + } + else + { + hit |= RE_rayobject_intersect( (RayObject*)node->child[i], isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + } + } + return hit; +} +*/ + +/* bvh tree generics */ +template static int bvh_intersect(Tree *obj, Isect *isec); + +template static void bvh_add(Tree *obj, RayObject *ob) +{ + rtbuild_add( obj->builder, ob ); +} + +template static void bvh_done(Tree *obj); + +template +static void bvh_free(Tree *obj) +{ + if(obj->builder) + rtbuild_free(obj->builder); + + if(obj->node_arena) + BLI_memarena_free(obj->node_arena); + + MEM_freeN(obj); +} + +template +static void bvh_bb(Tree *obj, float *min, float *max) +{ + bvh_node_merge_bb(obj->root, min, max); +} + + +template +static float bvh_cost(Tree *obj) +{ + assert(obj->cost >= 0.0); + return obj->cost; +} + + + +/* bvh tree nodes generics */ +template static inline int bvh_node_hit_test(Node *node, Isect *isec) +{ + return RE_rayobject_bb_intersect(isec, (const float*)node->bb) != FLT_MAX; +} + + +template +static void bvh_node_merge_bb(Node *node, float *min, float *max) +{ + if(RayObject_isAligned(node)) + { + DO_MIN(node->bb , min); + DO_MAX(node->bb+3, max); + } + else + { + RE_rayobject_merge_bb( (RayObject*)node, min, max); + } +} + + + +/* + * recursivly transverse a BVH looking for a rayhit using a local stack + */ +template static inline void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, int &stack_pos); + +template +static int bvh_node_stack_raycast(Node *root, Isect *isec) +{ + Node *stack[MAX_STACK_SIZE]; + int hit = 0, stack_pos = 0; + + stack[stack_pos++] = root; + while(stack_pos) + { + Node *node = stack[--stack_pos]; + if(RayObject_isAligned(node)) + { + if(bvh_node_hit_test(node,isec)) + { + bvh_node_push_childs(node, isec, stack, stack_pos); + assert(stack_pos <= MAX_STACK_SIZE); + } + } + else + { + hit |= RE_rayobject_intersect( (RayObject*)node, isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + } + return hit; + +} + +/* + * recursively transverse a BVH looking for a rayhit using system stack + */ +/* +template +static int bvh_node_raycast(Node *node, Isect *isec) +{ + int hit = 0; + if(bvh_test_node(node, isec)) + { + if(isec->idot_axis[node->split_axis] > 0.0f) + { + int i; + for(i=0; ichild[i])) + { + if(node->child[i] == 0) break; + + hit |= bvh_node_raycast(node->child[i], isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + else + { + hit |= RE_rayobject_intersect( (RayObject*)node->child[i], isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + } + else + { + int i; + for(i=BVH_NCHILDS-1; i>=0; i--) + if(RayObject_isAligned(node->child[i])) + { + if(node->child[i]) + { + hit |= dfs_raycast(node->child[i], isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + } + else + { + hit |= RE_rayobject_intersect( (RayObject*)node->child[i], isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + } + } + return hit; +} +*/ diff --git a/source/blender/render/intern/raytrace/rayobject_bvh.cpp b/source/blender/render/intern/raytrace/rayobject_bvh.cpp new file mode 100644 index 00000000000..7bf87e09181 --- /dev/null +++ b/source/blender/render/intern/raytrace/rayobject_bvh.cpp @@ -0,0 +1,470 @@ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +extern "C" +{ +#include +#include "MEM_guardedalloc.h" +#include "BKE_utildefines.h" +#include "BLI_arithb.h" +#include "BLI_memarena.h" +#include "RE_raytrace.h" +#include "rayobject_rtbuild.h" +#include "rayobject.h" +}; + +#include "bvh.h" + +#define BVH_NCHILDS 2 +#define RAY_BB_TEST_COST (0.2f) +#define DFS_STACK_SIZE 64 +#define DYNAMIC_ALLOC + +//#define rtbuild_split rtbuild_mean_split_largest_axis /* objects mean split on the longest axis, childs BB are allowed to overlap */ +//#define rtbuild_split rtbuild_median_split_largest_axis /* space median split on the longest axis, childs BB are allowed to overlap */ +#define rtbuild_split rtbuild_heuristic_object_split /* split objects using heuristic */ + +struct BVHNode +{ + BVHNode *child[BVH_NCHILDS]; + float bb[6]; + int split_axis; +}; + +struct BVHTree +{ + RayObject rayobj; + + BVHNode *root; + + MemArena *node_arena; + + float cost; + RTBuilder *builder; +}; + + +/* + * Push nodes (used on dfs) + */ +template +inline static void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, int &stack_pos) +{ + //push nodes in reverse visit order + if(isec->idot_axis[node->split_axis] < 0.0f) + { + int i; + for(i=0; ichild[i] == 0) + break; + else + stack[stack_pos++] = node->child[i]; + } + else + { + int i; + for(i=BVH_NCHILDS-1; i>=0; i--) + if(node->child[i] != 0) + stack[stack_pos++] = node->child[i]; + } +} + +/* + * BVH done + */ +static BVHNode *bvh_new_node(BVHTree *tree, int nid) +{ + BVHNode *node = (BVHNode*)BLI_memarena_alloc(tree->node_arena, sizeof(BVHNode)); + return node; +} + +static int child_id(int pid, int nchild) +{ + //N child of node A = A * K + (2 - K) + N, (0 <= N < K) + return pid*BVH_NCHILDS+(2-BVH_NCHILDS)+nchild; +} + + +static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid, float *cost) +{ + *cost = 0; + if(rtbuild_size(builder) == 0) + return 0; + + if(rtbuild_size(builder) == 1) + { + RayObject *child = builder->begin[0]; + + if(RayObject_isRayFace(child)) + { + int i; + BVHNode *parent = bvh_new_node(tree, nid); + parent->split_axis = 0; + + INIT_MINMAX(parent->bb, parent->bb+3); + + for(i=0; i<1; i++) + { + parent->child[i] = (BVHNode*)builder->begin[i]; + bvh_node_merge_bb(parent->child[i], parent->bb, parent->bb+3); + } + for(; ichild[i] = 0; + + *cost = RE_rayobject_cost(child)+RAY_BB_TEST_COST; + return parent; + } + else + { + assert(!RayObject_isAligned(child)); + //Its a sub-raytrace structure, assume it has it own raycast + //methods and adding a Bounding Box arround is unnecessary + + *cost = RE_rayobject_cost(child); + return (BVHNode*)child; + } + } + else + { + int i; + RTBuilder tmp; + BVHNode *parent = bvh_new_node(tree, nid); + int nc = rtbuild_split(builder, BVH_NCHILDS); + + + INIT_MINMAX(parent->bb, parent->bb+3); + parent->split_axis = builder->split_axis; + for(i=0; ichild[i] = bvh_rearrange( tree, rtbuild_get_child(builder, i, &tmp), child_id(nid,i), &tcost ); + + INIT_MINMAX(cbb, cbb+3); + bvh_node_merge_bb(parent->child[i], cbb, cbb+3); + DO_MIN(cbb, parent->bb); + DO_MAX(cbb+3, parent->bb+3); + + *cost += tcost*bb_area(cbb, cbb+3); + } + for(; ichild[i] = 0; + + *cost /= bb_area(parent->bb, parent->bb+3); + *cost += nc*RAY_BB_TEST_COST; + return parent; + } +} + +template<> +void bvh_done(BVHTree *obj) +{ + int needed_nodes = (rtbuild_size(obj->builder)+1)*2; + if(needed_nodes > BLI_MEMARENA_STD_BUFSIZE) + needed_nodes = BLI_MEMARENA_STD_BUFSIZE; + + obj->node_arena = BLI_memarena_new(needed_nodes); + BLI_memarena_use_malloc(obj->node_arena); + + + obj->root = bvh_rearrange( obj, obj->builder, 1, &obj->cost ); + + rtbuild_free( obj->builder ); + obj->builder = NULL; +} + +template<> +int bvh_intersect(BVHTree *obj, Isect* isec) +{ + if(RayObject_isAligned(obj->root)) + return bvh_node_stack_raycast(obj->root, isec); + else + return RE_rayobject_intersect( (RayObject*) obj->root, isec ); +} + + +/* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */ +static RayObjectAPI bvh_api = +{ + (RE_rayobject_raycast_callback) ((int(*)(BVHTree*,Isect*)) &bvh_intersect), + (RE_rayobject_add_callback) ((void(*)(BVHTree*,RayObject*)) &bvh_add), + (RE_rayobject_done_callback) ((void(*)(BVHTree*)) &bvh_done), + (RE_rayobject_free_callback) ((void(*)(BVHTree*)) &bvh_free), + (RE_rayobject_merge_bb_callback)((void(*)(BVHTree*,float*,float*)) &bvh_bb), + (RE_rayobject_cost_callback) ((float(*)(BVHTree*)) &bvh_cost) +}; + + +RayObject *RE_rayobject_bvh_create(int size) +{ + BVHTree *obj= (BVHTree*)MEM_callocN(sizeof(BVHTree), "BVHTree"); + assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ + + obj->rayobj.api = &bvh_api; + obj->root = NULL; + + obj->node_arena = NULL; + obj->builder = rtbuild_create( size ); + + return RayObject_unalignRayAPI((RayObject*) obj); +} +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +extern "C" +{ +#include +#include "MEM_guardedalloc.h" +#include "BKE_utildefines.h" +#include "BLI_arithb.h" +#include "BLI_memarena.h" +#include "RE_raytrace.h" +#include "rayobject_rtbuild.h" +#include "rayobject.h" +}; + +#include "bvh.h" + +#define BVH_NCHILDS 2 +#define RAY_BB_TEST_COST (0.2f) +#define DFS_STACK_SIZE 64 +#define DYNAMIC_ALLOC + +//#define rtbuild_split rtbuild_mean_split_largest_axis /* objects mean split on the longest axis, childs BB are allowed to overlap */ +//#define rtbuild_split rtbuild_median_split_largest_axis /* space median split on the longest axis, childs BB are allowed to overlap */ +#define rtbuild_split rtbuild_heuristic_object_split /* split objects using heuristic */ + +struct BVHNode +{ + BVHNode *child[BVH_NCHILDS]; + float bb[6]; + int split_axis; +}; + +struct BVHTree +{ + RayObject rayobj; + + BVHNode *root; + + MemArena *node_arena; + + float cost; + RTBuilder *builder; +}; + + +/* + * Push nodes (used on dfs) + */ +template +inline static void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, int &stack_pos) +{ + //push nodes in reverse visit order + if(isec->idot_axis[node->split_axis] < 0.0f) + { + int i; + for(i=0; ichild[i] == 0) + break; + else + stack[stack_pos++] = node->child[i]; + } + else + { + int i; + for(i=BVH_NCHILDS-1; i>=0; i--) + if(node->child[i] != 0) + stack[stack_pos++] = node->child[i]; + } +} + +/* + * BVH done + */ +static BVHNode *bvh_new_node(BVHTree *tree, int nid) +{ + BVHNode *node = (BVHNode*)BLI_memarena_alloc(tree->node_arena, sizeof(BVHNode)); + return node; +} + +static int child_id(int pid, int nchild) +{ + //N child of node A = A * K + (2 - K) + N, (0 <= N < K) + return pid*BVH_NCHILDS+(2-BVH_NCHILDS)+nchild; +} + + +static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid, float *cost) +{ + *cost = 0; + if(rtbuild_size(builder) == 0) + return 0; + + if(rtbuild_size(builder) == 1) + { + RayObject *child = builder->begin[0]; + + if(RayObject_isRayFace(child)) + { + int i; + BVHNode *parent = bvh_new_node(tree, nid); + parent->split_axis = 0; + + INIT_MINMAX(parent->bb, parent->bb+3); + + for(i=0; i<1; i++) + { + parent->child[i] = (BVHNode*)builder->begin[i]; + bvh_node_merge_bb(parent->child[i], parent->bb, parent->bb+3); + } + for(; ichild[i] = 0; + + *cost = RE_rayobject_cost(child)+RAY_BB_TEST_COST; + return parent; + } + else + { + assert(!RayObject_isAligned(child)); + //Its a sub-raytrace structure, assume it has it own raycast + //methods and adding a Bounding Box arround is unnecessary + + *cost = RE_rayobject_cost(child); + return (BVHNode*)child; + } + } + else + { + int i; + RTBuilder tmp; + BVHNode *parent = bvh_new_node(tree, nid); + int nc = rtbuild_split(builder, BVH_NCHILDS); + + + INIT_MINMAX(parent->bb, parent->bb+3); + parent->split_axis = builder->split_axis; + for(i=0; ichild[i] = bvh_rearrange( tree, rtbuild_get_child(builder, i, &tmp), child_id(nid,i), &tcost ); + + INIT_MINMAX(cbb, cbb+3); + bvh_node_merge_bb(parent->child[i], cbb, cbb+3); + DO_MIN(cbb, parent->bb); + DO_MAX(cbb+3, parent->bb+3); + + *cost += tcost*bb_area(cbb, cbb+3); + } + for(; ichild[i] = 0; + + *cost /= bb_area(parent->bb, parent->bb+3); + *cost += nc*RAY_BB_TEST_COST; + return parent; + } +} + +template<> +void bvh_done(BVHTree *obj) +{ + int needed_nodes = (rtbuild_size(obj->builder)+1)*2; + if(needed_nodes > BLI_MEMARENA_STD_BUFSIZE) + needed_nodes = BLI_MEMARENA_STD_BUFSIZE; + + obj->node_arena = BLI_memarena_new(needed_nodes); + BLI_memarena_use_malloc(obj->node_arena); + + + obj->root = bvh_rearrange( obj, obj->builder, 1, &obj->cost ); + + rtbuild_free( obj->builder ); + obj->builder = NULL; +} + +template<> +int bvh_intersect(BVHTree *obj, Isect* isec) +{ + if(RayObject_isAligned(obj->root)) + return bvh_node_stack_raycast(obj->root, isec); + else + return RE_rayobject_intersect( (RayObject*) obj->root, isec ); +} + + +/* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */ +static RayObjectAPI bvh_api = +{ + (RE_rayobject_raycast_callback) ((int(*)(BVHTree*,Isect*)) &bvh_intersect), + (RE_rayobject_add_callback) ((void(*)(BVHTree*,RayObject*)) &bvh_add), + (RE_rayobject_done_callback) ((void(*)(BVHTree*)) &bvh_done), + (RE_rayobject_free_callback) ((void(*)(BVHTree*)) &bvh_free), + (RE_rayobject_merge_bb_callback)((void(*)(BVHTree*,float*,float*)) &bvh_bb), + (RE_rayobject_cost_callback) ((float(*)(BVHTree*)) &bvh_cost) +}; + + +RayObject *RE_rayobject_bvh_create(int size) +{ + BVHTree *obj= (BVHTree*)MEM_callocN(sizeof(BVHTree), "BVHTree"); + assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ + + obj->rayobj.api = &bvh_api; + obj->root = NULL; + + obj->node_arena = NULL; + obj->builder = rtbuild_create( size ); + + return RayObject_unalignRayAPI((RayObject*) obj); +} diff --git a/source/blender/render/intern/source/rayobject_bvh.c b/source/blender/render/intern/source/rayobject_bvh.c deleted file mode 100644 index 181456c2b4d..00000000000 --- a/source/blender/render/intern/source/rayobject_bvh.c +++ /dev/null @@ -1,474 +0,0 @@ -/** - * $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) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#include -#include -#include - -#include "MEM_guardedalloc.h" -#include "BKE_utildefines.h" -#include "BLI_arithb.h" -#include "BLI_memarena.h" -#include "RE_raytrace.h" -#include "rayobject_rtbuild.h" -#include "rayobject.h" - -#define RAY_BB_TEST_COST (0.2f) -#define DFS_STACK_SIZE 64 -#define DYNAMIC_ALLOC - -//#define SPLIT_OVERLAP_MEAN_LONGEST_AXIS /* objects mean split on the longest axis, childs BB are allowed to overlap */ -//#define SPLIT_OVERLAP_MEDIAN_LONGEST_AXIS /* space median split on the longest axis, childs BB are allowed to overlap */ -#define SPLIT_OBJECTS_SAH /* split objects using heuristic */ - -#define BVH_NCHILDS 2 -typedef struct BVHTree BVHTree; - -static int bvh_intersect(BVHTree *obj, Isect *isec); -static int bvh_intersect_stack(BVHTree *obj, Isect *isec); -static void bvh_add(BVHTree *o, RayObject *ob); -static void bvh_done(BVHTree *o); -static void bvh_free(BVHTree *o); -static void bvh_bb(BVHTree *o, float *min, float *max); -static float bvh_cost(BVHTree *o); - -static RayObjectAPI bvh_api = -{ -#ifdef DFS_STACK_SIZE - (RE_rayobject_raycast_callback) bvh_intersect_stack, -#else - (RE_rayobject_raycast_callback) bvh_intersect, -#endif - (RE_rayobject_add_callback) bvh_add, - (RE_rayobject_done_callback) bvh_done, - (RE_rayobject_free_callback) bvh_free, - (RE_rayobject_merge_bb_callback)bvh_bb, - (RE_rayobject_cost_callback) bvh_cost -}; - -typedef struct BVHNode BVHNode; -struct BVHNode -{ - BVHNode *child[BVH_NCHILDS]; -#ifdef DYNAMIC_ALLOC - float bb[6]; -#else - float *bb; //[6]; //[2][3]; -#endif - int split_axis; -}; - -struct BVHTree -{ - RayObject rayobj; - - BVHNode *root; - -#ifdef DYNAMIC_ALLOC - MemArena *node_arena; -#else - BVHNode *node_alloc, *node_next; - float *bb_alloc, *bb_next; -#endif - float cost; - RTBuilder *builder; - -}; - - -RayObject *RE_rayobject_bvh_create(int size) -{ - BVHTree *obj= (BVHTree*)MEM_callocN(sizeof(BVHTree), "BVHTree"); - assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ - - obj->rayobj.api = &bvh_api; - obj->root = NULL; - -#ifdef DYNAMIC_ALLOC - obj->node_arena = NULL; -#else - obj->node_alloc = obj->node_next = NULL; - obj->bb_alloc = obj->bb_next = NULL; -#endif - obj->builder = rtbuild_create( size ); - - return RayObject_unalignRayAPI((RayObject*) obj); -} - -static void bvh_free(BVHTree *obj) -{ - if(obj->builder) - rtbuild_free(obj->builder); - -#ifdef DYNAMIC_ALLOC - if(obj->node_arena) - BLI_memarena_free(obj->node_arena); -#else - if(obj->node_alloc) - MEM_freeN(obj->node_alloc); - - if(obj->bb_alloc) - MEM_freeN(obj->bb_alloc); -#endif - - MEM_freeN(obj); -} - - -static void bvh_merge_bb(BVHNode *node, float *min, float *max) -{ - if(RayObject_isAligned(node)) - { - DO_MIN(node->bb , min); - DO_MAX(node->bb+3, max); - } - else - { - RE_rayobject_merge_bb( (RayObject*)node, min, max); - } -} - -static void bvh_bb(BVHTree *obj, float *min, float *max) -{ - bvh_merge_bb(obj->root, min, max); -} - -static float bvh_cost(BVHTree *obj) -{ - assert(obj->cost >= 0.0); - return obj->cost; -} - -/* - * Tree transverse - */ -static int dfs_raycast_stack(BVHNode *root, Isect *isec) -{ - BVHNode *stack[DFS_STACK_SIZE]; - int hit = 0, stack_pos = 0; -#ifdef RT_USE_HINT - BVHNode *last_processed_node = 0; -#endif - - stack[stack_pos++] = root; - - while(stack_pos) - { - BVHNode *node = stack[--stack_pos]; - if(RayObject_isAligned(node)) - { - if(RE_rayobject_bb_intersect(isec, (const float*)node->bb) != FLT_MAX) - { -#ifdef RT_USE_HINT - last_processed_node = node; -#endif - //push nodes in reverse visit order - if(isec->idot_axis[node->split_axis] < 0.0f) - { - int i; - for(i=0; ichild[i] == 0) break; - else -#ifdef RT_USE_HINT - if(node->child[i] != (BVHNode*)isec->hint) -#endif - stack[stack_pos++] = node->child[i]; - } - else - { - int i; - for(i=BVH_NCHILDS-1; i>=0; i--) - if(node->child[i] != 0 -#ifdef RT_USE_HINT - && node->child[i] != (BVHNode*)isec->hint -#endif - ) - stack[stack_pos++] = node->child[i]; - } - assert(stack_pos <= DFS_STACK_SIZE); - } - } - else - { - int ghit; -#ifdef RT_USE_HINT - RayTraceHint *b_hint = isec->hint; - isec->hint = 0; -#endif - ghit = RE_rayobject_intersect( (RayObject*)node, isec); - -#ifdef RT_USE_HINT - isec->hint = b_hint; - if(ghit) - isec->hit_hint = (RayTraceHint*)last_processed_node; -#endif - hit |= ghit; - if(hit && isec->mode == RE_RAY_SHADOW) return hit; - } - } - return hit; -} - -static int bvh_intersect_stack(BVHTree *obj, Isect *isec) -{ - if(RayObject_isAligned(obj->root)) - { -#ifdef RT_USE_HINT - if(isec->hint) - { - int hit; - RE_RC_COUNT(isec->raycounter->raytrace_hint.test); - hit = dfs_raycast_stack((BVHNode*) isec->hint, isec); - if(hit) - { - RE_RC_COUNT(isec->raycounter->raytrace_hint.hit); - - if(isec->mode == RE_RAY_SHADOW) return hit; - } - else isec->hint = 0; //Clear HINT on non-hit?, that sounds good, but no tests where made - - return hit | dfs_raycast_stack(obj->root, isec); - } -#endif - return dfs_raycast_stack(obj->root, isec); - } - else - return RE_rayobject_intersect( (RayObject*)obj->root, isec); -} - -static int dfs_raycast(BVHNode *node, Isect *isec) -{ - int hit = 0; - if(RE_rayobject_bb_intersect(isec, (const float*)node->bb) != FLT_MAX) - { - if(isec->idot_axis[node->split_axis] > 0.0f) - { - int i; - for(i=0; ichild[i])) - { - if(node->child[i] == 0) break; - - hit |= dfs_raycast(node->child[i], isec); - if(hit && isec->mode == RE_RAY_SHADOW) return hit; - } - else - { - hit |= RE_rayobject_intersect( (RayObject*)node->child[i], isec); - if(hit && isec->mode == RE_RAY_SHADOW) return hit; - } - } - else - { - int i; - for(i=BVH_NCHILDS-1; i>=0; i--) - if(RayObject_isAligned(node->child[i])) - { - if(node->child[i]) - { - hit |= dfs_raycast(node->child[i], isec); - if(hit && isec->mode == RE_RAY_SHADOW) return hit; - } - } - else - { - hit |= RE_rayobject_intersect( (RayObject*)node->child[i], isec); - if(hit && isec->mode == RE_RAY_SHADOW) return hit; - } - } - } - return hit; -} - -static int bvh_intersect(BVHTree *obj, Isect *isec) -{ - if(RayObject_isAligned(obj->root)) - return dfs_raycast(obj->root, isec); - else - return RE_rayobject_intersect( (RayObject*)obj->root, isec); -} - - -/* - * Builds a BVH tree from builder object - */ -static void bvh_add(BVHTree *obj, RayObject *ob) -{ - rtbuild_add( obj->builder, ob ); -} - -static BVHNode *bvh_new_node(BVHTree *tree, int nid) -{ -#ifdef DYNAMIC_ALLOC - BVHNode *node = BLI_memarena_alloc(tree->node_arena, sizeof(BVHNode)); - return node; -#else - BVHNode *node = tree->node_alloc + nid - 1; - assert(RayObject_isAligned(node)); - if(node+1 > tree->node_next) - tree->node_next = node+1; - - node->bb = tree->bb_alloc + (nid - 1)*6; - tree->bb_next += 6; - - return node; -#endif -} - -static int child_id(int pid, int nchild) -{ - //N child of node A = A * K + (2 - K) + N, (0 <= N < K) - return pid*BVH_NCHILDS+(2-BVH_NCHILDS)+nchild; -} - -static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid, float *cost) -{ - *cost = 0; - if(rtbuild_size(builder) == 0) - return 0; - - if(rtbuild_size(builder) == 1) - { - RayObject *child = builder->begin[0]; - - if(RayObject_isRayFace(child)) - { - int i; - BVHNode *parent = bvh_new_node(tree, nid); - parent->split_axis = 0; - - INIT_MINMAX(parent->bb, parent->bb+3); - - for(i=0; i<1; i++) - { - parent->child[i] = (BVHNode*)builder->begin[i]; - bvh_merge_bb(parent->child[i], parent->bb, parent->bb+3); - } - for(; ichild[i] = 0; - - *cost = RE_rayobject_cost(child)+RAY_BB_TEST_COST; - return parent; - } - else - { - assert(!RayObject_isAligned(child)); - //Its a sub-raytrace structure, assume it has it own raycast - //methods and adding a Bounding Box arround is unnecessary - - *cost = RE_rayobject_cost(child); - return (BVHNode*)child; - } - } - else - { - int i; - RTBuilder tmp; - BVHNode *parent = bvh_new_node(tree, nid); - int nc; - -#ifdef SPLIT_OVERLAP_MEAN_LONGEST_AXIS - nc = rtbuild_mean_split_largest_axis(builder, BVH_NCHILDS); -#elif defined(SPLIT_OVERLAP_MEDIAN_LONGEST_AXIS) - nc = rtbuild_median_split_largest_axis(builder, BVH_NCHILDS); -#elif defined(SPLIT_OBJECTS_SAH) - nc = rtbuild_heuristic_object_split(builder, BVH_NCHILDS); -#else - assert(0); -#endif - - INIT_MINMAX(parent->bb, parent->bb+3); - parent->split_axis = builder->split_axis; - for(i=0; ichild[i] = bvh_rearrange( tree, rtbuild_get_child(builder, i, &tmp), child_id(nid,i), &tcost ); - - INIT_MINMAX(cbb, cbb+3); - bvh_merge_bb(parent->child[i], cbb, cbb+3); - DO_MIN(cbb, parent->bb); - DO_MAX(cbb+3, parent->bb+3); - - *cost += tcost*bb_area(cbb, cbb+3); - } - for(; ichild[i] = 0; - - *cost /= bb_area(parent->bb, parent->bb+3); - *cost += nc*RAY_BB_TEST_COST; - return parent; - } -} - -/* -static void bvh_info(BVHTree *obj) -{ - printf("BVH: Used %d nodes\n", obj->node_next - obj->node_alloc); -} -*/ - -static void bvh_done(BVHTree *obj) -{ - -#ifdef DYNAMIC_ALLOC - int needed_nodes = (rtbuild_size(obj->builder)+1)*2; - if(needed_nodes > BLI_MEMARENA_STD_BUFSIZE) - needed_nodes = BLI_MEMARENA_STD_BUFSIZE; - - obj->node_arena = BLI_memarena_new(needed_nodes); - BLI_memarena_use_malloc(obj->node_arena); - -#else - int needed_nodes; - - //TODO exact calculate needed nodes - needed_nodes = (rtbuild_size(obj->builder)+1)*2; - assert(needed_nodes > 0); - - BVHNode *node = BLI_memarena_alloc(tree->node_arena, sizeof(BVHNode)); - return node; - obj->node_alloc = (BVHNode*)MEM_mallocN( sizeof(BVHNode)*needed_nodes, "BVHTree.Nodes"); - obj->node_next = obj->node_alloc; - - obj->bb_alloc = (float*)MEM_mallocN( sizeof(float)*6*needed_nodes, "BVHTree.NodesBB"); - obj->bb_next = obj->bb_alloc; -#endif - - obj->root = bvh_rearrange( obj, obj->builder, 1, &obj->cost ); -// obj->cost = 1.0; -// obj->cost = logf( rtbuild_size( obj->builder ) ); - -#ifndef DYNAMIC_ALLOC - assert(obj->node_alloc+needed_nodes >= obj->node_next); -#endif - - rtbuild_free( obj->builder ); - obj->builder = NULL; -} - From e264087fad7a55be67d409fe1748d4fc647fba0c Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sat, 11 Jul 2009 22:29:53 +0000 Subject: [PATCH 052/138] I had applied a patch twice.. code was duplicated --- source/blender/render/intern/raytrace/bvh.h | 172 +++---------- .../render/intern/raytrace/rayobject_bvh.cpp | 235 ------------------ 2 files changed, 28 insertions(+), 379 deletions(-) diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h index d2da2690c49..44f531faa9f 100644 --- a/source/blender/render/intern/raytrace/bvh.h +++ b/source/blender/render/intern/raytrace/bvh.h @@ -1,147 +1,31 @@ - -/* bvh tree generics */ -template static int bvh_intersect(Tree *obj, Isect *isec); - -template static void bvh_add(Tree *obj, RayObject *ob) -{ - rtbuild_add( obj->builder, ob ); -} - -template static void bvh_done(Tree *obj); - -template -static void bvh_free(Tree *obj) -{ - if(obj->builder) - rtbuild_free(obj->builder); - - if(obj->node_arena) - BLI_memarena_free(obj->node_arena); - - MEM_freeN(obj); -} - -template -static void bvh_bb(Tree *obj, float *min, float *max) -{ - bvh_node_merge_bb(obj->root, min, max); -} - - -template -static float bvh_cost(Tree *obj) -{ - assert(obj->cost >= 0.0); - return obj->cost; -} - - - -/* bvh tree nodes generics */ -template static inline int bvh_node_hit_test(Node *node, Isect *isec) -{ - return RE_rayobject_bb_intersect(isec, (const float*)node->bb) != FLT_MAX; -} - - -template -static void bvh_node_merge_bb(Node *node, float *min, float *max) -{ - if(RayObject_isAligned(node)) - { - DO_MIN(node->bb , min); - DO_MAX(node->bb+3, max); - } - else - { - RE_rayobject_merge_bb( (RayObject*)node, min, max); - } -} - - - -/* - * recursivly transverse a BVH looking for a rayhit using a local stack - */ -template static inline void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, int &stack_pos); - -template -static int bvh_node_stack_raycast(Node *root, Isect *isec) -{ - Node *stack[MAX_STACK_SIZE]; - int hit = 0, stack_pos = 0; - - stack[stack_pos++] = root; - while(stack_pos) - { - Node *node = stack[--stack_pos]; - if(RayObject_isAligned(node)) - { - if(bvh_node_hit_test(node,isec)) - { - bvh_node_push_childs(node, isec, stack, stack_pos); - assert(stack_pos <= MAX_STACK_SIZE); - } - } - else - { - hit |= RE_rayobject_intersect( (RayObject*)node, isec); - if(hit && isec->mode == RE_RAY_SHADOW) return hit; - } - } - return hit; - -} - -/* - * recursively transverse a BVH looking for a rayhit using system stack - */ -/* -template -static int bvh_node_raycast(Node *node, Isect *isec) -{ - int hit = 0; - if(bvh_test_node(node, isec)) - { - if(isec->idot_axis[node->split_axis] > 0.0f) - { - int i; - for(i=0; ichild[i])) - { - if(node->child[i] == 0) break; - - hit |= bvh_node_raycast(node->child[i], isec); - if(hit && isec->mode == RE_RAY_SHADOW) return hit; - } - else - { - hit |= RE_rayobject_intersect( (RayObject*)node->child[i], isec); - if(hit && isec->mode == RE_RAY_SHADOW) return hit; - } - } - else - { - int i; - for(i=BVH_NCHILDS-1; i>=0; i--) - if(RayObject_isAligned(node->child[i])) - { - if(node->child[i]) - { - hit |= dfs_raycast(node->child[i], isec); - if(hit && isec->mode == RE_RAY_SHADOW) return hit; - } - } - else - { - hit |= RE_rayobject_intersect( (RayObject*)node->child[i], isec); - if(hit && isec->mode == RE_RAY_SHADOW) return hit; - } - } - } - return hit; -} -*/ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ /* bvh tree generics */ template static int bvh_intersect(Tree *obj, Isect *isec); diff --git a/source/blender/render/intern/raytrace/rayobject_bvh.cpp b/source/blender/render/intern/raytrace/rayobject_bvh.cpp index 7bf87e09181..8a63e088a34 100644 --- a/source/blender/render/intern/raytrace/rayobject_bvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_bvh.cpp @@ -220,241 +220,6 @@ static RayObjectAPI bvh_api = }; -RayObject *RE_rayobject_bvh_create(int size) -{ - BVHTree *obj= (BVHTree*)MEM_callocN(sizeof(BVHTree), "BVHTree"); - assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ - - obj->rayobj.api = &bvh_api; - obj->root = NULL; - - obj->node_arena = NULL; - obj->builder = rtbuild_create( size ); - - return RayObject_unalignRayAPI((RayObject*) obj); -} -/** - * $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) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ -extern "C" -{ -#include -#include "MEM_guardedalloc.h" -#include "BKE_utildefines.h" -#include "BLI_arithb.h" -#include "BLI_memarena.h" -#include "RE_raytrace.h" -#include "rayobject_rtbuild.h" -#include "rayobject.h" -}; - -#include "bvh.h" - -#define BVH_NCHILDS 2 -#define RAY_BB_TEST_COST (0.2f) -#define DFS_STACK_SIZE 64 -#define DYNAMIC_ALLOC - -//#define rtbuild_split rtbuild_mean_split_largest_axis /* objects mean split on the longest axis, childs BB are allowed to overlap */ -//#define rtbuild_split rtbuild_median_split_largest_axis /* space median split on the longest axis, childs BB are allowed to overlap */ -#define rtbuild_split rtbuild_heuristic_object_split /* split objects using heuristic */ - -struct BVHNode -{ - BVHNode *child[BVH_NCHILDS]; - float bb[6]; - int split_axis; -}; - -struct BVHTree -{ - RayObject rayobj; - - BVHNode *root; - - MemArena *node_arena; - - float cost; - RTBuilder *builder; -}; - - -/* - * Push nodes (used on dfs) - */ -template -inline static void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, int &stack_pos) -{ - //push nodes in reverse visit order - if(isec->idot_axis[node->split_axis] < 0.0f) - { - int i; - for(i=0; ichild[i] == 0) - break; - else - stack[stack_pos++] = node->child[i]; - } - else - { - int i; - for(i=BVH_NCHILDS-1; i>=0; i--) - if(node->child[i] != 0) - stack[stack_pos++] = node->child[i]; - } -} - -/* - * BVH done - */ -static BVHNode *bvh_new_node(BVHTree *tree, int nid) -{ - BVHNode *node = (BVHNode*)BLI_memarena_alloc(tree->node_arena, sizeof(BVHNode)); - return node; -} - -static int child_id(int pid, int nchild) -{ - //N child of node A = A * K + (2 - K) + N, (0 <= N < K) - return pid*BVH_NCHILDS+(2-BVH_NCHILDS)+nchild; -} - - -static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid, float *cost) -{ - *cost = 0; - if(rtbuild_size(builder) == 0) - return 0; - - if(rtbuild_size(builder) == 1) - { - RayObject *child = builder->begin[0]; - - if(RayObject_isRayFace(child)) - { - int i; - BVHNode *parent = bvh_new_node(tree, nid); - parent->split_axis = 0; - - INIT_MINMAX(parent->bb, parent->bb+3); - - for(i=0; i<1; i++) - { - parent->child[i] = (BVHNode*)builder->begin[i]; - bvh_node_merge_bb(parent->child[i], parent->bb, parent->bb+3); - } - for(; ichild[i] = 0; - - *cost = RE_rayobject_cost(child)+RAY_BB_TEST_COST; - return parent; - } - else - { - assert(!RayObject_isAligned(child)); - //Its a sub-raytrace structure, assume it has it own raycast - //methods and adding a Bounding Box arround is unnecessary - - *cost = RE_rayobject_cost(child); - return (BVHNode*)child; - } - } - else - { - int i; - RTBuilder tmp; - BVHNode *parent = bvh_new_node(tree, nid); - int nc = rtbuild_split(builder, BVH_NCHILDS); - - - INIT_MINMAX(parent->bb, parent->bb+3); - parent->split_axis = builder->split_axis; - for(i=0; ichild[i] = bvh_rearrange( tree, rtbuild_get_child(builder, i, &tmp), child_id(nid,i), &tcost ); - - INIT_MINMAX(cbb, cbb+3); - bvh_node_merge_bb(parent->child[i], cbb, cbb+3); - DO_MIN(cbb, parent->bb); - DO_MAX(cbb+3, parent->bb+3); - - *cost += tcost*bb_area(cbb, cbb+3); - } - for(; ichild[i] = 0; - - *cost /= bb_area(parent->bb, parent->bb+3); - *cost += nc*RAY_BB_TEST_COST; - return parent; - } -} - -template<> -void bvh_done(BVHTree *obj) -{ - int needed_nodes = (rtbuild_size(obj->builder)+1)*2; - if(needed_nodes > BLI_MEMARENA_STD_BUFSIZE) - needed_nodes = BLI_MEMARENA_STD_BUFSIZE; - - obj->node_arena = BLI_memarena_new(needed_nodes); - BLI_memarena_use_malloc(obj->node_arena); - - - obj->root = bvh_rearrange( obj, obj->builder, 1, &obj->cost ); - - rtbuild_free( obj->builder ); - obj->builder = NULL; -} - -template<> -int bvh_intersect(BVHTree *obj, Isect* isec) -{ - if(RayObject_isAligned(obj->root)) - return bvh_node_stack_raycast(obj->root, isec); - else - return RE_rayobject_intersect( (RayObject*) obj->root, isec ); -} - - -/* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */ -static RayObjectAPI bvh_api = -{ - (RE_rayobject_raycast_callback) ((int(*)(BVHTree*,Isect*)) &bvh_intersect), - (RE_rayobject_add_callback) ((void(*)(BVHTree*,RayObject*)) &bvh_add), - (RE_rayobject_done_callback) ((void(*)(BVHTree*)) &bvh_done), - (RE_rayobject_free_callback) ((void(*)(BVHTree*)) &bvh_free), - (RE_rayobject_merge_bb_callback)((void(*)(BVHTree*,float*,float*)) &bvh_bb), - (RE_rayobject_cost_callback) ((float(*)(BVHTree*)) &bvh_cost) -}; - - RayObject *RE_rayobject_bvh_create(int size) { BVHTree *obj= (BVHTree*)MEM_callocN(sizeof(BVHTree), "BVHTree"); From a6b328b82577d3ec1429c02686ea1727e02140c0 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 12 Jul 2009 18:04:10 +0000 Subject: [PATCH 053/138] *Moved rtbuild to bf_render_raytrace *Added vbvh - Just a experimental tree type :) Variable Way BVH - there is no hardcoded number of childs per each Tree Node - idea is to optimize a tree to reduced the expected number of BB tests even after applying SAH (for that an hardcoded n-way is not enough) - for now childs are stored on a linked list --- source/blender/blenlib/BLI_memarena.h | 9 + .../render/extern/include/RE_raytrace.h | 12 +- .../blender/render/intern/include/rayobject.h | 11 + .../render/intern/include/rayobject_rtbuild.h | 9 + source/blender/render/intern/raytrace/bvh.h | 7 +- .../render/intern/raytrace/rayobject_bvh.cpp | 11 +- .../rayobject_rtbuild.cpp} | 4 +- .../render/intern/raytrace/rayobject_vbvh.cpp | 248 ++++++++++++++++++ .../blender/render/intern/source/rayshade.c | 8 +- 9 files changed, 306 insertions(+), 13 deletions(-) rename source/blender/render/intern/{source/rayobject_rtbuild.c => raytrace/rayobject_rtbuild.cpp} (98%) create mode 100644 source/blender/render/intern/raytrace/rayobject_vbvh.cpp diff --git a/source/blender/blenlib/BLI_memarena.h b/source/blender/blenlib/BLI_memarena.h index a2954f8fa0d..4b955e9fa20 100644 --- a/source/blender/blenlib/BLI_memarena.h +++ b/source/blender/blenlib/BLI_memarena.h @@ -37,6 +37,10 @@ #ifndef BLI_MEMARENA_H #define BLI_MEMARENA_H +#ifdef __cplusplus +extern "C" { +#endif + /* A reasonable standard buffer size, big * enough to not cause much internal fragmentation, * small enough not to waste resources @@ -55,5 +59,10 @@ void BLI_memarena_use_calloc (struct MemArena *ma); void* BLI_memarena_alloc (struct MemArena *ma, int size); +#ifdef __cplusplus +} +#endif + + #endif diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index 7624cd09edb..4d0c0b1a88c 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -31,6 +31,11 @@ #ifndef RE_RAYTRACE_H #define RE_RAYTRACE_H +#ifdef __cplusplus +extern "C" { +#endif + + #define RT_USE_LAST_HIT /* last shadow hit is reused before raycasting on whole tree */ //#define RT_USE_HINT /* last hit object is reused before raycasting on whole tree */ @@ -88,7 +93,8 @@ RayObject* RE_rayobject_octree_create(int ocres, int size); RayObject* RE_rayobject_instance_create(RayObject *target, float transform[][4], void *ob, void *target_ob); RayObject* RE_rayobject_blibvh_create(int size); /* BLI_kdopbvh.c */ -RayObject* RE_rayobject_bvh_create(int size); /* rayobject_bvh.c */ +RayObject* RE_rayobject_bvh_create(int size); /* raytrace/rayobject_bvh.c */ +RayObject* RE_rayobject_vbvh_create(int size); /* raytrace/rayobject_vbvh.c */ RayObject* RE_rayobject_bih_create(int size); /* rayobject_bih.c */ @@ -151,5 +157,9 @@ struct Isect /* TODO use: FLT_MAX? */ #define RE_RAYTRACE_MAXDIST 1e33 +#ifdef __cplusplus +} +#endif + #endif /*__RE_RAYTRACE_H__*/ diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index de36a1e4888..16ebc537ef9 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -29,9 +29,14 @@ #ifndef RE_RAYOBJECT_H #define RE_RAYOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + #include "RE_raytrace.h" #include + /* RayObject A ray object is everything where we can cast rays like: @@ -166,4 +171,10 @@ float RE_rayobject_cost(RayObject *r); #endif + +#ifdef __cplusplus +} +#endif + + #endif diff --git a/source/blender/render/intern/include/rayobject_rtbuild.h b/source/blender/render/intern/include/rayobject_rtbuild.h index a98ed38a581..b80e0868739 100644 --- a/source/blender/render/intern/include/rayobject_rtbuild.h +++ b/source/blender/render/intern/include/rayobject_rtbuild.h @@ -29,8 +29,13 @@ #ifndef RE_RAYOBJECT_RTBUILD_H #define RE_RAYOBJECT_RTBUILD_H +#ifdef __cplusplus +extern "C" { +#endif + #include "rayobject.h" + /* * Ray Tree Builder * this structs helps building any type of tree @@ -88,4 +93,8 @@ float bb_area(float *min, float *max); float bb_volume(float *min, float *max); int bb_largest_axis(float *min, float *max); +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h index 44f531faa9f..d9277f9a583 100644 --- a/source/blender/render/intern/raytrace/bvh.h +++ b/source/blender/render/intern/raytrace/bvh.h @@ -99,7 +99,12 @@ static int bvh_node_stack_raycast(Node *root, Isect *isec) Node *stack[MAX_STACK_SIZE]; int hit = 0, stack_pos = 0; - stack[stack_pos++] = root; + //Assume the BB of root always succeed + if(1) + bvh_node_push_childs(root, isec, stack, stack_pos); + else + stack[stack_pos++] = root; + while(stack_pos) { Node *node = stack[--stack_pos]; diff --git a/source/blender/render/intern/raytrace/rayobject_bvh.cpp b/source/blender/render/intern/raytrace/rayobject_bvh.cpp index 8a63e088a34..2c2a260df98 100644 --- a/source/blender/render/intern/raytrace/rayobject_bvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_bvh.cpp @@ -26,18 +26,15 @@ * * ***** END GPL LICENSE BLOCK ***** */ -extern "C" -{ #include + +#include "RE_raytrace.h" +#include "rayobject_rtbuild.h" +#include "rayobject.h" #include "MEM_guardedalloc.h" #include "BKE_utildefines.h" #include "BLI_arithb.h" #include "BLI_memarena.h" -#include "RE_raytrace.h" -#include "rayobject_rtbuild.h" -#include "rayobject.h" -}; - #include "bvh.h" #define BVH_NCHILDS 2 diff --git a/source/blender/render/intern/source/rayobject_rtbuild.c b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp similarity index 98% rename from source/blender/render/intern/source/rayobject_rtbuild.c rename to source/blender/render/intern/raytrace/rayobject_rtbuild.cpp index 3c301ce1f9f..dff0b02c00e 100644 --- a/source/blender/render/intern/source/rayobject_rtbuild.c +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp @@ -245,8 +245,8 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) float bcost = FLT_MAX; float childrens_cost = 0; int i, axis, baxis = -1, boffset = size/2, k, try_axis[3]; - CostObject *cost = MEM_mallocN( sizeof(CostObject)*size, "RTBuilder.HeuristicObjectSplitter" ); - float *acc_bb = MEM_mallocN( sizeof(float)*6*size, "RTBuilder.HeuristicObjectSplitterBB" ); + CostObject *cost = (CostObject*)MEM_mallocN( sizeof(CostObject)*size, "RTBuilder.HeuristicObjectSplitter" ); + float *acc_bb = (float*)MEM_mallocN( sizeof(float)*6*size, "RTBuilder.HeuristicObjectSplitterBB" ); for(i=0; i +#include "MEM_guardedalloc.h" +#include "BKE_utildefines.h" +#include "BLI_arithb.h" +#include "BLI_memarena.h" +#include "RE_raytrace.h" +#include "rayobject_rtbuild.h" +#include "rayobject.h" +}; + +#include "bvh.h" +#include + +#define BVHNode VBVHNode +#define BVHTree VBVHTree + +#define RAY_BB_TEST_COST (0.2f) +#define DFS_STACK_SIZE 128 +#define DYNAMIC_ALLOC + +//#define rtbuild_split rtbuild_mean_split_largest_axis /* objects mean split on the longest axis, childs BB are allowed to overlap */ +//#define rtbuild_split rtbuild_median_split_largest_axis /* space median split on the longest axis, childs BB are allowed to overlap */ +#define rtbuild_split rtbuild_heuristic_object_split /* split objects using heuristic */ + +struct BVHNode +{ + BVHNode *child; + BVHNode *sibling; + + float bb[6]; +}; + +struct BVHTree +{ + RayObject rayobj; + + BVHNode *root; + + MemArena *node_arena; + + float cost; + RTBuilder *builder; +}; + + +/* + * Push nodes (used on dfs) + */ +template +inline static void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, int &stack_pos) +{ + Node *child = node->child; + while(child) + { + stack[stack_pos++] = child; + if(RayObject_isAligned(child)) + child = child->sibling; + else break; + } +} + +/* + * BVH done + */ +static BVHNode *bvh_new_node(BVHTree *tree) +{ + BVHNode *node = (BVHNode*)BLI_memarena_alloc(tree->node_arena, sizeof(BVHNode)); + node->sibling = NULL; + node->child = NULL; + + assert(RayObject_isAligned(node)); + return node; +} + +template +float rtbuild_area(Builder *builder) +{ + float min[3], max[3]; + INIT_MINMAX(min, max); + rtbuild_merge_bb(builder, min, max); + return bb_area(min, max); +} + +template +void bvh_update_bb(Node *node) +{ + INIT_MINMAX(node->bb, node->bb+3); + Node *child = node->child; + + while(child) + { + bvh_node_merge_bb(child, node->bb, node->bb+3); + if(RayObject_isAligned(child)) + child = child->sibling; + else + child = 0; + } +} + + +template +Node *bvh_rearrange(Tree *tree, Builder *builder, float *cost) +{ + + int size = rtbuild_size(builder); + if(size == 1) + { + Node *node = bvh_new_node(tree); + INIT_MINMAX(node->bb, node->bb+3); + rtbuild_merge_bb(builder, node->bb, node->bb+3); + + node->child = (BVHNode*)builder->begin[0]; + + *cost = RE_rayobject_cost((RayObject*)node->child)+RAY_BB_TEST_COST; + return node; + } + else + { + Node *node = bvh_new_node(tree); + float parent_area; + + INIT_MINMAX(node->bb, node->bb+3); + rtbuild_merge_bb(builder, node->bb, node->bb+3); + + parent_area = bb_area( node->bb, node->bb+3 ); + Node **child = &node->child; + + std::queue childs; + childs.push(*builder); + + *cost = 0; + + while(!childs.empty()) + { + Builder b = childs.front(); + childs.pop(); + + float hit_prob = rtbuild_area(&b) / parent_area; + if(hit_prob > 1.0f / 2.0f && rtbuild_size(&b) > 1) + { + //The expected number of BB test is smaller if we directly add the 2 childs of this node + int nc = rtbuild_split(&b, 2); + assert(nc == 2); + for(int i=0; i(tree, &b, &tcost); + child = &((*child)->sibling); + + *cost += tcost*hit_prob + RAY_BB_TEST_COST; + } + } + assert(child != &node->child); + *child = 0; + + return node; + } +} + +template<> +void bvh_done(BVHTree *obj) +{ + int needed_nodes = (rtbuild_size(obj->builder)+1)*2; + if(needed_nodes > BLI_MEMARENA_STD_BUFSIZE) + needed_nodes = BLI_MEMARENA_STD_BUFSIZE; + + obj->node_arena = BLI_memarena_new(needed_nodes); + BLI_memarena_use_malloc(obj->node_arena); + + + obj->root = bvh_rearrange( obj, obj->builder, &obj->cost ); + obj->cost = 1.0; + + rtbuild_free( obj->builder ); + obj->builder = NULL; +} + +template<> +int bvh_intersect(BVHTree *obj, Isect* isec) +{ + if(RayObject_isAligned(obj->root)) + return bvh_node_stack_raycast(obj->root, isec); + else + return RE_rayobject_intersect( (RayObject*) obj->root, isec ); +} + +/* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */ +static RayObjectAPI bvh_api = +{ + (RE_rayobject_raycast_callback) ((int(*)(BVHTree*,Isect*)) &bvh_intersect), + (RE_rayobject_add_callback) ((void(*)(BVHTree*,RayObject*)) &bvh_add), + (RE_rayobject_done_callback) ((void(*)(BVHTree*)) &bvh_done), + (RE_rayobject_free_callback) ((void(*)(BVHTree*)) &bvh_free), + (RE_rayobject_merge_bb_callback)((void(*)(BVHTree*,float*,float*)) &bvh_bb), + (RE_rayobject_cost_callback) ((float(*)(BVHTree*)) &bvh_cost) +}; + +RayObject *RE_rayobject_vbvh_create(int size) +{ + BVHTree *obj= (BVHTree*)MEM_callocN(sizeof(BVHTree), "BVHTree"); + assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ + + obj->rayobj.api = &bvh_api; + obj->root = NULL; + + obj->node_arena = NULL; + obj->builder = rtbuild_create( size ); + + return RayObject_unalignRayAPI((RayObject*) obj); +} diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index b967f2bd8ce..52edd7a7e27 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -70,8 +70,13 @@ extern struct Render R; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -RayObject *RE_rayobject_tree_create(int type, int size) +RayObject * RE_rayobject_tree_create(int type, int size) __attribute__((noinline)); + +RayObject * RE_rayobject_tree_create(int type, int size) { +// if(type == R_RAYTRACE_TREE_BIH) + return RE_rayobject_vbvh_create(size); + if(type == R_RAYTRACE_TREE_BVH) return RE_rayobject_bvh_create(size); if(type == R_RAYTRACE_TREE_BIH) @@ -79,7 +84,6 @@ RayObject *RE_rayobject_tree_create(int type, int size) if(type == R_RAYTRACE_TREE_BLIBVH) return RE_rayobject_blibvh_create(size); - return RE_rayobject_bvh_create(size); } #ifdef RE_RAYCOUNTER From 7afffd2950aba313de3cab1c74657380aaf08067 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 14 Jul 2009 23:08:55 +0000 Subject: [PATCH 054/138] Just another experimental stuff to optimize the expected number of BB test on bvh trees *tree pushdowns after the pushsups :P (its still not local optimum) --- source/blender/blenlib/intern/BLI_memarena.c | 1 + .../render/intern/include/rayobject_rtbuild.h | 1 + .../intern/raytrace/rayobject_rtbuild.cpp | 12 +++ .../render/intern/raytrace/rayobject_vbvh.cpp | 100 +++++++++++++++--- 4 files changed, 101 insertions(+), 13 deletions(-) diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c index 87d2f0426b2..6312cbb22ca 100644 --- a/source/blender/blenlib/intern/BLI_memarena.c +++ b/source/blender/blenlib/intern/BLI_memarena.c @@ -95,3 +95,4 @@ void *BLI_memarena_alloc(MemArena *ma, int size) { return ptr; } + diff --git a/source/blender/render/intern/include/rayobject_rtbuild.h b/source/blender/render/intern/include/rayobject_rtbuild.h index b80e0868739..ed8560d948a 100644 --- a/source/blender/render/intern/include/rayobject_rtbuild.h +++ b/source/blender/render/intern/include/rayobject_rtbuild.h @@ -92,6 +92,7 @@ int rtbuild_median_split_largest_axis(RTBuilder *b, int nchilds); float bb_area(float *min, float *max); float bb_volume(float *min, float *max); int bb_largest_axis(float *min, float *max); +int bb_fits_inside(float *outer_min, float *outer_max, float *inner_min, float *inner_max); /* only returns 0 if merging inner and outerbox would create a box larger than outer box */ #ifdef __cplusplus } diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp index dff0b02c00e..86a92417d03 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp @@ -529,3 +529,15 @@ int bb_largest_axis(float *min, float *max) return 2; } } + +int bb_fits_inside(float *outer_min, float *outer_max, float *inner_min, float *inner_max) +{ + int i; + for(i=0; i<3; i++) + if(outer_min[i] > inner_min[i]) return 0; + + for(i=0; i<3; i++) + if(outer_max[i] < inner_max[i]) return 0; + + return 1; +} diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index 3f8f69a5abe..b4d30b51358 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -128,6 +128,41 @@ void bvh_update_bb(Node *node) } +static int tot_pushup = 0; +static int tot_pushdown = 0; + +template +void pushdown(Node *parent) +{ + Node **s_child = &parent->child; + Node * child = parent->child; + + while(child && RayObject_isAligned(child)) + { + Node *next = child->sibling; + + assert(bb_fits_inside(parent->bb, parent->bb+3, child->bb, child->bb+3)); + + for(Node *i = parent->child; RayObject_isAligned(i) && i; i = i->sibling) + if(child != i && bb_fits_inside(i->bb, i->bb+3, child->bb, child->bb+3)) + { +// todo optimize (hsould the one with the smallest area +// float ia = bb_area(i->bb, i->bb+3) +// if(child->i) + *s_child = child->sibling; + child->sibling = i->child; + i->child = child; + + tot_pushdown++; + break; + } + child = next; + } + + for(Node *i = parent->child; RayObject_isAligned(i) && i; i = i->sibling) + pushdown( i ); +} + template Node *bvh_rearrange(Tree *tree, Builder *builder, float *cost) { @@ -177,6 +212,7 @@ Node *bvh_rearrange(Tree *tree, Builder *builder, float *cost) rtbuild_get_child(&b, i, &tmp); childs.push(tmp); } + tot_pushup++; } else @@ -207,38 +243,76 @@ void bvh_done(BVHTree *obj) obj->root = bvh_rearrange( obj, obj->builder, &obj->cost ); + pushdown(obj->root); obj->cost = 1.0; rtbuild_free( obj->builder ); obj->builder = NULL; } -template<> -int bvh_intersect(BVHTree *obj, Isect* isec) +template +int intersect(BVHTree *obj, Isect* isec) { if(RayObject_isAligned(obj->root)) - return bvh_node_stack_raycast(obj->root, isec); + return bvh_node_stack_raycast(obj->root, isec); else return RE_rayobject_intersect( (RayObject*) obj->root, isec ); } -/* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */ -static RayObjectAPI bvh_api = + +void bfree(BVHTree *tree) { - (RE_rayobject_raycast_callback) ((int(*)(BVHTree*,Isect*)) &bvh_intersect), - (RE_rayobject_add_callback) ((void(*)(BVHTree*,RayObject*)) &bvh_add), - (RE_rayobject_done_callback) ((void(*)(BVHTree*)) &bvh_done), - (RE_rayobject_free_callback) ((void(*)(BVHTree*)) &bvh_free), - (RE_rayobject_merge_bb_callback)((void(*)(BVHTree*,float*,float*)) &bvh_bb), - (RE_rayobject_cost_callback) ((float(*)(BVHTree*)) &bvh_cost) -}; + if(tot_pushup + tot_pushdown) + { + printf("tot pushups: %d\n", tot_pushup); + printf("tot pushdowns: %d\n", tot_pushdown); + tot_pushup = 0; + tot_pushdown = 0; + } + bvh_free(tree); +} + +/* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */ +template +static RayObjectAPI make_api() +{ + static RayObjectAPI api = + { + (RE_rayobject_raycast_callback) ((int(*)(BVHTree*,Isect*)) &intersect), + (RE_rayobject_add_callback) ((void(*)(BVHTree*,RayObject*)) &bvh_add), + (RE_rayobject_done_callback) ((void(*)(BVHTree*)) &bvh_done), +// (RE_rayobject_free_callback) ((void(*)(BVHTree*)) &bvh_free), + (RE_rayobject_free_callback) ((void(*)(BVHTree*)) &bfree), + (RE_rayobject_merge_bb_callback)((void(*)(BVHTree*,float*,float*)) &bvh_bb), + (RE_rayobject_cost_callback) ((float(*)(BVHTree*)) &bvh_cost) + }; + + return api; +} + +static RayObjectAPI* get_api(int maxstacksize) +{ +// static RayObjectAPI bvh_api16 = make_api<16>(); +// static RayObjectAPI bvh_api32 = make_api<32>(); +// static RayObjectAPI bvh_api64 = make_api<64>(); + static RayObjectAPI bvh_api128 = make_api<128>(); + static RayObjectAPI bvh_api256 = make_api<256>(); + +// if(maxstacksize <= 16 ) return &bvh_api16; +// if(maxstacksize <= 32 ) return &bvh_api32; +// if(maxstacksize <= 64 ) return &bvh_api64; + if(maxstacksize <= 128) return &bvh_api128; + if(maxstacksize <= 256) return &bvh_api256; + assert(maxstacksize <= 256); + return 0; +} RayObject *RE_rayobject_vbvh_create(int size) { BVHTree *obj= (BVHTree*)MEM_callocN(sizeof(BVHTree), "BVHTree"); assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ - obj->rayobj.api = &bvh_api; + obj->rayobj.api = get_api(DFS_STACK_SIZE); obj->root = NULL; obj->node_arena = NULL; From e3f7cad32d4c597fec7576fe5530f5adc9a33159 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 14 Jul 2009 23:26:00 +0000 Subject: [PATCH 055/138] *fix (was losing childs) --- source/blender/render/intern/raytrace/rayobject_vbvh.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index b4d30b51358..305de145a72 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -140,6 +140,7 @@ void pushdown(Node *parent) while(child && RayObject_isAligned(child)) { Node *next = child->sibling; + Node **next_s_child = &child->sibling; assert(bb_fits_inside(parent->bb, parent->bb+3, child->bb, child->bb+3)); @@ -152,11 +153,13 @@ void pushdown(Node *parent) *s_child = child->sibling; child->sibling = i->child; i->child = child; + next_s_child = s_child; tot_pushdown++; break; } child = next; + s_child = next_s_child; } for(Node *i = parent->child; RayObject_isAligned(i) && i; i = i->sibling) From ef1fcd8ad1d8fb4feed704286982e8b5be03b149 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 15 Jul 2009 17:38:00 +0000 Subject: [PATCH 056/138] *Added support to "BB hints" (which works like a BB version of LCTS - longest common transversing subtree) It creates a tree cut after knowing that a given point will pass on a BB. This tree cut is used to accelarate the rays casted from a given BB, eliminating unnecessary BB tests from root till the tree cut. --- .../render/extern/include/RE_raytrace.h | 26 +++++- .../blender/render/intern/include/rayobject.h | 2 + source/blender/render/intern/raytrace/bvh.h | 5 +- .../render/intern/raytrace/rayobject_bvh.cpp | 2 +- .../render/intern/raytrace/rayobject_vbvh.cpp | 86 +++++++++++++++++-- .../blender/render/intern/source/rayobject.c | 14 +++ .../blender/render/intern/source/rayshade.c | 61 +++++++------ 7 files changed, 161 insertions(+), 35 deletions(-) diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index 4d0c0b1a88c..beae1b84b04 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -36,6 +36,7 @@ extern "C" { #endif +#define RE_RAY_LCTS_MAX_SIZE 256 #define RT_USE_LAST_HIT /* last shadow hit is reused before raycasting on whole tree */ //#define RT_USE_HINT /* last hit object is reused before raycasting on whole tree */ @@ -76,7 +77,7 @@ extern RayCounter re_rc_counter[]; /* Internals about raycasting structures can be found on intern/raytree.h */ typedef struct RayObject RayObject; typedef struct Isect Isect; - +typedef struct RayHint RayHint; typedef struct RayTraceHint RayTraceHint; struct DerivedMesh; @@ -87,6 +88,12 @@ void RE_rayobject_add (RayObject *r, RayObject *); void RE_rayobject_done(RayObject *r); void RE_rayobject_free(RayObject *r); +/* initializes an hint for optiming raycast where it is know that a ray will pass by the given BB often the origin point */ +void RE_rayobject_hint_bb(RayObject *r, RayHint *hint, float *min, float *max); + +/* initializes an hint for optiming raycast where it is know that a ray will be contained inside the given cone*/ +/* void RE_rayobject_hint_cone(RayObject *r, RayHint *hint, float *); */ + /* RayObject constructors */ RayObject* RE_rayobject_octree_create(int ocres, int size); @@ -97,6 +104,21 @@ RayObject* RE_rayobject_bvh_create(int size); /* raytrace/rayobject_bvh.c */ RayObject* RE_rayobject_vbvh_create(int size); /* raytrace/rayobject_vbvh.c */ RayObject* RE_rayobject_bih_create(int size); /* rayobject_bih.c */ +typedef struct LCTSHint LCTSHint; +struct LCTSHint +{ + int size; + RayObject *stack[RE_RAY_LCTS_MAX_SIZE]; +}; + +struct RayHint +{ + union + { + LCTSHint lcts; + } data; +}; + /* Ray Intersection */ struct Isect @@ -137,6 +159,8 @@ struct Isect void *userdata; + RayHint *hint; + #ifdef RE_RAYCOUNTER RayCounter *raycounter; #endif diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index 16ebc537ef9..6f8debead19 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -98,6 +98,7 @@ typedef void (*RE_rayobject_done_callback)(RayObject *); typedef void (*RE_rayobject_free_callback)(RayObject *); typedef void (*RE_rayobject_merge_bb_callback)(RayObject *, float *min, float *max); typedef float (*RE_rayobject_cost_callback)(RayObject *); +typedef void (*RE_rayobject_hint_bb_callback)(RayObject *, RayHint *, float *, float *); typedef struct RayObjectAPI { @@ -107,6 +108,7 @@ typedef struct RayObjectAPI RE_rayobject_free_callback free; RE_rayobject_merge_bb_callback bb; RE_rayobject_cost_callback cost; + RE_rayobject_hint_bb_callback hint_bb; } RayObjectAPI; diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h index d9277f9a583..8f7e6111684 100644 --- a/source/blender/render/intern/raytrace/bvh.h +++ b/source/blender/render/intern/raytrace/bvh.h @@ -93,14 +93,13 @@ static void bvh_node_merge_bb(Node *node, float *min, float *max) */ template static inline void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, int &stack_pos); -template +template static int bvh_node_stack_raycast(Node *root, Isect *isec) { Node *stack[MAX_STACK_SIZE]; int hit = 0, stack_pos = 0; - //Assume the BB of root always succeed - if(1) + if(!TEST_ROOT && RayObject_isAligned(root)) bvh_node_push_childs(root, isec, stack, stack_pos); else stack[stack_pos++] = root; diff --git a/source/blender/render/intern/raytrace/rayobject_bvh.cpp b/source/blender/render/intern/raytrace/rayobject_bvh.cpp index 2c2a260df98..435c49cdc42 100644 --- a/source/blender/render/intern/raytrace/rayobject_bvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_bvh.cpp @@ -199,7 +199,7 @@ template<> int bvh_intersect(BVHTree *obj, Isect* isec) { if(RayObject_isAligned(obj->root)) - return bvh_node_stack_raycast(obj->root, isec); + return bvh_node_stack_raycast(obj->root, isec); else return RE_rayobject_intersect( (RayObject*) obj->root, isec ); } diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index 305de145a72..ce3218c25fa 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -130,6 +130,7 @@ void bvh_update_bb(Node *node) static int tot_pushup = 0; static int tot_pushdown = 0; +static int tot_hints = 0; template void pushdown(Node *parent) @@ -142,7 +143,7 @@ void pushdown(Node *parent) Node *next = child->sibling; Node **next_s_child = &child->sibling; - assert(bb_fits_inside(parent->bb, parent->bb+3, child->bb, child->bb+3)); + //assert(bb_fits_inside(parent->bb, parent->bb+3, child->bb, child->bb+3)); for(Node *i = parent->child; RayObject_isAligned(i) && i; i = i->sibling) if(child != i && bb_fits_inside(i->bb, i->bb+3, child->bb, child->bb+3)) @@ -256,21 +257,93 @@ void bvh_done(BVHTree *obj) template int intersect(BVHTree *obj, Isect* isec) { - if(RayObject_isAligned(obj->root)) - return bvh_node_stack_raycast(obj->root, isec); + if(isec->hint) + { + LCTSHint *lcts = (LCTSHint*)isec->hint; + isec->hint = 0; + + int hit = 0; + for(int i=0; isize; i++) + { + BVHNode *node = (BVHNode*)lcts->stack[i]; + if(RayObject_isAligned(node)) + hit |= bvh_node_stack_raycast(node, isec); + else + hit |= RE_rayobject_intersect( (RayObject*)node, isec ); + + if(hit && isec->mode == RE_RAY_SHADOW) + break; + } + isec->hint = (RayHint*)lcts; + return hit; + } else - return RE_rayobject_intersect( (RayObject*) obj->root, isec ); + { + if(RayObject_isAligned(obj->root)) + return bvh_node_stack_raycast(obj->root, isec); + else + return RE_rayobject_intersect( (RayObject*) obj->root, isec ); + } } +template +void bvh_dfs_make_hint(Node *node, LCTSHint *hint, int reserve_space, float *min, float *max); + +template +void bvh_dfs_make_hint_push_siblings(Node *node, LCTSHint *hint, int reserve_space, float *min, float *max) +{ + if(!RayObject_isAligned(node)) + hint->stack[hint->size++] = (RayObject*)node; + else + { + if(node->sibling) + bvh_dfs_make_hint_push_siblings(node->sibling, hint, reserve_space+1, min, max); + + bvh_dfs_make_hint(node, hint, reserve_space, min, max); + } + + +} + +template +void bvh_dfs_make_hint(Node *node, LCTSHint *hint, int reserve_space, float *min, float *max) +{ + assert( hint->size - reserve_space + 1 <= RE_RAY_LCTS_MAX_SIZE ); + + if(hint->size - reserve_space + 1 == RE_RAY_LCTS_MAX_SIZE || !RayObject_isAligned(node)) + hint->stack[hint->size++] = (RayObject*)node; + else + { + /* We are 100% sure the ray will be pass inside this node */ + if(bb_fits_inside(node->bb, node->bb+3, min, max) ) + { + bvh_dfs_make_hint_push_siblings(node->child, hint, reserve_space, min, max); + } + else + { + hint->stack[hint->size++] = (RayObject*)node; + } + } +} + +template +void bvh_hint_bb(Tree *tree, LCTSHint *hint, float *min, float *max) +{ + hint->size = 0; + bvh_dfs_make_hint( tree->root, hint, 0, min, max ); + tot_hints++; +} void bfree(BVHTree *tree) { - if(tot_pushup + tot_pushdown) + if(tot_pushup + tot_pushdown + tot_hints) { printf("tot pushups: %d\n", tot_pushup); printf("tot pushdowns: %d\n", tot_pushdown); + printf("tot hints created: %d\n", tot_hints); tot_pushup = 0; tot_pushdown = 0; + tot_hints = 0; } bvh_free(tree); } @@ -287,7 +360,8 @@ static RayObjectAPI make_api() // (RE_rayobject_free_callback) ((void(*)(BVHTree*)) &bvh_free), (RE_rayobject_free_callback) ((void(*)(BVHTree*)) &bfree), (RE_rayobject_merge_bb_callback)((void(*)(BVHTree*,float*,float*)) &bvh_bb), - (RE_rayobject_cost_callback) ((float(*)(BVHTree*)) &bvh_cost) + (RE_rayobject_cost_callback) ((float(*)(BVHTree*)) &bvh_cost), + (RE_rayobject_hint_bb_callback) ((void(*)(BVHTree*,LCTSHint*,float*,float*)) &bvh_hint_bb) }; return api; diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index 949b7afb5a0..2e63dc78c0e 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -414,6 +414,20 @@ float RE_rayobject_cost(RayObject *r) else assert(0); } +void RE_rayobject_hint_bb(RayObject *r, RayHint *hint, float *min, float *max) +{ + if(RayObject_isRayFace(r)) + { + return; + } + else if(RayObject_isRayAPI(r)) + { + r = RayObject_align( r ); + return r->api->hint_bb( r, hint, min, max ); + } + else assert(0); +} + #ifdef RE_RAYCOUNTER void RE_RC_INFO(RayCounter *info) { diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 52edd7a7e27..66f564d4364 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -624,9 +624,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo isec.labda = dist_mir > 0 ? dist_mir : RE_RAYTRACE_MAXDIST; isec.mode= RE_RAY_MIRROR; isec.skip = RE_SKIP_VLR_NEIGHBOUR; -#ifdef RT_USE_HINT isec.hint = 0; -#endif isec.orig.ob = obi; isec.orig.face = vlr; @@ -1532,9 +1530,10 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr) isec.mode= RE_RAY_MIRROR; isec.orig.ob = ship->obi; isec.orig.face = ship->vlr; -#ifdef RT_USE_HINT isec.hint = 0; -#endif + + VECCOPY(isec.start, ship->co); + RE_RC_INIT(isec, shi); for(a=0; a<8*8; a++) { @@ -1548,7 +1547,6 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr) vec[2]-= vec[2]; } - VECCOPY(isec.start, ship->co); VECCOPY(isec.vec, vec ); isec.labda = RE_RAYTRACE_MAXDIST; @@ -1725,6 +1723,7 @@ static float *sphere_sampler(int type, int resol, int thread, int xs, int ys) static void ray_ao_qmc(ShadeInput *shi, float *shadfac) { Isect isec; + RayHint point_hint; QMCSampler *qsa=NULL; float samp3d[3]; float up[3], side[3], dir[3], nrm[3]; @@ -1744,9 +1743,7 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) isec.orig.ob = shi->obi; isec.orig.face = shi->vlr; isec.skip = RE_SKIP_VLR_NEIGHBOUR; -#ifdef RT_USE_HINT isec.hint = 0; -#endif isec.hit.ob = 0; isec.hit.face = 0; @@ -1756,6 +1753,11 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) isec.mode= (R.wrld.aomode & WO_AODIST)?RE_RAY_SHADOW_TRA:RE_RAY_SHADOW; isec.lay= -1; + VECCOPY(isec.start, shi->co); + RE_rayobject_hint_bb( R.raytree, &point_hint, isec.start, isec.start ); + isec.hint = &point_hint; + + shadfac[0]= shadfac[1]= shadfac[2]= 0.0f; /* prevent sky colors to be added for only shadow (shadow becomes alpha) */ @@ -1793,6 +1795,7 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) QMC_initPixel(qsa, shi->thread); + while (samples < max_samples) { /* sampling, returns quasi-random vector in unit hemisphere */ @@ -1804,7 +1807,6 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) Normalize(dir); - VECCOPY(isec.start, shi->co); isec.vec[0] = -dir[0]; isec.vec[1] = -dir[1]; isec.vec[2] = -dir[2]; @@ -1872,6 +1874,7 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) { Isect isec; + RayHint point_hint; float *vec, *nrm, div, bias, sh=0.0f; float maxdist = R.wrld.aodist; float dxyview[3]; @@ -1881,9 +1884,7 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) isec.orig.ob = shi->obi; isec.orig.face = shi->vlr; isec.skip = RE_SKIP_VLR_NEIGHBOUR; -#ifdef RT_USE_HINT isec.hint = 0; -#endif isec.hit.ob = 0; isec.hit.face = 0; @@ -1893,6 +1894,9 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) isec.mode= (R.wrld.aomode & WO_AODIST)?RE_RAY_SHADOW_TRA:RE_RAY_SHADOW; isec.lay= -1; + VECCOPY(isec.start, shi->co); + RE_rayobject_hint_bb( R.raytree, &point_hint, isec.start, isec.start ); + isec.hint = &point_hint; shadfac[0]= shadfac[1]= shadfac[2]= 0.0f; @@ -1940,7 +1944,6 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) actual++; /* always set start/vec/labda */ - VECCOPY(isec.start, shi->co); isec.vec[0] = -vec[0]; isec.vec[1] = -vec[1]; isec.vec[2] = -vec[2]; @@ -2058,7 +2061,10 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * float adapt_thresh = lar->adapt_thresh; int min_adapt_samples=4, max_samples = lar->ray_totsamp; float *co; - int do_soft=1, full_osa=0; + int do_soft=1, full_osa=0, i; + + float min[3], max[3]; + RayHint bb_hint; float jitco[RE_MAX_OSA][3]; int totjitco; @@ -2089,10 +2095,18 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * qsa = get_thread_qmcsampler(&R, shi->thread, SAMP_TYPE_HAMMERSLEY, max_samples); QMC_initPixel(qsa, shi->thread); + + INIT_MINMAX(min, max); + for(i=0; ihint = &bb_hint; + isec->skip = RE_SKIP_VLR_NEIGHBOUR; VECCOPY(vec, lampco); - isec->skip = RE_SKIP_VLR_NEIGHBOUR; while (samples < max_samples) { isec->orig.ob = shi->obi; @@ -2215,6 +2229,7 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa float *jitlamp; float fac=0.0f, div=0.0f, vec[3]; int a, j= -1, mask; + RayHint point_hint; if(isec->mode==RE_RAY_SHADOW_TRA) { shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 0.0f; @@ -2231,6 +2246,12 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa if(a==4) mask |= (mask>>4)|(mask>>8); else if(a==9) mask |= (mask>>9); + VECCOPY(isec->start, shi->co); + isec->orig.ob = shi->obi; + isec->orig.face = shi->vlr; + RE_rayobject_hint_bb( R.raytree, &point_hint, isec->start, isec->start ); + isec->hint = &point_hint; + while(a--) { if(R.r.mode & R_OSA) { @@ -2242,19 +2263,15 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa } } - isec->orig.ob = shi->obi; - isec->orig.face = shi->vlr; - vec[0]= jitlamp[0]; vec[1]= jitlamp[1]; vec[2]= 0.0f; Mat3MulVecfl(lar->mat, vec); /* set start and vec */ - VECCOPY(isec->start, shi->co); - isec->vec[0] = vec[0]+lampco[0]-shi->co[0]; - isec->vec[1] = vec[1]+lampco[1]-shi->co[1]; - isec->vec[2] = vec[2]+lampco[2]-shi->co[2]; + isec->vec[0] = vec[0]+lampco[0]-isec->start[0]; + isec->vec[1] = vec[1]+lampco[1]-isec->start[1]; + isec->vec[2] = vec[2]+lampco[2]-isec->start[2]; isec->labda = 1.0f; isec->skip = RE_SKIP_VLR_NEIGHBOUR; @@ -2299,9 +2316,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) RE_RC_INIT(isec, *shi); if(shi->mat->mode & MA_SHADOW_TRA) isec.mode= RE_RAY_SHADOW_TRA; else isec.mode= RE_RAY_SHADOW; -#ifdef RT_USE_HINT isec.hint = 0; -#endif if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) isec.lay= lar->lay; @@ -2390,9 +2405,7 @@ static void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float /* setup isec */ RE_RC_INIT(isec, *shi); isec.mode= RE_RAY_SHADOW_TRA; -#ifdef RT_USE_HINT isec.hint = 0; -#endif if(lar->mode & LA_LAYER) isec.lay= lar->lay; else isec.lay= -1; From 146b54d5e85c809858520674b2222f46e8ef1601 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 15 Jul 2009 17:44:25 +0000 Subject: [PATCH 057/138] *increased stack size (later this should be prepared for dealing with stack size in runtime) *put cost model back to normal --- source/blender/render/intern/raytrace/rayobject_vbvh.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index ce3218c25fa..8c2139fe6ca 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -45,7 +45,7 @@ extern "C" #define BVHTree VBVHTree #define RAY_BB_TEST_COST (0.2f) -#define DFS_STACK_SIZE 128 +#define DFS_STACK_SIZE 256 #define DYNAMIC_ALLOC //#define rtbuild_split rtbuild_mean_split_largest_axis /* objects mean split on the longest axis, childs BB are allowed to overlap */ @@ -248,7 +248,7 @@ void bvh_done(BVHTree *obj) obj->root = bvh_rearrange( obj, obj->builder, &obj->cost ); pushdown(obj->root); - obj->cost = 1.0; +// obj->cost = 1.0; rtbuild_free( obj->builder ); obj->builder = NULL; From 2830f25ff3bf7a80c88b86132f76081ced3e86a1 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 17 Jul 2009 19:09:42 +0000 Subject: [PATCH 058/138] Another try with building better trees (this should never make worst trees) Expected number of BB tests should reduce a bit (depending on the scene) --- .../render/intern/raytrace/rayobject_vbvh.cpp | 134 ++++++++++------- .../render/intern/raytrace/reorganize.h | 138 ++++++++++++++++++ 2 files changed, 222 insertions(+), 50 deletions(-) create mode 100644 source/blender/render/intern/raytrace/reorganize.h diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index 8c2139fe6ca..17ed63e3669 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -38,6 +38,7 @@ extern "C" #include "rayobject.h" }; +#include "reorganize.h" #include "bvh.h" #include @@ -146,9 +147,9 @@ void pushdown(Node *parent) //assert(bb_fits_inside(parent->bb, parent->bb+3, child->bb, child->bb+3)); for(Node *i = parent->child; RayObject_isAligned(i) && i; i = i->sibling) - if(child != i && bb_fits_inside(i->bb, i->bb+3, child->bb, child->bb+3)) + if(child != i && bb_fits_inside(i->bb, i->bb+3, child->bb, child->bb+3) && RayObject_isAligned(i->child)) { -// todo optimize (hsould the one with the smallest area +// todo optimize (should the one with the smallest area?) // float ia = bb_area(i->bb, i->bb+3) // if(child->i) *s_child = child->sibling; @@ -167,8 +168,65 @@ void pushdown(Node *parent) pushdown( i ); } +template +int count_childs(Node *parent) +{ + int n = 0; + for(Node *i = parent->child; i; i = i->sibling) + { + n++; + if(!RayObject_isAligned(i)) + break; + } + + return n; +} + +template +void append_sibling(Node *node, Node *sibling) +{ + while(node->sibling) + node = node->sibling; + + node->sibling = sibling; +} + +template +void pushup(Node *parent) +{ + float p_area = bb_area(parent->bb, parent->bb+3); + Node **prev = &parent->child; + for(Node *child = parent->child; RayObject_isAligned(child) && child; ) + { + float c_area = bb_area(child->bb, child->bb+3) ; + int nchilds = count_childs(child); + float original_cost = (c_area / p_area)*nchilds + 1; + float flatten_cost = nchilds; + if(flatten_cost < original_cost && nchilds >= 2) + { + append_sibling(child, child->child); + child = child->sibling; + *prev = child; + +// *prev = child->child; +// append_sibling( *prev, child->sibling ); +// child = *prev; + tot_pushup++; + } + else + { + *prev = child; + prev = &(*prev)->sibling; + child = *prev; + } + } + + for(Node *child = parent->child; RayObject_isAligned(child) && child; child = child->sibling) + pushup(child); +} + template -Node *bvh_rearrange(Tree *tree, Builder *builder, float *cost) +Node *bvh_rearrange(Tree *tree, Builder *builder) { int size = rtbuild_size(builder); @@ -176,61 +234,31 @@ Node *bvh_rearrange(Tree *tree, Builder *builder, float *cost) { Node *node = bvh_new_node(tree); INIT_MINMAX(node->bb, node->bb+3); - rtbuild_merge_bb(builder, node->bb, node->bb+3); - + rtbuild_merge_bb(builder, node->bb, node->bb+3); node->child = (BVHNode*)builder->begin[0]; - - *cost = RE_rayobject_cost((RayObject*)node->child)+RAY_BB_TEST_COST; return node; } else { Node *node = bvh_new_node(tree); - float parent_area; - + INIT_MINMAX(node->bb, node->bb+3); rtbuild_merge_bb(builder, node->bb, node->bb+3); - parent_area = bb_area( node->bb, node->bb+3 ); Node **child = &node->child; - - std::queue childs; - childs.push(*builder); - - *cost = 0; - - while(!childs.empty()) - { - Builder b = childs.front(); - childs.pop(); - - float hit_prob = rtbuild_area(&b) / parent_area; - if(hit_prob > 1.0f / 2.0f && rtbuild_size(&b) > 1) - { - //The expected number of BB test is smaller if we directly add the 2 childs of this node - int nc = rtbuild_split(&b, 2); - assert(nc == 2); - for(int i=0; i(tree, &b, &tcost); - child = &((*child)->sibling); - - *cost += tcost*hit_prob + RAY_BB_TEST_COST; - } - } - assert(child != &node->child); - *child = 0; + int nc = rtbuild_split(builder, 2); + assert(nc == 2); + for(int i=0; i(tree, &tmp); + child = &((*child)->sibling); + } + + *child = 0; return node; } } @@ -246,9 +274,13 @@ void bvh_done(BVHTree *obj) BLI_memarena_use_malloc(obj->node_arena); - obj->root = bvh_rearrange( obj, obj->builder, &obj->cost ); + obj->root = bvh_rearrange( obj, obj->builder ); + reorganize(obj->root); + remove_useless(obj->root, &obj->root); + pushup(obj->root); pushdown(obj->root); -// obj->cost = 1.0; +// obj->root = memory_rearrange(obj->root); + obj->cost = 1.0; rtbuild_free( obj->builder ); obj->builder = NULL; @@ -336,14 +368,16 @@ void bvh_hint_bb(Tree *tree, LCTSHint *hint, float *min, float *max) void bfree(BVHTree *tree) { - if(tot_pushup + tot_pushdown + tot_hints) + if(tot_pushup + tot_pushdown + tot_hints + tot_moves) { printf("tot pushups: %d\n", tot_pushup); printf("tot pushdowns: %d\n", tot_pushdown); + printf("tot moves: %d\n", tot_moves); printf("tot hints created: %d\n", tot_hints); tot_pushup = 0; tot_pushdown = 0; tot_hints = 0; + tot_moves = 0; } bvh_free(tree); } diff --git a/source/blender/render/intern/raytrace/reorganize.h b/source/blender/render/intern/raytrace/reorganize.h new file mode 100644 index 00000000000..723c2b77902 --- /dev/null +++ b/source/blender/render/intern/raytrace/reorganize.h @@ -0,0 +1,138 @@ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#include +#include + +template +bool node_fits_inside(Node *a, Node *b) +{ + return bb_fits_inside(b->bb, b->bb+3, a->bb, a->bb+3); +} + +template +void reorganize_find_fittest_parent(Node *tree, Node *node, std::pair &cost) +{ + std::queue q; + q.push(tree); + + while(!q.empty()) + { + Node *parent = q.front(); + q.pop(); + + if(parent == node) continue; + if(node_fits_inside(node, parent) && RayObject_isAligned(parent->child) ) + { + float pcost = bb_area(parent->bb, parent->bb+3); + cost = std::min( cost, std::make_pair(pcost,parent) ); + for(Node *child = parent->child; child; child = child->sibling) + q.push(child); + } + } +} + +static int tot_moves = 0; +template +void reorganize(Node *root) +{ + std::queue q; + + q.push(root); + while(!q.empty()) + { + Node * node = q.front(); + q.pop(); + + if( RayObject_isAligned(node->child) ) + { + for(Node **prev = &node->child; *prev; ) + { + assert( RayObject_isAligned(*prev) ); + q.push(*prev); + + std::pair best(FLT_MAX, root); + reorganize_find_fittest_parent( root, *prev, best ); + + if(best.second == node) + { + //Already inside the fitnest BB + prev = &(*prev)->sibling; + } + else + { + Node *tmp = *prev; + *prev = (*prev)->sibling; + + tmp->sibling = best.second->child; + best.second->child = tmp; + + tot_moves++; + } + + + } + } + if(node != root) + { + } + } +} + +/* + * Prunes useless nodes from trees: + * erases nodes with total ammount of primitives = 0 + * prunes nodes with only one child (except if that child is a primitive) + */ +template +void remove_useless(Node *node, Node **new_node) +{ + if( RayObject_isAligned(node->child) ) + { + + for(Node **prev = &node->child; *prev; ) + { + Node *next = (*prev)->sibling; + remove_useless(*prev, prev); + if(*prev == 0) + *prev = next; + else + { + (*prev)->sibling = next; + prev = &((*prev)->sibling); + } + } + } + if(node->child) + { + if(RayObject_isAligned(node->child) && node->child->child == 0) + *new_node = node->child; + } + else if(node->child == 0) + *new_node = 0; +} From bee82a360ef250b09f8af3216b1743334fb366b0 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 2 Aug 2009 11:32:03 +0000 Subject: [PATCH 059/138] Another quick-fix for background mode --- source/blender/windowmanager/intern/wm_init_exit.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 599844f1020..41d35ca9be4 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -228,7 +228,10 @@ void WM_exit(bContext *C) fastshade_free_render(); /* shaded view */ ED_preview_free_dbase(); /* frees a Main dbase, before free_blender! */ - wm_free_reports(C); /* before free_blender! - since the ListBases get freed there */ + + if(C && CTX_wm_manager(C)) + wm_free_reports(C); /* before free_blender! - since the ListBases get freed there */ + free_blender(); /* blender.c, does entire library and spacetypes */ // free_matcopybuf(); free_anim_copybuf(); From 84d86540ddd3ae6b0a23134db7c98bc59698b3cd Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 2 Aug 2009 12:11:14 +0000 Subject: [PATCH 060/138] changed to STL sort --- .../intern/raytrace/rayobject_rtbuild.cpp | 37 ++++++------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp index 86a92417d03..b0ac54bef2c 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "rayobject_rtbuild.h" #include "MEM_guardedalloc.h" @@ -198,34 +199,20 @@ struct CostObject float bb[6]; }; -//Ugly.. but using qsort and no globals its the cleaner I can get -#define costobject_cmp(axis) costobject_cmp##axis -#define define_costobject_cmp(axis) \ -int costobject_cmp(axis)(const CostObject *a, const CostObject *b) \ -{ \ - if(a->bb[axis] < b->bb[axis]) return -1; \ - if(a->bb[axis] > b->bb[axis]) return 1; \ - if(a->obj < b->obj) return -1; \ - if(a->obj > b->obj) return 1; \ - return 0; \ -} - -define_costobject_cmp(0) -define_costobject_cmp(1) -define_costobject_cmp(2) -define_costobject_cmp(3) -define_costobject_cmp(4) -define_costobject_cmp(5) +template +bool obj_bb_compare(const Obj &a, const Obj &b) +{ + if(a.bb[Axis] != b.bb[Axis]) + return a.bb[Axis] < b.bb[Axis]; + return a.obj < b.obj; +} void costobject_sort(CostObject *begin, CostObject *end, int axis) { - //TODO introsort - if(axis == 0) qsort(begin, end-begin, sizeof(*begin), (int(*)(const void *, const void *)) costobject_cmp(0)); - else if(axis == 1) qsort(begin, end-begin, sizeof(*begin), (int(*)(const void *, const void *)) costobject_cmp(1)); - else if(axis == 2) qsort(begin, end-begin, sizeof(*begin), (int(*)(const void *, const void *)) costobject_cmp(2)); - else if(axis == 3) qsort(begin, end-begin, sizeof(*begin), (int(*)(const void *, const void *)) costobject_cmp(3)); - else if(axis == 4) qsort(begin, end-begin, sizeof(*begin), (int(*)(const void *, const void *)) costobject_cmp(4)); - else if(axis == 5) qsort(begin, end-begin, sizeof(*begin), (int(*)(const void *, const void *)) costobject_cmp(5)); + if(axis == 0) return std::sort(begin, end, obj_bb_compare ); + if(axis == 1) return std::sort(begin, end, obj_bb_compare ); + if(axis == 2) return std::sort(begin, end, obj_bb_compare ); + assert(false); } From 29530beb904b9944b5ba0453cb5b5e873701b3db Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 3 Aug 2009 17:56:38 +0000 Subject: [PATCH 061/138] NlogN building: sort once select subsets and kept the order (on X, Y and Z) --- .../rayobject_bih.cpp} | 7 +- .../render/intern/raytrace/rayobject_bvh.cpp | 6 +- .../intern/raytrace/rayobject_rtbuild.cpp | 435 ++++++++---------- .../{include => raytrace}/rayobject_rtbuild.h | 26 +- .../render/intern/raytrace/rayobject_vbvh.cpp | 4 +- 5 files changed, 216 insertions(+), 262 deletions(-) rename source/blender/render/intern/{source/rayobject_bih.c => raytrace/rayobject_bih.cpp} (97%) rename source/blender/render/intern/{include => raytrace}/rayobject_rtbuild.h (87%) diff --git a/source/blender/render/intern/source/rayobject_bih.c b/source/blender/render/intern/raytrace/rayobject_bih.cpp similarity index 97% rename from source/blender/render/intern/source/rayobject_bih.c rename to source/blender/render/intern/raytrace/rayobject_bih.cpp index e2cb9bad302..102a347b470 100644 --- a/source/blender/render/intern/source/rayobject_bih.c +++ b/source/blender/render/intern/raytrace/rayobject_bih.cpp @@ -186,7 +186,7 @@ static BIHNode *bih_rearrange(BIHTree *tree, RTBuilder *builder, int nid, float { if(rtbuild_size(builder) == 1) { - RayObject *child = builder->begin[0]; + RayObject *child = rtbuild_get_primitive( builder, 0 ); assert(!RayObject_isAligned(child)); INIT_MINMAX(bb, bb+3); @@ -226,11 +226,6 @@ static BIHNode *bih_rearrange(BIHTree *tree, RTBuilder *builder, int nid, float } } -static void bih_info(BIHTree *obj) -{ - printf("BIH: Used %d nodes\n", obj->node_next - obj->node_alloc); -} - static void bih_done(BIHTree *obj) { int needed_nodes; diff --git a/source/blender/render/intern/raytrace/rayobject_bvh.cpp b/source/blender/render/intern/raytrace/rayobject_bvh.cpp index 435c49cdc42..48c1ac07cd4 100644 --- a/source/blender/render/intern/raytrace/rayobject_bvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_bvh.cpp @@ -115,7 +115,7 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid, float if(rtbuild_size(builder) == 1) { - RayObject *child = builder->begin[0]; + RayObject *child = rtbuild_get_primitive( builder, 0 ); if(RayObject_isRayFace(child)) { @@ -127,7 +127,7 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid, float for(i=0; i<1; i++) { - parent->child[i] = (BVHNode*)builder->begin[i]; + parent->child[i] = (BVHNode*)rtbuild_get_primitive( builder, i ); bvh_node_merge_bb(parent->child[i], parent->bb, parent->bb+3); } for(; i diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp index b0ac54bef2c..fb2d05a0a14 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp @@ -8,21 +8,23 @@ #include "BLI_arithb.h" #include "BKE_utildefines.h" -static int partition_nth_element(RTBuilder *b, int _begin, int _end, int n); -static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis); -static int split_leafs_by_plane(RTBuilder *b, int begin, int end, float plane); - -static void rtbuild_init(RTBuilder *b, RayObject **begin, RayObject **end) +static bool selected_node(RTBuilder::Object *node) { - int i; + return node->selected; +} - b->begin = begin; - b->end = end; - b->split_axis = 0; - b->child_sorted_axis = -1; +static void rtbuild_init(RTBuilder *b) +{ + b->split_axis = -1; + b->primitives.begin = 0; + b->primitives.end = 0; + b->primitives.maxsize = 0; - for(i=0; ichild_offset[i] = 0; + + for(int i=0; i<3; i++) + b->sorted_begin[i] = b->sorted_end[i] = 0; INIT_MINMAX(b->bb, b->bb+3); } @@ -30,29 +32,113 @@ static void rtbuild_init(RTBuilder *b, RayObject **begin, RayObject **end) RTBuilder* rtbuild_create(int size) { RTBuilder *builder = (RTBuilder*) MEM_mallocN( sizeof(RTBuilder), "RTBuilder" ); - RayObject **memblock= (RayObject**)MEM_mallocN( sizeof(RayObject*)*size,"RTBuilder.objects"); - rtbuild_init(builder, memblock, memblock); + RTBuilder::Object *memblock= (RTBuilder::Object*)MEM_mallocN( sizeof(RTBuilder::Object)*size,"RTBuilder.objects"); + + + rtbuild_init(builder); + + builder->primitives.begin = builder->primitives.end = memblock; + builder->primitives.maxsize = size; + + for(int i=0; i<3; i++) + { + builder->sorted_begin[i] = (RTBuilder::Object**)MEM_mallocN( sizeof(RTBuilder::Object*)*size,"RTBuilder.sorted_objects"); + builder->sorted_end[i] = builder->sorted_begin[i]; + } + + return builder; } void rtbuild_free(RTBuilder *b) { - MEM_freeN(b->begin); + if(b->primitives.begin) MEM_freeN(b->primitives.begin); + + for(int i=0; i<3; i++) + if(b->sorted_begin[i]) + MEM_freeN(b->sorted_begin[i]); + MEM_freeN(b); } void rtbuild_add(RTBuilder *b, RayObject *o) { - *(b->end++) = o; + assert( b->primitives.begin + b->primitives.maxsize != b->primitives.end ); + + b->primitives.end->obj = o; + b->primitives.end->cost = RE_rayobject_cost(o); + + INIT_MINMAX(b->primitives.end->bb, b->primitives.end->bb+3); + RE_rayobject_merge_bb(o, b->primitives.end->bb, b->primitives.end->bb+3); + + for(int i=0; i<3; i++) + { + *(b->sorted_end[i]) = b->primitives.end; + b->sorted_end[i]++; + } + b->primitives.end++; +} + +int rtbuild_size(RTBuilder *b) +{ + return b->sorted_end[0] - b->sorted_begin[0]; +} + + +template +static bool obj_bb_compare(const Obj &a, const Obj &b) +{ + if(a->bb[Axis] != b->bb[Axis]) + return a->bb[Axis] < b->bb[Axis]; + return a->obj < b->obj; +} + +template +static void object_sort(Item *begin, Item *end, int axis) +{ + if(axis == 0) return std::sort(begin, end, obj_bb_compare ); + if(axis == 1) return std::sort(begin, end, obj_bb_compare ); + if(axis == 2) return std::sort(begin, end, obj_bb_compare ); + assert(false); +} + +void rtbuild_done(RTBuilder *b) +{ + for(int i=0; i<3; i++) + if(b->sorted_begin[i]) + object_sort( b->sorted_begin[i], b->sorted_end[i], i ); +} + +RayObject* rtbuild_get_primitive(RTBuilder *b, int index) +{ + return b->sorted_begin[0][index]->obj; +} + +RTBuilder* rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp) +{ + rtbuild_init( tmp ); + + for(int i=0; i<3; i++) + if(b->sorted_begin[i]) + { + tmp->sorted_begin[i] = b->sorted_begin[i] + b->child_offset[child ]; + tmp->sorted_end [i] = b->sorted_begin[i] + b->child_offset[child+1]; + } + else + { + tmp->sorted_begin[i] = 0; + tmp->sorted_end [i] = 0; + } + + return tmp; } void rtbuild_calc_bb(RTBuilder *b) { if(b->bb[0] == 1.0e30f) { - RayObject **index = b->begin; - for(; index != b->end; index++) - RE_rayobject_merge_bb(*index, b->bb, b->bb+3); + for(RTBuilder::Object **index = b->sorted_begin[0]; index != b->sorted_end[0]; index++) + RE_rayobject_merge_bb( (*index)->obj , b->bb, b->bb+3); } } @@ -63,28 +149,13 @@ void rtbuild_merge_bb(RTBuilder *b, float *min, float *max) DO_MAX(b->bb+3, max); } +/* int rtbuild_get_largest_axis(RTBuilder *b) { rtbuild_calc_bb(b); return bb_largest_axis(b->bb, b->bb+3); } - -int rtbuild_size(RTBuilder *b) -{ - return b->end - b->begin; -} - - -RTBuilder* rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp) -{ - rtbuild_init( tmp, b->begin + b->child_offset[child], b->begin + b->child_offset[child+1] ); - tmp->child_sorted_axis = b->child_sorted_axis; - return tmp; -} - - - //Left balanced tree int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis) { @@ -142,11 +213,13 @@ int rtbuild_mean_split_largest_axis(RTBuilder *b, int nchilds) int axis = rtbuild_get_largest_axis(b); return rtbuild_mean_split(b, nchilds, axis); } +*/ /* * "separators" is an array of dim NCHILDS-1 * and indicates where to cut the childs */ +/* int rtbuild_median_split(RTBuilder *b, float *separators, int nchilds, int axis) { int size = rtbuild_size(b); @@ -189,120 +262,84 @@ int rtbuild_median_split_largest_axis(RTBuilder *b, int nchilds) return rtbuild_median_split(b, separators, nchilds, la); } +*/ //Heuristics Object Splitter -typedef struct CostObject CostObject; -struct CostObject + + +struct SweepCost { - RayObject *obj; - float cost; float bb[6]; + float cost; }; -template -bool obj_bb_compare(const Obj &a, const Obj &b) -{ - if(a.bb[Axis] != b.bb[Axis]) - return a.bb[Axis] < b.bb[Axis]; - return a.obj < b.obj; -} - -void costobject_sort(CostObject *begin, CostObject *end, int axis) -{ - if(axis == 0) return std::sort(begin, end, obj_bb_compare ); - if(axis == 1) return std::sort(begin, end, obj_bb_compare ); - if(axis == 2) return std::sort(begin, end, obj_bb_compare ); - assert(false); -} - - - /* Object Surface Area Heuristic splitter */ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) { int size = rtbuild_size(b); assert(nchilds == 2); + assert(size > 1); + int baxis = -1, boffset = 0; - if(size <= nchilds) - { - return rtbuild_mean_split_largest_axis(b, nchilds); - } - else + if(size > nchilds) { float bcost = FLT_MAX; - float childrens_cost = 0; - int i, axis, baxis = -1, boffset = size/2, k, try_axis[3]; - CostObject *cost = (CostObject*)MEM_mallocN( sizeof(CostObject)*size, "RTBuilder.HeuristicObjectSplitter" ); - float *acc_bb = (float*)MEM_mallocN( sizeof(float)*6*size, "RTBuilder.HeuristicObjectSplitterBB" ); + baxis = -1, boffset = size/2; - for(i=0; ibegin[i]; - INIT_MINMAX(cost[i].bb, cost[i].bb+3); - RE_rayobject_merge_bb(cost[i].obj, cost[i].bb, cost[i].bb+3); - cost[i].cost = RE_rayobject_cost(cost[i].obj); - childrens_cost += cost[i].cost; - } + SweepCost *sweep = (SweepCost*)MEM_mallocN( sizeof(SweepCost)*size, "RTBuilder.HeuristicSweep" ); - if(b->child_sorted_axis >= 0 && b->child_sorted_axis < 3) + for(int axis=0; axis<3; axis++) { - try_axis[0] = b->child_sorted_axis; - try_axis[1] = (b->child_sorted_axis+1)%3; - try_axis[2] = (b->child_sorted_axis+2)%3; - } - else - { - try_axis[0] = 0; - try_axis[1] = 1; - try_axis[2] = 2; - } - - for(axis=try_axis[k=0]; k<3; axis=try_axis[++k]) - { - float left_cost, right_cost; - float other_bb[6]; + SweepCost sweep_left; - - - costobject_sort(cost, cost+size, axis); - for(i=size-1; i>=0; i--) + RTBuilder::Object **obj = b->sorted_begin[axis]; + +// float right_cost = 0; + for(int i=size-1; i>=0; i--) { - float *bb = acc_bb+i*6; if(i == size-1) { - VECCOPY(bb, cost[i].bb); - VECCOPY(bb+3, cost[i].bb+3); + VECCOPY(sweep[i].bb, obj[i]->bb); + VECCOPY(sweep[i].bb+3, obj[i]->bb+3); + sweep[i].cost = obj[i]->cost; } else { - bb[0] = MIN2(cost[i].bb[0], bb[6+0]); - bb[1] = MIN2(cost[i].bb[1], bb[6+1]); - bb[2] = MIN2(cost[i].bb[2], bb[6+2]); - - bb[3] = MAX2(cost[i].bb[3], bb[6+3]); - bb[4] = MAX2(cost[i].bb[4], bb[6+4]); - bb[5] = MAX2(cost[i].bb[5], bb[6+5]); + sweep[i].bb[0] = MIN2(obj[i]->bb[0], sweep[i+1].bb[0]); + sweep[i].bb[1] = MIN2(obj[i]->bb[1], sweep[i+1].bb[1]); + sweep[i].bb[2] = MIN2(obj[i]->bb[2], sweep[i+1].bb[2]); + sweep[i].bb[3] = MAX2(obj[i]->bb[3], sweep[i+1].bb[3]); + sweep[i].bb[4] = MAX2(obj[i]->bb[4], sweep[i+1].bb[4]); + sweep[i].bb[5] = MAX2(obj[i]->bb[5], sweep[i+1].bb[5]); + sweep[i].cost = obj[i]->cost + sweep[i+1].cost; } +// right_cost += obj[i]->cost; } - INIT_MINMAX(other_bb, other_bb+3); - DO_MIN( cost[0].bb, other_bb ); - DO_MAX( cost[0].bb+3, other_bb+3 ); - left_cost = cost[0].cost; - right_cost = childrens_cost-cost[0].cost; - if(right_cost < 0) right_cost = 0; + sweep_left.bb[0] = obj[0]->bb[0]; + sweep_left.bb[1] = obj[0]->bb[1]; + sweep_left.bb[2] = obj[0]->bb[2]; + sweep_left.bb[3] = obj[0]->bb[3]; + sweep_left.bb[4] = obj[0]->bb[4]; + sweep_left.bb[5] = obj[0]->bb[5]; + sweep_left.cost = obj[0]->cost; + +// right_cost -= obj[0]->cost; if(right_cost < 0) right_cost = 0; - for(i=1; i 0); + assert(right_side > 0); if(left_side > bcost) break; //No way we can find a better heuristic in this axis - hcost = left_side+right_side; assert(hcost >= 0); if( hcost < bcost || (hcost == bcost && axis < baxis)) //this makes sure the tree built is the same whatever is the order of the sorting axis @@ -311,31 +348,43 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) baxis = axis; boffset = i; } - DO_MIN( cost[i].bb, other_bb ); - DO_MAX( cost[i].bb+3, other_bb+3 ); - left_cost += cost[i].cost; - right_cost -= cost[i].cost; - if(right_cost < 0.0f) right_cost = 0.0; - } - - if(baxis == axis) - { - for(i=0; ibegin[i] = cost[i].obj; - b->child_sorted_axis = axis; + DO_MIN( obj[i]->bb, sweep_left.bb ); + DO_MAX( obj[i]->bb+3, sweep_left.bb+3 ); + + sweep_left.cost += obj[i]->cost; +// right_cost -= obj[i]->cost; if(right_cost < 0) right_cost = 0; } assert(baxis >= 0 && baxis < 3); } - b->child_offset[0] = 0; - b->child_offset[1] = boffset; - b->child_offset[2] = size; - MEM_freeN(acc_bb); - MEM_freeN(cost); - return nchilds; + MEM_freeN(sweep); } + else if(size == 2) + { + baxis = 0; + boffset = 1; + } + else if(size == 1) + { + b->child_offset[0] = 0; + b->child_offset[1] = 1; + return 1; + } + + b->child_offset[0] = 0; + b->child_offset[1] = boffset; + b->child_offset[2] = size; + + + /* Adjust sorted arrays for childs */ + for(int i=0; isorted_begin[baxis][i]->selected = true; + for(int i=boffset; isorted_begin[baxis][i]->selected = false; + for(int i=0; i<3; i++) + std::stable_partition( b->sorted_begin[i], b->sorted_end[i], selected_node ); + + return nchilds; } /* @@ -343,110 +392,7 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) * PARTITION code / used on mean-split * basicly this a std::nth_element (like on C++ STL algorithm) */ -static void sort_swap(RTBuilder *b, int i, int j) -{ - SWAP(RayObject*, b->begin[i], b->begin[j]); -} - -static float sort_get_value(RTBuilder *b, int i) -{ - float min[3], max[3]; - INIT_MINMAX(min, max); - RE_rayobject_merge_bb(b->begin[i], min, max); - return max[b->split_axis]; -} - -static int medianof3(RTBuilder *d, int a, int b, int c) -{ - float fa = sort_get_value( d, a ); - float fb = sort_get_value( d, b ); - float fc = sort_get_value( d, c ); - - if(fb < fa) - { - if(fc < fb) - return b; - else - { - if(fc < fa) - return c; - else - return a; - } - } - else - { - if(fc < fb) - { - if(fc < fa) - return a; - else - return c; - } - else - return b; - } -} - -static void insertionsort(RTBuilder *b, int lo, int hi) -{ - int i; - for(i=lo; ibegin[i]; - float tv= sort_get_value(b, i); - int j=i; - - while( j != lo && tv < sort_get_value(b, j-1)) - { - b->begin[j] = b->begin[j-1]; - j--; - } - b->begin[j] = t; - } -} - -static int partition(RTBuilder *b, int lo, int mid, int hi) -{ - float x = sort_get_value( b, mid ); - - int i=lo, j=hi; - while (1) - { - while(sort_get_value(b,i) < x) i++; - j--; - while(x < sort_get_value(b,j)) j--; - if(!(i < j)) - return i; - - sort_swap(b, i, j); - i++; - } -} - -// -// PARTITION code / used on mean-split -// basicly this is an adapted std::nth_element (C++ STL ) -// -// after a call to this function you can expect one of: -// every node to left of a[n] are smaller or equal to it -// every node to the right of a[n] are greater or equal to it -static int partition_nth_element(RTBuilder *b, int _begin, int n, int _end) -{ - int begin = _begin, end = _end, cut; - while(end-begin > 3) - { - cut = partition(b, begin, medianof3(b, begin, begin+(end-begin)/2, end-1), end); - if(cut <= n) - begin = cut; - else - end = cut; - } - insertionsort(b, begin, end); - - return n; -} - +/* static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis) { int i; @@ -456,23 +402,12 @@ static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis) { assert(nth[i] < nth[i+1] && nth[i+1] < nth[partitions]); - partition_nth_element(b, nth[i], nth[i+1], nth[partitions] ); + if(split_axis == 0) std::nth_element(b, nth[i], nth[i+1], nth[partitions], obj_bb_compare); + if(split_axis == 1) std::nth_element(b, nth[i], nth[i+1], nth[partitions], obj_bb_compare); + if(split_axis == 2) std::nth_element(b, nth[i], nth[i+1], nth[partitions], obj_bb_compare); } } - -static int split_leafs_by_plane(RTBuilder *b, int begin, int end, float plane) -{ - int i; - for(i = begin; i != end; i++) - { - if(sort_get_value(b, i) < plane) - { - sort_swap(b, i, begin); - begin++; - } - } - return begin; -} +*/ /* * Bounding Box utils diff --git a/source/blender/render/intern/include/rayobject_rtbuild.h b/source/blender/render/intern/raytrace/rayobject_rtbuild.h similarity index 87% rename from source/blender/render/intern/include/rayobject_rtbuild.h rename to source/blender/render/intern/raytrace/rayobject_rtbuild.h index ed8560d948a..8f471f095e2 100644 --- a/source/blender/render/intern/include/rayobject_rtbuild.h +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.h @@ -47,18 +47,35 @@ extern "C" { * specific structure on the fly. */ #define RTBUILD_MAX_CHILDS 32 + + typedef struct RTBuilder { - /* list to all primitives in this tree */ - RayObject **begin, **end; + struct Object + { + RayObject *obj; + float cost; + float bb[6]; + int selected; + }; + /* list to all primitives added in this tree */ + struct + { + Object *begin, *end; + int maxsize; + } primitives; + + /* sorted list of rayobjects */ + struct Object **sorted_begin[3], **sorted_end[3]; + /* axis used (if any) on the split method */ int split_axis; /* child partitions calculated during splitting */ int child_offset[RTBUILD_MAX_CHILDS+1]; - int child_sorted_axis; /* -1 if not sorted */ +// int child_sorted_axis; /* -1 if not sorted */ float bb[6]; @@ -68,9 +85,12 @@ typedef struct RTBuilder RTBuilder* rtbuild_create(int size); void rtbuild_free(RTBuilder *b); void rtbuild_add(RTBuilder *b, RayObject *o); +void rtbuild_done(RTBuilder *b); void rtbuild_merge_bb(RTBuilder *b, float *min, float *max); int rtbuild_size(RTBuilder *b); +RayObject* rtbuild_get_primitive(RTBuilder *b, int offset); + /* used during tree reorganization */ RTBuilder* rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp); diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index 17ed63e3669..2dde485d3d1 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -235,7 +235,7 @@ Node *bvh_rearrange(Tree *tree, Builder *builder) Node *node = bvh_new_node(tree); INIT_MINMAX(node->bb, node->bb+3); rtbuild_merge_bb(builder, node->bb, node->bb+3); - node->child = (BVHNode*)builder->begin[0]; + node->child = (BVHNode*) rtbuild_get_primitive( builder, 0 ); return node; } else @@ -266,6 +266,8 @@ Node *bvh_rearrange(Tree *tree, Builder *builder) template<> void bvh_done(BVHTree *obj) { + rtbuild_done(obj->builder); + int needed_nodes = (rtbuild_size(obj->builder)+1)*2; if(needed_nodes > BLI_MEMARENA_STD_BUFSIZE) needed_nodes = BLI_MEMARENA_STD_BUFSIZE; From eaf232cad9f48dd2aa48ebba7197aee6d5586ec2 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 3 Aug 2009 23:25:38 +0000 Subject: [PATCH 062/138] single tree (by default) now that build is nlogn (it should be worth to the tree of trees) --- .../intern/raytrace/rayobject_rtbuild.cpp | 4 +- .../blender/render/intern/source/rayshade.c | 56 ++++++++++++------- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp index fb2d05a0a14..238929e1dbb 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp @@ -335,8 +335,8 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) right_side= bb_area(sweep[i].bb, sweep[i].bb+3)*(sweep[i].cost+logf(size-i)); hcost = left_side+right_side; - assert(left_side > 0); - assert(right_side > 0); + assert(left_side >= 0); + assert(right_side >= 0); if(left_side > bcost) break; //No way we can find a better heuristic in this axis diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index f6ba45308a5..1df201f7b00 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -308,13 +308,18 @@ static void makeraytree_single(Render *re) ObjectRen *obr = obi->obr; obs++; - assert((obi->flag & R_TRANSFORMED) == 0); //Not suported - - for(v=0;vtotvlak;v++) + if(obi->flag & R_TRANSFORMED) { - VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); - if(is_raytraceable_vlr(re, vlr)) - faces++; + faces++; + } + else + { + for(v=0;vtotvlak;v++) + { + VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); + if(is_raytraceable_vlr(re, vlr)) + faces++; + } } } @@ -329,22 +334,30 @@ static void makeraytree_single(Render *re) for(obi=re->instancetable.first; obi; obi=obi->next) if(is_raytraceable(re, obi)) { - int v; - ObjectRen *obr = obi->obr; - - for(v=0;vtotvlak;v++) + if(obi->flag & R_TRANSFORMED) { - VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); - face->v1 = vlr->v1->co; - face->v2 = vlr->v2->co; - face->v3 = vlr->v3->co; - face->v4 = vlr->v4 ? vlr->v4->co : NULL; - - face->ob = obi; - face->face = vlr; - - RE_rayobject_add( raytree, RayObject_unalignRayFace(face) ); - face++; + RayObject *obj = makeraytree_object(re, obi); + RE_rayobject_add( re->raytree, obj ); + } + else + { + int v; + ObjectRen *obr = obi->obr; + + for(v=0;vtotvlak;v++) + { + VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); + face->v1 = vlr->v1->co; + face->v2 = vlr->v2->co; + face->v3 = vlr->v3->co; + face->v4 = vlr->v4 ? vlr->v4->co : NULL; + + face->ob = obi; + face->face = vlr; + + RE_rayobject_add( raytree, RayObject_unalignRayFace(face) ); + face++; + } } } RE_rayobject_done( raytree ); @@ -356,6 +369,7 @@ void makeraytree(Render *re) int i; const char *tree_type = "Tree(unknown)"; + re->r.raytrace_tree_type = R_RAYSTRUCTURE_SINGLE_BVH; #ifdef RE_RAYCOUNTER if(re->r.raytrace_tree_type == R_RAYTRACE_TREE_BVH) tree_type = "BVH"; From 5e21e68f834d80e264e0cb222e65d2767419f046 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 4 Aug 2009 00:00:05 +0000 Subject: [PATCH 063/138] (fix) --- source/blender/render/intern/source/rayshade.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 1df201f7b00..58bfa506e2b 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -369,7 +369,7 @@ void makeraytree(Render *re) int i; const char *tree_type = "Tree(unknown)"; - re->r.raytrace_tree_type = R_RAYSTRUCTURE_SINGLE_BVH; + re->r.raystructure = R_RAYSTRUCTURE_SINGLE_BVH; #ifdef RE_RAYCOUNTER if(re->r.raytrace_tree_type == R_RAYTRACE_TREE_BVH) tree_type = "BVH"; From 7e9dc51cd1a9c35eb54660ea650570f81d102e2e Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 4 Aug 2009 17:24:49 +0000 Subject: [PATCH 064/138] Skip BB tests on primitives the efficiency of this depends on ray-bb and ray-triangle functions efficiency --- .../blender/render/extern/include/RE_raytrace.h | 2 +- .../render/intern/raytrace/rayobject_vbvh.cpp | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index beae1b84b04..864b6124db4 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -37,7 +37,7 @@ extern "C" { #define RE_RAY_LCTS_MAX_SIZE 256 -#define RT_USE_LAST_HIT /* last shadow hit is reused before raycasting on whole tree */ +#define RT_USE_LAST_HIT /* last shadow hit is reused before raycasting on whole tree */ //#define RT_USE_HINT /* last hit object is reused before raycasting on whole tree */ #define RE_RAYCOUNTER diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index 2dde485d3d1..774a465092d 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -81,12 +81,23 @@ template inline static void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, int &stack_pos) { Node *child = node->child; - while(child) + + if(!RayObject_isAligned(child)) { stack[stack_pos++] = child; - if(RayObject_isAligned(child)) + } + else + { + while(child) + { + //Skips BB tests on primitives + if(!RayObject_isAligned(child->child)) + stack[stack_pos++] = child->child; + else + stack[stack_pos++] = child; + child = child->sibling; - else break; + } } } From 2160f36fea5ec0f7cd2747f8889f6005a14d9e6c Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 4 Aug 2009 18:03:04 +0000 Subject: [PATCH 065/138] Fix point-hint --- .../render/intern/raytrace/rayobject_vbvh.cpp | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index 774a465092d..5c9807baa29 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -345,24 +345,32 @@ void bvh_dfs_make_hint_push_siblings(Node *node, LCTSHint *hint, int reserve_spa bvh_dfs_make_hint_push_siblings(node->sibling, hint, reserve_space+1, min, max); bvh_dfs_make_hint(node, hint, reserve_space, min, max); - } - - + } } template void bvh_dfs_make_hint(Node *node, LCTSHint *hint, int reserve_space, float *min, float *max) { - assert( hint->size - reserve_space + 1 <= RE_RAY_LCTS_MAX_SIZE ); + assert( hint->size + reserve_space + 1 <= RE_RAY_LCTS_MAX_SIZE ); - if(hint->size - reserve_space + 1 == RE_RAY_LCTS_MAX_SIZE || !RayObject_isAligned(node)) + if(!RayObject_isAligned(node)) + { hint->stack[hint->size++] = (RayObject*)node; + } else { - /* We are 100% sure the ray will be pass inside this node */ - if(bb_fits_inside(node->bb, node->bb+3, min, max) ) + int childs = count_childs(node); + if(hint->size + reserve_space + childs <= RE_RAY_LCTS_MAX_SIZE) { - bvh_dfs_make_hint_push_siblings(node->child, hint, reserve_space, min, max); + /* We are 100% sure the ray will be pass inside this node */ + if(bb_fits_inside(node->bb, node->bb+3, min, max) ) + { + bvh_dfs_make_hint_push_siblings(node->child, hint, reserve_space, min, max); + } + else + { + hint->stack[hint->size++] = (RayObject*)node; + } } else { From bbdba89d06496e1e9a2bc63ce0f70aac8b8cc3f3 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 5 Aug 2009 12:44:11 +0000 Subject: [PATCH 066/138] generic hints for raytracer for now only BB hint (i am hoping to find a decent frustum-test) --- .../render/intern/raytrace/rayobject_hint.h | 65 +++++++++++++++++++ .../render/intern/raytrace/rayobject_vbvh.cpp | 32 +++++---- 2 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 source/blender/render/intern/raytrace/rayobject_hint.h diff --git a/source/blender/render/intern/raytrace/rayobject_hint.h b/source/blender/render/intern/raytrace/rayobject_hint.h new file mode 100644 index 00000000000..cc8728a28cb --- /dev/null +++ b/source/blender/render/intern/raytrace/rayobject_hint.h @@ -0,0 +1,65 @@ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#define HINT_RECURSE 1 +#define HINT_ACCEPT 0 +#define HINT_DISCARD -1 + +struct HintBB +{ + float bb[6]; +}; + +inline int hint_test_bb(HintBB *obj, float *Nmin, float *Nmax) +{ + if(bb_fits_inside( Nmin, Nmax, obj->bb, obj->bb+3 ) ) + return HINT_RECURSE; + else + return HINT_ACCEPT; +} +/* +struct HintFrustum +{ + float co[3]; + float no[4][3]; +}; + +inline int hint_test_bb(HintFrustum &obj, float *Nmin, float *Nmax) +{ + //if frustum inside BB + { + return HINT_RECURSE; + } + //if BB outside frustum + { + return HINT_DISCARD; + } + + return HINT_ACCEPT; +} +*/ diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index 5c9807baa29..e8bc59641d7 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -38,6 +38,7 @@ extern "C" #include "rayobject.h" }; +#include "rayobject_hint.h" #include "reorganize.h" #include "bvh.h" #include @@ -331,25 +332,25 @@ int intersect(BVHTree *obj, Isect* isec) } } -template -void bvh_dfs_make_hint(Node *node, LCTSHint *hint, int reserve_space, float *min, float *max); +template +void bvh_dfs_make_hint(Node *node, LCTSHint *hint, int reserve_space, HintObject *hintObject); -template -void bvh_dfs_make_hint_push_siblings(Node *node, LCTSHint *hint, int reserve_space, float *min, float *max) +template +void bvh_dfs_make_hint_push_siblings(Node *node, LCTSHint *hint, int reserve_space, HintObject *hintObject) { if(!RayObject_isAligned(node)) hint->stack[hint->size++] = (RayObject*)node; else { if(node->sibling) - bvh_dfs_make_hint_push_siblings(node->sibling, hint, reserve_space+1, min, max); + bvh_dfs_make_hint_push_siblings(node->sibling, hint, reserve_space+1, hintObject); - bvh_dfs_make_hint(node, hint, reserve_space, min, max); + bvh_dfs_make_hint(node, hint, reserve_space, hintObject); } } -template -void bvh_dfs_make_hint(Node *node, LCTSHint *hint, int reserve_space, float *min, float *max) +template +void bvh_dfs_make_hint(Node *node, LCTSHint *hint, int reserve_space, HintObject *hintObject) { assert( hint->size + reserve_space + 1 <= RE_RAY_LCTS_MAX_SIZE ); @@ -362,12 +363,13 @@ void bvh_dfs_make_hint(Node *node, LCTSHint *hint, int reserve_space, float *min int childs = count_childs(node); if(hint->size + reserve_space + childs <= RE_RAY_LCTS_MAX_SIZE) { - /* We are 100% sure the ray will be pass inside this node */ - if(bb_fits_inside(node->bb, node->bb+3, min, max) ) + int result = hint_test_bb(hintObject, node->bb, node->bb+3); + if(result == HINT_RECURSE) { - bvh_dfs_make_hint_push_siblings(node->child, hint, reserve_space, min, max); + /* We are 100% sure the ray will be pass inside this node */ + bvh_dfs_make_hint_push_siblings(node->child, hint, reserve_space, hintObject); } - else + else if(result == HINT_ACCEPT) { hint->stack[hint->size++] = (RayObject*)node; } @@ -382,8 +384,12 @@ void bvh_dfs_make_hint(Node *node, LCTSHint *hint, int reserve_space, float *min template void bvh_hint_bb(Tree *tree, LCTSHint *hint, float *min, float *max) { + HintBB bb; + VECCOPY(bb.bb, min); + VECCOPY(bb.bb+3, max); + hint->size = 0; - bvh_dfs_make_hint( tree->root, hint, 0, min, max ); + bvh_dfs_make_hint( tree->root, hint, 0, &bb ); tot_hints++; } From e4e9b569e1b766dc07ae074439a894be8d7cda49 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 5 Aug 2009 14:40:38 +0000 Subject: [PATCH 067/138] experiences with memory organization (store the vertexs coords on RayFace) --- .../blender/editors/armature/meshlaplacian.c | 3 +- .../blender/render/intern/include/rayobject.h | 32 ++++- .../blender/render/intern/source/rayobject.c | 33 ++++- .../render/intern/source/rayobject_mesh.c | 132 ------------------ .../blender/render/intern/source/rayshade.c | 26 +--- 5 files changed, 69 insertions(+), 157 deletions(-) delete mode 100644 source/blender/render/intern/source/rayobject_mesh.c diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 7a0eda16d39..ff3fed6be34 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -401,7 +401,8 @@ static void heat_ray_tree_create(LaplacianSystem *sys) MFace *mface; int a; - sys->heat.raytree = RE_rayobject_mesh_create(me, me); + assert(0); //TODO + //sys->heat.raytree = RE_rayobject_mesh_create(me, me); sys->heat.vface = MEM_callocN(sizeof(MFace*)*me->totvert, "HeatVFaces"); for(a=0, mface=me->mface; atotface; a++, mface++) { diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index 6f8debead19..dddeebd5048 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -34,6 +34,7 @@ extern "C" { #endif #include "RE_raytrace.h" +#include "render_types.h" #include @@ -75,16 +76,38 @@ extern "C" { You actually don't need to care about this if you are only using the API described on RE_raytrace.h */ + +/* defines where coordinates of rayface primitives are stored */ +#define RE_RAYFACE_COORDS_LOCAL +//#define RE_RAYFACE_COORDS_POINTER +//#define RE_RAYFACE_COORDS_VLAKREN typedef struct RayFace { - float *v1, *v2, *v3, *v4; - +#ifdef RE_RAYFACE_COORDS_LOCAL + float v1[4], v2[4], v3[4], v4[3]; + int quad; void *ob; void *face; +#elif defined(RE_RAYFACE_COORDS_POINTER) + float *v1, *v2, *v3, *v4; + void *ob; + void *face; +#elif defined(RE_RAYFACE_COORDS_VLAKREN) + void *ob; + void *face; +#endif } RayFace; +#ifdef RE_RAYFACE_COORDS_LOCAL +# define RE_rayface_isQuad(a) ((a)->quad) +#elif defined(RE_RAYFACE_COORDS_POINTER) +# define RE_rayface_isQuad(a) ((a)->v4) +#elif defined(RE_RAYFACE_COORDS_VLAKREN) +#endif + + struct RayObject { struct RayObjectAPI *api; @@ -120,6 +143,11 @@ typedef struct RayObjectAPI #define RayObject_isRayFace(o) ((((intptr_t)o)&3) == 1) #define RayObject_isRayAPI(o) ((((intptr_t)o)&3) == 2) +/* + * Loads a VlakRen on a RayFace + */ +void RE_rayface_from_vlak(RayFace *face, ObjectInstanceRen *obi, VlakRen *vlr); + /* * Extend min/max coords so that the rayobject is inside them */ diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index 2e63dc78c0e..c0c2c36fe13 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -165,7 +165,7 @@ static int intersect_rayface(RayFace *face, Isect *is) VECCOPY(co1, face->v1); VECCOPY(co2, face->v2); - if(face->v4) + if(RE_rayface_isQuad(face)) { VECCOPY(co3, face->v4); VECCOPY(co4, face->v3); @@ -219,7 +219,7 @@ static int intersect_rayface(RayFace *face, Isect *is) } } - if(ok==0 && face->v4) { + if(ok==0 && RE_rayface_isQuad(face)) { t20= co3[0]-co4[0]; t21= co3[1]-co4[1]; @@ -297,6 +297,33 @@ static int intersect_rayface(RayFace *face, Isect *is) return 0; } +void RE_rayface_from_vlak(RayFace *face, ObjectInstanceRen *obi, VlakRen *vlr) +{ +#ifdef RE_RAYFACE_COORDS_LOCAL + VECCOPY(face->v1, vlr->v1->co); + VECCOPY(face->v2, vlr->v2->co); + VECCOPY(face->v3, vlr->v3->co); + if(vlr->v4) + { + VECCOPY(face->v4, vlr->v4->co); + face->quad = 1; + } + else + { + face->quad = 0; + } +#elif defined(RE_RAYFACE_COORDS_POINTER) + face->v1 = vlr->v1->co; + face->v2 = vlr->v2->co; + face->v3 = vlr->v3->co; + face->v4 = vlr->v4 ? vlr->v4->co : NULL; +#elif defined(RE_RAYFACE_COORDS_VLAKREN) +#endif + face->ob = obi; + face->face = vlr; +} + + int RE_rayobject_raycast(RayObject *r, Isect *isec) { int i; @@ -390,7 +417,7 @@ void RE_rayobject_merge_bb(RayObject *r, float *min, float *max) DO_MINMAX( face->v1, min, max ); DO_MINMAX( face->v2, min, max ); DO_MINMAX( face->v3, min, max ); - if(face->v4) DO_MINMAX( face->v4, min, max ); + if(RE_rayface_isQuad(face)) DO_MINMAX( face->v4, min, max ); } else if(RayObject_isRayAPI(r)) { diff --git a/source/blender/render/intern/source/rayobject_mesh.c b/source/blender/render/intern/source/rayobject_mesh.c deleted file mode 100644 index 538c245988d..00000000000 --- a/source/blender/render/intern/source/rayobject_mesh.c +++ /dev/null @@ -1,132 +0,0 @@ -/** - * $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) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#include - -#include "rayobject.h" - -#include "MEM_guardedalloc.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "BKE_utildefines.h" - -typedef struct RayMesh -{ - RayObject rayobj; - - Mesh *mesh; - void *ob; - - RayFace *faces; - int num_faces; - -} RayMesh; - -static int RayObject_mesh_intersect(RayObject *o, Isect *isec); -static void RayObject_mesh_add(RayObject *o, RayObject *ob); -static void RayObject_mesh_done(RayObject *o); -static void RayObject_mesh_free(RayObject *o); -static void RayObject_mesh_bb(RayObject *o, float *min, float *max); - -static RayObjectAPI mesh_api = -{ - RayObject_mesh_intersect, - RayObject_mesh_add, - RayObject_mesh_done, - RayObject_mesh_free, - RayObject_mesh_bb -}; - - -static int RayObject_mesh_intersect(RayObject *o, Isect *isec) -{ - RayMesh *rm= (RayMesh*)o; - int i, hit = 0; - for(i = 0; inum_faces; i++) - if(RE_rayobject_raycast( (RayObject*)rm->faces+i, isec )) - { - hit = 1; - if(isec->mode == RE_RAY_SHADOW) - break; - } - - return hit; -} - -static void RayObject_mesh_add(RayObject *o, RayObject *ob) -{ -} - -static void RayObject_mesh_done(RayObject *o) -{ -} - -static void RayObject_mesh_free(RayObject *o) -{ - RayMesh *rm= (RayMesh*)o; - MEM_freeN( rm->faces ); - MEM_freeN( rm ); -} - -static void RayObject_mesh_bb(RayObject *o, float *min, float *max) -{ - RayMesh *rm= (RayMesh*)o; - int i; - for(i = 0; imesh->totvert; i++) - DO_MINMAX( rm->mesh->mvert[i].co, min, max); -} - -RayObject* RE_rayobject_mesh_create(Mesh *mesh, void *ob) -{ - RayMesh *rm= MEM_callocN(sizeof(RayMesh), "Octree"); - int i; - RayFace *face; - MFace *mface; - - assert( RayObject_isAligned(rm) ); /* RayObject API assumes real data to be 4-byte aligned */ - - rm->rayobj.api = &mesh_api; - rm->mesh = mesh; - rm->faces = MEM_callocN(sizeof(RayFace)*mesh->totface, "octree rayobject nodes"); - rm->num_faces = mesh->totface; - - face = rm->faces; - mface = mesh->mface; - for(i=0; itotface; i++, face++, mface++) - { - face->v1 = mesh->mvert[mface->v1].co; - face->v2 = mesh->mvert[mface->v2].co; - face->v3 = mesh->mvert[mface->v3].co; - face->v4 = mface->v4 ? mesh->mvert[mface->v4].co : NULL; - - face->ob = ob; - face->face = (void*)i; - } - - return RayObject_unalignRayAPI((RayObject*) rm); -} diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 58bfa506e2b..685b82d9da2 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -220,16 +220,8 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); if(is_raytraceable_vlr(re, vlr)) { - face->v1 = vlr->v1->co; - face->v2 = vlr->v2->co; - face->v3 = vlr->v3->co; - face->v4 = vlr->v4 ? vlr->v4->co : NULL; - - face->ob = obi; - face->face = vlr; - + RE_rayface_from_vlak( face, obi, vlr ); RE_rayobject_add( raytree, RayObject_unalignRayFace(face) ); - face++; } } @@ -347,16 +339,12 @@ static void makeraytree_single(Render *re) for(v=0;vtotvlak;v++) { VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); - face->v1 = vlr->v1->co; - face->v2 = vlr->v2->co; - face->v3 = vlr->v3->co; - face->v4 = vlr->v4 ? vlr->v4->co : NULL; - - face->ob = obi; - face->face = vlr; - - RE_rayobject_add( raytree, RayObject_unalignRayFace(face) ); - face++; + if(is_raytraceable_vlr(re, vlr)) + { + RE_rayface_from_vlak(face, obi, vlr); + RE_rayobject_add( raytree, RayObject_unalignRayFace(face) ); + face++; + } } } } From 9565ef3087a17894fab4847bd5d8d6003e3d2a68 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 5 Aug 2009 15:50:57 +0000 Subject: [PATCH 068/138] #define to store coordinates at VlakRen and not at VlakFace adds some additional cost retrieving coords during ray-primitive tests, but reduces some memory usage (4*3floats per face) --- .../blender/render/intern/include/rayobject.h | 6 ++--- .../blender/render/intern/source/rayobject.c | 26 +++++++++++++++++++ .../render/intern/source/rayobject_octree.c | 21 +++++++++++---- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index dddeebd5048..8f0dbed3176 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -78,9 +78,9 @@ extern "C" { */ /* defines where coordinates of rayface primitives are stored */ -#define RE_RAYFACE_COORDS_LOCAL +//#define RE_RAYFACE_COORDS_LOCAL //#define RE_RAYFACE_COORDS_POINTER -//#define RE_RAYFACE_COORDS_VLAKREN +#define RE_RAYFACE_COORDS_VLAKREN typedef struct RayFace { @@ -105,13 +105,13 @@ typedef struct RayFace #elif defined(RE_RAYFACE_COORDS_POINTER) # define RE_rayface_isQuad(a) ((a)->v4) #elif defined(RE_RAYFACE_COORDS_VLAKREN) +# define RE_rayface_isQuad(a) ((((VlakRen*)((a)->face))->v4) != NULL) #endif struct RayObject { struct RayObjectAPI *api; - }; diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index c0c2c36fe13..7316120e477 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -163,6 +163,22 @@ static int intersect_rayface(RayFace *face, Isect *is) RE_RC_COUNT(is->raycounter->faces.test); +#ifdef RE_RAYFACE_COORDS_VLAKREN + { + VlakRen *vlr = (VlakRen*)face->face; + VECCOPY(co1, vlr->v1->co); + VECCOPY(co2, vlr->v2->co); + if(vlr->v4) + { + VECCOPY(co3, vlr->v4->co); + VECCOPY(co4, vlr->v3->co); + } + else + { + VECCOPY(co3, vlr->v3->co); + } + } +#else VECCOPY(co1, face->v1); VECCOPY(co2, face->v2); if(RE_rayface_isQuad(face)) @@ -174,6 +190,7 @@ static int intersect_rayface(RayFace *face, Isect *is) { VECCOPY(co3, face->v3); } +#endif t00= co3[0]-co1[0]; t01= co3[1]-co1[1]; @@ -414,10 +431,19 @@ void RE_rayobject_merge_bb(RayObject *r, float *min, float *max) if(RayObject_isRayFace(r)) { RayFace *face = (RayFace*) RayObject_align(r); + +#ifdef RE_RAYFACE_COORDS_VLAKREN + VlakRen *vlr = (VlakRen*)face->face; + DO_MINMAX( vlr->v1->co, min, max ); + DO_MINMAX( vlr->v2->co, min, max ); + DO_MINMAX( vlr->v3->co, min, max ); + if(RE_rayface_isQuad(face)) DO_MINMAX( vlr->v4->co, min, max ); +#else DO_MINMAX( face->v1, min, max ); DO_MINMAX( face->v2, min, max ); DO_MINMAX( face->v3, min, max ); if(RE_rayface_isQuad(face)) DO_MINMAX( face->v4, min, max ); +#endif } else if(RayObject_isRayAPI(r)) { diff --git a/source/blender/render/intern/source/rayobject_octree.c b/source/blender/render/intern/source/rayobject_octree.c index 88ea2bb38ed..da1083a654d 100644 --- a/source/blender/render/intern/source/rayobject_octree.c +++ b/source/blender/render/intern/source/rayobject_octree.c @@ -489,11 +489,22 @@ static void octree_fill_rayface(Octree *oc, RayFace *face) ocres2= oc->ocres*oc->ocres; +#ifdef RE_RAYFACE_COORDS_VLAKREN + { + VlakRen *vlr = (VlakRen*)face->face; + VECCOPY(co1, vlr->v1->co); + VECCOPY(co2, vlr->v2->co); + VECCOPY(co3, vlr->v3->co); + if(RE_rayface_isQuad(face)) + VECCOPY(co4, vlr->v4->co); + } +#else VECCOPY(co1, face->v1); VECCOPY(co2, face->v2); VECCOPY(co3, face->v3); if(face->v4) VECCOPY(co4, face->v4); +#endif for(c=0;c<3;c++) { rtf[0][c]= (co1[c]-oc->min[c])*ocfac[c] ; @@ -502,7 +513,7 @@ static void octree_fill_rayface(Octree *oc, RayFace *face) rts[1][c]= (short)rtf[1][c]; rtf[2][c]= (co3[c]-oc->min[c])*ocfac[c] ; rts[2][c]= (short)rtf[2][c]; - if(face->v4) { + if(RE_rayface_isQuad(face)) { rtf[3][c]= (co4[c]-oc->min[c])*ocfac[c] ; rts[3][c]= (short)rtf[3][c]; } @@ -512,7 +523,7 @@ static void octree_fill_rayface(Octree *oc, RayFace *face) oc1= rts[0][c]; oc2= rts[1][c]; oc3= rts[2][c]; - if(face->v4==NULL) { + if(!RE_rayface_isQuad(face)) { ocmin[c]= MIN3(oc1,oc2,oc3); ocmax[c]= MAX3(oc1,oc2,oc3); } @@ -526,7 +537,7 @@ static void octree_fill_rayface(Octree *oc, RayFace *face) } if(ocmin[0]==ocmax[0] && ocmin[1]==ocmax[1] && ocmin[2]==ocmax[2]) { - ocwrite(oc, face, (face->v4 != NULL), ocmin[0], ocmin[1], ocmin[2], rtf); + ocwrite(oc, face, RE_rayface_isQuad(face), ocmin[0], ocmin[1], ocmin[2], rtf); } else { @@ -536,7 +547,7 @@ static void octree_fill_rayface(Octree *oc, RayFace *face) d2dda(oc, 1,2,0,1,ocface+ocres2,rts,rtf); d2dda(oc, 1,2,0,2,ocface,rts,rtf); d2dda(oc, 1,2,1,2,ocface+2*ocres2,rts,rtf); - if(face->v4==NULL) { + if(!RE_rayface_isQuad(face)) { d2dda(oc, 2,0,0,1,ocface+ocres2,rts,rtf); d2dda(oc, 2,0,0,2,ocface,rts,rtf); d2dda(oc, 2,0,1,2,ocface+2*ocres2,rts,rtf); @@ -565,7 +576,7 @@ static void octree_fill_rayface(Octree *oc, RayFace *face) for(z=ocmin[2];z<=ocmax[2];z++) { if(ocface[b+z] && ocface[a+z]) { if(face_in_node(NULL, x, y, z, rtf)) - ocwrite(oc, face, (face->v4 != NULL), x,y,z, rtf); + ocwrite(oc, face, RE_rayface_isQuad(face), x,y,z, rtf); } } } From f7179efde35689ad915948298fe905e36704c126 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 5 Aug 2009 21:09:41 +0000 Subject: [PATCH 069/138] no need to calculate the exact nearest distance if we are not using any heuristic based on that --- .../blender/render/intern/include/rayobject.h | 3 +- source/blender/render/intern/raytrace/bvh.h | 43 ++++++++++++++++++- .../blender/render/intern/source/rayobject.c | 22 ++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index 8f0dbed3176..2c63c8ceae9 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -164,7 +164,8 @@ int RE_rayobject_intersect(RayObject *r, Isect *i); * Returns distance ray must travel to hit the given bounding box * BB should be in format [2][3] */ -float RE_rayobject_bb_intersect(const Isect *i, const float *bb); +/* float RE_rayobject_bb_intersect(const Isect *i, const float *bb); */ +int RE_rayobject_bb_intersect_test(const Isect *i, const float *bb); /* same as bb_intersect but doens't calculates distance */ /* * Returns the expected cost of raycast on this node, primitives have a cost of 1 diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h index 8f7e6111684..56bb907acfc 100644 --- a/source/blender/render/intern/raytrace/bvh.h +++ b/source/blender/render/intern/raytrace/bvh.h @@ -26,6 +26,47 @@ * * ***** END GPL LICENSE BLOCK ***** */ +/* +template +struct BBGroup +{ + float bb[6][SIZE]; +}; + + +static inline int test_bb_group(BBGroup<4> *bb_group, Isect *isec) +{ + const float *bb = _bb; + __m128 tmin={0}, tmax = {isec->labda}; + + tmin = _mm_max_ps(tmin, _mm_mul_ps( _mm_sub_ps( group->bb[isec->bv_index[0]], isec->sse_start[0] ), isec->sse_idot_axis[0]) ); + tmax = _mm_min_ps(tmax, _mm_mul_ps( _mm_sub_ps( group->bb[isec->bv_index[1]], isec->sse_start[0] ), isec->sse_idot_axis[0]) ); + tmin = _mm_max_ps(tmin, _mm_mul_ps( _mm_sub_ps( group->bb[isec->bv_index[2]], isec->sse_start[1] ), isec->sse_idot_axis[1]) ); + tmax = _mm_min_ps(tmax, _mm_mul_ps( _mm_sub_ps( group->bb[isec->bv_index[3]], isec->sse_start[1] ), isec->sse_idot_axis[1]) ); + tmin = _mm_max_ps(tmin, _mm_mul_ps( _mm_sub_ps( group->bb[isec->bv_index[4]], isec->sse_start[2] ), isec->sse_idot_axis[2]) ); + tmax = _mm_min_ps(tmax, _mm_mul_ps( _mm_sub_ps( group->bb[isec->bv_index[5]], isec->sse_start[2] ), isec->sse_idot_axis[2]) ); + + return _mm_movemask_ps(_mm_cmpge_ps(tmax, tmin)); +} + +static inline int test_bb_group(BBGroup<1> *bb_group, Isect *isec) +{ + float t1x = (bb[isec->bv_index[0]] - isec->start[0]) * isec->idot_axis[0]; + float t2x = (bb[isec->bv_index[1]] - isec->start[0]) * isec->idot_axis[0]; + float t1y = (bb[isec->bv_index[2]] - isec->start[1]) * isec->idot_axis[1]; + float t2y = (bb[isec->bv_index[3]] - isec->start[1]) * isec->idot_axis[1]; + float t1z = (bb[isec->bv_index[4]] - isec->start[2]) * isec->idot_axis[2]; + float t2z = (bb[isec->bv_index[5]] - isec->start[2]) * isec->idot_axis[2]; + + RE_RC_COUNT(isec->raycounter->bb.test); + if(t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) return 0; + if(t2x < 0.0 || t2y < 0.0 || t2z < 0.0) return 0; + if(t1x > isec->labda || t1y > isec->labda || t1z > isec->labda) return 0; + + RE_RC_COUNT(isec->raycounter->bb.hit); + return 1; +} +*/ /* bvh tree generics */ template static int bvh_intersect(Tree *obj, Isect *isec); @@ -68,7 +109,7 @@ static float bvh_cost(Tree *obj) /* bvh tree nodes generics */ template static inline int bvh_node_hit_test(Node *node, Isect *isec) { - return RE_rayobject_bb_intersect(isec, (const float*)node->bb) != FLT_MAX; + return RE_rayobject_bb_intersect_test(isec, (const float*)node->bb); } diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index 7316120e477..5639080c406 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -42,6 +42,7 @@ * Based on Tactical Optimization of Ray/Box Intersection, by Graham Fyffe * [http://tog.acm.org/resources/RTNews/html/rtnv21n1.html#art9] */ +/* float RE_rayobject_bb_intersect(const Isect *isec, const float *_bb) { const float *bb = _bb; @@ -67,6 +68,27 @@ float RE_rayobject_bb_intersect(const Isect *isec, const float *_bb) if (t1z > dist) dist = t1z; return dist; } +*/ +int RE_rayobject_bb_intersect_test(const Isect *isec, const float *_bb) +{ + const float *bb = _bb; + + float t1x = (bb[isec->bv_index[0]] - isec->start[0]) * isec->idot_axis[0]; + float t2x = (bb[isec->bv_index[1]] - isec->start[0]) * isec->idot_axis[0]; + float t1y = (bb[isec->bv_index[2]] - isec->start[1]) * isec->idot_axis[1]; + float t2y = (bb[isec->bv_index[3]] - isec->start[1]) * isec->idot_axis[1]; + float t1z = (bb[isec->bv_index[4]] - isec->start[2]) * isec->idot_axis[2]; + float t2z = (bb[isec->bv_index[5]] - isec->start[2]) * isec->idot_axis[2]; + + RE_RC_COUNT(isec->raycounter->bb.test); + + if(t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) return 0; + if(t2x < 0.0 || t2y < 0.0 || t2z < 0.0) return 0; + if(t1x > isec->labda || t1y > isec->labda || t1z > isec->labda) return 0; + RE_RC_COUNT(isec->raycounter->bb.hit); + + return 1; +} /* only for self-intersecting test with current render face (where ray left) */ From f16df034c3ea2824b0fb3cd6a10ab1627089ec22 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Thu, 6 Aug 2009 17:45:51 +0000 Subject: [PATCH 070/138] *Process leafs as soon as found instead of pushing them on stack for later evaluation (leads to early exits) (this is mixed with some simd code commit, althouth no simd is being used up to the moment) --- source/blender/render/intern/raytrace/bvh.h | 146 +++++++++++++----- .../render/intern/raytrace/rayobject_vbvh.cpp | 38 ++++- 2 files changed, 146 insertions(+), 38 deletions(-) diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h index 56bb907acfc..0f40ab5a408 100644 --- a/source/blender/render/intern/raytrace/bvh.h +++ b/source/blender/render/intern/raytrace/bvh.h @@ -26,47 +26,24 @@ * * ***** END GPL LICENSE BLOCK ***** */ -/* -template -struct BBGroup -{ - float bb[6][SIZE]; -}; +#include - -static inline int test_bb_group(BBGroup<4> *bb_group, Isect *isec) +inline int test_bb_group4(__m128 *bb_group, Isect *isec) { +/* const float *bb = _bb; __m128 tmin={0}, tmax = {isec->labda}; - tmin = _mm_max_ps(tmin, _mm_mul_ps( _mm_sub_ps( group->bb[isec->bv_index[0]], isec->sse_start[0] ), isec->sse_idot_axis[0]) ); - tmax = _mm_min_ps(tmax, _mm_mul_ps( _mm_sub_ps( group->bb[isec->bv_index[1]], isec->sse_start[0] ), isec->sse_idot_axis[0]) ); - tmin = _mm_max_ps(tmin, _mm_mul_ps( _mm_sub_ps( group->bb[isec->bv_index[2]], isec->sse_start[1] ), isec->sse_idot_axis[1]) ); - tmax = _mm_min_ps(tmax, _mm_mul_ps( _mm_sub_ps( group->bb[isec->bv_index[3]], isec->sse_start[1] ), isec->sse_idot_axis[1]) ); - tmin = _mm_max_ps(tmin, _mm_mul_ps( _mm_sub_ps( group->bb[isec->bv_index[4]], isec->sse_start[2] ), isec->sse_idot_axis[2]) ); - tmax = _mm_min_ps(tmax, _mm_mul_ps( _mm_sub_ps( group->bb[isec->bv_index[5]], isec->sse_start[2] ), isec->sse_idot_axis[2]) ); - - return _mm_movemask_ps(_mm_cmpge_ps(tmax, tmin)); + tmin = _mm_max_ps(tmin, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[0]], isec->sse_start[0] ), isec->sse_idot_axis[0]) ); + tmax = _mm_min_ps(tmax, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[1]], isec->sse_start[0] ), isec->sse_idot_axis[0]) ); + tmin = _mm_max_ps(tmin, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[2]], isec->sse_start[1] ), isec->sse_idot_axis[1]) ); + tmax = _mm_min_ps(tmax, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[3]], isec->sse_start[1] ), isec->sse_idot_axis[1]) ); + tmin = _mm_max_ps(tmin, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[4]], isec->sse_start[2] ), isec->sse_idot_axis[2]) ); + tmax = _mm_min_ps(tmax, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[5]], isec->sse_start[2] ), isec->sse_idot_axis[2]) ); + */ + return 4; //_mm_movemask_ps(_mm_cmpge_ps(tmax, tmin)); } -static inline int test_bb_group(BBGroup<1> *bb_group, Isect *isec) -{ - float t1x = (bb[isec->bv_index[0]] - isec->start[0]) * isec->idot_axis[0]; - float t2x = (bb[isec->bv_index[1]] - isec->start[0]) * isec->idot_axis[0]; - float t1y = (bb[isec->bv_index[2]] - isec->start[1]) * isec->idot_axis[1]; - float t2y = (bb[isec->bv_index[3]] - isec->start[1]) * isec->idot_axis[1]; - float t1z = (bb[isec->bv_index[4]] - isec->start[2]) * isec->idot_axis[2]; - float t2z = (bb[isec->bv_index[5]] - isec->start[2]) * isec->idot_axis[2]; - - RE_RC_COUNT(isec->raycounter->bb.test); - if(t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) return 0; - if(t2x < 0.0 || t2y < 0.0 || t2z < 0.0) return 0; - if(t1x > isec->labda || t1y > isec->labda || t1z > isec->labda) return 0; - - RE_RC_COUNT(isec->raycounter->bb.hit); - return 1; -} -*/ /* bvh tree generics */ template static int bvh_intersect(Tree *obj, Isect *isec); @@ -163,9 +140,108 @@ static int bvh_node_stack_raycast(Node *root, Isect *isec) } } return hit; - } + +/* + * Generic SIMD bvh recursion + * this was created to be able to use any simd (with the cost of some memmoves) + * it can take advantage of any SIMD width and doens't needs any special tree care + */ +template +static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) +{ + Node *stack[MAX_STACK_SIZE]; + __m128 t_bb[6]; + Node * t_node[4]; + + int hit = 0, stack_pos = 0; + + if(!TEST_ROOT) + { + if(RayObject_isAligned(root)) + { + if(RayObject_isAligned(root->child)) + bvh_node_push_childs(root, isec, stack, stack_pos); + else + return RE_rayobject_intersect( (RayObject*)root->child, isec); + } + else + return RE_rayobject_intersect( (RayObject*)root, isec); + } + else + { + if(RayObject_isAligned(root)) + stack[stack_pos++] = root; + else + return RE_rayobject_intersect( (RayObject*)root, isec); + } + + while(true) + { + //Use SIMD 4 + if(0 && stack_pos >= 4) + { + stack_pos -= 4; + for(int i=0; i<4; i++) + { + Node *t = stack[stack_pos+i]; + assert(RayObject_isAligned(t)); + + float *bb = ((float*)t_bb)+i; + bb[4*0] = t->bb[0]; + bb[4*1] = t->bb[1]; + bb[4*2] = t->bb[2]; + bb[4*3] = t->bb[3]; + bb[4*4] = t->bb[4]; + bb[4*5] = t->bb[5]; + t_node[i] = t->child; + } + int res = test_bb_group4( t_bb, isec ); + + for(int i=0; i<4; i++) + if(res & (1<sibling) + { + assert(stack_pos < MAX_STACK_SIZE); + stack[stack_pos++] = t; + } + } + else + { + hit |= RE_rayobject_intersect( (RayObject*)t_node[i], isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + } + } + else if(stack_pos > 0) + { + Node *node = stack[--stack_pos]; + assert(RayObject_isAligned(node)); + + if(bvh_node_hit_test(node,isec)) + { + if(RayObject_isAligned(node->child)) + { + bvh_node_push_childs(node, isec, stack, stack_pos); + assert(stack_pos <= MAX_STACK_SIZE); + } + else + { + hit |= RE_rayobject_intersect( (RayObject*)node->child, isec); + if(hit && isec->mode == RE_RAY_SHADOW) return hit; + } + } + } + else break; + } + return hit; +} + + /* * recursively transverse a BVH looking for a rayhit using system stack */ diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index e8bc59641d7..9a67f490aeb 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -48,7 +48,7 @@ extern "C" #define RAY_BB_TEST_COST (0.2f) #define DFS_STACK_SIZE 256 -#define DYNAMIC_ALLOC +//#define DYNAMIC_ALLOC_BB //#define rtbuild_split rtbuild_mean_split_largest_axis /* objects mean split on the longest axis, childs BB are allowed to overlap */ //#define rtbuild_split rtbuild_median_split_largest_axis /* space median split on the longest axis, childs BB are allowed to overlap */ @@ -59,7 +59,11 @@ struct BVHNode BVHNode *child; BVHNode *sibling; +#ifdef DYNAMIC_ALLOC_BB + float *bb; +#else float bb[6]; +#endif }; struct BVHTree @@ -92,9 +96,11 @@ inline static void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, i while(child) { //Skips BB tests on primitives +/* if(!RayObject_isAligned(child->child)) stack[stack_pos++] = child->child; else +*/ stack[stack_pos++] = child; child = child->sibling; @@ -111,6 +117,9 @@ static BVHNode *bvh_new_node(BVHTree *tree) node->sibling = NULL; node->child = NULL; +#ifdef DYNAMIC_ALLOC_BB + node->bb = (float*)BLI_memarena_alloc(tree->node_arena, 6*sizeof(float)); +#endif assert(RayObject_isAligned(node)); return node; } @@ -275,6 +284,28 @@ Node *bvh_rearrange(Tree *tree, Builder *builder) } } +template +float bvh_refit(Node *node) +{ + if(RayObject_isAligned(node)) return 0; + if(RayObject_isAligned(node->child)) return 0; + + float total = 0; + + for(Node *child = node->child; RayObject_isAligned(child) && child; child = child->sibling) + total += bvh_refit(child); + + float old_area = bb_area(node->bb, node->bb+3); + INIT_MINMAX(node->bb, node->bb+3); + for(Node *child = node->child; RayObject_isAligned(child) && child; child = child->sibling) + { + DO_MIN(child->bb, node->bb); + DO_MIN(child->bb+3, node->bb+3); + } + total += old_area - bb_area(node->bb, node->bb+3); + return total; +} + template<> void bvh_done(BVHTree *obj) { @@ -292,6 +323,7 @@ void bvh_done(BVHTree *obj) reorganize(obj->root); remove_useless(obj->root, &obj->root); pushup(obj->root); + printf("refit: %f\n", bvh_refit(obj->root) ); pushdown(obj->root); // obj->root = memory_rearrange(obj->root); obj->cost = 1.0; @@ -313,7 +345,7 @@ int intersect(BVHTree *obj, Isect* isec) { BVHNode *node = (BVHNode*)lcts->stack[i]; if(RayObject_isAligned(node)) - hit |= bvh_node_stack_raycast(node, isec); + hit |= bvh_node_stack_raycast_simd(node, isec); else hit |= RE_rayobject_intersect( (RayObject*)node, isec ); @@ -326,7 +358,7 @@ int intersect(BVHTree *obj, Isect* isec) else { if(RayObject_isAligned(obj->root)) - return bvh_node_stack_raycast(obj->root, isec); + return bvh_node_stack_raycast_simd(obj->root, isec); else return RE_rayobject_intersect( (RayObject*) obj->root, isec ); } From 4bc9ebd61f6a05532c59741073d2565fc4d6a8c7 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Thu, 6 Aug 2009 20:20:40 +0000 Subject: [PATCH 071/138] usage of simd on bb tests --- source/blender/render/intern/raytrace/bvh.h | 31 +++++++++++---------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h index 0f40ab5a408..50cdca4193d 100644 --- a/source/blender/render/intern/raytrace/bvh.h +++ b/source/blender/render/intern/raytrace/bvh.h @@ -28,20 +28,20 @@ */ #include -inline int test_bb_group4(__m128 *bb_group, Isect *isec) +inline int test_bb_group4(__m128 *bb_group, __m128 *start, __m128 *idot_axis, Isect *isec) { -/* - const float *bb = _bb; - __m128 tmin={0}, tmax = {isec->labda}; + + __m128 tmin = _mm_setzero_ps(); + __m128 tmax = _mm_load1_ps(&isec->labda); - tmin = _mm_max_ps(tmin, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[0]], isec->sse_start[0] ), isec->sse_idot_axis[0]) ); - tmax = _mm_min_ps(tmax, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[1]], isec->sse_start[0] ), isec->sse_idot_axis[0]) ); - tmin = _mm_max_ps(tmin, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[2]], isec->sse_start[1] ), isec->sse_idot_axis[1]) ); - tmax = _mm_min_ps(tmax, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[3]], isec->sse_start[1] ), isec->sse_idot_axis[1]) ); - tmin = _mm_max_ps(tmin, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[4]], isec->sse_start[2] ), isec->sse_idot_axis[2]) ); - tmax = _mm_min_ps(tmax, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[5]], isec->sse_start[2] ), isec->sse_idot_axis[2]) ); - */ - return 4; //_mm_movemask_ps(_mm_cmpge_ps(tmax, tmin)); + tmin = _mm_max_ps(tmin, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[0]], start[0] ), idot_axis[0]) ); + tmax = _mm_min_ps(tmax, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[1]], start[0] ), idot_axis[0]) ); + tmin = _mm_max_ps(tmin, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[2]], start[1] ), idot_axis[1]) ); + tmax = _mm_min_ps(tmax, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[3]], start[1] ), idot_axis[1]) ); + tmin = _mm_max_ps(tmin, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[4]], start[2] ), idot_axis[2]) ); + tmax = _mm_min_ps(tmax, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[5]], start[2] ), idot_axis[2]) ); + + return _mm_movemask_ps(_mm_cmpge_ps(tmax, tmin)); } @@ -151,6 +151,9 @@ static int bvh_node_stack_raycast(Node *root, Isect *isec) template static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) { + __m128 idot_axis[3] = { _mm_load1_ps(&isec->idot_axis[0]), _mm_load1_ps(&isec->idot_axis[1]), _mm_load1_ps(&isec->idot_axis[2]) }; + __m128 start[3] = { _mm_load1_ps(&isec->start[0]), _mm_load1_ps(&isec->start[1]), _mm_load1_ps(&isec->start[2]) }; + Node *stack[MAX_STACK_SIZE]; __m128 t_bb[6]; Node * t_node[4]; @@ -180,7 +183,7 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) while(true) { //Use SIMD 4 - if(0 && stack_pos >= 4) + if(stack_pos >= 4) { stack_pos -= 4; for(int i=0; i<4; i++) @@ -197,7 +200,7 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) bb[4*5] = t->bb[5]; t_node[i] = t->child; } - int res = test_bb_group4( t_bb, isec ); + int res = test_bb_group4( t_bb, start, idot_axis, isec ); for(int i=0; i<4; i++) if(res & (1< Date: Fri, 7 Aug 2009 00:51:41 +0000 Subject: [PATCH 072/138] improved SIMD on raytrace (up to the moment support of SIMD is done at dfs and on any type of tree) (it only shows worth on -O3 -msse2) because it seems gcc makes horrible asm code on -O2 --- source/blender/render/intern/raytrace/bvh.h | 54 ++++++++++++++++----- 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h index 50cdca4193d..52d361e707b 100644 --- a/source/blender/render/intern/raytrace/bvh.h +++ b/source/blender/render/intern/raytrace/bvh.h @@ -28,20 +28,20 @@ */ #include -inline int test_bb_group4(__m128 *bb_group, __m128 *start, __m128 *idot_axis, Isect *isec) +inline int test_bb_group4(__m128 *bb_group, __m128 *start, __m128 *idot_axis, const Isect *isec) { - __m128 tmin = _mm_setzero_ps(); - __m128 tmax = _mm_load1_ps(&isec->labda); + const __m128 tmin0 = _mm_setzero_ps(); + const __m128 tmax0 = _mm_load1_ps(&isec->labda); - tmin = _mm_max_ps(tmin, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[0]], start[0] ), idot_axis[0]) ); - tmax = _mm_min_ps(tmax, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[1]], start[0] ), idot_axis[0]) ); - tmin = _mm_max_ps(tmin, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[2]], start[1] ), idot_axis[1]) ); - tmax = _mm_min_ps(tmax, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[3]], start[1] ), idot_axis[1]) ); - tmin = _mm_max_ps(tmin, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[4]], start[2] ), idot_axis[2]) ); - tmax = _mm_min_ps(tmax, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[5]], start[2] ), idot_axis[2]) ); + const __m128 tmin1 = _mm_max_ps(tmin0, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[0]], _mm_load1_ps(&isec->start[0]) ), _mm_load1_ps(&isec->idot_axis[0])) ); + const __m128 tmax1 = _mm_min_ps(tmax0, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[1]], _mm_load1_ps(&isec->start[0]) ), _mm_load1_ps(&isec->idot_axis[0])) ); + const __m128 tmin2 = _mm_max_ps(tmin1, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[2]], _mm_load1_ps(&isec->start[1]) ), _mm_load1_ps(&isec->idot_axis[1])) ); + const __m128 tmax2 = _mm_min_ps(tmax1, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[3]], _mm_load1_ps(&isec->start[1]) ), _mm_load1_ps(&isec->idot_axis[1])) ); + const __m128 tmin3 = _mm_max_ps(tmin2, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[4]], _mm_load1_ps(&isec->start[2]) ), _mm_load1_ps(&isec->idot_axis[2])) ); + const __m128 tmax3 = _mm_min_ps(tmax2, _mm_mul_ps( _mm_sub_ps( bb_group[isec->bv_index[5]], _mm_load1_ps(&isec->start[2]) ), _mm_load1_ps(&isec->idot_axis[2])) ); - return _mm_movemask_ps(_mm_cmpge_ps(tmax, tmin)); + return _mm_movemask_ps(_mm_cmpge_ps(tmax3, tmin3)); } @@ -155,8 +155,6 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) __m128 start[3] = { _mm_load1_ps(&isec->start[0]), _mm_load1_ps(&isec->start[1]), _mm_load1_ps(&isec->start[2]) }; Node *stack[MAX_STACK_SIZE]; - __m128 t_bb[6]; - Node * t_node[4]; int hit = 0, stack_pos = 0; @@ -185,8 +183,37 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) //Use SIMD 4 if(stack_pos >= 4) { + __m128 t_bb[6]; + Node * t_node[4]; + stack_pos -= 4; - for(int i=0; i<4; i++) + + t_node[0] = stack[stack_pos+0]->child; + t_node[1] = stack[stack_pos+1]->child; + t_node[2] = stack[stack_pos+2]->child; + t_node[3] = stack[stack_pos+3]->child; + + const float *bb0 = stack[stack_pos+0]->bb; + const float *bb1 = stack[stack_pos+1]->bb; + const float *bb2 = stack[stack_pos+2]->bb; + const float *bb3 = stack[stack_pos+3]->bb; + + const __m128 x0y0x1y1 = _mm_shuffle_ps( _mm_loadu_ps(bb0), _mm_loadu_ps(bb1), _MM_SHUFFLE(0,1,0,1) ); + const __m128 x2y2x3y3 = _mm_shuffle_ps( _mm_loadu_ps(bb2), _mm_loadu_ps(bb3), _MM_SHUFFLE(0,1,0,1) ); + t_bb[0] = _mm_shuffle_ps( x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(0,2,0,2) ); + t_bb[1] = _mm_shuffle_ps( x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(1,3,1,3) ); + + const __m128 z0X0z1X1 = _mm_shuffle_ps( _mm_loadu_ps(bb0+2), _mm_loadu_ps(bb1+2), _MM_SHUFFLE(0,1,0,1) ); + const __m128 z2X2z3X3 = _mm_shuffle_ps( _mm_loadu_ps(bb2+2), _mm_loadu_ps(bb3+2), _MM_SHUFFLE(0,1,0,1) ); + t_bb[2] = _mm_shuffle_ps( z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(0,2,0,2) ); + t_bb[3] = _mm_shuffle_ps( z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(1,3,1,3) ); + + const __m128 Y0Z0Y1Z1 = _mm_shuffle_ps( _mm_loadu_ps(bb0+4), _mm_loadu_ps(bb1+4), _MM_SHUFFLE(0,1,0,1) ); + const __m128 Y2Z2Y3Z3 = _mm_shuffle_ps( _mm_loadu_ps(bb2+4), _mm_loadu_ps(bb3+4), _MM_SHUFFLE(0,1,0,1) ); + t_bb[4] = _mm_shuffle_ps( Y0Z0Y1Z1, Y2Z2Y3Z3, _MM_SHUFFLE(0,2,0,2) ); + t_bb[5] = _mm_shuffle_ps( Y0Z0Y1Z1, Y2Z2Y3Z3, _MM_SHUFFLE(1,3,1,3) ); + +/* for(int i=0; i<4; i++) { Node *t = stack[stack_pos+i]; assert(RayObject_isAligned(t)); @@ -200,6 +227,7 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) bb[4*5] = t->bb[5]; t_node[i] = t->child; } + */ int res = test_bb_group4( t_bb, start, idot_axis, isec ); for(int i=0; i<4; i++) From 20c9f2e8abf5d81e5b8a340b12ff8f6f66eee2ca Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 7 Aug 2009 01:42:51 +0000 Subject: [PATCH 073/138] Fix _MM_SHUFFLE_ order --- source/blender/render/intern/raytrace/bvh.h | 46 +++++++++++---------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h index 52d361e707b..b17a072f3a6 100644 --- a/source/blender/render/intern/raytrace/bvh.h +++ b/source/blender/render/intern/raytrace/bvh.h @@ -28,7 +28,7 @@ */ #include -inline int test_bb_group4(__m128 *bb_group, __m128 *start, __m128 *idot_axis, const Isect *isec) +inline int test_bb_group4(__m128 *bb_group, const Isect *isec) { const __m128 tmin0 = _mm_setzero_ps(); @@ -151,9 +151,6 @@ static int bvh_node_stack_raycast(Node *root, Isect *isec) template static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) { - __m128 idot_axis[3] = { _mm_load1_ps(&isec->idot_axis[0]), _mm_load1_ps(&isec->idot_axis[1]), _mm_load1_ps(&isec->idot_axis[2]) }; - __m128 start[3] = { _mm_load1_ps(&isec->start[0]), _mm_load1_ps(&isec->start[1]), _mm_load1_ps(&isec->start[2]) }; - Node *stack[MAX_STACK_SIZE]; int hit = 0, stack_pos = 0; @@ -187,7 +184,8 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) Node * t_node[4]; stack_pos -= 4; - + + /* prepare the 4BB for SIMD */ t_node[0] = stack[stack_pos+0]->child; t_node[1] = stack[stack_pos+1]->child; t_node[2] = stack[stack_pos+2]->child; @@ -198,22 +196,22 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) const float *bb2 = stack[stack_pos+2]->bb; const float *bb3 = stack[stack_pos+3]->bb; - const __m128 x0y0x1y1 = _mm_shuffle_ps( _mm_loadu_ps(bb0), _mm_loadu_ps(bb1), _MM_SHUFFLE(0,1,0,1) ); - const __m128 x2y2x3y3 = _mm_shuffle_ps( _mm_loadu_ps(bb2), _mm_loadu_ps(bb3), _MM_SHUFFLE(0,1,0,1) ); - t_bb[0] = _mm_shuffle_ps( x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(0,2,0,2) ); - t_bb[1] = _mm_shuffle_ps( x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(1,3,1,3) ); + const __m128 x0y0x1y1 = _mm_shuffle_ps( _mm_loadu_ps(bb0), _mm_loadu_ps(bb1), _MM_SHUFFLE(1,0,1,0) ); + const __m128 x2y2x3y3 = _mm_shuffle_ps( _mm_loadu_ps(bb2), _mm_loadu_ps(bb3), _MM_SHUFFLE(1,0,1,0) ); + t_bb[0] = _mm_shuffle_ps( x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(2,0,2,0) ); + t_bb[1] = _mm_shuffle_ps( x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(3,1,3,1) ); - const __m128 z0X0z1X1 = _mm_shuffle_ps( _mm_loadu_ps(bb0+2), _mm_loadu_ps(bb1+2), _MM_SHUFFLE(0,1,0,1) ); - const __m128 z2X2z3X3 = _mm_shuffle_ps( _mm_loadu_ps(bb2+2), _mm_loadu_ps(bb3+2), _MM_SHUFFLE(0,1,0,1) ); - t_bb[2] = _mm_shuffle_ps( z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(0,2,0,2) ); - t_bb[3] = _mm_shuffle_ps( z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(1,3,1,3) ); + const __m128 z0X0z1X1 = _mm_shuffle_ps( _mm_loadu_ps(bb0+2), _mm_loadu_ps(bb1+2), _MM_SHUFFLE(1,0,1,0) ); + const __m128 z2X2z3X3 = _mm_shuffle_ps( _mm_loadu_ps(bb2+2), _mm_loadu_ps(bb3+2), _MM_SHUFFLE(1,0,1,0) ); + t_bb[2] = _mm_shuffle_ps( z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(2,0,2,0) ); + t_bb[3] = _mm_shuffle_ps( z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(3,1,3,1) ); - const __m128 Y0Z0Y1Z1 = _mm_shuffle_ps( _mm_loadu_ps(bb0+4), _mm_loadu_ps(bb1+4), _MM_SHUFFLE(0,1,0,1) ); - const __m128 Y2Z2Y3Z3 = _mm_shuffle_ps( _mm_loadu_ps(bb2+4), _mm_loadu_ps(bb3+4), _MM_SHUFFLE(0,1,0,1) ); - t_bb[4] = _mm_shuffle_ps( Y0Z0Y1Z1, Y2Z2Y3Z3, _MM_SHUFFLE(0,2,0,2) ); - t_bb[5] = _mm_shuffle_ps( Y0Z0Y1Z1, Y2Z2Y3Z3, _MM_SHUFFLE(1,3,1,3) ); - -/* for(int i=0; i<4; i++) + const __m128 Y0Z0Y1Z1 = _mm_shuffle_ps( _mm_loadu_ps(bb0+4), _mm_loadu_ps(bb1+4), _MM_SHUFFLE(1,0,1,0) ); + const __m128 Y2Z2Y3Z3 = _mm_shuffle_ps( _mm_loadu_ps(bb2+4), _mm_loadu_ps(bb3+4), _MM_SHUFFLE(1,0,1,0) ); + t_bb[4] = _mm_shuffle_ps( Y0Z0Y1Z1, Y2Z2Y3Z3, _MM_SHUFFLE(2,0,2,0) ); + t_bb[5] = _mm_shuffle_ps( Y0Z0Y1Z1, Y2Z2Y3Z3, _MM_SHUFFLE(3,1,3,1) ); +/* + for(int i=0; i<4; i++) { Node *t = stack[stack_pos+i]; assert(RayObject_isAligned(t)); @@ -227,12 +225,18 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) bb[4*5] = t->bb[5]; t_node[i] = t->child; } - */ - int res = test_bb_group4( t_bb, start, idot_axis, isec ); +*/ + RE_RC_COUNT(isec->raycounter->bb.test); + RE_RC_COUNT(isec->raycounter->bb.test); + RE_RC_COUNT(isec->raycounter->bb.test); + RE_RC_COUNT(isec->raycounter->bb.test); + + int res = test_bb_group4( t_bb, isec ); for(int i=0; i<4; i++) if(res & (1<raycounter->bb.hit); if(RayObject_isAligned(t_node[i])) { for(Node *t=t_node[i]; t; t=t->sibling) From 51cad12120a673959abfbb1d4445edb782b5f13b Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 7 Aug 2009 13:49:15 +0000 Subject: [PATCH 074/138] *BLI_memarena support for any power of two alignment *some simd stuff on bvh --- source/blender/blenlib/BLI_memarena.h | 2 ++ source/blender/blenlib/intern/BLI_memarena.c | 23 +++++++++++++++++-- source/blender/render/intern/raytrace/bvh.h | 12 +++++----- .../render/intern/raytrace/rayobject_vbvh.cpp | 13 ++++++++--- 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/source/blender/blenlib/BLI_memarena.h b/source/blender/blenlib/BLI_memarena.h index 4b955e9fa20..fcf6ae02900 100644 --- a/source/blender/blenlib/BLI_memarena.h +++ b/source/blender/blenlib/BLI_memarena.h @@ -57,6 +57,8 @@ void BLI_memarena_free (struct MemArena *ma); void BLI_memarena_use_malloc (struct MemArena *ma); void BLI_memarena_use_calloc (struct MemArena *ma); +void BLI_memarena_use_align(struct MemArena *ma, int align); + void* BLI_memarena_alloc (struct MemArena *ma, int size); #ifdef __cplusplus diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c index 6312cbb22ca..275ab12540b 100644 --- a/source/blender/blenlib/intern/BLI_memarena.c +++ b/source/blender/blenlib/intern/BLI_memarena.c @@ -45,6 +45,7 @@ struct MemArena { int bufsize, cursize; int use_calloc; + int align; LinkNode *bufs; }; @@ -52,6 +53,7 @@ struct MemArena { MemArena *BLI_memarena_new(int bufsize) { MemArena *ma= MEM_callocN(sizeof(*ma), "memarena"); ma->bufsize= bufsize; + ma->align = 8; return ma; } @@ -64,6 +66,11 @@ void BLI_memarena_use_malloc(MemArena *ma) { ma->use_calloc= 0; } +void BLI_memarena_use_align(struct MemArena *ma, int align) { + /* align should be a power of two */ + ma->align = align; +} + void BLI_memarena_free(MemArena *ma) { BLI_linklist_free(ma->bufs, (void(*)(void*)) MEM_freeN); MEM_freeN(ma); @@ -77,16 +84,28 @@ void *BLI_memarena_alloc(MemArena *ma, int size) { /* ensure proper alignment by rounding * size up to multiple of 8 */ - size= PADUP(size, 8); + size= PADUP(size, ma->align); if (size>ma->cursize) { - ma->cursize= (size>ma->bufsize)?size:ma->bufsize; + unsigned char *tmp; + + if(size > ma->bufsize - (ma->align - 1)) + { + ma->cursize = PADUP(size+1, ma->align); + } + else ma->cursize = ma->bufsize; + if(ma->use_calloc) ma->curbuf= MEM_callocN(ma->cursize, "memarena calloc"); else ma->curbuf= MEM_mallocN(ma->cursize, "memarena malloc"); BLI_linklist_prepend(&ma->bufs, ma->curbuf); + + /* align alloc'ed memory (needed if align > 8) */ + tmp = (unsigned char*)PADUP( (intptr_t) ma->curbuf, ma->align); + ma->cursize -= (tmp - ma->curbuf); + ma->curbuf = tmp; } ptr= ma->curbuf; diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h index b17a072f3a6..2d75cd800a7 100644 --- a/source/blender/render/intern/raytrace/bvh.h +++ b/source/blender/render/intern/raytrace/bvh.h @@ -196,18 +196,18 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) const float *bb2 = stack[stack_pos+2]->bb; const float *bb3 = stack[stack_pos+3]->bb; - const __m128 x0y0x1y1 = _mm_shuffle_ps( _mm_loadu_ps(bb0), _mm_loadu_ps(bb1), _MM_SHUFFLE(1,0,1,0) ); - const __m128 x2y2x3y3 = _mm_shuffle_ps( _mm_loadu_ps(bb2), _mm_loadu_ps(bb3), _MM_SHUFFLE(1,0,1,0) ); + const __m128 x0y0x1y1 = _mm_shuffle_ps( _mm_load_ps(bb0), _mm_load_ps(bb1), _MM_SHUFFLE(1,0,1,0) ); + const __m128 x2y2x3y3 = _mm_shuffle_ps( _mm_load_ps(bb2), _mm_load_ps(bb3), _MM_SHUFFLE(1,0,1,0) ); t_bb[0] = _mm_shuffle_ps( x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(2,0,2,0) ); t_bb[1] = _mm_shuffle_ps( x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(3,1,3,1) ); - const __m128 z0X0z1X1 = _mm_shuffle_ps( _mm_loadu_ps(bb0+2), _mm_loadu_ps(bb1+2), _MM_SHUFFLE(1,0,1,0) ); - const __m128 z2X2z3X3 = _mm_shuffle_ps( _mm_loadu_ps(bb2+2), _mm_loadu_ps(bb3+2), _MM_SHUFFLE(1,0,1,0) ); + const __m128 z0X0z1X1 = _mm_shuffle_ps( _mm_load_ps(bb0), _mm_load_ps(bb1), _MM_SHUFFLE(3,1,3,1) ); + const __m128 z2X2z3X3 = _mm_shuffle_ps( _mm_load_ps(bb2), _mm_load_ps(bb3), _MM_SHUFFLE(3,1,3,1) ); t_bb[2] = _mm_shuffle_ps( z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(2,0,2,0) ); t_bb[3] = _mm_shuffle_ps( z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(3,1,3,1) ); - const __m128 Y0Z0Y1Z1 = _mm_shuffle_ps( _mm_loadu_ps(bb0+4), _mm_loadu_ps(bb1+4), _MM_SHUFFLE(1,0,1,0) ); - const __m128 Y2Z2Y3Z3 = _mm_shuffle_ps( _mm_loadu_ps(bb2+4), _mm_loadu_ps(bb3+4), _MM_SHUFFLE(1,0,1,0) ); + const __m128 Y0Z0Y1Z1 = _mm_shuffle_ps( _mm_load_ps(bb0+4), _mm_load_ps(bb1+4), _MM_SHUFFLE(1,0,1,0) ); + const __m128 Y2Z2Y3Z3 = _mm_shuffle_ps( _mm_load_ps(bb2+4), _mm_load_ps(bb3+4), _MM_SHUFFLE(1,0,1,0) ); t_bb[4] = _mm_shuffle_ps( Y0Z0Y1Z1, Y2Z2Y3Z3, _MM_SHUFFLE(2,0,2,0) ); t_bb[5] = _mm_shuffle_ps( Y0Z0Y1Z1, Y2Z2Y3Z3, _MM_SHUFFLE(3,1,3,1) ); /* diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index 9a67f490aeb..2f0efa80445 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -56,14 +56,14 @@ extern "C" struct BVHNode { - BVHNode *child; - BVHNode *sibling; - #ifdef DYNAMIC_ALLOC_BB float *bb; #else float bb[6]; #endif + + BVHNode *child; + BVHNode *sibling; }; struct BVHTree @@ -114,6 +114,12 @@ inline static void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, i static BVHNode *bvh_new_node(BVHTree *tree) { BVHNode *node = (BVHNode*)BLI_memarena_alloc(tree->node_arena, sizeof(BVHNode)); + + if( (((intptr_t)node) & (0x0f)) != 0 ) + { + puts("WRONG!"); + printf("%08x\n", (intptr_t)node); + } node->sibling = NULL; node->child = NULL; @@ -317,6 +323,7 @@ void bvh_done(BVHTree *obj) obj->node_arena = BLI_memarena_new(needed_nodes); BLI_memarena_use_malloc(obj->node_arena); + BLI_memarena_use_align(obj->node_arena, 16); obj->root = bvh_rearrange( obj, obj->builder ); From b7a696e2ad8cc7d5c2b91d8fa714f3637aee64e3 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 7 Aug 2009 15:57:02 +0000 Subject: [PATCH 075/138] Made -O3 and -msse2 default flags for bf_render_raytrace --- source/blender/render/SConscript | 7 ++++--- source/blender/render/intern/raytrace/bvh.h | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript index fb210afa545..2228ff9ebb9 100644 --- a/source/blender/render/SConscript +++ b/source/blender/render/SConscript @@ -1,7 +1,8 @@ #!/usr/bin/python Import ('env') -cflags='' +cflags = ['-O3'] +cxxflags = ['-O3','-msse2','-mfpmath=sse'] sources = env.Glob('intern/source/*.c') raysources = env.Glob('intern/raytrace/*.cpp') @@ -22,7 +23,7 @@ if env['WITH_BF_OPENEXR']: defs.append('WITH_OPENEXR') if env['OURPLATFORM']=='linux2': - cflags='-pthread' + cflags += ['-pthread'] env.BlenderLib ( libname = 'bf_render', sources = sources, includes = Split(incs), defines=defs, libtype='core', priority=145, compileflags=cflags ) -env.BlenderLib ( libname = 'bf_render_raytrace', sources = raysources, includes = Split(incs), defines=defs, libtype='core', priority=145, compileflags=cflags ) +env.BlenderLib ( libname = 'bf_render_raytrace', sources = raysources, includes = Split(incs), defines=defs, libtype='core', priority=145, compileflags=cflags, cxx_compileflags=cxxflags ) diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h index 2d75cd800a7..f6c12f4b3fb 100644 --- a/source/blender/render/intern/raytrace/bvh.h +++ b/source/blender/render/intern/raytrace/bvh.h @@ -201,8 +201,8 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) t_bb[0] = _mm_shuffle_ps( x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(2,0,2,0) ); t_bb[1] = _mm_shuffle_ps( x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(3,1,3,1) ); - const __m128 z0X0z1X1 = _mm_shuffle_ps( _mm_load_ps(bb0), _mm_load_ps(bb1), _MM_SHUFFLE(3,1,3,1) ); - const __m128 z2X2z3X3 = _mm_shuffle_ps( _mm_load_ps(bb2), _mm_load_ps(bb3), _MM_SHUFFLE(3,1,3,1) ); + const __m128 z0X0z1X1 = _mm_shuffle_ps( _mm_load_ps(bb0), _mm_load_ps(bb1), _MM_SHUFFLE(3,2,3,2) ); + const __m128 z2X2z3X3 = _mm_shuffle_ps( _mm_load_ps(bb2), _mm_load_ps(bb3), _MM_SHUFFLE(3,2,3,2) ); t_bb[2] = _mm_shuffle_ps( z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(2,0,2,0) ); t_bb[3] = _mm_shuffle_ps( z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(3,1,3,1) ); From 4ce316ee0fd230659485496c2fe0335e9e7ac7a1 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 10 Aug 2009 21:37:16 +0000 Subject: [PATCH 076/138] Ability to disable hints at compile time --- source/blender/render/SConscript | 2 +- .../render/intern/raytrace/rayobject_vbvh.cpp | 37 ++++++++++++------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript index 2228ff9ebb9..9c1dd385635 100644 --- a/source/blender/render/SConscript +++ b/source/blender/render/SConscript @@ -1,7 +1,7 @@ #!/usr/bin/python Import ('env') -cflags = ['-O3'] +cflags = ['-O3','-msse2','-mfpmath=sse'] cxxflags = ['-O3','-msse2','-mfpmath=sse'] sources = env.Glob('intern/source/*.c') raysources = env.Glob('intern/raytrace/*.cpp') diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index 2f0efa80445..834a1286fb8 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -46,6 +46,8 @@ extern "C" #define BVHNode VBVHNode #define BVHTree VBVHTree + +#define RE_DO_HINTS (0) #define RAY_BB_TEST_COST (0.2f) #define DFS_STACK_SIZE 256 //#define DYNAMIC_ALLOC_BB @@ -293,20 +295,20 @@ Node *bvh_rearrange(Tree *tree, Builder *builder) template float bvh_refit(Node *node) { - if(RayObject_isAligned(node)) return 0; - if(RayObject_isAligned(node->child)) return 0; + if(!RayObject_isAligned(node)) return 0; + if(!RayObject_isAligned(node->child)) return 0; float total = 0; - for(Node *child = node->child; RayObject_isAligned(child) && child; child = child->sibling) + for(Node *child = node->child; child; child = child->sibling) total += bvh_refit(child); float old_area = bb_area(node->bb, node->bb+3); INIT_MINMAX(node->bb, node->bb+3); - for(Node *child = node->child; RayObject_isAligned(child) && child; child = child->sibling) + for(Node *child = node->child; child; child = child->sibling) { DO_MIN(child->bb, node->bb); - DO_MIN(child->bb+3, node->bb+3); + DO_MAX(child->bb+3, node->bb+3); } total += old_area - bb_area(node->bb, node->bb+3); return total; @@ -329,8 +331,8 @@ void bvh_done(BVHTree *obj) obj->root = bvh_rearrange( obj, obj->builder ); reorganize(obj->root); remove_useless(obj->root, &obj->root); - pushup(obj->root); printf("refit: %f\n", bvh_refit(obj->root) ); + pushup(obj->root); pushdown(obj->root); // obj->root = memory_rearrange(obj->root); obj->cost = 1.0; @@ -342,7 +344,7 @@ void bvh_done(BVHTree *obj) template int intersect(BVHTree *obj, Isect* isec) { - if(isec->hint) + if(RE_DO_HINTS && isec->hint) { LCTSHint *lcts = (LCTSHint*)isec->hint; isec->hint = 0; @@ -423,13 +425,22 @@ void bvh_dfs_make_hint(Node *node, LCTSHint *hint, int reserve_space, HintObject template void bvh_hint_bb(Tree *tree, LCTSHint *hint, float *min, float *max) { - HintBB bb; - VECCOPY(bb.bb, min); - VECCOPY(bb.bb+3, max); + if(RE_DO_HINTS) + { + HintBB bb; + VECCOPY(bb.bb, min); + VECCOPY(bb.bb+3, max); - hint->size = 0; - bvh_dfs_make_hint( tree->root, hint, 0, &bb ); - tot_hints++; + hint->size = 0; + bvh_dfs_make_hint( tree->root, hint, 0, &bb ); + tot_hints++; + } + else + { + hint->size = 0; + hint->stack[hint->size++] = (RayObject*)tree->root; + tot_hints++; + } } void bfree(BVHTree *tree) From 5d40c1b59784316473b79d5a61188f3e17f020b7 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 11 Aug 2009 00:33:51 +0000 Subject: [PATCH 077/138] *Added a tree structure with a variable number of childs per node, but with groupped childs (for SIMD) *SIMD support for the first 4*N childs of each node *Some bvh code organized --- source/blender/render/intern/raytrace/bvh.h | 41 ++- .../render/intern/raytrace/rayobject_vbvh.cpp | 336 +++++++++--------- .../render/intern/raytrace/reorganize.h | 108 +++++- source/blender/render/intern/raytrace/svbvh.h | 230 ++++++++++++ 4 files changed, 523 insertions(+), 192 deletions(-) create mode 100644 source/blender/render/intern/raytrace/svbvh.h diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h index f6c12f4b3fb..8538d9201e0 100644 --- a/source/blender/render/intern/raytrace/bvh.h +++ b/source/blender/render/intern/raytrace/bvh.h @@ -28,6 +28,9 @@ */ #include +#ifndef RE_RAYTRACE_BVH_H +#define RE_RAYTRACE_BVH_H + inline int test_bb_group4(__m128 *bb_group, const Isect *isec) { @@ -53,6 +56,12 @@ template static void bvh_add(Tree *obj, RayObject *ob) rtbuild_add( obj->builder, ob ); } +template +inline bool is_leaf(Node *node) +{ + return !RayObject_isAligned(node); +} + template static void bvh_done(Tree *obj); template @@ -93,14 +102,14 @@ template static inline int bvh_node_hit_test(Node *node, Isect *isec template static void bvh_node_merge_bb(Node *node, float *min, float *max) { - if(RayObject_isAligned(node)) + if(is_leaf(node)) { - DO_MIN(node->bb , min); - DO_MAX(node->bb+3, max); + RE_rayobject_merge_bb( (RayObject*)node, min, max); } else { - RE_rayobject_merge_bb( (RayObject*)node, min, max); + DO_MIN(node->bb , min); + DO_MAX(node->bb+3, max); } } @@ -117,7 +126,7 @@ static int bvh_node_stack_raycast(Node *root, Isect *isec) Node *stack[MAX_STACK_SIZE]; int hit = 0, stack_pos = 0; - if(!TEST_ROOT && RayObject_isAligned(root)) + if(!TEST_ROOT && !is_leaf(root)) bvh_node_push_childs(root, isec, stack, stack_pos); else stack[stack_pos++] = root; @@ -125,7 +134,7 @@ static int bvh_node_stack_raycast(Node *root, Isect *isec) while(stack_pos) { Node *node = stack[--stack_pos]; - if(RayObject_isAligned(node)) + if(!is_leaf(node)) { if(bvh_node_hit_test(node,isec)) { @@ -157,9 +166,9 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) if(!TEST_ROOT) { - if(RayObject_isAligned(root)) + if(!is_leaf(root)) { - if(RayObject_isAligned(root->child)) + if(!is_leaf(root->child)) bvh_node_push_childs(root, isec, stack, stack_pos); else return RE_rayobject_intersect( (RayObject*)root->child, isec); @@ -169,7 +178,7 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) } else { - if(RayObject_isAligned(root)) + if(!is_leaf(root)) stack[stack_pos++] = root; else return RE_rayobject_intersect( (RayObject*)root, isec); @@ -214,7 +223,7 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) for(int i=0; i<4; i++) { Node *t = stack[stack_pos+i]; - assert(RayObject_isAligned(t)); + assert(!is_leaf(t)); float *bb = ((float*)t_bb)+i; bb[4*0] = t->bb[0]; @@ -237,7 +246,7 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) if(res & (1<raycounter->bb.hit); - if(RayObject_isAligned(t_node[i])) + if(!is_leaf(t_node[i])) { for(Node *t=t_node[i]; t; t=t->sibling) { @@ -255,11 +264,11 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) else if(stack_pos > 0) { Node *node = stack[--stack_pos]; - assert(RayObject_isAligned(node)); + assert(!is_leaf(node)); if(bvh_node_hit_test(node,isec)) { - if(RayObject_isAligned(node->child)) + if(!is_leaf(node->child)) { bvh_node_push_childs(node, isec, stack, stack_pos); assert(stack_pos <= MAX_STACK_SIZE); @@ -291,7 +300,7 @@ static int bvh_node_raycast(Node *node, Isect *isec) { int i; for(i=0; ichild[i])) + if(!is_leaf(node->child[i])) { if(node->child[i] == 0) break; @@ -308,7 +317,7 @@ static int bvh_node_raycast(Node *node, Isect *isec) { int i; for(i=BVH_NCHILDS-1; i>=0; i--) - if(RayObject_isAligned(node->child[i])) + if(!is_leaf(node->child[i])) { if(node->child[i]) { @@ -326,3 +335,5 @@ static int bvh_node_raycast(Node *node, Isect *isec) return hit; } */ + +#endif diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index 834a1286fb8..7f990e06152 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -26,6 +26,12 @@ * * ***** END GPL LICENSE BLOCK ***** */ +#define RE_USE_HINT (0) +static int tot_pushup = 0; +static int tot_pushdown = 0; +static int tot_hints = 0; + + extern "C" { #include @@ -41,22 +47,21 @@ extern "C" #include "rayobject_hint.h" #include "reorganize.h" #include "bvh.h" +#include "svbvh.h" #include -#define BVHNode VBVHNode -#define BVHTree VBVHTree - #define RE_DO_HINTS (0) #define RAY_BB_TEST_COST (0.2f) #define DFS_STACK_SIZE 256 //#define DYNAMIC_ALLOC_BB + //#define rtbuild_split rtbuild_mean_split_largest_axis /* objects mean split on the longest axis, childs BB are allowed to overlap */ //#define rtbuild_split rtbuild_median_split_largest_axis /* space median split on the longest axis, childs BB are allowed to overlap */ #define rtbuild_split rtbuild_heuristic_object_split /* split objects using heuristic */ -struct BVHNode +struct VBVHNode { #ifdef DYNAMIC_ALLOC_BB float *bb; @@ -64,15 +69,15 @@ struct BVHNode float bb[6]; #endif - BVHNode *child; - BVHNode *sibling; + VBVHNode *child; + VBVHNode *sibling; }; -struct BVHTree +struct VBVHTree { RayObject rayobj; - BVHNode *root; + SVBVHNode *root; MemArena *node_arena; @@ -81,6 +86,54 @@ struct BVHTree }; + + +template +struct Reorganize_VBVH +{ + Tree *tree; + + Reorganize_VBVH(Tree *t) + { + tree = t; + } + + VBVHNode *create_node() + { + VBVHNode *node = (VBVHNode*)BLI_memarena_alloc(tree->node_arena, sizeof(VBVHNode)); + return node; + } + + void copy_bb(VBVHNode *node, OldNode *old) + { + std::copy( old->bb, old->bb+6, node->bb ); + } + + VBVHNode *transform(OldNode *old) + { + if(is_leaf(old)) + return (VBVHNode*)old; + + VBVHNode *node = create_node(); + VBVHNode **child_ptr = &node->child; + node->sibling = 0; + + copy_bb(node,old); + + for(OldNode *o_child = old->child; o_child; o_child = o_child->sibling) + { + VBVHNode *n_child = transform(o_child); + *child_ptr = n_child; + if(is_leaf(n_child)) return node; + child_ptr = &n_child->sibling; + } + *child_ptr = 0; + + return node; + } +}; + + /* * Push nodes (used on dfs) */ @@ -89,7 +142,7 @@ inline static void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, i { Node *child = node->child; - if(!RayObject_isAligned(child)) + if(is_leaf(child)) { stack[stack_pos++] = child; } @@ -99,7 +152,7 @@ inline static void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, i { //Skips BB tests on primitives /* - if(!RayObject_isAligned(child->child)) + if(is_leaf(child->child)) stack[stack_pos++] = child->child; else */ @@ -113,9 +166,9 @@ inline static void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, i /* * BVH done */ -static BVHNode *bvh_new_node(BVHTree *tree) +static VBVHNode *bvh_new_node(VBVHTree *tree) { - BVHNode *node = (BVHNode*)BLI_memarena_alloc(tree->node_arena, sizeof(BVHNode)); + VBVHNode *node = (VBVHNode*)BLI_memarena_alloc(tree->node_arena, sizeof(VBVHNode)); if( (((intptr_t)node) & (0x0f)) != 0 ) { @@ -132,70 +185,7 @@ static BVHNode *bvh_new_node(BVHTree *tree) return node; } -template -float rtbuild_area(Builder *builder) -{ - float min[3], max[3]; - INIT_MINMAX(min, max); - rtbuild_merge_bb(builder, min, max); - return bb_area(min, max); -} -template -void bvh_update_bb(Node *node) -{ - INIT_MINMAX(node->bb, node->bb+3); - Node *child = node->child; - - while(child) - { - bvh_node_merge_bb(child, node->bb, node->bb+3); - if(RayObject_isAligned(child)) - child = child->sibling; - else - child = 0; - } -} - - -static int tot_pushup = 0; -static int tot_pushdown = 0; -static int tot_hints = 0; - -template -void pushdown(Node *parent) -{ - Node **s_child = &parent->child; - Node * child = parent->child; - - while(child && RayObject_isAligned(child)) - { - Node *next = child->sibling; - Node **next_s_child = &child->sibling; - - //assert(bb_fits_inside(parent->bb, parent->bb+3, child->bb, child->bb+3)); - - for(Node *i = parent->child; RayObject_isAligned(i) && i; i = i->sibling) - if(child != i && bb_fits_inside(i->bb, i->bb+3, child->bb, child->bb+3) && RayObject_isAligned(i->child)) - { -// todo optimize (should the one with the smallest area?) -// float ia = bb_area(i->bb, i->bb+3) -// if(child->i) - *s_child = child->sibling; - child->sibling = i->child; - i->child = child; - next_s_child = s_child; - - tot_pushdown++; - break; - } - child = next; - s_child = next_s_child; - } - - for(Node *i = parent->child; RayObject_isAligned(i) && i; i = i->sibling) - pushdown( i ); -} template int count_childs(Node *parent) @@ -204,7 +194,7 @@ int count_childs(Node *parent) for(Node *i = parent->child; i; i = i->sibling) { n++; - if(!RayObject_isAligned(i)) + if(is_leaf(i)) break; } @@ -220,39 +210,6 @@ void append_sibling(Node *node, Node *sibling) node->sibling = sibling; } -template -void pushup(Node *parent) -{ - float p_area = bb_area(parent->bb, parent->bb+3); - Node **prev = &parent->child; - for(Node *child = parent->child; RayObject_isAligned(child) && child; ) - { - float c_area = bb_area(child->bb, child->bb+3) ; - int nchilds = count_childs(child); - float original_cost = (c_area / p_area)*nchilds + 1; - float flatten_cost = nchilds; - if(flatten_cost < original_cost && nchilds >= 2) - { - append_sibling(child, child->child); - child = child->sibling; - *prev = child; - -// *prev = child->child; -// append_sibling( *prev, child->sibling ); -// child = *prev; - tot_pushup++; - } - else - { - *prev = child; - prev = &(*prev)->sibling; - child = *prev; - } - } - - for(Node *child = parent->child; RayObject_isAligned(child) && child; child = child->sibling) - pushup(child); -} template Node *bvh_rearrange(Tree *tree, Builder *builder) @@ -264,7 +221,7 @@ Node *bvh_rearrange(Tree *tree, Builder *builder) Node *node = bvh_new_node(tree); INIT_MINMAX(node->bb, node->bb+3); rtbuild_merge_bb(builder, node->bb, node->bb+3); - node->child = (BVHNode*) rtbuild_get_primitive( builder, 0 ); + node->child = (VBVHNode*) rtbuild_get_primitive( builder, 0 ); return node; } else @@ -292,30 +249,8 @@ Node *bvh_rearrange(Tree *tree, Builder *builder) } } -template -float bvh_refit(Node *node) -{ - if(!RayObject_isAligned(node)) return 0; - if(!RayObject_isAligned(node->child)) return 0; - - float total = 0; - - for(Node *child = node->child; child; child = child->sibling) - total += bvh_refit(child); - - float old_area = bb_area(node->bb, node->bb+3); - INIT_MINMAX(node->bb, node->bb+3); - for(Node *child = node->child; child; child = child->sibling) - { - DO_MIN(child->bb, node->bb); - DO_MAX(child->bb+3, node->bb+3); - } - total += old_area - bb_area(node->bb, node->bb+3); - return total; -} - template<> -void bvh_done(BVHTree *obj) +void bvh_done(VBVHTree *obj) { rtbuild_done(obj->builder); @@ -323,18 +258,47 @@ void bvh_done(BVHTree *obj) if(needed_nodes > BLI_MEMARENA_STD_BUFSIZE) needed_nodes = BLI_MEMARENA_STD_BUFSIZE; - obj->node_arena = BLI_memarena_new(needed_nodes); - BLI_memarena_use_malloc(obj->node_arena); - BLI_memarena_use_align(obj->node_arena, 16); - + MemArena *arena1 = BLI_memarena_new(needed_nodes); + BLI_memarena_use_malloc(arena1); + BLI_memarena_use_align(arena1, 16); + obj->node_arena = arena1; - obj->root = bvh_rearrange( obj, obj->builder ); - reorganize(obj->root); - remove_useless(obj->root, &obj->root); - printf("refit: %f\n", bvh_refit(obj->root) ); - pushup(obj->root); - pushdown(obj->root); -// obj->root = memory_rearrange(obj->root); + VBVHNode *root = bvh_rearrange( obj, obj->builder ); + reorganize(root); + remove_useless(root, &root); + printf("refit: %f\n", bvh_refit(root) ); + + pushup(root); + pushdown(root); + + //Memory re-organize + if(0) + { + MemArena *arena2 = BLI_memarena_new(needed_nodes); + BLI_memarena_use_malloc(arena2); + BLI_memarena_use_align(arena2, 16); + obj->node_arena = arena2; + root = Reorganize_VBVH(obj).transform(root); + + BLI_memarena_free(arena1); + } + + if(1) + { + MemArena *arena2 = BLI_memarena_new(needed_nodes); + BLI_memarena_use_malloc(arena2); + BLI_memarena_use_align(arena2, 16); + obj->node_arena = arena2; + obj->root = Reorganize_SVBVH(obj).transform(root); + + BLI_memarena_free(arena1); + } +/* + { + obj->root = root; + } +*/ + obj->cost = 1.0; rtbuild_free( obj->builder ); @@ -342,8 +306,9 @@ void bvh_done(BVHTree *obj) } template -int intersect(BVHTree *obj, Isect* isec) +int intersect(VBVHTree *obj, Isect* isec) { +/* if(RE_DO_HINTS && isec->hint) { LCTSHint *lcts = (LCTSHint*)isec->hint; @@ -352,9 +317,9 @@ int intersect(BVHTree *obj, Isect* isec) int hit = 0; for(int i=0; isize; i++) { - BVHNode *node = (BVHNode*)lcts->stack[i]; + VBVHNode *node = (VBVHNode*)lcts->stack[i]; if(RayObject_isAligned(node)) - hit |= bvh_node_stack_raycast_simd(node, isec); + hit |= bvh_node_stack_raycast(node, isec); else hit |= RE_rayobject_intersect( (RayObject*)node, isec ); @@ -365,9 +330,10 @@ int intersect(BVHTree *obj, Isect* isec) return hit; } else +*/ { if(RayObject_isAligned(obj->root)) - return bvh_node_stack_raycast_simd(obj->root, isec); + return bvh_node_stack_raycast( obj->root, isec); else return RE_rayobject_intersect( (RayObject*) obj->root, isec ); } @@ -395,7 +361,7 @@ void bvh_dfs_make_hint(Node *node, LCTSHint *hint, int reserve_space, HintObject { assert( hint->size + reserve_space + 1 <= RE_RAY_LCTS_MAX_SIZE ); - if(!RayObject_isAligned(node)) + if(is_leaf(node)) { hint->stack[hint->size++] = (RayObject*)node; } @@ -425,25 +391,26 @@ void bvh_dfs_make_hint(Node *node, LCTSHint *hint, int reserve_space, HintObject template void bvh_hint_bb(Tree *tree, LCTSHint *hint, float *min, float *max) { - if(RE_DO_HINTS) +/* + if(RE_USE_HINT) { HintBB bb; VECCOPY(bb.bb, min); VECCOPY(bb.bb+3, max); - + hint->size = 0; bvh_dfs_make_hint( tree->root, hint, 0, &bb ); tot_hints++; } else +*/ { - hint->size = 0; - hint->stack[hint->size++] = (RayObject*)tree->root; - tot_hints++; + hint->size = 0; + hint->stack[hint->size++] = (RayObject*)tree->root; } } -void bfree(BVHTree *tree) +void bfree(VBVHTree *tree) { if(tot_pushup + tot_pushdown + tot_hints + tot_moves) { @@ -460,47 +427,40 @@ void bfree(BVHTree *tree) } /* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */ -template +template static RayObjectAPI make_api() { static RayObjectAPI api = { - (RE_rayobject_raycast_callback) ((int(*)(BVHTree*,Isect*)) &intersect), - (RE_rayobject_add_callback) ((void(*)(BVHTree*,RayObject*)) &bvh_add), - (RE_rayobject_done_callback) ((void(*)(BVHTree*)) &bvh_done), -// (RE_rayobject_free_callback) ((void(*)(BVHTree*)) &bvh_free), - (RE_rayobject_free_callback) ((void(*)(BVHTree*)) &bfree), - (RE_rayobject_merge_bb_callback)((void(*)(BVHTree*,float*,float*)) &bvh_bb), - (RE_rayobject_cost_callback) ((float(*)(BVHTree*)) &bvh_cost), - (RE_rayobject_hint_bb_callback) ((void(*)(BVHTree*,LCTSHint*,float*,float*)) &bvh_hint_bb) + (RE_rayobject_raycast_callback) ((int(*)(Tree*,Isect*)) &intersect), + (RE_rayobject_add_callback) ((void(*)(Tree*,RayObject*)) &bvh_add), + (RE_rayobject_done_callback) ((void(*)(Tree*)) &bvh_done), +// (RE_rayobject_free_callback) ((void(*)(Tree*)) &bvh_free), + (RE_rayobject_free_callback) ((void(*)(Tree*)) &bfree), + (RE_rayobject_merge_bb_callback)((void(*)(Tree*,float*,float*)) &bvh_bb), + (RE_rayobject_cost_callback) ((float(*)(Tree*)) &bvh_cost), + (RE_rayobject_hint_bb_callback) ((void(*)(Tree*,LCTSHint*,float*,float*)) &bvh_hint_bb) }; return api; } +template static RayObjectAPI* get_api(int maxstacksize) { -// static RayObjectAPI bvh_api16 = make_api<16>(); -// static RayObjectAPI bvh_api32 = make_api<32>(); -// static RayObjectAPI bvh_api64 = make_api<64>(); - static RayObjectAPI bvh_api128 = make_api<128>(); - static RayObjectAPI bvh_api256 = make_api<256>(); + static RayObjectAPI bvh_api256 = make_api(); -// if(maxstacksize <= 16 ) return &bvh_api16; -// if(maxstacksize <= 32 ) return &bvh_api32; -// if(maxstacksize <= 64 ) return &bvh_api64; - if(maxstacksize <= 128) return &bvh_api128; - if(maxstacksize <= 256) return &bvh_api256; + if(maxstacksize <= 1024) return &bvh_api256; assert(maxstacksize <= 256); return 0; } RayObject *RE_rayobject_vbvh_create(int size) { - BVHTree *obj= (BVHTree*)MEM_callocN(sizeof(BVHTree), "BVHTree"); + VBVHTree *obj= (VBVHTree*)MEM_callocN(sizeof(VBVHTree), "VBVHTree"); assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ - obj->rayobj.api = get_api(DFS_STACK_SIZE); + obj->rayobj.api = get_api(DFS_STACK_SIZE); obj->root = NULL; obj->node_arena = NULL; @@ -508,3 +468,27 @@ RayObject *RE_rayobject_vbvh_create(int size) return RayObject_unalignRayAPI((RayObject*) obj); } + + + +/* SVBVH */ +template +void bvh_dfs_make_hint(VBVHNode *node, LCTSHint *hint, int reserve_space, HintObject *hintObject) +{ + return; +} +/* +RayObject *RE_rayobject_svbvh_create(int size) +{ + SVBVHTree *obj= (SVBVHTree*)MEM_callocN(sizeof(SVBVHTree), "SVBVHTree"); + assert( RayObject_isAligned(obj) ); // RayObject API assumes real data to be 4-byte aligned + + obj->rayobj.api = get_api(DFS_STACK_SIZE); + obj->root = NULL; + + obj->node_arena = NULL; + obj->builder = rtbuild_create( size ); + + return RayObject_unalignRayAPI((RayObject*) obj); +} +*/ \ No newline at end of file diff --git a/source/blender/render/intern/raytrace/reorganize.h b/source/blender/render/intern/raytrace/reorganize.h index 723c2b77902..2f79b0f6e82 100644 --- a/source/blender/render/intern/raytrace/reorganize.h +++ b/source/blender/render/intern/raytrace/reorganize.h @@ -130,9 +130,115 @@ void remove_useless(Node *node, Node **new_node) } if(node->child) { - if(RayObject_isAligned(node->child) && node->child->child == 0) + if(RayObject_isAligned(node->child) && node->child->sibling == 0) *new_node = node->child; } else if(node->child == 0) *new_node = 0; } + +/* + * Minimizes expected number of BBtest by colapsing nodes + * it uses surface area heuristic for determining whether a node should be colapsed + */ +template +void pushup(Node *parent) +{ + float p_area = bb_area(parent->bb, parent->bb+3); + Node **prev = &parent->child; + for(Node *child = parent->child; RayObject_isAligned(child) && child; ) + { + float c_area = bb_area(child->bb, child->bb+3) ; + int nchilds = count_childs(child); + float original_cost = (c_area / p_area)*nchilds + 1; + float flatten_cost = nchilds; + if(flatten_cost < original_cost && nchilds >= 2) + { + append_sibling(child, child->child); + child = child->sibling; + *prev = child; + +// *prev = child->child; +// append_sibling( *prev, child->sibling ); +// child = *prev; + tot_pushup++; + } + else + { + *prev = child; + prev = &(*prev)->sibling; + child = *prev; + } + } + + for(Node *child = parent->child; RayObject_isAligned(child) && child; child = child->sibling) + pushup(child); +} + + + +/* + * Pushdown + * makes sure no child fits inside any of its sibling + */ +template +void pushdown(Node *parent) +{ + Node **s_child = &parent->child; + Node * child = parent->child; + + while(child && RayObject_isAligned(child)) + { + Node *next = child->sibling; + Node **next_s_child = &child->sibling; + + //assert(bb_fits_inside(parent->bb, parent->bb+3, child->bb, child->bb+3)); + + for(Node *i = parent->child; RayObject_isAligned(i) && i; i = i->sibling) + if(child != i && bb_fits_inside(i->bb, i->bb+3, child->bb, child->bb+3) && RayObject_isAligned(i->child)) + { +// todo optimize (should the one with the smallest area?) +// float ia = bb_area(i->bb, i->bb+3) +// if(child->i) + *s_child = child->sibling; + child->sibling = i->child; + i->child = child; + next_s_child = s_child; + + tot_pushdown++; + break; + } + child = next; + s_child = next_s_child; + } + + for(Node *i = parent->child; RayObject_isAligned(i) && i; i = i->sibling) + pushdown( i ); +} + + +/* + * BVH refit + * reajust nodes BB (useful if nodes childs where modified) + */ +template +float bvh_refit(Node *node) +{ + if(is_leaf(node)) return 0; + if(is_leaf(node->child)) return 0; + + float total = 0; + + for(Node *child = node->child; child; child = child->sibling) + total += bvh_refit(child); + + float old_area = bb_area(node->bb, node->bb+3); + INIT_MINMAX(node->bb, node->bb+3); + for(Node *child = node->child; child; child = child->sibling) + { + DO_MIN(child->bb, node->bb); + DO_MAX(child->bb+3, node->bb+3); + } + total += old_area - bb_area(node->bb, node->bb+3); + return total; +} diff --git a/source/blender/render/intern/raytrace/svbvh.h b/source/blender/render/intern/raytrace/svbvh.h new file mode 100644 index 00000000000..f537aa79dac --- /dev/null +++ b/source/blender/render/intern/raytrace/svbvh.h @@ -0,0 +1,230 @@ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef RE_RAYTRACE_SVBVH_H +#define RE_RAYTRACE_SVBVH_H + +#define SVBVH_SIMD 1 + +#include "bvh.h" +#include + +struct SVBVHNode +{ + int nchilds; + + //Array of bb, array of childs + float *bb; + SVBVHNode **child; +}; + +template<> +inline int bvh_node_hit_test(SVBVHNode *node, Isect *isec) +{ + return 1; +} + +template<> +inline void bvh_node_push_childs(SVBVHNode *node, Isect *isec, SVBVHNode **stack, int &stack_pos) +{ + if(SVBVH_SIMD) + { + int i=0; + while(i+4 <= node->nchilds) + { + int res = test_bb_group4( (__m128*) (node->bb+6*i), isec ); + RE_RC_COUNT(isec->raycounter->bb.test); + RE_RC_COUNT(isec->raycounter->bb.test); + RE_RC_COUNT(isec->raycounter->bb.test); + RE_RC_COUNT(isec->raycounter->bb.test); + + if(res & 1) { stack[stack_pos++] = node->child[i+0]; RE_RC_COUNT(isec->raycounter->bb.hit); } + if(res & 2) { stack[stack_pos++] = node->child[i+1]; RE_RC_COUNT(isec->raycounter->bb.hit); } + if(res & 4) { stack[stack_pos++] = node->child[i+2]; RE_RC_COUNT(isec->raycounter->bb.hit); } + if(res & 8) { stack[stack_pos++] = node->child[i+3]; RE_RC_COUNT(isec->raycounter->bb.hit); } + + i += 4; + } + while(i < node->nchilds) + { + if(RE_rayobject_bb_intersect_test(isec, (const float*)node->bb+6*i)) + stack[stack_pos++] = node->child[i]; + i++; + } + } + else + { + for(int i=0; inchilds; i++) + { + if(RE_rayobject_bb_intersect_test(isec, (const float*)node->bb+6*i)) + stack[stack_pos++] = node->child[i]; + } + } +} + +struct SVBVHTree +{ + RayObject rayobj; + + SVBVHNode *root; + + MemArena *node_arena; + + float cost; + RTBuilder *builder; +}; + + + +template +struct Reorganize_SVBVH +{ + Tree *tree; + + float childs_per_node; + int nodes_with_childs[16]; + int nodes; + + Reorganize_SVBVH(Tree *t) + { + tree = t; + nodes = 0; + childs_per_node = 0; + + for(int i=0; i<16; i++) + nodes_with_childs[i] = 0; + } + + ~Reorganize_SVBVH() + { + printf("%f childs per node\n", childs_per_node / nodes); + for(int i=0; i<16; i++) + printf("%i childs per node: %d/%d = %f\n", i, nodes_with_childs[i], nodes, nodes_with_childs[i]/float(nodes)); + } + + SVBVHNode *create_node(int nchilds) + { + SVBVHNode *node = (SVBVHNode*)BLI_memarena_alloc(tree->node_arena, sizeof(SVBVHNode)); + node->nchilds = nchilds; + node->bb = (float*)BLI_memarena_alloc(tree->node_arena, sizeof(float)*6*nchilds); + node->child= (SVBVHNode**)BLI_memarena_alloc(tree->node_arena, sizeof(SVBVHNode*)*nchilds); + + return node; + } + + void copy_bb(float *bb, float *old_bb) + { + std::copy( old_bb, old_bb+6, bb ); + } + + void prepare_for_simd(SVBVHNode *node) + { + int i=0; + while(i+4 <= node->nchilds) + { + float vec_tmp[4*6]; + float *res = node->bb+6*i; + std::copy( node->bb+6*i, node->bb+6*(i+4), vec_tmp); + + for(int j=0; j<6; j++) + { + res[4*j+0] = vec_tmp[6*0+j]; + res[4*j+1] = vec_tmp[6*1+j]; + res[4*j+2] = vec_tmp[6*2+j]; + res[4*j+3] = vec_tmp[6*3+j]; + } +/* + const float *bb0 = vec_tmp+6*(i+0); + const float *bb1 = vec_tmp+6*(i+1); + const float *bb2 = vec_tmp+6*(i+2); + const float *bb3 = vec_tmp+6*(i+3); + + //memmoves could be memory alligned + const __m128 x0y0x1y1 = _mm_shuffle_ps( _mm_loadu_ps(bb0), _mm_loadu_ps(bb1), _MM_SHUFFLE(1,0,1,0) ); + const __m128 x2y2x3y3 = _mm_shuffle_ps( _mm_loadu_ps(bb2), _mm_loadu_ps(bb3), _MM_SHUFFLE(1,0,1,0) ); + _mm_store_ps( node->bb+6*i+4*0, _mm_shuffle_ps( x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(2,0,2,0) ) ); + _mm_store_ps( node->bb+6*i+4*1, _mm_shuffle_ps( x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(3,1,3,1) ) ); + + const __m128 z0X0z1X1 = _mm_shuffle_ps( _mm_loadu_ps(bb0), _mm_loadu_ps(bb1), _MM_SHUFFLE(3,2,3,2) ); + const __m128 z2X2z3X3 = _mm_shuffle_ps( _mm_loadu_ps(bb2), _mm_loadu_ps(bb3), _MM_SHUFFLE(3,2,3,2) ); + _mm_store_ps( node->bb+6*i+4*2, _mm_shuffle_ps( z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(2,0,2,0) ) ); + _mm_store_ps( node->bb+6*i+4*3, _mm_shuffle_ps( z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(3,1,3,1) ) ); + + const __m128 Y0Z0Y1Z1 = _mm_shuffle_ps( _mm_loadu_ps(bb0+4), _mm_loadu_ps(bb1+4), _MM_SHUFFLE(1,0,1,0) ); + const __m128 Y2Z2Y3Z3 = _mm_shuffle_ps( _mm_loadu_ps(bb2+4), _mm_loadu_ps(bb3+4), _MM_SHUFFLE(1,0,1,0) ); + _mm_store_ps( node->bb+6*i+4*4, _mm_shuffle_ps( Y0Z0Y1Z1, Y2Z2Y3Z3, _MM_SHUFFLE(2,0,2,0) ) ); + _mm_store_ps( node->bb+6*i+4*5, _mm_shuffle_ps( Y0Z0Y1Z1, Y2Z2Y3Z3, _MM_SHUFFLE(3,1,3,1) ) ); + */ + + i += 4; + } + } + + SVBVHNode *transform(OldNode *old) + { + if(is_leaf(old)) + return (SVBVHNode*)old; + if(is_leaf(old->child)) + return (SVBVHNode*)old->child; + + int nchilds = count_childs(old); + SVBVHNode *node = create_node(nchilds); + + childs_per_node += nchilds; + nodes++; + if(nchilds < 16) + nodes_with_childs[nchilds]++; + + int i=nchilds; + for(OldNode *o_child = old->child; o_child; o_child = o_child->sibling) + { + i--; + node->child[i] = transform(o_child); + if(is_leaf(o_child)) + { + float bb[6]; + INIT_MINMAX(bb, bb+3); + RE_rayobject_merge_bb( (RayObject*)o_child, bb, bb+3); + copy_bb(node->bb+i*6, bb); + break; + } + else + { + copy_bb(node->bb+i*6, o_child->bb); + } + } + assert( i == 0 ); + + if(SVBVH_SIMD) + prepare_for_simd(node); + + return node; + } +}; + +#endif From 495ef8a6a24f516826175f78cb6cb60facd82592 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 11 Aug 2009 17:28:58 +0000 Subject: [PATCH 078/138] fix instance support when using SIMD --- source/blender/render/intern/raytrace/svbvh.h | 69 +++++++++++++++---- 1 file changed, 54 insertions(+), 15 deletions(-) diff --git a/source/blender/render/intern/raytrace/svbvh.h b/source/blender/render/intern/raytrace/svbvh.h index f537aa79dac..cc875ad6dba 100644 --- a/source/blender/render/intern/raytrace/svbvh.h +++ b/source/blender/render/intern/raytrace/svbvh.h @@ -39,7 +39,7 @@ struct SVBVHNode int nchilds; //Array of bb, array of childs - float *bb; + float *child_bb; SVBVHNode **child; }; @@ -57,7 +57,7 @@ inline void bvh_node_push_childs(SVBVHNode *node, Isect *isec, SVBVHN int i=0; while(i+4 <= node->nchilds) { - int res = test_bb_group4( (__m128*) (node->bb+6*i), isec ); + int res = test_bb_group4( (__m128*) (node->child_bb+6*i), isec ); RE_RC_COUNT(isec->raycounter->bb.test); RE_RC_COUNT(isec->raycounter->bb.test); RE_RC_COUNT(isec->raycounter->bb.test); @@ -72,7 +72,7 @@ inline void bvh_node_push_childs(SVBVHNode *node, Isect *isec, SVBVHN } while(i < node->nchilds) { - if(RE_rayobject_bb_intersect_test(isec, (const float*)node->bb+6*i)) + if(RE_rayobject_bb_intersect_test(isec, (const float*)node->child_bb+6*i)) stack[stack_pos++] = node->child[i]; i++; } @@ -81,12 +81,51 @@ inline void bvh_node_push_childs(SVBVHNode *node, Isect *isec, SVBVHN { for(int i=0; inchilds; i++) { - if(RE_rayobject_bb_intersect_test(isec, (const float*)node->bb+6*i)) + if(RE_rayobject_bb_intersect_test(isec, (const float*)node->child_bb+6*i)) stack[stack_pos++] = node->child[i]; } } } +template<> +void bvh_node_merge_bb(SVBVHNode *node, float *min, float *max) +{ + if(is_leaf(node)) + { + RE_rayobject_merge_bb( (RayObject*)node, min, max); + } + else + { + int i=0; + while(SVBVH_SIMD && i+4 <= node->nchilds) + { + float *res = node->child_bb + 6*i; + for(int j=0; j<3; j++) + { + min[j] = MIN2(min[j], res[4*j+0]); + min[j] = MIN2(min[j], res[4*j+1]); + min[j] = MIN2(min[j], res[4*j+2]); + min[j] = MIN2(min[j], res[4*j+3]); + } + for(int j=0; j<3; j++) + { + max[j] = MAX2(max[j], res[4*(j+3)+0]); + max[j] = MAX2(max[j], res[4*(j+3)+1]); + max[j] = MAX2(max[j], res[4*(j+3)+2]); + max[j] = MAX2(max[j], res[4*(j+3)+3]); + } + + i += 4; + } + + for(; inchilds; i++) + { + DO_MIN(node->child_bb+6*i , min); + DO_MAX(node->child_bb+3+6*i, max); + } + } +} + struct SVBVHTree { RayObject rayobj; @@ -131,7 +170,7 @@ struct Reorganize_SVBVH { SVBVHNode *node = (SVBVHNode*)BLI_memarena_alloc(tree->node_arena, sizeof(SVBVHNode)); node->nchilds = nchilds; - node->bb = (float*)BLI_memarena_alloc(tree->node_arena, sizeof(float)*6*nchilds); + node->child_bb = (float*)BLI_memarena_alloc(tree->node_arena, sizeof(float)*6*nchilds); node->child= (SVBVHNode**)BLI_memarena_alloc(tree->node_arena, sizeof(SVBVHNode*)*nchilds); return node; @@ -148,8 +187,8 @@ struct Reorganize_SVBVH while(i+4 <= node->nchilds) { float vec_tmp[4*6]; - float *res = node->bb+6*i; - std::copy( node->bb+6*i, node->bb+6*(i+4), vec_tmp); + float *res = node->child_bb+6*i; + std::copy( res, res+6*4, vec_tmp); for(int j=0; j<6; j++) { @@ -167,18 +206,18 @@ struct Reorganize_SVBVH //memmoves could be memory alligned const __m128 x0y0x1y1 = _mm_shuffle_ps( _mm_loadu_ps(bb0), _mm_loadu_ps(bb1), _MM_SHUFFLE(1,0,1,0) ); const __m128 x2y2x3y3 = _mm_shuffle_ps( _mm_loadu_ps(bb2), _mm_loadu_ps(bb3), _MM_SHUFFLE(1,0,1,0) ); - _mm_store_ps( node->bb+6*i+4*0, _mm_shuffle_ps( x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(2,0,2,0) ) ); - _mm_store_ps( node->bb+6*i+4*1, _mm_shuffle_ps( x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(3,1,3,1) ) ); + _mm_store_ps( node->child_bb+6*i+4*0, _mm_shuffle_ps( x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(2,0,2,0) ) ); + _mm_store_ps( node->child_bb+6*i+4*1, _mm_shuffle_ps( x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(3,1,3,1) ) ); const __m128 z0X0z1X1 = _mm_shuffle_ps( _mm_loadu_ps(bb0), _mm_loadu_ps(bb1), _MM_SHUFFLE(3,2,3,2) ); const __m128 z2X2z3X3 = _mm_shuffle_ps( _mm_loadu_ps(bb2), _mm_loadu_ps(bb3), _MM_SHUFFLE(3,2,3,2) ); - _mm_store_ps( node->bb+6*i+4*2, _mm_shuffle_ps( z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(2,0,2,0) ) ); - _mm_store_ps( node->bb+6*i+4*3, _mm_shuffle_ps( z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(3,1,3,1) ) ); + _mm_store_ps( node->child_bb+6*i+4*2, _mm_shuffle_ps( z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(2,0,2,0) ) ); + _mm_store_ps( node->child_bb+6*i+4*3, _mm_shuffle_ps( z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(3,1,3,1) ) ); const __m128 Y0Z0Y1Z1 = _mm_shuffle_ps( _mm_loadu_ps(bb0+4), _mm_loadu_ps(bb1+4), _MM_SHUFFLE(1,0,1,0) ); const __m128 Y2Z2Y3Z3 = _mm_shuffle_ps( _mm_loadu_ps(bb2+4), _mm_loadu_ps(bb3+4), _MM_SHUFFLE(1,0,1,0) ); - _mm_store_ps( node->bb+6*i+4*4, _mm_shuffle_ps( Y0Z0Y1Z1, Y2Z2Y3Z3, _MM_SHUFFLE(2,0,2,0) ) ); - _mm_store_ps( node->bb+6*i+4*5, _mm_shuffle_ps( Y0Z0Y1Z1, Y2Z2Y3Z3, _MM_SHUFFLE(3,1,3,1) ) ); + _mm_store_ps( node->child_bb+6*i+4*4, _mm_shuffle_ps( Y0Z0Y1Z1, Y2Z2Y3Z3, _MM_SHUFFLE(2,0,2,0) ) ); + _mm_store_ps( node->child_bb+6*i+4*5, _mm_shuffle_ps( Y0Z0Y1Z1, Y2Z2Y3Z3, _MM_SHUFFLE(3,1,3,1) ) ); */ i += 4; @@ -210,12 +249,12 @@ struct Reorganize_SVBVH float bb[6]; INIT_MINMAX(bb, bb+3); RE_rayobject_merge_bb( (RayObject*)o_child, bb, bb+3); - copy_bb(node->bb+i*6, bb); + copy_bb(node->child_bb+i*6, bb); break; } else { - copy_bb(node->bb+i*6, o_child->bb); + copy_bb(node->child_bb+i*6, o_child->bb); } } assert( i == 0 ); From eff93b099d5d347b692aa065b93f287baf1055c8 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 11 Aug 2009 18:43:55 +0000 Subject: [PATCH 079/138] Fix ray_trace_shadow_tra --- source/blender/render/intern/source/rayshade.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 685b82d9da2..a71d45b871c 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -1467,6 +1467,7 @@ static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int if it has col[3]>0.0f continue. so exit when alpha is full */ ShadeInput shi; ShadeResult shr; + float initial_labda = is->labda; if(RE_rayobject_raycast(R.raytree, is)) { float d= 1.0f; @@ -1499,7 +1500,7 @@ static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int /* adapt isect struct */ VECCOPY(is->start, shi.co); - + is->labda = initial_labda-is->labda; is->orig.ob = shi.obi; is->orig.face = shi.vlr; From c101d58d42da8b8be77fd9faa58932e781a5a2fd Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Wed, 12 Aug 2009 02:00:44 +0000 Subject: [PATCH 080/138] *Instance support is only enabled if target mesh uses more than 4 faces if theres very few faces its not worth it to create a separated tree for beinng reused. should speedup some particle renders. This "fixes" a bug relationed with a arithmetic precision on instances and raytrace of very close objects which usually happens on rendering (almost) overlapping alpha-enabled leafs/feathers --- .../blender/render/intern/include/rayobject.h | 6 ++-- .../blender/render/intern/source/rayobject.c | 1 + .../blender/render/intern/source/rayshade.c | 34 +++++++++++++++++-- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index 2c63c8ceae9..b058f260052 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -78,9 +78,11 @@ extern "C" { */ /* defines where coordinates of rayface primitives are stored */ -//#define RE_RAYFACE_COORDS_LOCAL +#define RE_RAYFACE_COORDS_LOCAL + +//(ATM this won't work good with all types of instances) //#define RE_RAYFACE_COORDS_POINTER -#define RE_RAYFACE_COORDS_VLAKREN +//#define RE_RAYFACE_COORDS_VLAKREN typedef struct RayFace { diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index 5639080c406..bc98e7e0467 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -188,6 +188,7 @@ static int intersect_rayface(RayFace *face, Isect *is) #ifdef RE_RAYFACE_COORDS_VLAKREN { VlakRen *vlr = (VlakRen*)face->face; + VECCOPY(co1, vlr->v1->co); VECCOPY(co2, vlr->v2->co); if(vlr->v4) diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index a71d45b871c..fe76fa07433 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -180,6 +180,7 @@ static int is_raytraceable(Render *re, ObjectInstanceRen *obi) return 0; } + RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) { //TODO @@ -283,6 +284,26 @@ static void makeraytree_hier(Render *re) re->stats_draw(re->sdh, &re->i); } +static int has_special_rayobject(Render *re, ObjectInstanceRen *obi) +{ + if( (obi->flag & R_TRANSFORMED) ) + { + ObjectRen *obr = obi->obr; + int v, faces = 0; + + for(v=0;vtotvlak;v++) + { + VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); + if(is_raytraceable_vlr(re, vlr)) + { + faces++; + if(faces > 4) + return 1; + } + } + } + return 0; +} /* * create a single raytrace structure with all faces */ @@ -300,7 +321,7 @@ static void makeraytree_single(Render *re) ObjectRen *obr = obi->obr; obs++; - if(obi->flag & R_TRANSFORMED) + if(has_special_rayobject(re, obi)) { faces++; } @@ -326,7 +347,7 @@ static void makeraytree_single(Render *re) for(obi=re->instancetable.first; obi; obi=obi->next) if(is_raytraceable(re, obi)) { - if(obi->flag & R_TRANSFORMED) + if(has_special_rayobject(re, obi)) { RayObject *obj = makeraytree_object(re, obi); RE_rayobject_add( re->raytree, obj ); @@ -342,6 +363,15 @@ static void makeraytree_single(Render *re) if(is_raytraceable_vlr(re, vlr)) { RE_rayface_from_vlak(face, obi, vlr); + if((obi->flag & R_TRANSFORMED)) + { + Mat4MulVecfl(obi->mat, face->v1); + Mat4MulVecfl(obi->mat, face->v2); + Mat4MulVecfl(obi->mat, face->v3); + if(RE_rayface_isQuad(face)) + Mat4MulVecfl(obi->mat, face->v4); + } + RE_rayobject_add( raytree, RayObject_unalignRayFace(face) ); face++; } From 7050a4a6a2f20d6ba3f53cc7673bc822d75d8902 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Thu, 13 Aug 2009 12:23:21 +0000 Subject: [PATCH 081/138] *Bug fix on finding hit on neighbour face (think this is the last know bug) This bug fix makes the "non-smoothed" faces appear again (just like they do in 2.49 and blender2.5) Meaning the "detect neighbour faces" isn't working 100%. --- source/blender/render/intern/source/rayobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index bc98e7e0467..daa6b8d95de 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -306,7 +306,7 @@ static int intersect_rayface(RayFace *face, Isect *is) || a->v1==b->v2 || a->v2==b->v2 || a->v3==b->v2 || a->v4==b->v2 || a->v1==b->v3 || a->v2==b->v3 || a->v3==b->v3 || a->v4==b->v3 || (b->v4 && (a->v1==b->v4 || a->v2==b->v4 || a->v3==b->v4 || a->v4==b->v4))) - if(intersection2((VlakRen*)b, -r0, -r1, -r2, is->start[0], is->start[1], is->start[2])) + if(!intersection2((VlakRen*)a, -r0, -r1, -r2, is->start[0], is->start[1], is->start[2])) { return 0; } From cb40f0ff804a21a06d4e28ea72b30d7b76ff1d39 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Thu, 13 Aug 2009 15:56:24 +0000 Subject: [PATCH 082/138] Another tree pass during build to increase the number of nodes that have multipe of 4childs --- .../render/intern/raytrace/rayobject_vbvh.cpp | 1 + .../render/intern/raytrace/reorganize.h | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index 7f990e06152..b703e57fdd8 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -270,6 +270,7 @@ void bvh_done(VBVHTree *obj) pushup(root); pushdown(root); + pushup_simd(root); //Memory re-organize if(0) diff --git a/source/blender/render/intern/raytrace/reorganize.h b/source/blender/render/intern/raytrace/reorganize.h index 2f79b0f6e82..b77a51bbf65 100644 --- a/source/blender/render/intern/raytrace/reorganize.h +++ b/source/blender/render/intern/raytrace/reorganize.h @@ -144,6 +144,8 @@ void remove_useless(Node *node, Node **new_node) template void pushup(Node *parent) { + if(is_leaf(parent)) return; + float p_area = bb_area(parent->bb, parent->bb+3); Node **prev = &parent->child; for(Node *child = parent->child; RayObject_isAligned(child) && child; ) @@ -175,6 +177,38 @@ void pushup(Node *parent) pushup(child); } +/* + * try to optimize number of childs to be a multiple of SSize + */ +template +void pushup_simd(Node *parent) +{ + if(is_leaf(parent)) return; + + int n = count_childs(parent); + + Node **prev = &parent->child; + for(Node *child = parent->child; RayObject_isAligned(child) && child; ) + { + int cn = count_childs(child); + if(cn-1 <= (SSize - (n%SSize) ) % SSize && RayObject_isAligned(child->child) ) + { + n += (cn - 1); + append_sibling(child, child->child); + child = child->sibling; + *prev = child; + } + else + { + *prev = child; + prev = &(*prev)->sibling; + child = *prev; + } + } + + for(Node *child = parent->child; RayObject_isAligned(child) && child; child = child->sibling) + pushup_simd(child); +} /* From cc0dafa627141eb7dcbf014ada58336fa71b50d5 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Thu, 13 Aug 2009 20:35:53 +0000 Subject: [PATCH 083/138] Addition of some fake nodes to use SIMD even when theres only 3 nodes --- source/blender/render/intern/raytrace/svbvh.h | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/source/blender/render/intern/raytrace/svbvh.h b/source/blender/render/intern/raytrace/svbvh.h index cc875ad6dba..95f1c40765e 100644 --- a/source/blender/render/intern/raytrace/svbvh.h +++ b/source/blender/render/intern/raytrace/svbvh.h @@ -147,6 +147,7 @@ struct Reorganize_SVBVH float childs_per_node; int nodes_with_childs[16]; + int useless_bb; int nodes; Reorganize_SVBVH(Tree *t) @@ -154,6 +155,7 @@ struct Reorganize_SVBVH tree = t; nodes = 0; childs_per_node = 0; + useless_bb = 0; for(int i=0; i<16; i++) nodes_with_childs[i] = 0; @@ -161,7 +163,8 @@ struct Reorganize_SVBVH ~Reorganize_SVBVH() { - printf("%f childs per node\n", childs_per_node / nodes); + printf("%f childs per node\n", childs_per_node / nodes); + printf("%d childs BB are useless\n", useless_bb); for(int i=0; i<16; i++) printf("%i childs per node: %d/%d = %f\n", i, nodes_with_childs[i], nodes, nodes_with_childs[i]/float(nodes)); } @@ -176,7 +179,7 @@ struct Reorganize_SVBVH return node; } - void copy_bb(float *bb, float *old_bb) + void copy_bb(float *bb, const float *old_bb) { std::copy( old_bb, old_bb+6, bb ); } @@ -224,6 +227,12 @@ struct Reorganize_SVBVH } } + /* amt must be power of two */ + inline int padup(int num, int amt) + { + return ((num+(amt-1))&~(amt-1)); + } + SVBVHNode *transform(OldNode *old) { if(is_leaf(old)) @@ -232,13 +241,26 @@ struct Reorganize_SVBVH return (SVBVHNode*)old->child; int nchilds = count_childs(old); - SVBVHNode *node = create_node(nchilds); + int alloc_childs = nchilds; + if(nchilds % 4 > 2) + alloc_childs = padup(nchilds, 4); + + SVBVHNode *node = create_node(alloc_childs); childs_per_node += nchilds; nodes++; if(nchilds < 16) nodes_with_childs[nchilds]++; + useless_bb += alloc_childs-nchilds; + while(alloc_childs > nchilds) + { + const static float def_bb[6] = { FLT_MAX, FLT_MAX, FLT_MAX, FLT_MIN, FLT_MIN, FLT_MIN }; + alloc_childs--; + node->child[alloc_childs] = 0; + copy_bb(node->child_bb+alloc_childs*6, def_bb); + } + int i=nchilds; for(OldNode *o_child = old->child; o_child; o_child = o_child->sibling) { @@ -258,6 +280,7 @@ struct Reorganize_SVBVH } } assert( i == 0 ); + if(SVBVH_SIMD) prepare_for_simd(node); From 0e3acbaa386384f1b1d27a2b4e0f0dcd07c0e0e2 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 17 Aug 2009 17:04:58 +0000 Subject: [PATCH 084/138] fix raycounters --- source/blender/render/intern/source/rayshade.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index fe76fa07433..071c70ae504 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -785,6 +785,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo else { ray_fadeout_endcolor(col, origshi, &shi, origshr, &isec, vec); } + RE_RC_MERGE(&origshi->raycounter, &shi.raycounter); } /* **************** jitter blocks ********** */ @@ -1536,6 +1537,8 @@ static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int ray_trace_shadow_tra(is, origshi, depth-1, traflag | RAY_TRA); } + + RE_RC_MERGE(&origshi->raycounter, &shi.raycounter); } } From aec7f2f2c47d02b08383a4f30c0dd0067830b8c8 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 25 Aug 2009 20:26:50 +0000 Subject: [PATCH 085/138] *Changed RayObject_ calls to RE_rayobject to keep consistency on calls *Moved part of counters code to a separated file (rayobject_raycounter.c) --- .../blender/render/intern/include/rayobject.h | 37 +---- source/blender/render/intern/raytrace/bvh.h | 2 +- .../render/intern/raytrace/rayobject_bih.cpp | 12 +- .../render/intern/raytrace/rayobject_bvh.cpp | 10 +- .../render/intern/raytrace/rayobject_vbvh.cpp | 16 +- .../render/intern/raytrace/reorganize.h | 28 ++-- .../blender/render/intern/source/rayobject.c | 155 +++--------------- .../render/intern/source/rayobject_blibvh.c | 34 ++-- .../render/intern/source/rayobject_instance.c | 32 ++-- .../render/intern/source/rayobject_octree.c | 57 +++---- .../intern/source/rayobject_raycounter.c | 77 +++++++++ .../blender/render/intern/source/rayshade.c | 4 +- 12 files changed, 196 insertions(+), 268 deletions(-) create mode 100644 source/blender/render/intern/source/rayobject_raycounter.c diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index b058f260052..36b0d2692c0 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -77,39 +77,16 @@ extern "C" { described on RE_raytrace.h */ -/* defines where coordinates of rayface primitives are stored */ -#define RE_RAYFACE_COORDS_LOCAL - -//(ATM this won't work good with all types of instances) -//#define RE_RAYFACE_COORDS_POINTER -//#define RE_RAYFACE_COORDS_VLAKREN - typedef struct RayFace { -#ifdef RE_RAYFACE_COORDS_LOCAL float v1[4], v2[4], v3[4], v4[3]; int quad; void *ob; void *face; -#elif defined(RE_RAYFACE_COORDS_POINTER) - float *v1, *v2, *v3, *v4; - void *ob; - void *face; -#elif defined(RE_RAYFACE_COORDS_VLAKREN) - void *ob; - void *face; -#endif } RayFace; -#ifdef RE_RAYFACE_COORDS_LOCAL -# define RE_rayface_isQuad(a) ((a)->quad) -#elif defined(RE_RAYFACE_COORDS_POINTER) -# define RE_rayface_isQuad(a) ((a)->v4) -#elif defined(RE_RAYFACE_COORDS_VLAKREN) -# define RE_rayface_isQuad(a) ((((VlakRen*)((a)->face))->v4) != NULL) -#endif - +#define RE_rayface_isQuad(a) ((a)->quad) struct RayObject { @@ -137,13 +114,13 @@ typedef struct RayObjectAPI } RayObjectAPI; -#define RayObject_align(o) ((RayObject*)(((intptr_t)o)&(~3))) -#define RayObject_unalignRayFace(o) ((RayObject*)(((intptr_t)o)|1)) -#define RayObject_unalignRayAPI(o) ((RayObject*)(((intptr_t)o)|2)) +#define RE_rayobject_align(o) ((RayObject*)(((intptr_t)o)&(~3))) +#define RE_rayobject_unalignRayFace(o) ((RayObject*)(((intptr_t)o)|1)) +#define RE_rayobject_unalignRayAPI(o) ((RayObject*)(((intptr_t)o)|2)) -#define RayObject_isAligned(o) ((((intptr_t)o)&3) == 0) -#define RayObject_isRayFace(o) ((((intptr_t)o)&3) == 1) -#define RayObject_isRayAPI(o) ((((intptr_t)o)&3) == 2) +#define RE_rayobject_isAligned(o) ((((intptr_t)o)&3) == 0) +#define RE_rayobject_isRayFace(o) ((((intptr_t)o)&3) == 1) +#define RE_rayobject_isRayAPI(o) ((((intptr_t)o)&3) == 2) /* * Loads a VlakRen on a RayFace diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h index 8538d9201e0..55bed6f0662 100644 --- a/source/blender/render/intern/raytrace/bvh.h +++ b/source/blender/render/intern/raytrace/bvh.h @@ -59,7 +59,7 @@ template static void bvh_add(Tree *obj, RayObject *ob) template inline bool is_leaf(Node *node) { - return !RayObject_isAligned(node); + return !RE_rayobject_isAligned(node); } template static void bvh_done(Tree *obj); diff --git a/source/blender/render/intern/raytrace/rayobject_bih.cpp b/source/blender/render/intern/raytrace/rayobject_bih.cpp index 102a347b470..efbf70616b7 100644 --- a/source/blender/render/intern/raytrace/rayobject_bih.cpp +++ b/source/blender/render/intern/raytrace/rayobject_bih.cpp @@ -78,7 +78,7 @@ struct BIHTree RayObject *RE_rayobject_bih_create(int size) { BIHTree *obj= (BIHTree*)MEM_callocN(sizeof(BIHTree), "BIHTree"); - assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ + assert( RE_rayobject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ obj->rayobj.api = &bih_api; obj->root = NULL; @@ -86,7 +86,7 @@ RayObject *RE_rayobject_bih_create(int size) obj->node_alloc = obj->node_next = NULL; obj->builder = rtbuild_create( size ); - return RayObject_unalignRayAPI((RayObject*) obj); + return RE_rayobject_unalignRayAPI((RayObject*) obj); } static void bih_free(BIHTree *obj) @@ -128,7 +128,7 @@ static int dfs_raycast(const BIHNode *const node, Isect *isec, float tmin, float if(t1 <= t2) { - if(RayObject_isAligned(node->child[i])) + if(RE_rayobject_isAligned(node->child[i])) { if(node->child[i] == 0) break; @@ -151,7 +151,7 @@ static int dfs_raycast(const BIHNode *const node, Isect *isec, float tmin, float static int bih_intersect(BIHTree *obj, Isect *isec) { - if(RayObject_isAligned(obj->root)) + if(RE_rayobject_isAligned(obj->root)) return dfs_raycast(obj->root, isec, 0, isec->labda); else return RE_rayobject_intersect( (RayObject*)obj->root, isec); @@ -169,7 +169,7 @@ static void bih_add(BIHTree *obj, RayObject *ob) static BIHNode *bih_new_node(BIHTree *tree, int nid) { BIHNode *node = tree->node_alloc + nid - 1; - assert(RayObject_isAligned(node)); + assert(RE_rayobject_isAligned(node)); if(node+1 > tree->node_next) tree->node_next = node+1; @@ -187,7 +187,7 @@ static BIHNode *bih_rearrange(BIHTree *tree, RTBuilder *builder, int nid, float if(rtbuild_size(builder) == 1) { RayObject *child = rtbuild_get_primitive( builder, 0 ); - assert(!RayObject_isAligned(child)); + assert(!RE_rayobject_isAligned(child)); INIT_MINMAX(bb, bb+3); RE_rayobject_merge_bb( (RayObject*)child, bb, bb+3); diff --git a/source/blender/render/intern/raytrace/rayobject_bvh.cpp b/source/blender/render/intern/raytrace/rayobject_bvh.cpp index 48c1ac07cd4..bf54f889ebf 100644 --- a/source/blender/render/intern/raytrace/rayobject_bvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_bvh.cpp @@ -117,7 +117,7 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid, float { RayObject *child = rtbuild_get_primitive( builder, 0 ); - if(RayObject_isRayFace(child)) + if(RE_rayobject_isRayFace(child)) { int i; BVHNode *parent = bvh_new_node(tree, nid); @@ -138,7 +138,7 @@ static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid, float } else { - assert(!RayObject_isAligned(child)); + assert(!RE_rayobject_isAligned(child)); //Its a sub-raytrace structure, assume it has it own raycast //methods and adding a Bounding Box arround is unnecessary @@ -200,7 +200,7 @@ void bvh_done(BVHTree *obj) template<> int bvh_intersect(BVHTree *obj, Isect* isec) { - if(RayObject_isAligned(obj->root)) + if(RE_rayobject_isAligned(obj->root)) return bvh_node_stack_raycast(obj->root, isec); else return RE_rayobject_intersect( (RayObject*) obj->root, isec ); @@ -222,7 +222,7 @@ static RayObjectAPI bvh_api = RayObject *RE_rayobject_bvh_create(int size) { BVHTree *obj= (BVHTree*)MEM_callocN(sizeof(BVHTree), "BVHTree"); - assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ + assert( RE_rayobject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ obj->rayobj.api = &bvh_api; obj->root = NULL; @@ -230,5 +230,5 @@ RayObject *RE_rayobject_bvh_create(int size) obj->node_arena = NULL; obj->builder = rtbuild_create( size ); - return RayObject_unalignRayAPI((RayObject*) obj); + return RE_rayobject_unalignRayAPI((RayObject*) obj); } diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index b703e57fdd8..6ec8fab15e4 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -181,7 +181,7 @@ static VBVHNode *bvh_new_node(VBVHTree *tree) #ifdef DYNAMIC_ALLOC_BB node->bb = (float*)BLI_memarena_alloc(tree->node_arena, 6*sizeof(float)); #endif - assert(RayObject_isAligned(node)); + assert(RE_rayobject_isAligned(node)); return node; } @@ -319,7 +319,7 @@ int intersect(VBVHTree *obj, Isect* isec) for(int i=0; isize; i++) { VBVHNode *node = (VBVHNode*)lcts->stack[i]; - if(RayObject_isAligned(node)) + if(RE_rayobject_isAligned(node)) hit |= bvh_node_stack_raycast(node, isec); else hit |= RE_rayobject_intersect( (RayObject*)node, isec ); @@ -333,7 +333,7 @@ int intersect(VBVHTree *obj, Isect* isec) else */ { - if(RayObject_isAligned(obj->root)) + if(RE_rayobject_isAligned(obj->root)) return bvh_node_stack_raycast( obj->root, isec); else return RE_rayobject_intersect( (RayObject*) obj->root, isec ); @@ -346,7 +346,7 @@ void bvh_dfs_make_hint(Node *node, LCTSHint *hint, int reserve_space, HintObject template void bvh_dfs_make_hint_push_siblings(Node *node, LCTSHint *hint, int reserve_space, HintObject *hintObject) { - if(!RayObject_isAligned(node)) + if(!RE_rayobject_isAligned(node)) hint->stack[hint->size++] = (RayObject*)node; else { @@ -459,7 +459,7 @@ static RayObjectAPI* get_api(int maxstacksize) RayObject *RE_rayobject_vbvh_create(int size) { VBVHTree *obj= (VBVHTree*)MEM_callocN(sizeof(VBVHTree), "VBVHTree"); - assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ + assert( RE_rayobject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ obj->rayobj.api = get_api(DFS_STACK_SIZE); obj->root = NULL; @@ -467,7 +467,7 @@ RayObject *RE_rayobject_vbvh_create(int size) obj->node_arena = NULL; obj->builder = rtbuild_create( size ); - return RayObject_unalignRayAPI((RayObject*) obj); + return RE_rayobject_unalignRayAPI((RayObject*) obj); } @@ -482,7 +482,7 @@ void bvh_dfs_make_hint(VBVHNode *node, LCTSHint *hint, int reserve_space, HintOb RayObject *RE_rayobject_svbvh_create(int size) { SVBVHTree *obj= (SVBVHTree*)MEM_callocN(sizeof(SVBVHTree), "SVBVHTree"); - assert( RayObject_isAligned(obj) ); // RayObject API assumes real data to be 4-byte aligned + assert( RE_rayobject_isAligned(obj) ); // RayObject API assumes real data to be 4-byte aligned obj->rayobj.api = get_api(DFS_STACK_SIZE); obj->root = NULL; @@ -490,6 +490,6 @@ RayObject *RE_rayobject_svbvh_create(int size) obj->node_arena = NULL; obj->builder = rtbuild_create( size ); - return RayObject_unalignRayAPI((RayObject*) obj); + return RE_rayobject_unalignRayAPI((RayObject*) obj); } */ \ No newline at end of file diff --git a/source/blender/render/intern/raytrace/reorganize.h b/source/blender/render/intern/raytrace/reorganize.h index b77a51bbf65..2494f102003 100644 --- a/source/blender/render/intern/raytrace/reorganize.h +++ b/source/blender/render/intern/raytrace/reorganize.h @@ -47,7 +47,7 @@ void reorganize_find_fittest_parent(Node *tree, Node *node, std::pairchild) ) + if(node_fits_inside(node, parent) && RE_rayobject_isAligned(parent->child) ) { float pcost = bb_area(parent->bb, parent->bb+3); cost = std::min( cost, std::make_pair(pcost,parent) ); @@ -69,11 +69,11 @@ void reorganize(Node *root) Node * node = q.front(); q.pop(); - if( RayObject_isAligned(node->child) ) + if( RE_rayobject_isAligned(node->child) ) { for(Node **prev = &node->child; *prev; ) { - assert( RayObject_isAligned(*prev) ); + assert( RE_rayobject_isAligned(*prev) ); q.push(*prev); std::pair best(FLT_MAX, root); @@ -112,7 +112,7 @@ void reorganize(Node *root) template void remove_useless(Node *node, Node **new_node) { - if( RayObject_isAligned(node->child) ) + if( RE_rayobject_isAligned(node->child) ) { for(Node **prev = &node->child; *prev; ) @@ -130,7 +130,7 @@ void remove_useless(Node *node, Node **new_node) } if(node->child) { - if(RayObject_isAligned(node->child) && node->child->sibling == 0) + if(RE_rayobject_isAligned(node->child) && node->child->sibling == 0) *new_node = node->child; } else if(node->child == 0) @@ -148,7 +148,7 @@ void pushup(Node *parent) float p_area = bb_area(parent->bb, parent->bb+3); Node **prev = &parent->child; - for(Node *child = parent->child; RayObject_isAligned(child) && child; ) + for(Node *child = parent->child; RE_rayobject_isAligned(child) && child; ) { float c_area = bb_area(child->bb, child->bb+3) ; int nchilds = count_childs(child); @@ -173,7 +173,7 @@ void pushup(Node *parent) } } - for(Node *child = parent->child; RayObject_isAligned(child) && child; child = child->sibling) + for(Node *child = parent->child; RE_rayobject_isAligned(child) && child; child = child->sibling) pushup(child); } @@ -188,10 +188,10 @@ void pushup_simd(Node *parent) int n = count_childs(parent); Node **prev = &parent->child; - for(Node *child = parent->child; RayObject_isAligned(child) && child; ) + for(Node *child = parent->child; RE_rayobject_isAligned(child) && child; ) { int cn = count_childs(child); - if(cn-1 <= (SSize - (n%SSize) ) % SSize && RayObject_isAligned(child->child) ) + if(cn-1 <= (SSize - (n%SSize) ) % SSize && RE_rayobject_isAligned(child->child) ) { n += (cn - 1); append_sibling(child, child->child); @@ -206,7 +206,7 @@ void pushup_simd(Node *parent) } } - for(Node *child = parent->child; RayObject_isAligned(child) && child; child = child->sibling) + for(Node *child = parent->child; RE_rayobject_isAligned(child) && child; child = child->sibling) pushup_simd(child); } @@ -221,15 +221,15 @@ void pushdown(Node *parent) Node **s_child = &parent->child; Node * child = parent->child; - while(child && RayObject_isAligned(child)) + while(child && RE_rayobject_isAligned(child)) { Node *next = child->sibling; Node **next_s_child = &child->sibling; //assert(bb_fits_inside(parent->bb, parent->bb+3, child->bb, child->bb+3)); - for(Node *i = parent->child; RayObject_isAligned(i) && i; i = i->sibling) - if(child != i && bb_fits_inside(i->bb, i->bb+3, child->bb, child->bb+3) && RayObject_isAligned(i->child)) + for(Node *i = parent->child; RE_rayobject_isAligned(i) && i; i = i->sibling) + if(child != i && bb_fits_inside(i->bb, i->bb+3, child->bb, child->bb+3) && RE_rayobject_isAligned(i->child)) { // todo optimize (should the one with the smallest area?) // float ia = bb_area(i->bb, i->bb+3) @@ -246,7 +246,7 @@ void pushdown(Node *parent) s_child = next_s_child; } - for(Node *i = parent->child; RayObject_isAligned(i) && i; i = i->sibling) + for(Node *i = parent->child; RE_rayobject_isAligned(i) && i; i = i->sibling) pushdown( i ); } diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index daa6b8d95de..996be35090e 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -27,7 +27,6 @@ * ***** END GPL LICENSE BLOCK ***** */ #include -#include #include "BKE_utildefines.h" #include "BLI_arithb.h" @@ -42,33 +41,6 @@ * Based on Tactical Optimization of Ray/Box Intersection, by Graham Fyffe * [http://tog.acm.org/resources/RTNews/html/rtnv21n1.html#art9] */ -/* -float RE_rayobject_bb_intersect(const Isect *isec, const float *_bb) -{ - const float *bb = _bb; - float dist; - - float t1x = (bb[isec->bv_index[0]] - isec->start[0]) * isec->idot_axis[0]; - float t2x = (bb[isec->bv_index[1]] - isec->start[0]) * isec->idot_axis[0]; - float t1y = (bb[isec->bv_index[2]] - isec->start[1]) * isec->idot_axis[1]; - float t2y = (bb[isec->bv_index[3]] - isec->start[1]) * isec->idot_axis[1]; - float t1z = (bb[isec->bv_index[4]] - isec->start[2]) * isec->idot_axis[2]; - float t2z = (bb[isec->bv_index[5]] - isec->start[2]) * isec->idot_axis[2]; - - RE_RC_COUNT(isec->raycounter->bb.test); - - if(t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) return FLT_MAX; - if(t2x < 0.0 || t2y < 0.0 || t2z < 0.0) return FLT_MAX; - if(t1x > isec->labda || t1y > isec->labda || t1z > isec->labda) return FLT_MAX; - - RE_RC_COUNT(isec->raycounter->bb.hit); - - dist = t1x; - if (t1y > dist) dist = t1y; - if (t1z > dist) dist = t1z; - return dist; -} -*/ int RE_rayobject_bb_intersect_test(const Isect *isec, const float *_bb) { const float *bb = _bb; @@ -185,23 +157,7 @@ static int intersect_rayface(RayFace *face, Isect *is) RE_RC_COUNT(is->raycounter->faces.test); -#ifdef RE_RAYFACE_COORDS_VLAKREN - { - VlakRen *vlr = (VlakRen*)face->face; - - VECCOPY(co1, vlr->v1->co); - VECCOPY(co2, vlr->v2->co); - if(vlr->v4) - { - VECCOPY(co3, vlr->v4->co); - VECCOPY(co4, vlr->v3->co); - } - else - { - VECCOPY(co3, vlr->v3->co); - } - } -#else + //Load coords VECCOPY(co1, face->v1); VECCOPY(co2, face->v2); if(RE_rayface_isQuad(face)) @@ -213,7 +169,6 @@ static int intersect_rayface(RayFace *face, Isect *is) { VECCOPY(co3, face->v3); } -#endif t00= co3[0]-co1[0]; t01= co3[1]-co1[1]; @@ -312,13 +267,6 @@ static int intersect_rayface(RayFace *face, Isect *is) } } } -#if 0 - else if(labda < ISECT_EPSILON) - { - /* too close to origin */ - return 0; - } -#endif RE_RC_COUNT(is->raycounter->faces.hit); @@ -329,7 +277,7 @@ static int intersect_rayface(RayFace *face, Isect *is) is->hit.ob = face->ob; is->hit.face = face->face; #ifdef RT_USE_LAST_HIT - is->last_hit = (RayObject*) RayObject_unalignRayFace(face); + is->last_hit = (RayObject*) RE_rayobject_unalignRayFace(face); #endif return 1; } @@ -339,7 +287,6 @@ static int intersect_rayface(RayFace *face, Isect *is) void RE_rayface_from_vlak(RayFace *face, ObjectInstanceRen *obi, VlakRen *vlr) { -#ifdef RE_RAYFACE_COORDS_LOCAL VECCOPY(face->v1, vlr->v1->co); VECCOPY(face->v2, vlr->v2->co); VECCOPY(face->v3, vlr->v3->co); @@ -352,13 +299,7 @@ void RE_rayface_from_vlak(RayFace *face, ObjectInstanceRen *obi, VlakRen *vlr) { face->quad = 0; } -#elif defined(RE_RAYFACE_COORDS_POINTER) - face->v1 = vlr->v1->co; - face->v2 = vlr->v2->co; - face->v3 = vlr->v3->co; - face->v4 = vlr->v4 ? vlr->v4->co : NULL; -#elif defined(RE_RAYFACE_COORDS_VLAKREN) -#endif + face->ob = obi; face->face = vlr; } @@ -405,9 +346,7 @@ int RE_rayobject_raycast(RayObject *r, Isect *isec) if(RE_rayobject_intersect(r, isec)) { -#ifdef RE_RAYCOUNTER RE_RC_COUNT(isec->raycounter->raycast.hit); -#endif #ifdef RT_USE_HINT isec->hint = isec->hit_hint; @@ -419,13 +358,13 @@ int RE_rayobject_raycast(RayObject *r, Isect *isec) int RE_rayobject_intersect(RayObject *r, Isect *i) { - if(RayObject_isRayFace(r)) + if(RE_rayobject_isRayFace(r)) { - return intersect_rayface( (RayFace*) RayObject_align(r), i); + return intersect_rayface( (RayFace*) RE_rayobject_align(r), i); } - else if(RayObject_isRayAPI(r)) + else if(RE_rayobject_isRayAPI(r)) { - r = RayObject_align( r ); + r = RE_rayobject_align( r ); return r->api->raycast( r, i ); } else assert(0); @@ -433,44 +372,36 @@ int RE_rayobject_intersect(RayObject *r, Isect *i) void RE_rayobject_add(RayObject *r, RayObject *o) { - r = RayObject_align( r ); + r = RE_rayobject_align( r ); return r->api->add( r, o ); } void RE_rayobject_done(RayObject *r) { - r = RayObject_align( r ); + r = RE_rayobject_align( r ); r->api->done( r ); } void RE_rayobject_free(RayObject *r) { - r = RayObject_align( r ); + r = RE_rayobject_align( r ); r->api->free( r ); } void RE_rayobject_merge_bb(RayObject *r, float *min, float *max) { - if(RayObject_isRayFace(r)) + if(RE_rayobject_isRayFace(r)) { - RayFace *face = (RayFace*) RayObject_align(r); + RayFace *face = (RayFace*) RE_rayobject_align(r); -#ifdef RE_RAYFACE_COORDS_VLAKREN - VlakRen *vlr = (VlakRen*)face->face; - DO_MINMAX( vlr->v1->co, min, max ); - DO_MINMAX( vlr->v2->co, min, max ); - DO_MINMAX( vlr->v3->co, min, max ); - if(RE_rayface_isQuad(face)) DO_MINMAX( vlr->v4->co, min, max ); -#else DO_MINMAX( face->v1, min, max ); DO_MINMAX( face->v2, min, max ); DO_MINMAX( face->v3, min, max ); if(RE_rayface_isQuad(face)) DO_MINMAX( face->v4, min, max ); -#endif } - else if(RayObject_isRayAPI(r)) + else if(RE_rayobject_isRayAPI(r)) { - r = RayObject_align( r ); + r = RE_rayobject_align( r ); r->api->bb( r, min, max ); } else assert(0); @@ -478,13 +409,13 @@ void RE_rayobject_merge_bb(RayObject *r, float *min, float *max) float RE_rayobject_cost(RayObject *r) { - if(RayObject_isRayFace(r)) + if(RE_rayobject_isRayFace(r)) { return 1.0; } - else if(RayObject_isRayAPI(r)) + else if(RE_rayobject_isRayAPI(r)) { - r = RayObject_align( r ); + r = RE_rayobject_align( r ); return r->api->cost( r ); } else assert(0); @@ -492,61 +423,15 @@ float RE_rayobject_cost(RayObject *r) void RE_rayobject_hint_bb(RayObject *r, RayHint *hint, float *min, float *max) { - if(RayObject_isRayFace(r)) + if(RE_rayobject_isRayFace(r)) { return; } - else if(RayObject_isRayAPI(r)) + else if(RE_rayobject_isRayAPI(r)) { - r = RayObject_align( r ); + r = RE_rayobject_align( r ); return r->api->hint_bb( r, hint, min, max ); } else assert(0); } -#ifdef RE_RAYCOUNTER -void RE_RC_INFO(RayCounter *info) -{ - printf("----------- Raycast counter --------\n"); - printf("Rays total: %llu\n", info->raycast.test ); - printf("Rays hit: %llu\n", info->raycast.hit ); - printf("\n"); - printf("BB tests: %llu\n", info->bb.test ); - printf("BB hits: %llu\n", info->bb.hit ); - printf("\n"); - printf("Primitives tests: %llu\n", info->faces.test ); - printf("Primitives hits: %llu\n", info->faces.hit ); - printf("------------------------------------\n"); - printf("Shadow last-hit tests per ray: %f\n", info->rayshadow_last_hit.test / ((float)info->raycast.test) ); - printf("Shadow last-hit hits per ray: %f\n", info->rayshadow_last_hit.hit / ((float)info->raycast.test) ); - printf("\n"); - printf("Hint tests per ray: %f\n", info->raytrace_hint.test / ((float)info->raycast.test) ); - printf("Hint hits per ray: %f\n", info->raytrace_hint.hit / ((float)info->raycast.test) ); - printf("\n"); - printf("BB tests per ray: %f\n", info->bb.test / ((float)info->raycast.test) ); - printf("BB hits per ray: %f\n", info->bb.hit / ((float)info->raycast.test) ); - printf("\n"); - printf("Primitives tests per ray: %f\n", info->faces.test / ((float)info->raycast.test) ); - printf("Primitives hits per ray: %f\n", info->faces.hit / ((float)info->raycast.test) ); - printf("------------------------------------\n"); -} - -void RE_RC_MERGE(RayCounter *dest, RayCounter *tmp) -{ - dest->faces.test += tmp->faces.test; - dest->faces.hit += tmp->faces.hit; - - dest->bb.test += tmp->bb.test; - dest->bb.hit += tmp->bb.hit; - - dest->raycast.test += tmp->raycast.test; - dest->raycast.hit += tmp->raycast.hit; - - dest->rayshadow_last_hit.test += tmp->rayshadow_last_hit.test; - dest->rayshadow_last_hit.hit += tmp->rayshadow_last_hit.hit; - - dest->raytrace_hint.test += tmp->raytrace_hint.test; - dest->raytrace_hint.hit += tmp->raytrace_hint.hit; -} - -#endif \ No newline at end of file diff --git a/source/blender/render/intern/source/rayobject_blibvh.c b/source/blender/render/intern/source/rayobject_blibvh.c index 9b872d8f249..6e789862207 100644 --- a/source/blender/render/intern/source/rayobject_blibvh.c +++ b/source/blender/render/intern/source/rayobject_blibvh.c @@ -36,19 +36,19 @@ #include "render_types.h" #include "rayobject.h" -static int RayObject_blibvh_intersect(RayObject *o, Isect *isec); -static void RayObject_blibvh_add(RayObject *o, RayObject *ob); -static void RayObject_blibvh_done(RayObject *o); -static void RayObject_blibvh_free(RayObject *o); -static void RayObject_blibvh_bb(RayObject *o, float *min, float *max); +static int RE_rayobject_blibvh_intersect(RayObject *o, Isect *isec); +static void RE_rayobject_blibvh_add(RayObject *o, RayObject *ob); +static void RE_rayobject_blibvh_done(RayObject *o); +static void RE_rayobject_blibvh_free(RayObject *o); +static void RE_rayobject_blibvh_bb(RayObject *o, float *min, float *max); static RayObjectAPI bvh_api = { - RayObject_blibvh_intersect, - RayObject_blibvh_add, - RayObject_blibvh_done, - RayObject_blibvh_free, - RayObject_blibvh_bb + RE_rayobject_blibvh_intersect, + RE_rayobject_blibvh_add, + RE_rayobject_blibvh_done, + RE_rayobject_blibvh_free, + RE_rayobject_blibvh_bb }; typedef struct BVHObject @@ -63,13 +63,13 @@ typedef struct BVHObject RayObject *RE_rayobject_blibvh_create(int size) { BVHObject *obj= (BVHObject*)MEM_callocN(sizeof(BVHObject), "BVHObject"); - assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ + assert( RE_rayobject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ obj->rayobj.api = &bvh_api; obj->bvh = BLI_bvhtree_new(size, 0.0, 4, 6); INIT_MINMAX(obj->bb[0], obj->bb[1]); - return RayObject_unalignRayAPI((RayObject*) obj); + return RE_rayobject_unalignRayAPI((RayObject*) obj); } static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) @@ -88,7 +88,7 @@ static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTr } } -static int RayObject_blibvh_intersect(RayObject *o, Isect *isec) +static int RE_rayobject_blibvh_intersect(RayObject *o, Isect *isec) { BVHObject *obj = (BVHObject*)o; BVHTreeRayHit hit; @@ -103,7 +103,7 @@ static int RayObject_blibvh_intersect(RayObject *o, Isect *isec) return BLI_bvhtree_ray_cast(obj->bvh, isec->start, dir, 0.0, &hit, bvh_callback, isec); } -static void RayObject_blibvh_add(RayObject *o, RayObject *ob) +static void RE_rayobject_blibvh_add(RayObject *o, RayObject *ob) { BVHObject *obj = (BVHObject*)o; float min_max[6]; @@ -116,13 +116,13 @@ static void RayObject_blibvh_add(RayObject *o, RayObject *ob) BLI_bvhtree_insert(obj->bvh, (int)ob, min_max, 2 ); } -static void RayObject_blibvh_done(RayObject *o) +static void RE_rayobject_blibvh_done(RayObject *o) { BVHObject *obj = (BVHObject*)o; BLI_bvhtree_balance(obj->bvh); } -static void RayObject_blibvh_free(RayObject *o) +static void RE_rayobject_blibvh_free(RayObject *o) { BVHObject *obj = (BVHObject*)o; @@ -132,7 +132,7 @@ static void RayObject_blibvh_free(RayObject *o) MEM_freeN(obj); } -static void RayObject_blibvh_bb(RayObject *o, float *min, float *max) +static void RE_rayobject_blibvh_bb(RayObject *o, float *min, float *max) { BVHObject *obj = (BVHObject*)o; DO_MIN( obj->bb[0], min ); diff --git a/source/blender/render/intern/source/rayobject_instance.c b/source/blender/render/intern/source/rayobject_instance.c index 14f333a7f86..9329d110870 100644 --- a/source/blender/render/intern/source/rayobject_instance.c +++ b/source/blender/render/intern/source/rayobject_instance.c @@ -36,19 +36,19 @@ #define RE_COST_INSTANCE (1.0f) -static int RayObject_instance_intersect(RayObject *o, Isect *isec); -static void RayObject_instance_free(RayObject *o); -static void RayObject_instance_bb(RayObject *o, float *min, float *max); -static float RayObject_instance_cost(RayObject *o); +static int RE_rayobject_instance_intersect(RayObject *o, Isect *isec); +static void RE_rayobject_instance_free(RayObject *o); +static void RE_rayobject_instance_bb(RayObject *o, float *min, float *max); +static float RE_rayobject_instance_cost(RayObject *o); static RayObjectAPI instance_api = { - RayObject_instance_intersect, - NULL, //static void RayObject_instance_add(RayObject *o, RayObject *ob); - NULL, //static void RayObject_instance_done(RayObject *o); - RayObject_instance_free, - RayObject_instance_bb, - RayObject_instance_cost + RE_rayobject_instance_intersect, + NULL, //static void RE_rayobject_instance_add(RayObject *o, RayObject *ob); + NULL, //static void RE_rayobject_instance_done(RayObject *o); + RE_rayobject_instance_free, + RE_rayobject_instance_bb, + RE_rayobject_instance_cost }; typedef struct InstanceRayObject @@ -68,7 +68,7 @@ typedef struct InstanceRayObject RayObject *RE_rayobject_instance_create(RayObject *target, float transform[][4], void *ob, void *target_ob) { InstanceRayObject *obj= (InstanceRayObject*)MEM_callocN(sizeof(InstanceRayObject), "InstanceRayObject"); - assert( RayObject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ + assert( RE_rayobject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ obj->rayobj.api = &instance_api; obj->target = target; @@ -78,10 +78,10 @@ RayObject *RE_rayobject_instance_create(RayObject *target, float transform[][4], Mat4CpyMat4(obj->target2global, transform); Mat4Invert(obj->global2target, obj->target2global); - return RayObject_unalignRayAPI((RayObject*) obj); + return RE_rayobject_unalignRayAPI((RayObject*) obj); } -static int RayObject_instance_intersect(RayObject *o, Isect *isec) +static int RE_rayobject_instance_intersect(RayObject *o, Isect *isec) { //TODO // *there is probably a faster way to convert between coordinates @@ -162,19 +162,19 @@ static int RayObject_instance_intersect(RayObject *o, Isect *isec) return res; } -static void RayObject_instance_free(RayObject *o) +static void RE_rayobject_instance_free(RayObject *o) { InstanceRayObject *obj = (InstanceRayObject*)o; MEM_freeN(obj); } -static float RayObject_instance_cost(RayObject *o) +static float RE_rayobject_instance_cost(RayObject *o) { InstanceRayObject *obj = (InstanceRayObject*)o; return RE_rayobject_cost(obj->target) + RE_COST_INSTANCE; } -static void RayObject_instance_bb(RayObject *o, float *min, float *max) +static void RE_rayobject_instance_bb(RayObject *o, float *min, float *max) { //TODO: // *better bb.. calculated without rotations of bb diff --git a/source/blender/render/intern/source/rayobject_octree.c b/source/blender/render/intern/source/rayobject_octree.c index da1083a654d..4246dd522db 100644 --- a/source/blender/render/intern/source/rayobject_octree.c +++ b/source/blender/render/intern/source/rayobject_octree.c @@ -84,19 +84,19 @@ typedef struct Octree { } Octree; -static int RayObject_octree_intersect(RayObject *o, Isect *isec); -static void RayObject_octree_add(RayObject *o, RayObject *ob); -static void RayObject_octree_done(RayObject *o); -static void RayObject_octree_free(RayObject *o); -static void RayObject_octree_bb(RayObject *o, float *min, float *max); +static int RE_rayobject_octree_intersect(RayObject *o, Isect *isec); +static void RE_rayobject_octree_add(RayObject *o, RayObject *ob); +static void RE_rayobject_octree_done(RayObject *o); +static void RE_rayobject_octree_free(RayObject *o); +static void RE_rayobject_octree_bb(RayObject *o, float *min, float *max); static RayObjectAPI octree_api = { - RayObject_octree_intersect, - RayObject_octree_add, - RayObject_octree_done, - RayObject_octree_free, - RayObject_octree_bb + RE_rayobject_octree_intersect, + RE_rayobject_octree_add, + RE_rayobject_octree_done, + RE_rayobject_octree_free, + RE_rayobject_octree_bb }; /* **************** ocval method ******************* */ @@ -294,7 +294,7 @@ static void ocwrite(Octree *oc, RayFace *face, int quad, short x, short y, short while(no->v[a]!=NULL) a++; } - no->v[a]= (RayFace*) RayObject_align(face); + no->v[a]= (RayFace*) RE_rayobject_align(face); if(quad) calc_ocval_face(rtf[0], rtf[1], rtf[2], rtf[3], x>>2, y>>1, z, &no->ov[a]); @@ -406,7 +406,7 @@ static void filltriangle(Octree *oc, short c1, short c2, char *ocface, short *oc } } -static void RayObject_octree_free(RayObject *tree) +static void RE_rayobject_octree_free(RayObject *tree) { Octree *oc= (Octree*)tree; @@ -450,7 +450,7 @@ static void RayObject_octree_free(RayObject *tree) RayObject *RE_rayobject_octree_create(int ocres, int size) { Octree *oc= MEM_callocN(sizeof(Octree), "Octree"); - assert( RayObject_isAligned(oc) ); /* RayObject API assumes real data to be 4-byte aligned */ + assert( RE_rayobject_isAligned(oc) ); /* RayObject API assumes real data to be 4-byte aligned */ oc->rayobj.api = &octree_api; @@ -461,17 +461,17 @@ RayObject *RE_rayobject_octree_create(int ocres, int size) oc->ro_nodes_used = 0; - return RayObject_unalignRayAPI((RayObject*) oc); + return RE_rayobject_unalignRayAPI((RayObject*) oc); } -static void RayObject_octree_add(RayObject *tree, RayObject *node) +static void RE_rayobject_octree_add(RayObject *tree, RayObject *node) { Octree *oc = (Octree*)tree; - assert( RayObject_isRayFace(node) ); + assert( RE_rayobject_isRayFace(node) ); assert( oc->ro_nodes_used < oc->ro_nodes_size ); - oc->ro_nodes[ oc->ro_nodes_used++ ] = (RayFace*)RayObject_align(node); + oc->ro_nodes[ oc->ro_nodes_used++ ] = (RayFace*)RE_rayobject_align(node); } static void octree_fill_rayface(Octree *oc, RayFace *face) @@ -489,22 +489,11 @@ static void octree_fill_rayface(Octree *oc, RayFace *face) ocres2= oc->ocres*oc->ocres; -#ifdef RE_RAYFACE_COORDS_VLAKREN - { - VlakRen *vlr = (VlakRen*)face->face; - VECCOPY(co1, vlr->v1->co); - VECCOPY(co2, vlr->v2->co); - VECCOPY(co3, vlr->v3->co); - if(RE_rayface_isQuad(face)) - VECCOPY(co4, vlr->v4->co); - } -#else VECCOPY(co1, face->v1); VECCOPY(co2, face->v2); VECCOPY(co3, face->v3); if(face->v4) VECCOPY(co4, face->v4); -#endif for(c=0;c<3;c++) { rtf[0][c]= (co1[c]-oc->min[c])*ocfac[c] ; @@ -602,7 +591,7 @@ static void octree_fill_rayface(Octree *oc, RayFace *face) } } -static void RayObject_octree_done(RayObject *tree) +static void RE_rayobject_octree_done(RayObject *tree) { Octree *oc = (Octree*)tree; int c; @@ -613,7 +602,7 @@ static void RayObject_octree_done(RayObject *tree) /* Calculate Bounding Box */ for(c=0; cro_nodes_used; c++) - RE_rayobject_merge_bb( RayObject_unalignRayFace(oc->ro_nodes[c]), oc->min, oc->max); + RE_rayobject_merge_bb( RE_rayobject_unalignRayFace(oc->ro_nodes[c]), oc->min, oc->max); /* Alloc memory */ oc->adrbranch= MEM_callocN(sizeof(void *)*BRANCH_ARRAY, "octree branches"); @@ -656,7 +645,7 @@ static void RayObject_octree_done(RayObject *tree) printf("%f %f - %f\n", oc->min[2], oc->max[2], oc->ocfacz ); } -static void RayObject_octree_bb(RayObject *tree, float *min, float *max) +static void RE_rayobject_octree_bb(RayObject *tree, float *min, float *max) { Octree *oc = (Octree*)tree; DO_MINMAX(oc->min, min, max); @@ -681,7 +670,7 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval) if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { - if( RE_rayobject_intersect( RayObject_unalignRayFace(face),is) ) + if( RE_rayobject_intersect( RE_rayobject_unalignRayFace(face),is) ) return 1; } } @@ -700,7 +689,7 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval) if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { - if( RE_rayobject_intersect( RayObject_unalignRayFace(face),is) ) + if( RE_rayobject_intersect( RE_rayobject_unalignRayFace(face),is) ) found= 1; } } @@ -828,7 +817,7 @@ static int do_coherence_test(int ocx1, int ocx2, int ocy1, int ocy2, int ocz1, i /* return 1: found valid intersection */ /* starts with is->orig.face */ -static int RayObject_octree_intersect(RayObject *tree, Isect *is) +static int RE_rayobject_octree_intersect(RayObject *tree, Isect *is) { Octree *oc= (Octree*)tree; Node *no; diff --git a/source/blender/render/intern/source/rayobject_raycounter.c b/source/blender/render/intern/source/rayobject_raycounter.c new file mode 100644 index 00000000000..83ba15602da --- /dev/null +++ b/source/blender/render/intern/source/rayobject_raycounter.c @@ -0,0 +1,77 @@ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#include "rayobject.h" + +#ifdef RE_RAYCOUNTER + +void RE_RC_INFO(RayCounter *info) +{ + printf("----------- Raycast counter --------\n"); + printf("Rays total: %llu\n", info->raycast.test ); + printf("Rays hit: %llu\n", info->raycast.hit ); + printf("\n"); + printf("BB tests: %llu\n", info->bb.test ); + printf("BB hits: %llu\n", info->bb.hit ); + printf("\n"); + printf("Primitives tests: %llu\n", info->faces.test ); + printf("Primitives hits: %llu\n", info->faces.hit ); + printf("------------------------------------\n"); + printf("Shadow last-hit tests per ray: %f\n", info->rayshadow_last_hit.test / ((float)info->raycast.test) ); + printf("Shadow last-hit hits per ray: %f\n", info->rayshadow_last_hit.hit / ((float)info->raycast.test) ); + printf("\n"); + printf("Hint tests per ray: %f\n", info->raytrace_hint.test / ((float)info->raycast.test) ); + printf("Hint hits per ray: %f\n", info->raytrace_hint.hit / ((float)info->raycast.test) ); + printf("\n"); + printf("BB tests per ray: %f\n", info->bb.test / ((float)info->raycast.test) ); + printf("BB hits per ray: %f\n", info->bb.hit / ((float)info->raycast.test) ); + printf("\n"); + printf("Primitives tests per ray: %f\n", info->faces.test / ((float)info->raycast.test) ); + printf("Primitives hits per ray: %f\n", info->faces.hit / ((float)info->raycast.test) ); + printf("------------------------------------\n"); +} + +void RE_RC_MERGE(RayCounter *dest, RayCounter *tmp) +{ + dest->faces.test += tmp->faces.test; + dest->faces.hit += tmp->faces.hit; + + dest->bb.test += tmp->bb.test; + dest->bb.hit += tmp->bb.hit; + + dest->raycast.test += tmp->raycast.test; + dest->raycast.hit += tmp->raycast.hit; + + dest->rayshadow_last_hit.test += tmp->rayshadow_last_hit.test; + dest->rayshadow_last_hit.hit += tmp->rayshadow_last_hit.hit; + + dest->raytrace_hint.test += tmp->raytrace_hint.test; + dest->raytrace_hint.hit += tmp->raytrace_hint.hit; +} + +#endif diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 05c961d49de..af2c0f99174 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -222,7 +222,7 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) if(is_raytraceable_vlr(re, vlr)) { RE_rayface_from_vlak( face, obi, vlr ); - RE_rayobject_add( raytree, RayObject_unalignRayFace(face) ); + RE_rayobject_add( raytree, RE_rayobject_unalignRayFace(face) ); face++; } } @@ -372,7 +372,7 @@ static void makeraytree_single(Render *re) Mat4MulVecfl(obi->mat, face->v4); } - RE_rayobject_add( raytree, RayObject_unalignRayFace(face) ); + RE_rayobject_add( raytree, RE_rayobject_unalignRayFace(face) ); face++; } } From ea18c6ef0abcdd5841d77175a67e2611dce446b5 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sat, 29 Aug 2009 17:24:45 +0000 Subject: [PATCH 086/138] Code reorganization -separated vbvh, svbvh, qbvh in diferent files (before the only way to switch between them was at compile time) --- .../render/extern/include/RE_raytrace.h | 2 + source/blender/render/intern/raytrace/bvh.h | 59 ++- source/blender/render/intern/raytrace/qbvh.h | 0 .../render/intern/raytrace/rayobject_hint.h | 5 + .../render/intern/raytrace/rayobject_qbvh.cpp | 100 +++++ .../intern/raytrace/rayobject_svbvh.cpp | 104 +++++ .../render/intern/raytrace/rayobject_vbvh.cpp | 401 ++---------------- .../render/intern/raytrace/reorganize.h | 3 + source/blender/render/intern/raytrace/svbvh.h | 108 ++--- source/blender/render/intern/raytrace/vbvh.h | 186 ++++++++ .../blender/render/intern/source/rayshade.c | 2 +- 11 files changed, 523 insertions(+), 447 deletions(-) create mode 100644 source/blender/render/intern/raytrace/qbvh.h create mode 100644 source/blender/render/intern/raytrace/rayobject_qbvh.cpp create mode 100644 source/blender/render/intern/raytrace/rayobject_svbvh.cpp create mode 100644 source/blender/render/intern/raytrace/vbvh.h diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index 864b6124db4..01b64c15058 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -102,6 +102,8 @@ RayObject* RE_rayobject_instance_create(RayObject *target, float transform[][4], RayObject* RE_rayobject_blibvh_create(int size); /* BLI_kdopbvh.c */ RayObject* RE_rayobject_bvh_create(int size); /* raytrace/rayobject_bvh.c */ RayObject* RE_rayobject_vbvh_create(int size); /* raytrace/rayobject_vbvh.c */ +RayObject* RE_rayobject_qbvh_create(int size); /* raytrace/rayobject_vbvh.c */ +RayObject* RE_rayobject_svbvh_create(int size); /* raytrace/rayobject_vbvh.c */ RayObject* RE_rayobject_bih_create(int size); /* rayobject_bih.c */ typedef struct LCTSHint LCTSHint; diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h index 55bed6f0662..21234a40673 100644 --- a/source/blender/render/intern/raytrace/bvh.h +++ b/source/blender/render/intern/raytrace/bvh.h @@ -26,6 +26,12 @@ * * ***** END GPL LICENSE BLOCK ***** */ +#include "rayobject.h" +#include "MEM_guardedalloc.h" +#include "rayobject_rtbuild.h" +#include "rayobject_hint.h" + +#include #include #ifndef RE_RAYTRACE_BVH_H @@ -285,7 +291,6 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) return hit; } - /* * recursively transverse a BVH looking for a rayhit using system stack */ @@ -336,4 +341,56 @@ static int bvh_node_raycast(Node *node, Isect *isec) } */ +template +void bvh_dfs_make_hint(Node *node, LCTSHint *hint, int reserve_space, HintObject *hintObject) +{ + assert( hint->size + reserve_space + 1 <= RE_RAY_LCTS_MAX_SIZE ); + + if(is_leaf(node)) + { + hint->stack[hint->size++] = (RayObject*)node; + } + else + { + int childs = count_childs(node); + if(hint->size + reserve_space + childs <= RE_RAY_LCTS_MAX_SIZE) + { + int result = hint_test_bb(hintObject, node->bb, node->bb+3); + if(result == HINT_RECURSE) + { + /* We are 100% sure the ray will be pass inside this node */ + bvh_dfs_make_hint_push_siblings(node->child, hint, reserve_space, hintObject); + } + else if(result == HINT_ACCEPT) + { + hint->stack[hint->size++] = (RayObject*)node; + } + } + else + { + hint->stack[hint->size++] = (RayObject*)node; + } + } +} + + +template +static RayObjectAPI* bvh_get_api(int maxstacksize); + + +template +static inline RayObject *bvh_create_tree(int size) +{ + Tree *obj= (Tree*)MEM_callocN(sizeof(Tree), "BVHTree" ); + assert( RE_rayobject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ + + obj->rayobj.api = bvh_get_api(DFS_STACK_SIZE); + obj->root = NULL; + + obj->node_arena = NULL; + obj->builder = rtbuild_create( size ); + + return RE_rayobject_unalignRayAPI((RayObject*) obj); +} + #endif diff --git a/source/blender/render/intern/raytrace/qbvh.h b/source/blender/render/intern/raytrace/qbvh.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/source/blender/render/intern/raytrace/rayobject_hint.h b/source/blender/render/intern/raytrace/rayobject_hint.h index cc8728a28cb..d85465aec66 100644 --- a/source/blender/render/intern/raytrace/rayobject_hint.h +++ b/source/blender/render/intern/raytrace/rayobject_hint.h @@ -26,6 +26,9 @@ * * ***** END GPL LICENSE BLOCK ***** */ +#ifndef RE_RAYTRACE_RAYOBJECT_HINT_H +#define RE_RAYTRACE_RAYOBJECT_HINT_H + #define HINT_RECURSE 1 #define HINT_ACCEPT 0 #define HINT_DISCARD -1 @@ -63,3 +66,5 @@ inline int hint_test_bb(HintFrustum &obj, float *Nmin, float *Nmax) return HINT_ACCEPT; } */ + +#endif diff --git a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp new file mode 100644 index 00000000000..e3a15b5d7f3 --- /dev/null +++ b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp @@ -0,0 +1,100 @@ +#include "vbvh.h" +#include "svbvh.h" +#include "qbvh.h" +#include "reorganize.h" + +#define DFS_STACK_SIZE 256 + +struct QBVHTree +{ + RayObject rayobj; + + SVBVHNode *root; + MemArena *node_arena; + + float cost; + RTBuilder *builder; +}; + + +template<> +void bvh_done(QBVHTree *obj) +{ + rtbuild_done(obj->builder); + + //TODO find a away to exactly calculate the needed memory + MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); + BLI_memarena_use_malloc(arena1); + + MemArena *arena2 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); + BLI_memarena_use_malloc(arena2); + BLI_memarena_use_align(arena2, 16); + + //Build and optimize the tree + VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); + pushup_simd(root); + obj->root = Reorganize_SVBVH(arena2).transform(root); + + //Cleanup + BLI_memarena_free(arena1); + + rtbuild_free( obj->builder ); + obj->builder = NULL; + + obj->node_arena = arena2; + obj->cost = 1.0; +} + + +template +int intersect(QBVHTree *obj, Isect* isec) +{ + //TODO renable hint support + if(RE_rayobject_isAligned(obj->root)) + return bvh_node_stack_raycast( obj->root, isec); + else + return RE_rayobject_intersect( (RayObject*) obj->root, isec ); +} + +template +void bvh_hint_bb(Tree *tree, LCTSHint *hint, float *min, float *max) +{ + //TODO renable hint support + { + hint->size = 0; + hint->stack[hint->size++] = (RayObject*)tree->root; + } +} +/* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */ +template +RayObjectAPI make_api() +{ + static RayObjectAPI api = + { + (RE_rayobject_raycast_callback) ((int(*)(Tree*,Isect*)) &intersect), + (RE_rayobject_add_callback) ((void(*)(Tree*,RayObject*)) &bvh_add), + (RE_rayobject_done_callback) ((void(*)(Tree*)) &bvh_done), + (RE_rayobject_free_callback) ((void(*)(Tree*)) &bvh_free), + (RE_rayobject_merge_bb_callback)((void(*)(Tree*,float*,float*)) &bvh_bb), + (RE_rayobject_cost_callback) ((float(*)(Tree*)) &bvh_cost), + (RE_rayobject_hint_bb_callback) ((void(*)(Tree*,LCTSHint*,float*,float*)) &bvh_hint_bb) + }; + + return api; +} + +template +RayObjectAPI* bvh_get_api(int maxstacksize) +{ + static RayObjectAPI bvh_api256 = make_api(); + + if(maxstacksize <= 1024) return &bvh_api256; + assert(maxstacksize <= 256); + return 0; +} + + +RayObject *RE_rayobject_qbvh_create(int size) +{ + return bvh_create_tree(size); +} diff --git a/source/blender/render/intern/raytrace/rayobject_svbvh.cpp b/source/blender/render/intern/raytrace/rayobject_svbvh.cpp new file mode 100644 index 00000000000..df033901526 --- /dev/null +++ b/source/blender/render/intern/raytrace/rayobject_svbvh.cpp @@ -0,0 +1,104 @@ +#include "vbvh.h" +#include "svbvh.h" +#include "reorganize.h" + +#define DFS_STACK_SIZE 256 + +struct SVBVHTree +{ + RayObject rayobj; + + SVBVHNode *root; + MemArena *node_arena; + + float cost; + RTBuilder *builder; +}; + + +template<> +void bvh_done(SVBVHTree *obj) +{ + rtbuild_done(obj->builder); + + //TODO find a away to exactly calculate the needed memory + MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); + BLI_memarena_use_malloc(arena1); + + //Build and optimize the tree + VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); + + reorganize(root); + remove_useless(root, &root); + bvh_refit(root); + + pushup(root); + pushdown(root); + pushup_simd(root); + + MemArena *arena2 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); + BLI_memarena_use_malloc(arena2); + BLI_memarena_use_align(arena2, 16); + obj->root = Reorganize_SVBVH(arena2).transform(root); + + BLI_memarena_free(arena1); + + obj->node_arena = arena2; + obj->cost = 1.0; + + + rtbuild_free( obj->builder ); + obj->builder = NULL; +} + +template +int intersect(SVBVHTree *obj, Isect* isec) +{ + //TODO renable hint support + if(RE_rayobject_isAligned(obj->root)) + return bvh_node_stack_raycast( obj->root, isec); + else + return RE_rayobject_intersect( (RayObject*) obj->root, isec ); +} + +template +void bvh_hint_bb(Tree *tree, LCTSHint *hint, float *min, float *max) +{ + //TODO renable hint support + { + hint->size = 0; + hint->stack[hint->size++] = (RayObject*)tree->root; + } +} +/* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */ +template +RayObjectAPI make_api() +{ + static RayObjectAPI api = + { + (RE_rayobject_raycast_callback) ((int(*)(Tree*,Isect*)) &intersect), + (RE_rayobject_add_callback) ((void(*)(Tree*,RayObject*)) &bvh_add), + (RE_rayobject_done_callback) ((void(*)(Tree*)) &bvh_done), + (RE_rayobject_free_callback) ((void(*)(Tree*)) &bvh_free), + (RE_rayobject_merge_bb_callback)((void(*)(Tree*,float*,float*)) &bvh_bb), + (RE_rayobject_cost_callback) ((float(*)(Tree*)) &bvh_cost), + (RE_rayobject_hint_bb_callback) ((void(*)(Tree*,LCTSHint*,float*,float*)) &bvh_hint_bb) + }; + + return api; +} + +template +RayObjectAPI* bvh_get_api(int maxstacksize) +{ + static RayObjectAPI bvh_api256 = make_api(); + + if(maxstacksize <= 1024) return &bvh_api256; + assert(maxstacksize <= 256); + return 0; +} + +RayObject *RE_rayobject_svbvh_create(int size) +{ + return bvh_create_tree(size); +} diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index 6ec8fab15e4..f81ca1e5d1b 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -26,385 +26,82 @@ * * ***** END GPL LICENSE BLOCK ***** */ -#define RE_USE_HINT (0) -static int tot_pushup = 0; -static int tot_pushdown = 0; -static int tot_hints = 0; +int tot_pushup = 0; +int tot_pushdown = 0; +int tot_hints = 0; -extern "C" -{ #include +#include "rayobject.h" +#include "rayobject_rtbuild.h" +#include "RE_raytrace.h" +#include "BLI_memarena.h" #include "MEM_guardedalloc.h" #include "BKE_utildefines.h" #include "BLI_arithb.h" -#include "BLI_memarena.h" -#include "RE_raytrace.h" -#include "rayobject_rtbuild.h" -#include "rayobject.h" -}; -#include "rayobject_hint.h" #include "reorganize.h" #include "bvh.h" +#include "vbvh.h" #include "svbvh.h" #include +#include - -#define RE_DO_HINTS (0) -#define RAY_BB_TEST_COST (0.2f) #define DFS_STACK_SIZE 256 -//#define DYNAMIC_ALLOC_BB - - -//#define rtbuild_split rtbuild_mean_split_largest_axis /* objects mean split on the longest axis, childs BB are allowed to overlap */ -//#define rtbuild_split rtbuild_median_split_largest_axis /* space median split on the longest axis, childs BB are allowed to overlap */ -#define rtbuild_split rtbuild_heuristic_object_split /* split objects using heuristic */ - -struct VBVHNode -{ -#ifdef DYNAMIC_ALLOC_BB - float *bb; -#else - float bb[6]; -#endif - - VBVHNode *child; - VBVHNode *sibling; -}; struct VBVHTree { RayObject rayobj; - - SVBVHNode *root; - + VBVHNode *root; MemArena *node_arena; - float cost; RTBuilder *builder; }; - - -template -struct Reorganize_VBVH -{ - Tree *tree; - - Reorganize_VBVH(Tree *t) - { - tree = t; - } - - VBVHNode *create_node() - { - VBVHNode *node = (VBVHNode*)BLI_memarena_alloc(tree->node_arena, sizeof(VBVHNode)); - return node; - } - - void copy_bb(VBVHNode *node, OldNode *old) - { - std::copy( old->bb, old->bb+6, node->bb ); - } - - VBVHNode *transform(OldNode *old) - { - if(is_leaf(old)) - return (VBVHNode*)old; - - VBVHNode *node = create_node(); - VBVHNode **child_ptr = &node->child; - node->sibling = 0; - - copy_bb(node,old); - - for(OldNode *o_child = old->child; o_child; o_child = o_child->sibling) - { - VBVHNode *n_child = transform(o_child); - *child_ptr = n_child; - if(is_leaf(n_child)) return node; - child_ptr = &n_child->sibling; - } - *child_ptr = 0; - - return node; - } -}; - - -/* - * Push nodes (used on dfs) - */ -template -inline static void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, int &stack_pos) -{ - Node *child = node->child; - - if(is_leaf(child)) - { - stack[stack_pos++] = child; - } - else - { - while(child) - { - //Skips BB tests on primitives -/* - if(is_leaf(child->child)) - stack[stack_pos++] = child->child; - else -*/ - stack[stack_pos++] = child; - - child = child->sibling; - } - } -} - -/* - * BVH done - */ -static VBVHNode *bvh_new_node(VBVHTree *tree) -{ - VBVHNode *node = (VBVHNode*)BLI_memarena_alloc(tree->node_arena, sizeof(VBVHNode)); - - if( (((intptr_t)node) & (0x0f)) != 0 ) - { - puts("WRONG!"); - printf("%08x\n", (intptr_t)node); - } - node->sibling = NULL; - node->child = NULL; - -#ifdef DYNAMIC_ALLOC_BB - node->bb = (float*)BLI_memarena_alloc(tree->node_arena, 6*sizeof(float)); -#endif - assert(RE_rayobject_isAligned(node)); - return node; -} - - - -template -int count_childs(Node *parent) -{ - int n = 0; - for(Node *i = parent->child; i; i = i->sibling) - { - n++; - if(is_leaf(i)) - break; - } - - return n; -} - -template -void append_sibling(Node *node, Node *sibling) -{ - while(node->sibling) - node = node->sibling; - - node->sibling = sibling; -} - - -template -Node *bvh_rearrange(Tree *tree, Builder *builder) -{ - - int size = rtbuild_size(builder); - if(size == 1) - { - Node *node = bvh_new_node(tree); - INIT_MINMAX(node->bb, node->bb+3); - rtbuild_merge_bb(builder, node->bb, node->bb+3); - node->child = (VBVHNode*) rtbuild_get_primitive( builder, 0 ); - return node; - } - else - { - Node *node = bvh_new_node(tree); - - INIT_MINMAX(node->bb, node->bb+3); - rtbuild_merge_bb(builder, node->bb, node->bb+3); - - Node **child = &node->child; - - int nc = rtbuild_split(builder, 2); - assert(nc == 2); - for(int i=0; i(tree, &tmp); - child = &((*child)->sibling); - } - - *child = 0; - return node; - } -} - template<> void bvh_done(VBVHTree *obj) { rtbuild_done(obj->builder); - int needed_nodes = (rtbuild_size(obj->builder)+1)*2; - if(needed_nodes > BLI_MEMARENA_STD_BUFSIZE) - needed_nodes = BLI_MEMARENA_STD_BUFSIZE; + //TODO find a away to exactly calculate the needed memory + MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); + BLI_memarena_use_malloc(arena1); - MemArena *arena1 = BLI_memarena_new(needed_nodes); - BLI_memarena_use_malloc(arena1); - BLI_memarena_use_align(arena1, 16); - obj->node_arena = arena1; - VBVHNode *root = bvh_rearrange( obj, obj->builder ); + //Build and optimize the tree + VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); + reorganize(root); remove_useless(root, &root); - printf("refit: %f\n", bvh_refit(root) ); + bvh_refit(root); pushup(root); pushdown(root); - pushup_simd(root); - //Memory re-organize - if(0) - { - MemArena *arena2 = BLI_memarena_new(needed_nodes); - BLI_memarena_use_malloc(arena2); - BLI_memarena_use_align(arena2, 16); - obj->node_arena = arena2; - root = Reorganize_VBVH(obj).transform(root); - - BLI_memarena_free(arena1); - } - - if(1) - { - MemArena *arena2 = BLI_memarena_new(needed_nodes); - BLI_memarena_use_malloc(arena2); - BLI_memarena_use_align(arena2, 16); - obj->node_arena = arena2; - obj->root = Reorganize_SVBVH(obj).transform(root); - - BLI_memarena_free(arena1); - } -/* - { - obj->root = root; - } -*/ - - obj->cost = 1.0; - + //Cleanup rtbuild_free( obj->builder ); obj->builder = NULL; + + obj->node_arena = arena1; + obj->root = root; + obj->cost = 1.0; } template int intersect(VBVHTree *obj, Isect* isec) { -/* - if(RE_DO_HINTS && isec->hint) - { - LCTSHint *lcts = (LCTSHint*)isec->hint; - isec->hint = 0; - - int hit = 0; - for(int i=0; isize; i++) - { - VBVHNode *node = (VBVHNode*)lcts->stack[i]; - if(RE_rayobject_isAligned(node)) - hit |= bvh_node_stack_raycast(node, isec); - else - hit |= RE_rayobject_intersect( (RayObject*)node, isec ); - - if(hit && isec->mode == RE_RAY_SHADOW) - break; - } - isec->hint = (RayHint*)lcts; - return hit; - } + //TODO renable hint support + if(RE_rayobject_isAligned(obj->root)) + return bvh_node_stack_raycast( obj->root, isec); else -*/ - { - if(RE_rayobject_isAligned(obj->root)) - return bvh_node_stack_raycast( obj->root, isec); - else - return RE_rayobject_intersect( (RayObject*) obj->root, isec ); - } -} - -template -void bvh_dfs_make_hint(Node *node, LCTSHint *hint, int reserve_space, HintObject *hintObject); - -template -void bvh_dfs_make_hint_push_siblings(Node *node, LCTSHint *hint, int reserve_space, HintObject *hintObject) -{ - if(!RE_rayobject_isAligned(node)) - hint->stack[hint->size++] = (RayObject*)node; - else - { - if(node->sibling) - bvh_dfs_make_hint_push_siblings(node->sibling, hint, reserve_space+1, hintObject); - - bvh_dfs_make_hint(node, hint, reserve_space, hintObject); - } -} - -template -void bvh_dfs_make_hint(Node *node, LCTSHint *hint, int reserve_space, HintObject *hintObject) -{ - assert( hint->size + reserve_space + 1 <= RE_RAY_LCTS_MAX_SIZE ); - - if(is_leaf(node)) - { - hint->stack[hint->size++] = (RayObject*)node; - } - else - { - int childs = count_childs(node); - if(hint->size + reserve_space + childs <= RE_RAY_LCTS_MAX_SIZE) - { - int result = hint_test_bb(hintObject, node->bb, node->bb+3); - if(result == HINT_RECURSE) - { - /* We are 100% sure the ray will be pass inside this node */ - bvh_dfs_make_hint_push_siblings(node->child, hint, reserve_space, hintObject); - } - else if(result == HINT_ACCEPT) - { - hint->stack[hint->size++] = (RayObject*)node; - } - } - else - { - hint->stack[hint->size++] = (RayObject*)node; - } - } + return RE_rayobject_intersect( (RayObject*) obj->root, isec ); } template void bvh_hint_bb(Tree *tree, LCTSHint *hint, float *min, float *max) { -/* - if(RE_USE_HINT) - { - HintBB bb; - VECCOPY(bb.bb, min); - VECCOPY(bb.bb+3, max); - - hint->size = 0; - bvh_dfs_make_hint( tree->root, hint, 0, &bb ); - tot_hints++; - } - else -*/ + //TODO renable hint support { hint->size = 0; hint->stack[hint->size++] = (RayObject*)tree->root; @@ -428,16 +125,15 @@ void bfree(VBVHTree *tree) } /* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */ -template -static RayObjectAPI make_api() +template +RayObjectAPI make_api() { static RayObjectAPI api = { (RE_rayobject_raycast_callback) ((int(*)(Tree*,Isect*)) &intersect), (RE_rayobject_add_callback) ((void(*)(Tree*,RayObject*)) &bvh_add), (RE_rayobject_done_callback) ((void(*)(Tree*)) &bvh_done), -// (RE_rayobject_free_callback) ((void(*)(Tree*)) &bvh_free), - (RE_rayobject_free_callback) ((void(*)(Tree*)) &bfree), + (RE_rayobject_free_callback) ((void(*)(Tree*)) &bvh_free), (RE_rayobject_merge_bb_callback)((void(*)(Tree*,float*,float*)) &bvh_bb), (RE_rayobject_cost_callback) ((float(*)(Tree*)) &bvh_cost), (RE_rayobject_hint_bb_callback) ((void(*)(Tree*,LCTSHint*,float*,float*)) &bvh_hint_bb) @@ -447,7 +143,7 @@ static RayObjectAPI make_api() } template -static RayObjectAPI* get_api(int maxstacksize) +RayObjectAPI* bvh_get_api(int maxstacksize) { static RayObjectAPI bvh_api256 = make_api(); @@ -458,38 +154,5 @@ static RayObjectAPI* get_api(int maxstacksize) RayObject *RE_rayobject_vbvh_create(int size) { - VBVHTree *obj= (VBVHTree*)MEM_callocN(sizeof(VBVHTree), "VBVHTree"); - assert( RE_rayobject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ - - obj->rayobj.api = get_api(DFS_STACK_SIZE); - obj->root = NULL; - - obj->node_arena = NULL; - obj->builder = rtbuild_create( size ); - - return RE_rayobject_unalignRayAPI((RayObject*) obj); + return bvh_create_tree(size); } - - - -/* SVBVH */ -template -void bvh_dfs_make_hint(VBVHNode *node, LCTSHint *hint, int reserve_space, HintObject *hintObject) -{ - return; -} -/* -RayObject *RE_rayobject_svbvh_create(int size) -{ - SVBVHTree *obj= (SVBVHTree*)MEM_callocN(sizeof(SVBVHTree), "SVBVHTree"); - assert( RE_rayobject_isAligned(obj) ); // RayObject API assumes real data to be 4-byte aligned - - obj->rayobj.api = get_api(DFS_STACK_SIZE); - obj->root = NULL; - - obj->node_arena = NULL; - obj->builder = rtbuild_create( size ); - - return RE_rayobject_unalignRayAPI((RayObject*) obj); -} -*/ \ No newline at end of file diff --git a/source/blender/render/intern/raytrace/reorganize.h b/source/blender/render/intern/raytrace/reorganize.h index 2494f102003..712221fb739 100644 --- a/source/blender/render/intern/raytrace/reorganize.h +++ b/source/blender/render/intern/raytrace/reorganize.h @@ -29,6 +29,9 @@ #include #include +extern int tot_pushup; +extern int tot_pushdown; + template bool node_fits_inside(Node *a, Node *b) { diff --git a/source/blender/render/intern/raytrace/svbvh.h b/source/blender/render/intern/raytrace/svbvh.h index 95f1c40765e..b243e91d381 100644 --- a/source/blender/render/intern/raytrace/svbvh.h +++ b/source/blender/render/intern/raytrace/svbvh.h @@ -29,10 +29,10 @@ #ifndef RE_RAYTRACE_SVBVH_H #define RE_RAYTRACE_SVBVH_H -#define SVBVH_SIMD 1 - #include "bvh.h" +#include "BLI_memarena.h" #include +#include struct SVBVHNode { @@ -52,38 +52,27 @@ inline int bvh_node_hit_test(SVBVHNode *node, Isect *isec) template<> inline void bvh_node_push_childs(SVBVHNode *node, Isect *isec, SVBVHNode **stack, int &stack_pos) { - if(SVBVH_SIMD) + int i=0; + while(i+4 <= node->nchilds) { - int i=0; - while(i+4 <= node->nchilds) - { - int res = test_bb_group4( (__m128*) (node->child_bb+6*i), isec ); - RE_RC_COUNT(isec->raycounter->bb.test); - RE_RC_COUNT(isec->raycounter->bb.test); - RE_RC_COUNT(isec->raycounter->bb.test); - RE_RC_COUNT(isec->raycounter->bb.test); - - if(res & 1) { stack[stack_pos++] = node->child[i+0]; RE_RC_COUNT(isec->raycounter->bb.hit); } - if(res & 2) { stack[stack_pos++] = node->child[i+1]; RE_RC_COUNT(isec->raycounter->bb.hit); } - if(res & 4) { stack[stack_pos++] = node->child[i+2]; RE_RC_COUNT(isec->raycounter->bb.hit); } - if(res & 8) { stack[stack_pos++] = node->child[i+3]; RE_RC_COUNT(isec->raycounter->bb.hit); } - - i += 4; - } - while(i < node->nchilds) - { - if(RE_rayobject_bb_intersect_test(isec, (const float*)node->child_bb+6*i)) - stack[stack_pos++] = node->child[i]; - i++; - } + int res = test_bb_group4( (__m128*) (node->child_bb+6*i), isec ); + RE_RC_COUNT(isec->raycounter->bb.test); + RE_RC_COUNT(isec->raycounter->bb.test); + RE_RC_COUNT(isec->raycounter->bb.test); + RE_RC_COUNT(isec->raycounter->bb.test); + + if(res & 1) { stack[stack_pos++] = node->child[i+0]; RE_RC_COUNT(isec->raycounter->bb.hit); } + if(res & 2) { stack[stack_pos++] = node->child[i+1]; RE_RC_COUNT(isec->raycounter->bb.hit); } + if(res & 4) { stack[stack_pos++] = node->child[i+2]; RE_RC_COUNT(isec->raycounter->bb.hit); } + if(res & 8) { stack[stack_pos++] = node->child[i+3]; RE_RC_COUNT(isec->raycounter->bb.hit); } + + i += 4; } - else + while(i < node->nchilds) { - for(int i=0; inchilds; i++) - { - if(RE_rayobject_bb_intersect_test(isec, (const float*)node->child_bb+6*i)) - stack[stack_pos++] = node->child[i]; - } + if(RE_rayobject_bb_intersect_test(isec, (const float*)node->child_bb+6*i)) + stack[stack_pos++] = node->child[i]; + i++; } } @@ -97,7 +86,7 @@ void bvh_node_merge_bb(SVBVHNode *node, float *min, float *max) else { int i=0; - while(SVBVH_SIMD && i+4 <= node->nchilds) + while(i+4 <= node->nchilds) { float *res = node->child_bb + 6*i; for(int j=0; j<3; j++) @@ -126,33 +115,24 @@ void bvh_node_merge_bb(SVBVHNode *node, float *min, float *max) } } -struct SVBVHTree -{ - RayObject rayobj; - - SVBVHNode *root; - - MemArena *node_arena; - - float cost; - RTBuilder *builder; -}; - -template +/* + * Builds a SVBVH tree form a VBVHTree + */ +template struct Reorganize_SVBVH { - Tree *tree; + MemArena *arena; float childs_per_node; int nodes_with_childs[16]; int useless_bb; int nodes; - Reorganize_SVBVH(Tree *t) + Reorganize_SVBVH(MemArena *a) { - tree = t; + arena = a; nodes = 0; childs_per_node = 0; useless_bb = 0; @@ -171,10 +151,10 @@ struct Reorganize_SVBVH SVBVHNode *create_node(int nchilds) { - SVBVHNode *node = (SVBVHNode*)BLI_memarena_alloc(tree->node_arena, sizeof(SVBVHNode)); + SVBVHNode *node = (SVBVHNode*)BLI_memarena_alloc(arena, sizeof(SVBVHNode)); node->nchilds = nchilds; - node->child_bb = (float*)BLI_memarena_alloc(tree->node_arena, sizeof(float)*6*nchilds); - node->child= (SVBVHNode**)BLI_memarena_alloc(tree->node_arena, sizeof(SVBVHNode*)*nchilds); + node->child_bb = (float*)BLI_memarena_alloc(arena, sizeof(float)*6*nchilds); + node->child= (SVBVHNode**)BLI_memarena_alloc(arena, sizeof(SVBVHNode*)*nchilds); return node; } @@ -200,29 +180,7 @@ struct Reorganize_SVBVH res[4*j+2] = vec_tmp[6*2+j]; res[4*j+3] = vec_tmp[6*3+j]; } -/* - const float *bb0 = vec_tmp+6*(i+0); - const float *bb1 = vec_tmp+6*(i+1); - const float *bb2 = vec_tmp+6*(i+2); - const float *bb3 = vec_tmp+6*(i+3); - //memmoves could be memory alligned - const __m128 x0y0x1y1 = _mm_shuffle_ps( _mm_loadu_ps(bb0), _mm_loadu_ps(bb1), _MM_SHUFFLE(1,0,1,0) ); - const __m128 x2y2x3y3 = _mm_shuffle_ps( _mm_loadu_ps(bb2), _mm_loadu_ps(bb3), _MM_SHUFFLE(1,0,1,0) ); - _mm_store_ps( node->child_bb+6*i+4*0, _mm_shuffle_ps( x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(2,0,2,0) ) ); - _mm_store_ps( node->child_bb+6*i+4*1, _mm_shuffle_ps( x0y0x1y1, x2y2x3y3, _MM_SHUFFLE(3,1,3,1) ) ); - - const __m128 z0X0z1X1 = _mm_shuffle_ps( _mm_loadu_ps(bb0), _mm_loadu_ps(bb1), _MM_SHUFFLE(3,2,3,2) ); - const __m128 z2X2z3X3 = _mm_shuffle_ps( _mm_loadu_ps(bb2), _mm_loadu_ps(bb3), _MM_SHUFFLE(3,2,3,2) ); - _mm_store_ps( node->child_bb+6*i+4*2, _mm_shuffle_ps( z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(2,0,2,0) ) ); - _mm_store_ps( node->child_bb+6*i+4*3, _mm_shuffle_ps( z0X0z1X1, z2X2z3X3, _MM_SHUFFLE(3,1,3,1) ) ); - - const __m128 Y0Z0Y1Z1 = _mm_shuffle_ps( _mm_loadu_ps(bb0+4), _mm_loadu_ps(bb1+4), _MM_SHUFFLE(1,0,1,0) ); - const __m128 Y2Z2Y3Z3 = _mm_shuffle_ps( _mm_loadu_ps(bb2+4), _mm_loadu_ps(bb3+4), _MM_SHUFFLE(1,0,1,0) ); - _mm_store_ps( node->child_bb+6*i+4*4, _mm_shuffle_ps( Y0Z0Y1Z1, Y2Z2Y3Z3, _MM_SHUFFLE(2,0,2,0) ) ); - _mm_store_ps( node->child_bb+6*i+4*5, _mm_shuffle_ps( Y0Z0Y1Z1, Y2Z2Y3Z3, _MM_SHUFFLE(3,1,3,1) ) ); - */ - i += 4; } } @@ -280,10 +238,8 @@ struct Reorganize_SVBVH } } assert( i == 0 ); - - if(SVBVH_SIMD) - prepare_for_simd(node); + prepare_for_simd(node); return node; } diff --git a/source/blender/render/intern/raytrace/vbvh.h b/source/blender/render/intern/raytrace/vbvh.h new file mode 100644 index 00000000000..7c07bd9ded0 --- /dev/null +++ b/source/blender/render/intern/raytrace/vbvh.h @@ -0,0 +1,186 @@ +#include + +#include +#include "rayobject_rtbuild.h" +#include "BLI_memarena.h" + + +/* + * VBVHNode represents a BVHNode with support for a variable number of childrens + */ +struct VBVHNode +{ + float bb[6]; + + VBVHNode *child; + VBVHNode *sibling; +}; + + +/* + * Push nodes (used on dfs) + */ +template +inline static void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, int &stack_pos) +{ + Node *child = node->child; + + if(is_leaf(child)) + { + stack[stack_pos++] = child; + } + else + { + while(child) + { + //Skips BB tests on primitives +/* + if(is_leaf(child->child)) + stack[stack_pos++] = child->child; + else +*/ + stack[stack_pos++] = child; + + child = child->sibling; + } + } +} + + +template +int count_childs(Node *parent) +{ + int n = 0; + for(Node *i = parent->child; i; i = i->sibling) + { + n++; + if(is_leaf(i)) + break; + } + + return n; +} + + +template +void append_sibling(Node *node, Node *sibling) +{ + while(node->sibling) + node = node->sibling; + + node->sibling = sibling; +} + + +/* + * Builds a binary VBVH from a rtbuild + */ +struct BuildBinaryVBVH +{ + MemArena *arena; + + BuildBinaryVBVH(MemArena *a) + { + arena = a; + } + + VBVHNode *create_node() + { + VBVHNode *node = (VBVHNode*)BLI_memarena_alloc( arena, sizeof(VBVHNode) ); + assert( RE_rayobject_isAligned(node) ); + + node->sibling = NULL; + node->child = NULL; + + return node; + } + + int rtbuild_split(RTBuilder *builder) + { + return ::rtbuild_heuristic_object_split(builder, 2); + } + + VBVHNode *transform(RTBuilder *builder) + { + + int size = rtbuild_size(builder); + if(size == 1) + { + VBVHNode *node = create_node(); + INIT_MINMAX(node->bb, node->bb+3); + rtbuild_merge_bb(builder, node->bb, node->bb+3); + node->child = (VBVHNode*) rtbuild_get_primitive( builder, 0 ); + return node; + } + else + { + VBVHNode *node = create_node(); + + INIT_MINMAX(node->bb, node->bb+3); + rtbuild_merge_bb(builder, node->bb, node->bb+3); + + VBVHNode **child = &node->child; + + int nc = rtbuild_split(builder); + assert(nc == 2); + for(int i=0; isibling); + } + + *child = 0; + return node; + } + } +}; + +/* +template +struct Reorganize_VBVH +{ + Tree *tree; + + Reorganize_VBVH(Tree *t) + { + tree = t; + } + + VBVHNode *create_node() + { + VBVHNode *node = (VBVHNode*)BLI_memarena_alloc(tree->node_arena, sizeof(VBVHNode)); + return node; + } + + void copy_bb(VBVHNode *node, OldNode *old) + { + std::copy( old->bb, old->bb+6, node->bb ); + } + + VBVHNode *transform(OldNode *old) + { + if(is_leaf(old)) + return (VBVHNode*)old; + + VBVHNode *node = create_node(); + VBVHNode **child_ptr = &node->child; + node->sibling = 0; + + copy_bb(node,old); + + for(OldNode *o_child = old->child; o_child; o_child = o_child->sibling) + { + VBVHNode *n_child = transform(o_child); + *child_ptr = n_child; + if(is_leaf(n_child)) return node; + child_ptr = &n_child->sibling; + } + *child_ptr = 0; + + return node; + } +}; +*/ \ No newline at end of file diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index af2c0f99174..928083620e1 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -75,7 +75,7 @@ RayObject * RE_rayobject_tree_create(int type, int size) __attribute__((noinlin RayObject * RE_rayobject_tree_create(int type, int size) { // if(type == R_RAYTRACE_TREE_BIH) - return RE_rayobject_vbvh_create(size); + return RE_rayobject_svbvh_create(size); if(type == R_RAYTRACE_TREE_BVH) return RE_rayobject_bvh_create(size); From 64af3a26184632f53b2ed536f784303e963f033c Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 6 Sep 2009 19:14:06 +0000 Subject: [PATCH 087/138] *introduced new method for packing/optimizing trees after building (this is a generalization of some of the experimental stuff i tried during SoC, but only had time to improve a few days ago) - it should yield slightly better results - the cost model can somehow be tweaked to optimize for diferent trees. *cleaned up some code *added counters for number of SIMD BB tests *added GPL license block on missing files --- source/blender/makesdna/DNA_scene_types.h | 16 +- source/blender/makesrna/intern/rna_scene.c | 26 +- .../render/extern/include/RE_raytrace.h | 2 +- source/blender/render/intern/raytrace/bvh.h | 8 +- source/blender/render/intern/raytrace/qbvh.h | 0 .../render/intern/raytrace/rayobject_bvh.cpp | 1 - .../render/intern/raytrace/rayobject_qbvh.cpp | 57 ++++- .../intern/raytrace/rayobject_rtbuild.cpp | 28 +++ .../intern/raytrace/rayobject_svbvh.cpp | 44 +++- .../render/intern/raytrace/rayobject_vbvh.cpp | 2 +- .../render/intern/raytrace/reorganize.h | 235 ++++++++++++++++++ source/blender/render/intern/raytrace/svbvh.h | 13 +- source/blender/render/intern/raytrace/vbvh.h | 43 +++- .../intern/source/rayobject_raycounter.c | 9 + .../blender/render/intern/source/rayshade.c | 136 ++++------ 15 files changed, 465 insertions(+), 155 deletions(-) delete mode 100644 source/blender/render/intern/raytrace/qbvh.h diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 6efd47d9348..82658be24bf 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -769,15 +769,13 @@ typedef struct Scene { #define R_YAFRAY 1 /* raytrace structure */ -#define R_RAYSTRUCTURE_HIER_BVH_BVH 0 -#define R_RAYSTRUCTURE_HIER_BVH_OCTREE 1 -#define R_RAYSTRUCTURE_SINGLE_OCTREE 2 -#define R_RAYSTRUCTURE_SINGLE_BVH 3 - -/* raytrace tree type */ -#define R_RAYTRACE_TREE_BVH 0 -#define R_RAYTRACE_TREE_BLIBVH 1 -#define R_RAYTRACE_TREE_BIH 2 +#define R_RAYSTRUCTURE_AUTO 0 +#define R_RAYSTRUCTURE_OCTREE 1 +#define R_RAYSTRUCTURE_BLIBVH 2 +#define R_RAYSTRUCTURE_VBVH 3 +#define R_RAYSTRUCTURE_SIMD_SVBVH 4 /* needs SIMD */ +#define R_RAYSTRUCTURE_SIMD_QBVH 5 /* needs SIMD */ +#define R_RAYSTRUCTURE_BIH 6 /* scemode (int now) */ #define R_DOSEQ 0x0001 diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 7baf8c8fd93..db832f1d31c 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1032,18 +1032,16 @@ static void rna_def_scene_render_data(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem raytrace_structure_items[] = { - {R_RAYSTRUCTURE_HIER_BVH_BVH, "{R_RAYSTRUCTURE_HIER_BVH_BVH", 0, "BVH of BVH's", "Create a BVH of objects (each object has it own BVH)"}, - {R_RAYSTRUCTURE_HIER_BVH_OCTREE, "{R_RAYSTRUCTURE_HIER_BVH_OCTREE", 0, "BVH of octree", "Create a BVH of objects (each object has it own octree)"}, - {R_RAYSTRUCTURE_SINGLE_BVH, "{R_RAYSTRUCTURE_SINGLE_BVH", 0, "Single BVH", "BVH of all primitives (no instance support)"}, - {R_RAYSTRUCTURE_SINGLE_OCTREE, "{R_RAYSTRUCTURE_SINGLE_OCTREE", 0, "Octree", "Octree of all primitives (no instance support)"}, - {0, NULL, 0, NULL, NULL}}; + {R_RAYSTRUCTURE_AUTO, "{R_RAYSTRUCTURE_AUTO", 0, "auto", ""}, + {R_RAYSTRUCTURE_OCTREE, "R_RAYSTRUCTURE_OCTREE", 0, "octree", "Use old octree structure (no support for instances)"}, + {R_RAYSTRUCTURE_BLIBVH, "R_RAYSTRUCTURE_BLIBVH", 0, "blibvh", "Use BLI_kdopbvh.c"}, + {R_RAYSTRUCTURE_VBVH, "R_RAYSTRUCTURE_VBVH", 0, "vBVH", ""}, + {R_RAYSTRUCTURE_SIMD_SVBVH, "R_RAYSTRUCTURE_SIMD_SVBVH", 0, "SIMD SVBVH", "Requires SIMD"}, + {R_RAYSTRUCTURE_SIMD_QBVH, "R_RAYSTRUCTURE_SIMD_QBVH", 0, "SIMD QBVH", "Requires SIMD"}, + {R_RAYSTRUCTURE_BIH, "R_RAYSTRUCTURE_BIH", 0, "BIH", ""}, + {0, NULL, 0, NULL, NULL} + }; - static EnumPropertyItem raytrace_tree_type_items[] = { - {R_RAYTRACE_TREE_BVH, "{R_RAYTRACE_TREE_BVH", 0, "BVH", "rayobject_bvh.c"}, - {R_RAYTRACE_TREE_BLIBVH, "{R_RAYTRACE_TREE_BLIBVH", 0, "BLIbvh", "rayobject_blibvh.c"}, - {R_RAYTRACE_TREE_BIH, "{R_RAYSTRUCTURE_SINGLE_BVH", 0, "BIH", "rayobject_bih.c"}, - {0, NULL, 0, NULL, NULL}}; - static EnumPropertyItem fixed_oversample_items[] = { {5, "OVERSAMPLE_5", 0, "5", ""}, {8, "OVERSAMPLE_8", 0, "8", ""}, @@ -1462,12 +1460,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Raytrace Acceleration Structure", "Type of raytrace accelerator structure."); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); - prop= RNA_def_property(srna, "raytrace_tree_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "raytrace_tree_type"); - RNA_def_property_enum_items(prop, raytrace_tree_type_items); - RNA_def_property_ui_text(prop, "Raytrace tree type", "Type of raytrace accelerator structure."); - RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); - prop= RNA_def_property(srna, "antialiasing", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_OSA); RNA_def_property_ui_text(prop, "Anti-Aliasing", "Render and combine multiple samples per pixel to prevent jagged edges."); diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index 01b64c15058..c775a7d18ef 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -53,7 +53,7 @@ struct RayCounter { unsigned long long test, hit; - } faces, bb, raycast, raytrace_hint, rayshadow_last_hit; + } faces, bb, simd_bb, raycast, raytrace_hint, rayshadow_last_hit; }; /* #define RE_RC_INIT(isec, shi) (isec).count = re_rc_counter+(shi).thread */ diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h index 21234a40673..7d3479e5331 100644 --- a/source/blender/render/intern/raytrace/bvh.h +++ b/source/blender/render/intern/raytrace/bvh.h @@ -241,17 +241,13 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) t_node[i] = t->child; } */ - RE_RC_COUNT(isec->raycounter->bb.test); - RE_RC_COUNT(isec->raycounter->bb.test); - RE_RC_COUNT(isec->raycounter->bb.test); - RE_RC_COUNT(isec->raycounter->bb.test); - + RE_RC_COUNT(isec->raycounter->simd_bb.test); int res = test_bb_group4( t_bb, isec ); for(int i=0; i<4; i++) if(res & (1<raycounter->bb.hit); + RE_RC_COUNT(isec->raycounter->simd_bb.hit); if(!is_leaf(t_node[i])) { for(Node *t=t_node[i]; t; t=t->sibling) diff --git a/source/blender/render/intern/raytrace/qbvh.h b/source/blender/render/intern/raytrace/qbvh.h deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/source/blender/render/intern/raytrace/rayobject_bvh.cpp b/source/blender/render/intern/raytrace/rayobject_bvh.cpp index bf54f889ebf..a7e96f6d3fc 100644 --- a/source/blender/render/intern/raytrace/rayobject_bvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_bvh.cpp @@ -65,7 +65,6 @@ struct BVHTree RTBuilder *builder; }; - /* * Push nodes (used on dfs) */ diff --git a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp index e3a15b5d7f3..53579d2915f 100644 --- a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp @@ -1,6 +1,33 @@ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ #include "vbvh.h" #include "svbvh.h" -#include "qbvh.h" #include "reorganize.h" #define DFS_STACK_SIZE 256 @@ -17,6 +44,17 @@ struct QBVHTree }; +/* + * Cost to test N childs + */ +struct PackCost +{ + float operator()(int n) + { + return (n / 4) + ((n % 4) > 2 ? 1 : n%4); + } +}; + template<> void bvh_done(QBVHTree *obj) { @@ -31,9 +69,20 @@ void bvh_done(QBVHTree *obj) BLI_memarena_use_align(arena2, 16); //Build and optimize the tree - VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); - pushup_simd(root); - obj->root = Reorganize_SVBVH(arena2).transform(root); + + if(0) + { + VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); + pushup_simd(root); + obj->root = Reorganize_SVBVH(arena2).transform(root); + } + else + { + //Finds the optimal packing of this tree using a given cost model + OVBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); + VBVH_optimalPackSIMD(PackCost()).transform(root); + obj->root = Reorganize_SVBVH(arena2).transform(root); + } //Cleanup BLI_memarena_free(arena1); diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp index 238929e1dbb..430045b56b6 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp @@ -1,3 +1,31 @@ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ #include #include #include diff --git a/source/blender/render/intern/raytrace/rayobject_svbvh.cpp b/source/blender/render/intern/raytrace/rayobject_svbvh.cpp index df033901526..1bcffddd0ac 100644 --- a/source/blender/render/intern/raytrace/rayobject_svbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_svbvh.cpp @@ -1,3 +1,31 @@ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ #include "vbvh.h" #include "svbvh.h" #include "reorganize.h" @@ -25,9 +53,12 @@ void bvh_done(SVBVHTree *obj) MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); BLI_memarena_use_malloc(arena1); - //Build and optimize the tree - VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); + MemArena *arena2 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); + BLI_memarena_use_malloc(arena2); + BLI_memarena_use_align(arena2, 16); + //Build and optimize the tree + VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); reorganize(root); remove_useless(root, &root); bvh_refit(root); @@ -35,12 +66,11 @@ void bvh_done(SVBVHTree *obj) pushup(root); pushdown(root); pushup_simd(root); - - MemArena *arena2 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); - BLI_memarena_use_malloc(arena2); - BLI_memarena_use_align(arena2, 16); - obj->root = Reorganize_SVBVH(arena2).transform(root); + obj->root = Reorganize_SVBVH(arena2).transform(root); + + + //Free data BLI_memarena_free(arena1); obj->node_arena = arena2; diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index f81ca1e5d1b..4e51de0da07 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -70,7 +70,7 @@ void bvh_done(VBVHTree *obj) //Build and optimize the tree - VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); + VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); reorganize(root); remove_useless(root, &root); diff --git a/source/blender/render/intern/raytrace/reorganize.h b/source/blender/render/intern/raytrace/reorganize.h index 712221fb739..f0335b769d5 100644 --- a/source/blender/render/intern/raytrace/reorganize.h +++ b/source/blender/render/intern/raytrace/reorganize.h @@ -26,7 +26,10 @@ * * ***** END GPL LICENSE BLOCK ***** */ +#include +#include #include +#include #include extern int tot_pushup; @@ -279,3 +282,235 @@ float bvh_refit(Node *node) total += old_area - bb_area(node->bb, node->bb+3); return total; } + + +/* + * this finds the best way to packing a tree acording to a given test cost function + * with the purpose to reduce the expected cost (eg.: number of BB tests). + */ +#include +#include +#define MAX_CUT_SIZE 16 +#define MAX_OPTIMIZE_CHILDS MAX_CUT_SIZE + +struct OVBVHNode +{ + float bb[6]; + + OVBVHNode *child; + OVBVHNode *sibling; + + /* + * Returns min cost to represent the subtree starting at the given node, + * allowing it to have a given cutsize + */ + float cut_cost[MAX_CUT_SIZE]; + float get_cost(int cutsize) + { + return cut_cost[cutsize-1]; + } + + /* + * This saves the cut size of this child, when parent is reaching + * its minimum cut with the given cut size + */ + int cut_size[MAX_CUT_SIZE]; + int get_cut_size(int parent_cut_size) + { + return cut_size[parent_cut_size-1]; + } + + /* + * Reorganize the node based on calculated cut costs + */ + int best_cutsize; + void set_cut(int cutsize, OVBVHNode ***cut) + { + if(cutsize == 1) + { + **cut = this; + *cut = &(**cut)->sibling; + } + else + { + if(cutsize > MAX_CUT_SIZE) + { + for(OVBVHNode *child = this->child; child && RE_rayobject_isAligned(child); child = child->sibling) + { + child->set_cut( 1, cut ); + cutsize--; + } + assert(cutsize == 0); + } + else + for(OVBVHNode *child = this->child; child && RE_rayobject_isAligned(child); child = child->sibling) + child->set_cut( child->get_cut_size( cutsize ), cut ); + } + } + + void optimize() + { + if(RE_rayobject_isAligned(this->child)) + { + //Calc new childs + { + OVBVHNode **cut = &(this->child); + set_cut( best_cutsize, &cut ); + *cut = NULL; + } + + //Optimize new childs + for(OVBVHNode *child = this->child; child && RE_rayobject_isAligned(child); child = child->sibling) + child->optimize(); + } + } +}; + +/* + * Calculates an optimal SIMD packing + * + */ +template +struct VBVH_optimalPackSIMD +{ + TestCost testcost; + + VBVH_optimalPackSIMD(TestCost testcost) + { + this->testcost = testcost; + } + + /* + * calc best cut on a node + */ + struct calc_best + { + Node *child[MAX_OPTIMIZE_CHILDS]; + float child_hit_prob[MAX_OPTIMIZE_CHILDS]; + + calc_best(Node *node) + { + int nchilds = 0; + //Fetch childs and needed data + { + float parent_area = bb_area(node->bb, node->bb+3); + for(Node *child = node->child; child && RE_rayobject_isAligned(child); child = child->sibling) + { + this->child[nchilds] = child; + this->child_hit_prob[nchilds] = bb_area(child->bb, child->bb+3) / parent_area; + nchilds++; + } + + assert(nchilds >= 2 && nchilds <= MAX_OPTIMIZE_CHILDS); + } + + + //Build DP table to find minimum cost to represent this node with a given cutsize + int bt [MAX_OPTIMIZE_CHILDS+1][MAX_CUT_SIZE+1]; //backtrace table + float cost[MAX_OPTIMIZE_CHILDS+1][MAX_CUT_SIZE+1]; //cost table (can be reduced to float[2][MAX_CUT_COST]) + + for(int i=0; i<=nchilds; i++) + for(int j=0; j<=MAX_CUT_SIZE; j++) + cost[i][j] = INFINITY; + + cost[0][0] = 0; + + for(int i=1; i<=nchilds; i++) + for(int size=i-1; size/*+(nchilds-i)*/<=MAX_CUT_SIZE; size++) + for(int cut=1; cut+size/*+(nchilds-i)*/<=MAX_CUT_SIZE; cut++) + { + float new_cost = cost[i-1][size] + child_hit_prob[i-1]*child[i-1]->get_cost(cut); + if(new_cost < cost[i][size+cut]) + { + cost[i][size+cut] = new_cost; + bt[i][size+cut] = cut; + } + } + + //Save the ways to archieve the minimum cost with a given cutsize + for(int i = nchilds; i <= MAX_CUT_SIZE; i++) + { + node->cut_cost[i-1] = cost[nchilds][i]; + if(cost[nchilds][i] < INFINITY) + { + int current_size = i; + for(int j=nchilds; j>0; j--) + { + child[j-1]->cut_size[i-1] = bt[j][current_size]; + current_size -= bt[j][current_size]; + } + } + } + } + }; + + void calc_costs(Node *node) + { + + if( RE_rayobject_isAligned(node->child) ) + { + int nchilds = 0; + for(Node *child = node->child; child && RE_rayobject_isAligned(child); child = child->sibling) + { + calc_costs(child); + nchilds++; + } + + for(int i=0; icut_cost[i] = INFINITY; + + //We are not allowed to look on nodes with with so many childs + if(nchilds > MAX_CUT_SIZE) + { + float cost = 0; + + float parent_area = bb_area(node->bb, node->bb+3); + for(Node *child = node->child; child && RE_rayobject_isAligned(child); child = child->sibling) + { + cost += ( bb_area(child->bb, child->bb+3) / parent_area ) * child->get_cost(1); + } + + cost += testcost(nchilds); + node->cut_cost[0] = cost; + node->best_cutsize = nchilds; + } + else + { + calc_best calc(node); + + //calc expected cost if we optimaly pack this node + for(int cutsize=nchilds; cutsize<=MAX_CUT_SIZE; cutsize++) + { + float m = node->get_cost(cutsize) + testcost(cutsize); + if(m < node->cut_cost[0]) + { + node->cut_cost[0] = m; + node->best_cutsize = cutsize; + } + } + } + assert(node->cut_cost[0] != INFINITY); + } + else + { + node->cut_cost[0] = 1.0f; + for(int i=1; icut_cost[i] = INFINITY; + } + } + + Node *transform(Node *node) + { + if(RE_rayobject_isAligned(node->child)) + { + static int num = 0; + bool first = false; + if(num == 0) { num++; first = true; } + + calc_costs(node); + if(first) printf("expected cost = %f (%d)\n", node->cut_cost[0], node->best_cutsize ); + node->optimize(); + } + return node; + } +}; diff --git a/source/blender/render/intern/raytrace/svbvh.h b/source/blender/render/intern/raytrace/svbvh.h index b243e91d381..840ccc24d1a 100644 --- a/source/blender/render/intern/raytrace/svbvh.h +++ b/source/blender/render/intern/raytrace/svbvh.h @@ -56,15 +56,12 @@ inline void bvh_node_push_childs(SVBVHNode *node, Isect *isec, SVBVHN while(i+4 <= node->nchilds) { int res = test_bb_group4( (__m128*) (node->child_bb+6*i), isec ); - RE_RC_COUNT(isec->raycounter->bb.test); - RE_RC_COUNT(isec->raycounter->bb.test); - RE_RC_COUNT(isec->raycounter->bb.test); - RE_RC_COUNT(isec->raycounter->bb.test); + RE_RC_COUNT(isec->raycounter->simd_bb.test); - if(res & 1) { stack[stack_pos++] = node->child[i+0]; RE_RC_COUNT(isec->raycounter->bb.hit); } - if(res & 2) { stack[stack_pos++] = node->child[i+1]; RE_RC_COUNT(isec->raycounter->bb.hit); } - if(res & 4) { stack[stack_pos++] = node->child[i+2]; RE_RC_COUNT(isec->raycounter->bb.hit); } - if(res & 8) { stack[stack_pos++] = node->child[i+3]; RE_RC_COUNT(isec->raycounter->bb.hit); } + if(res & 1) { stack[stack_pos++] = node->child[i+0]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); } + if(res & 2) { stack[stack_pos++] = node->child[i+1]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); } + if(res & 4) { stack[stack_pos++] = node->child[i+2]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); } + if(res & 8) { stack[stack_pos++] = node->child[i+3]; RE_RC_COUNT(isec->raycounter->simd_bb.hit); } i += 4; } diff --git a/source/blender/render/intern/raytrace/vbvh.h b/source/blender/render/intern/raytrace/vbvh.h index 7c07bd9ded0..db1df43f665 100644 --- a/source/blender/render/intern/raytrace/vbvh.h +++ b/source/blender/render/intern/raytrace/vbvh.h @@ -1,3 +1,31 @@ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ #include #include @@ -75,6 +103,7 @@ void append_sibling(Node *node, Node *sibling) /* * Builds a binary VBVH from a rtbuild */ +template struct BuildBinaryVBVH { MemArena *arena; @@ -84,9 +113,9 @@ struct BuildBinaryVBVH arena = a; } - VBVHNode *create_node() + Node *create_node() { - VBVHNode *node = (VBVHNode*)BLI_memarena_alloc( arena, sizeof(VBVHNode) ); + Node *node = (Node*)BLI_memarena_alloc( arena, sizeof(Node) ); assert( RE_rayobject_isAligned(node) ); node->sibling = NULL; @@ -100,26 +129,26 @@ struct BuildBinaryVBVH return ::rtbuild_heuristic_object_split(builder, 2); } - VBVHNode *transform(RTBuilder *builder) + Node *transform(RTBuilder *builder) { int size = rtbuild_size(builder); if(size == 1) { - VBVHNode *node = create_node(); + Node *node = create_node(); INIT_MINMAX(node->bb, node->bb+3); rtbuild_merge_bb(builder, node->bb, node->bb+3); - node->child = (VBVHNode*) rtbuild_get_primitive( builder, 0 ); + node->child = (Node*) rtbuild_get_primitive( builder, 0 ); return node; } else { - VBVHNode *node = create_node(); + Node *node = create_node(); INIT_MINMAX(node->bb, node->bb+3); rtbuild_merge_bb(builder, node->bb, node->bb+3); - VBVHNode **child = &node->child; + Node **child = &node->child; int nc = rtbuild_split(builder); assert(nc == 2); diff --git a/source/blender/render/intern/source/rayobject_raycounter.c b/source/blender/render/intern/source/rayobject_raycounter.c index 83ba15602da..b47df607c10 100644 --- a/source/blender/render/intern/source/rayobject_raycounter.c +++ b/source/blender/render/intern/source/rayobject_raycounter.c @@ -39,6 +39,9 @@ void RE_RC_INFO(RayCounter *info) printf("BB tests: %llu\n", info->bb.test ); printf("BB hits: %llu\n", info->bb.hit ); printf("\n"); + printf("SIMD BB tests: %llu\n", info->simd_bb.test ); + printf("SIMD BB hits: %llu\n", info->simd_bb.hit ); + printf("\n"); printf("Primitives tests: %llu\n", info->faces.test ); printf("Primitives hits: %llu\n", info->faces.hit ); printf("------------------------------------\n"); @@ -51,6 +54,9 @@ void RE_RC_INFO(RayCounter *info) printf("BB tests per ray: %f\n", info->bb.test / ((float)info->raycast.test) ); printf("BB hits per ray: %f\n", info->bb.hit / ((float)info->raycast.test) ); printf("\n"); + printf("SIMD tests per ray: %f\n", info->simd_bb.test / ((float)info->raycast.test) ); + printf("SIMD hits per ray: %f\n", info->simd_bb.hit / ((float)info->raycast.test) ); + printf("\n"); printf("Primitives tests per ray: %f\n", info->faces.test / ((float)info->raycast.test) ); printf("Primitives hits per ray: %f\n", info->faces.hit / ((float)info->raycast.test) ); printf("------------------------------------\n"); @@ -64,6 +70,9 @@ void RE_RC_MERGE(RayCounter *dest, RayCounter *tmp) dest->bb.test += tmp->bb.test; dest->bb.hit += tmp->bb.hit; + dest->simd_bb.test += tmp->simd_bb.test; + dest->simd_bb.hit += tmp->simd_bb.hit; + dest->raycast.test += tmp->raycast.test; dest->raycast.hit += tmp->raycast.hit; diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 928083620e1..727d5826e49 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -69,21 +69,47 @@ /* only to be used here in this file, it's for speed */ extern struct Render R; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -RayObject * RE_rayobject_tree_create(int type, int size) __attribute__((noinline)); - -RayObject * RE_rayobject_tree_create(int type, int size) +RayObject * RE_rayobject_create(int type, int size) { -// if(type == R_RAYTRACE_TREE_BIH) - return RE_rayobject_svbvh_create(size); + if(type == R_RAYSTRUCTURE_AUTO) + { + //TODO +// if(detect_simd()) +// type = R_RAYSTRUCTURE_SIMD_SVBVH; +// else +// type = R_RAYSTRUCTURE_VBVH; - if(type == R_RAYTRACE_TREE_BVH) - return RE_rayobject_bvh_create(size); - if(type == R_RAYTRACE_TREE_BIH) - return RE_rayobject_bih_create(size); - if(type == R_RAYTRACE_TREE_BLIBVH) + type = R_RAYSTRUCTURE_SIMD_QBVH; + } + + + if(type == R_RAYSTRUCTURE_OCTREE) + { + //TODO dynamic ocres + return RE_rayobject_octree_create(R.r.ocres, size); + } + if(type == R_RAYSTRUCTURE_BLIBVH) + { return RE_rayobject_blibvh_create(size); - + } + if(type == R_RAYSTRUCTURE_VBVH) + { + return RE_rayobject_vbvh_create(size); + } + if(type == R_RAYSTRUCTURE_SIMD_SVBVH) + { + return RE_rayobject_svbvh_create(size); + } + if(type == R_RAYSTRUCTURE_SIMD_QBVH) + { + return RE_rayobject_qbvh_create(size); + } + if(type == R_RAYSTRUCTURE_BIH) + { +// return RE_rayobject_bih_create(size); + } + + return NULL; } #ifdef RE_RAYCOUNTER @@ -205,14 +231,8 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) } assert( faces > 0 ); - //Create Ray cast accelaration structure - - //TODO dynamic ocres - if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_OCTREE) - raytree = obr->raytree = RE_rayobject_octree_create( re->r.ocres, faces ); - else //if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_BVH) - raytree = obr->raytree = RE_rayobject_tree_create( re->r.raytrace_tree_type, faces ); - + //Create Ray cast accelaration structure + raytree = obr->raytree = RE_rayobject_create( re->r.raytrace_tree_type, faces ); face = obr->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "ObjectRen faces"); obr->rayobi = obi; @@ -239,51 +259,6 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) return obi->obr->raytree; } -/* - * create an hierarchic raytrace structure with all objects - * - * R_TRANSFORMED objects instances reuse the same tree by using the rayobject_instance - */ -static void makeraytree_hier(Render *re) -{ - //TODO - // out-of-memory safeproof - // break render - // update render stats - - ObjectInstanceRen *obi; - int num_objects = 0; - - re->i.infostr="Creating raytrace structure"; - re->stats_draw(re->sdh, &re->i); - - //Count number of objects - for(obi=re->instancetable.first; obi; obi=obi->next) - if(is_raytraceable(re, obi)) - num_objects++; - - //Create raytree - re->raytree = RE_rayobject_tree_create( re->r.raytrace_tree_type, num_objects ); - - for(obi=re->instancetable.first; obi; obi=obi->next) - if(is_raytraceable(re, obi)) - { - RayObject *obj = makeraytree_object(re, obi); - RE_rayobject_add( re->raytree, obj ); - - if(re->test_break(re->tbh)) - break; - } - - if(!re->test_break(re->tbh)) - { - RE_rayobject_done( re->raytree ); - } - - re->i.infostr= NULL; - re->stats_draw(re->sdh, &re->i); -} - static int has_special_rayobject(Render *re, ObjectInstanceRen *obi) { if( (obi->flag & R_TRANSFORMED) ) @@ -337,10 +312,7 @@ static void makeraytree_single(Render *re) } //Create raytree - if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_OCTREE) - raytree = re->raytree = RE_rayobject_octree_create( re->r.ocres, faces ); - else //if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_BVH) - raytree = re->raytree = RE_rayobject_tree_create( re->r.raytrace_tree_type, faces ); + raytree = re->raytree = RE_rayobject_create( re->r.raytrace_tree_type, faces ); face = re->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces"); @@ -385,32 +357,8 @@ void makeraytree(Render *re) { float min[3], max[3], sub[3]; int i; - const char *tree_type = "Tree(unknown)"; - re->r.raystructure = R_RAYSTRUCTURE_SINGLE_BVH; -#ifdef RE_RAYCOUNTER - if(re->r.raytrace_tree_type == R_RAYTRACE_TREE_BVH) - tree_type = "BVH"; - if(re->r.raytrace_tree_type == R_RAYTRACE_TREE_BIH) - tree_type = "BIH"; - if(re->r.raytrace_tree_type == R_RAYTRACE_TREE_BLIBVH) - tree_type = "BLIBVH"; - - if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_OCTREE) - printf("Building single octree\n"); - else if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_BVH) - printf("Building single tree(%s)\n", tree_type); - else if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_OCTREE) - printf("Building tree(%s) of octrees\n", tree_type); - else - printf("Building tree(%s) of trees(%s)\n", tree_type, tree_type); -#endif - - if(ELEM(re->r.raystructure, R_RAYSTRUCTURE_SINGLE_BVH, R_RAYSTRUCTURE_SINGLE_OCTREE)) - BENCH(makeraytree_single(re), tree_build); - else - BENCH(makeraytree_hier(re), tree_build); - + BENCH(makeraytree_single(re), tree_build); //Calculate raytree max_size //This is ONLY needed to kept a bogus behaviour of SUN and HEMI lights From 732bf328c51d630bace201b40ab2bedcb314d96e Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 7 Sep 2009 00:58:17 +0000 Subject: [PATCH 088/138] Bug fix (layers and some other checks were disabled) *bug found and isolated by ZanQdo (Daniel Salazar) --- .../render/extern/include/RE_raytrace.h | 3 +- .../blender/render/intern/source/rayobject.c | 20 +++++++++++++ .../blender/render/intern/source/rayshade.c | 29 ++++--------------- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index c775a7d18ef..8fc3a96ca99 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -178,7 +178,8 @@ struct Isect #define RE_SKIP_CULLFACE (1 << 0) /* if using this flag then *face should be a pointer to a VlakRen */ -#define RE_SKIP_VLR_NEIGHBOUR (1 << 1) +#define RE_SKIP_VLR_NEIGHBOUR (1 << 1) +#define RE_SKIP_VLR_RENDER_CHECK (1 << 2) /* TODO use: FLT_MAX? */ #define RE_RAYTRACE_MAXDIST 1e33 diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index 996be35090e..73711272935 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -141,6 +141,20 @@ static int intersection2(VlakRen *face, float r0, float r1, float r2, float rx1, return 0; } +#include "DNA_material_types.h" +static int vlr_check_intersect(Isect *is, ObjectInstanceRen *obi, VlakRen *vlr) +{ + /* for baking selected to active non-traceable materials might still + * be in the raytree */ + if(!(vlr->mat->mode & MA_TRACEBLE)) + return 0; + + /* I know... cpu cycle waste, might do smarter once */ + if(is->mode==RE_RAY_MIRROR) + return !(vlr->mat->mode & MA_ONLYCAST); + else + return (is->lay & obi->lay); +} /* ray - triangle or quad intersection */ /* this function shall only modify Isect if it detects an hit */ @@ -154,6 +168,12 @@ static int intersect_rayface(RayFace *face, Isect *is) if(is->orig.ob == face->ob && is->orig.face == face->face) return 0; + + if(is->skip & RE_SKIP_VLR_RENDER_CHECK) + { + if(vlr_check_intersect(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face ) == 0) + return 0; + } RE_RC_COUNT(is->raycounter->faces.test); diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 727d5826e49..8733b89b88a 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -116,25 +116,6 @@ RayObject * RE_rayobject_create(int type, int size) RayCounter re_rc_counter[BLENDER_MAX_THREADS] = {}; #endif -#if 0 -static int vlr_check_intersect(Isect *is, int ob, RayFace *face) -{ - ObjectInstanceRen *obi= RAY_OBJECT_GET((Render*)is->userdata, ob); - VlakRen *vlr = (VlakRen*)face; - - /* for baking selected to active non-traceable materials might still - * be in the raytree */ - if(!(vlr->mat->mode & MA_TRACEBLE)) - return 0; - - /* I know... cpu cycle waste, might do smarter once */ - if(is->mode==RE_RAY_MIRROR) - return !(vlr->mat->mode & MA_ONLYCAST); - else - return (is->lay & obi->lay); -} -#endif - void freeraytree(Render *re) { ObjectInstanceRen *obi; @@ -602,7 +583,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo VECCOPY(isec.vec, vec ); isec.labda = dist_mir > 0 ? dist_mir : RE_RAYTRACE_MAXDIST; isec.mode= RE_RAY_MIRROR; - isec.skip = RE_SKIP_VLR_NEIGHBOUR; + isec.skip = RE_SKIP_VLR_NEIGHBOUR | RE_SKIP_VLR_RENDER_CHECK; isec.hint = 0; isec.orig.ob = obi; @@ -1725,7 +1706,7 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac) RE_RC_INIT(isec, *shi); isec.orig.ob = shi->obi; isec.orig.face = shi->vlr; - isec.skip = RE_SKIP_VLR_NEIGHBOUR; + isec.skip = RE_SKIP_VLR_NEIGHBOUR | RE_SKIP_VLR_RENDER_CHECK; isec.hint = 0; isec.hit.ob = 0; @@ -1866,7 +1847,7 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) RE_RC_INIT(isec, *shi); isec.orig.ob = shi->obi; isec.orig.face = shi->vlr; - isec.skip = RE_SKIP_VLR_NEIGHBOUR; + isec.skip = RE_SKIP_VLR_NEIGHBOUR | RE_SKIP_VLR_RENDER_CHECK; isec.hint = 0; isec.hit.ob = 0; @@ -2087,7 +2068,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float * RE_rayobject_hint_bb( R.raytree, &bb_hint, min, max); isec->hint = &bb_hint; - isec->skip = RE_SKIP_VLR_NEIGHBOUR; + isec->skip = RE_SKIP_VLR_NEIGHBOUR | RE_SKIP_VLR_RENDER_CHECK; VECCOPY(vec, lampco); while (samples < max_samples) { @@ -2256,7 +2237,7 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa isec->vec[1] = vec[1]+lampco[1]-isec->start[1]; isec->vec[2] = vec[2]+lampco[2]-isec->start[2]; isec->labda = 1.0f; - isec->skip = RE_SKIP_VLR_NEIGHBOUR; + isec->skip = RE_SKIP_VLR_NEIGHBOUR | RE_SKIP_VLR_RENDER_CHECK; if(isec->mode==RE_RAY_SHADOW_TRA) { /* isec.col is like shadfac, so defines amount of light (0.0 is full shadow) */ From f8657be654f89c6a4826ef8dd3e2275dfe2d4a5a Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 13 Sep 2009 20:59:25 +0000 Subject: [PATCH 089/138] *Ray counters (number of BB/primitive tests/hits and other raytrace counters) can now be enabled/disabled at compile-time. #define RE_RAYCOUNTER (/source/blender/render/extern/include/RE_raytrace.h) *Some other small organization on code (will be disable as this only matters for testing and developping) --- .../render/extern/include/RE_raytrace.h | 41 ++---------- .../render/intern/include/raycounter.h | 66 +++++++++++++++++++ .../blender/render/intern/include/rayobject.h | 51 ++++++++++---- source/blender/render/intern/raytrace/bvh.h | 1 + .../blender/render/intern/source/rayobject.c | 2 +- .../intern/source/rayobject_raycounter.c | 1 + .../blender/render/intern/source/rayshade.c | 6 ++ .../blender/render/intern/source/shadeinput.c | 5 ++ 8 files changed, 125 insertions(+), 48 deletions(-) create mode 100644 source/blender/render/intern/include/raycounter.h diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index 8fc3a96ca99..0bdecb333e8 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -35,43 +35,12 @@ extern "C" { #endif +//#define RE_RAYCOUNTER /* enable counters per ray, usefull for measuring raytrace structures performance */ #define RE_RAY_LCTS_MAX_SIZE 256 #define RT_USE_LAST_HIT /* last shadow hit is reused before raycasting on whole tree */ //#define RT_USE_HINT /* last hit object is reused before raycasting on whole tree */ -#define RE_RAYCOUNTER - - -#ifdef RE_RAYCOUNTER - -typedef struct RayCounter RayCounter; -struct RayCounter -{ - - struct - { - unsigned long long test, hit; - - } faces, bb, simd_bb, raycast, raytrace_hint, rayshadow_last_hit; -}; - -/* #define RE_RC_INIT(isec, shi) (isec).count = re_rc_counter+(shi).thread */ -#define RE_RC_INIT(isec, shi) (isec).raycounter = &((shi).raycounter) -void RE_RC_INFO (RayCounter *rc); -void RE_RC_MERGE(RayCounter *rc, RayCounter *tmp); -#define RE_RC_COUNT(var) (var)++ - -extern RayCounter re_rc_counter[]; - -#else - -#define RE_RC_INIT(isec,shi) -#define RE_RC_INFO(rc) -#define RE_RC_MERGE(dest,src) -#define RE_RC_COUNT(var) - -#endif /* Internals about raycasting structures can be found on intern/raytree.h */ @@ -79,6 +48,7 @@ typedef struct RayObject RayObject; typedef struct Isect Isect; typedef struct RayHint RayHint; typedef struct RayTraceHint RayTraceHint; +typedef struct RayCounter RayCounter; struct DerivedMesh; struct Mesh; @@ -95,17 +65,17 @@ void RE_rayobject_hint_bb(RayObject *r, RayHint *hint, float *min, float *max); /* void RE_rayobject_hint_cone(RayObject *r, RayHint *hint, float *); */ /* RayObject constructors */ - RayObject* RE_rayobject_octree_create(int ocres, int size); RayObject* RE_rayobject_instance_create(RayObject *target, float transform[][4], void *ob, void *target_ob); RayObject* RE_rayobject_blibvh_create(int size); /* BLI_kdopbvh.c */ RayObject* RE_rayobject_bvh_create(int size); /* raytrace/rayobject_bvh.c */ RayObject* RE_rayobject_vbvh_create(int size); /* raytrace/rayobject_vbvh.c */ -RayObject* RE_rayobject_qbvh_create(int size); /* raytrace/rayobject_vbvh.c */ -RayObject* RE_rayobject_svbvh_create(int size); /* raytrace/rayobject_vbvh.c */ +RayObject* RE_rayobject_qbvh_create(int size); /* raytrace/rayobject_qbvh.c */ +RayObject* RE_rayobject_svbvh_create(int size); /* raytrace/rayobject_svbvh.c */ RayObject* RE_rayobject_bih_create(int size); /* rayobject_bih.c */ + typedef struct LCTSHint LCTSHint; struct LCTSHint { @@ -166,7 +136,6 @@ struct Isect #ifdef RE_RAYCOUNTER RayCounter *raycounter; #endif - }; /* ray types */ diff --git a/source/blender/render/intern/include/raycounter.h b/source/blender/render/intern/include/raycounter.h new file mode 100644 index 00000000000..06579b366ee --- /dev/null +++ b/source/blender/render/intern/include/raycounter.h @@ -0,0 +1,66 @@ +/** + * $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) 2009 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): André Pinto. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef RE_RAYCOUNTER_H +#define RE_RAYCOUNTER_H + +#include "RE_raytrace.h" + + +#ifdef RE_RAYCOUNTER + +typedef struct RayCounter RayCounter; +struct RayCounter +{ + + struct + { + unsigned long long test, hit; + + } faces, bb, simd_bb, raycast, raytrace_hint, rayshadow_last_hit; +}; + +/* #define RE_RC_INIT(isec, shi) (isec).count = re_rc_counter+(shi).thread */ +#define RE_RC_INIT(isec, shi) (isec).raycounter = &((shi).raycounter) +void RE_RC_INFO (RayCounter *rc); +void RE_RC_MERGE(RayCounter *rc, RayCounter *tmp); +#define RE_RC_COUNT(var) (var)++ + +extern RayCounter re_rc_counter[]; + +#else + +# define RE_RC_INIT(isec,shi) +# define RE_RC_INFO(rc) +# define RE_RC_MERGE(dest,src) +# define RE_RC_COUNT(var) + +#endif + + +#endif diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index 36b0d2692c0..2a9b42d22fe 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -67,7 +67,7 @@ extern "C" { 0 Self (reserved for each structure) 1 RayFace 2 RayObject (generic with API callbacks) - 3 unused + 3 RayObject_Vlak 0 means it's reserved and has it own meaning inside each ray acceleration structure (this way each structure can use the allign offset to determine if a node represents a @@ -77,6 +77,35 @@ extern "C" { described on RE_raytrace.h */ +/* used to align a given ray object */ +#define RE_rayobject_align(o) ((RayObject*)(((intptr_t)o)&(~3))) + +/* used to unalign a given ray object */ +#define RE_rayobject_unalignRayFace(o) ((RayObject*)(((intptr_t)o)|1)) +#define RE_rayobject_unalignRayAPI(o) ((RayObject*)(((intptr_t)o)|2)) +#define RE_rayobject_unalignRayVlak(o) ((RayObject*)(((intptr_t)o)|3)) + +/* used to test the type of ray object */ +#define RE_rayobject_isAligned(o) ((((intptr_t)o)&3) == 0) +#define RE_rayobject_isRayFace(o) ((((intptr_t)o)&3) == 1) +#define RE_rayobject_isRayAPI(o) ((((intptr_t)o)&3) == 2) +#define RE_rayobject_isRayVlak(o) ((((intptr_t)o)&3) == 3) + + +/* + * This ray object represents faces directly from a given VlakRen structure. + * Thus allowing to save memory, but making code dependant on render structures +typedef struct RayVlak +{ + struct ObjectInstanceRen *ob; + struct VlakRen *face; +} RayVlak; + */ + +/* + * This ray object represents a triangle or a quad face. + * All data needed to realize intersection is "localy" available. + */ typedef struct RayFace { float v1[4], v2[4], v3[4], v4[3]; @@ -87,7 +116,15 @@ typedef struct RayFace } RayFace; #define RE_rayface_isQuad(a) ((a)->quad) +/* Loads a VlakRen on a RayFace */ +void RE_rayface_from_vlak(RayFace *face, ObjectInstanceRen *obi, VlakRen *vlr); + + +/* + * This rayobject represents a generic object. With it's own callbacks for raytrace operations. + * It's suitable to implement things like LOD. + */ struct RayObject { struct RayObjectAPI *api; @@ -114,18 +151,8 @@ typedef struct RayObjectAPI } RayObjectAPI; -#define RE_rayobject_align(o) ((RayObject*)(((intptr_t)o)&(~3))) -#define RE_rayobject_unalignRayFace(o) ((RayObject*)(((intptr_t)o)|1)) -#define RE_rayobject_unalignRayAPI(o) ((RayObject*)(((intptr_t)o)|2)) -#define RE_rayobject_isAligned(o) ((((intptr_t)o)&3) == 0) -#define RE_rayobject_isRayFace(o) ((((intptr_t)o)&3) == 1) -#define RE_rayobject_isRayAPI(o) ((((intptr_t)o)&3) == 2) -/* - * Loads a VlakRen on a RayFace - */ -void RE_rayface_from_vlak(RayFace *face, ObjectInstanceRen *obi, VlakRen *vlr); /* * Extend min/max coords so that the rayobject is inside them @@ -152,6 +179,8 @@ int RE_rayobject_bb_intersect_test(const Isect *i, const float *bb); /* same as float RE_rayobject_cost(RayObject *r); + + #define ISECT_EPSILON ((float)FLT_EPSILON) diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h index 7d3479e5331..f0302ddba3a 100644 --- a/source/blender/render/intern/raytrace/bvh.h +++ b/source/blender/render/intern/raytrace/bvh.h @@ -27,6 +27,7 @@ * ***** END GPL LICENSE BLOCK ***** */ #include "rayobject.h" +#include "raycounter.h" #include "MEM_guardedalloc.h" #include "rayobject_rtbuild.h" #include "rayobject_hint.h" diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index 73711272935..05308361fdb 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -34,7 +34,7 @@ #include "RE_raytrace.h" #include "render_types.h" #include "rayobject.h" - +#include "raycounter.h" /* * Determines the distance that the ray must travel to hit the bounding volume of the given node diff --git a/source/blender/render/intern/source/rayobject_raycounter.c b/source/blender/render/intern/source/rayobject_raycounter.c index b47df607c10..a82a21348c1 100644 --- a/source/blender/render/intern/source/rayobject_raycounter.c +++ b/source/blender/render/intern/source/rayobject_raycounter.c @@ -27,6 +27,7 @@ * ***** END GPL LICENSE BLOCK ***** */ #include "rayobject.h" +#include "raycounter.h" #ifdef RE_RAYCOUNTER diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 8733b89b88a..7e2cb4c6992 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -58,6 +58,7 @@ #include "RE_raytrace.h" #include "rayobject.h" +#include "raycounter.h" #define RAY_TRA 1 #define RAY_TRAFLIP 2 @@ -338,6 +339,9 @@ void makeraytree(Render *re) { float min[3], max[3], sub[3]; int i; + + re->i.infostr= "Make raytree"; + re->stats_draw(re->sdh, &re->i); BENCH(makeraytree_single(re), tree_build); @@ -351,6 +355,8 @@ void makeraytree(Render *re) sub[i] = max[i]-min[i]; } re->maxdist = sqrt( sub[0]*sub[0] + sub[1]*sub[1] + sub[2]*sub[2] ); + + re->i.infostr= "Raytree finished"; } diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index 0da2f0b1c9d..496d187cf05 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -44,6 +44,7 @@ #include "BKE_node.h" /* local include */ +#include "raycounter.h" #include "renderpipeline.h" #include "render_types.h" #include "renderdatabase.h" @@ -175,7 +176,9 @@ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr) float alpha; /* ------ main shading loop -------- */ +#ifdef RE_RAYCOUNTER memset(&shi->raycounter, 0, sizeof(shi->raycounter)); +#endif if(shi->mat->nodetree && shi->mat->use_nodes) { ntreeShaderExecTree(shi->mat->nodetree, shi, shr); @@ -221,6 +224,7 @@ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr) shr->z= -shi->co[2]; /* RAYHITS */ +/* if(1 || shi->passflag & SCE_PASS_RAYHITS) { shr->rayhits[0] = (float)shi->raycounter.faces.test; @@ -229,6 +233,7 @@ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr) shr->rayhits[3] = 1.0; RE_RC_MERGE(&re_rc_counter[shi->thread], &shi->raycounter); } + */ } /* **************************************************************************** */ From 5e609c9c52c76c26e890b676184ed6b52c82b393 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Thu, 17 Sep 2009 12:56:16 +0000 Subject: [PATCH 090/138] * converted raytrace visibility test on meshlaplacian.c to new raytrace API I need test scenes and test instructions to make sure this is ok, since i have no idea how to test this feature. --- .../blender/editors/armature/meshlaplacian.c | 40 ++++++++++------- .../render/extern/include/RE_raytrace.h | 22 ++++++++++ .../blender/render/intern/include/rayobject.h | 19 -------- .../blender/render/intern/source/rayobject.c | 44 ++++++++++++++----- 4 files changed, 78 insertions(+), 47 deletions(-) diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 7f95fb47d61..c994f7789a0 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -30,7 +30,6 @@ #include #include -#include #include "MEM_guardedalloc.h" @@ -107,7 +106,8 @@ struct LaplacianSystem { float *mindist; /* minimum distance to a bone for all vertices */ RayObject *raytree; /* ray tracing acceleration structure */ - MFace **vface; /* a face that the vertex belongs to */ + RayFace *faces; /* faces to add to the ray tracing struture */ + MFace **vface; /* a face that the vertex belongs to */ } heat; #ifdef RIGID_DEFORM @@ -398,14 +398,25 @@ float laplacian_system_get_solution(int v) static void heat_ray_tree_create(LaplacianSystem *sys) { Mesh *me = sys->heat.mesh; - MFace *mface; int a; - assert(0); //TODO - //sys->heat.raytree = RE_rayobject_mesh_create(me, me); - + sys->heat.raytree = RE_rayobject_vbvh_create(me->totface); + sys->heat.faces = MEM_callocN(sizeof(RayFace)*me->totface, "Heat RayFaces"); sys->heat.vface = MEM_callocN(sizeof(MFace*)*me->totvert, "HeatVFaces"); - for(a=0, mface=me->mface; atotface; a++, mface++) { + + for(a=0; atotface; a++) { + + MFace *mface = me->mface+a; + RayFace *rayface = sys->heat.faces+a; + + RayObject *obj = RE_rayface_from_coords( + rayface, me, mface, + sys->heat.verts[mface->v1], sys->heat.verts[mface->v2], + sys->heat.verts[mface->v3], mface->v4 ? sys->heat.verts[mface->v4] : 0 + ); + RE_rayobject_add(sys->heat.raytree, obj); + + //Setup inverse pointers to use on isect.orig sys->heat.vface[mface->v1]= mface; sys->heat.vface[mface->v2]= mface; sys->heat.vface[mface->v3]= mface; @@ -420,7 +431,6 @@ static int heat_ray_bone_visible(LaplacianSystem *sys, int vertex, int bone) float end[3]; int visible; - assert( 0 ); mface= sys->heat.vface[vertex]; if(!mface) return 1; @@ -429,23 +439,18 @@ static int heat_ray_bone_visible(LaplacianSystem *sys, int vertex, int bone) memset(&isec, 0, sizeof(isec)); isec.mode= RE_RAY_SHADOW; isec.lay= -1; + isec.orig.ob = sys->heat.mesh; isec.orig.face = mface; isec.skip = RE_SKIP_CULLFACE; + VECCOPY(isec.start, sys->heat.verts[vertex]); PclosestVL3Dfl(end, isec.start, sys->heat.root[bone], sys->heat.tip[bone]); VECSUB(isec.vec, end, isec.start); - isec.labda = 1.0f; + isec.labda = 1.0f - 1e-5; + VECADDFAC( isec.start, isec.start, isec.vec, 1e-5); -#if 0 - TODO - /* add an extra offset to the start position to avoid self intersection */ - VECCOPY(dir, isec.vec); - Normalize(dir); - VecMulf(dir, 1e-5); - VecAddf(isec.start, isec.start, dir); -#endif visible= !RE_rayobject_raycast(sys->heat.raytree, &isec); return visible; @@ -712,6 +717,7 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numbones, RE_rayobject_free(sys->heat.raytree); MEM_freeN(sys->heat.vface); + MEM_freeN(sys->heat.faces); MEM_freeN(sys->heat.mindist); MEM_freeN(sys->heat.H); diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index af3ea8e2ac0..fe490461da0 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -79,6 +79,28 @@ RayObject* RE_rayobject_svbvh_create(int size); /* raytrace/rayobject_svbvh.c * RayObject* RE_rayobject_bih_create(int size); /* rayobject_bih.c */ +/* + * This ray object represents a triangle or a quad face. + * All data needed to realize intersection is "localy" available. + */ +typedef struct RayFace +{ + float v1[4], v2[4], v3[4], v4[3]; + int quad; + void *ob; + void *face; + +} RayFace; + +#define RE_rayface_isQuad(a) ((a)->quad) +struct VlakRen; +struct ObjectInstanceRen; + +RayObject* RE_rayface_from_vlak(RayFace *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr); +RayObject* RE_rayface_from_coords(RayFace *rayface, void *ob, void *face, float *co1, float *co2, float *co3, float *co4); + + + typedef struct LCTSHint LCTSHint; struct LCTSHint { diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index 19608fba262..dbd68fe8b8b 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -102,25 +102,6 @@ typedef struct RayVlak } RayVlak; */ -/* - * This ray object represents a triangle or a quad face. - * All data needed to realize intersection is "localy" available. - */ -typedef struct RayFace -{ - float v1[4], v2[4], v3[4], v4[3]; - int quad; - void *ob; - void *face; - -} RayFace; - -#define RE_rayface_isQuad(a) ((a)->quad) -/* Loads a VlakRen on a RayFace */ -void RE_rayface_from_vlak(RayFace *face, ObjectInstanceRen *obi, VlakRen *vlr); - - - /* * This rayobject represents a generic object. With it's own callbacks for raytrace operations. * It's suitable to implement things like LOD. diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/source/rayobject.c index 4bd8a12aa01..df457a37123 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/source/rayobject.c @@ -165,6 +165,17 @@ static int vlr_check_intersect_solid(Isect *is, ObjectInstanceRen* obi, VlakRen return 0; } +static int rayface_check_cullface(RayFace *face, Isect *is) +{ + float nor[3]; + + /* don't intersect if the ray faces along the face normal */ + if(face->quad) CalcNormFloat4(face->v1, face->v2, face->v3, face->v4, nor); + else CalcNormFloat(face->v1, face->v2, face->v3, nor); + + return (INPR(nor, is->vec) < 0); +} + /* ray - triangle or quad intersection */ /* this function shall only modify Isect if it detects an hit */ static int intersect_rayface(RayFace *face, Isect *is) @@ -188,6 +199,11 @@ static int intersect_rayface(RayFace *face, Isect *is) if(vlr_check_intersect_solid(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0) return 0; } + if(is->skip & RE_SKIP_CULLFACE) + { + if(rayface_check_cullface(face, is) == 0) + return 0; + } RE_RC_COUNT(is->raycounter->faces.test); @@ -319,26 +335,32 @@ static int intersect_rayface(RayFace *face, Isect *is) return 0; } -void RE_rayface_from_vlak(RayFace *face, ObjectInstanceRen *obi, VlakRen *vlr) +RayObject* RE_rayface_from_vlak(RayFace *rayface, ObjectInstanceRen *obi, VlakRen *vlr) { - VECCOPY(face->v1, vlr->v1->co); - VECCOPY(face->v2, vlr->v2->co); - VECCOPY(face->v3, vlr->v3->co); - if(vlr->v4) + return RE_rayface_from_coords(rayface, obi, vlr, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4 ? vlr->v4->co : 0 ); +} + +RayObject* RE_rayface_from_coords(RayFace *rayface, void *ob, void *face, float *v1, float *v2, float *v3, float *v4) +{ + rayface->ob = ob; + rayface->face = face; + + VECCOPY(rayface->v1, v1); + VECCOPY(rayface->v2, v2); + VECCOPY(rayface->v3, v3); + if(v4) { - VECCOPY(face->v4, vlr->v4->co); - face->quad = 1; + VECCOPY(rayface->v4, v4); + rayface->quad = 1; } else { - face->quad = 0; + rayface->quad = 0; } - face->ob = obi; - face->face = vlr; + return RE_rayobject_unalignRayFace(rayface); } - int RE_rayobject_raycast(RayObject *r, Isect *isec) { int i; From d3e88cb3e0d4117ab845a7c77254a5ab05ce1657 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 20 Sep 2009 16:49:05 +0000 Subject: [PATCH 091/138] *fix bone weighting forgot to call RE_rayobject_done --- source/blender/editors/armature/meshlaplacian.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index c994f7789a0..436048f5427 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -422,6 +422,7 @@ static void heat_ray_tree_create(LaplacianSystem *sys) sys->heat.vface[mface->v3]= mface; if(mface->v4) sys->heat.vface[mface->v4]= mface; } + RE_rayobject_done(sys->heat.raytree); } static int heat_ray_bone_visible(LaplacianSystem *sys, int vertex, int bone) From 1305715d2d84f67027b870f263cef3a7f009c056 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Thu, 24 Sep 2009 22:55:57 +0000 Subject: [PATCH 092/138] *Added VlakPrimitive (this rayobject rimitive only stores ObjectRenderInstance and VlakRen pointers) - it difers from RayFace that localy stored the vertex coordinates. - basicaly this reduces memory usage --- .../render/extern/include/RE_raytrace.h | 20 ++++- .../blender/render/intern/include/rayobject.h | 27 ++---- .../render/intern/include/render_types.h | 3 + .../rayobject.c => raytrace/rayobject.cpp} | 52 +++++++++-- .../blender/render/intern/source/rayshade.c | 86 +++++++++++++++---- .../render/intern/source/renderdatabase.c | 5 ++ 6 files changed, 146 insertions(+), 47 deletions(-) rename source/blender/render/intern/{source/rayobject.c => raytrace/rayobject.cpp} (88%) diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index fe490461da0..f868e06d27c 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -52,6 +52,8 @@ typedef struct RayCounter RayCounter; struct DerivedMesh; struct Mesh; +struct VlakRen; +struct ObjectInstanceRen; int RE_rayobject_raycast(RayObject *r, Isect *i); void RE_rayobject_add (RayObject *r, RayObject *); @@ -93,14 +95,28 @@ typedef struct RayFace } RayFace; #define RE_rayface_isQuad(a) ((a)->quad) -struct VlakRen; -struct ObjectInstanceRen; RayObject* RE_rayface_from_vlak(RayFace *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr); RayObject* RE_rayface_from_coords(RayFace *rayface, void *ob, void *face, float *co1, float *co2, float *co3, float *co4); +/* + * This ray object represents faces directly from a given VlakRen structure. + * Thus allowing to save memory, but making code triangle intersection dependant on render structures + */ +typedef struct VlakPrimitive +{ + struct ObjectInstanceRen *ob; + struct VlakRen *face; +} VlakPrimitive; +RayObject* RE_vlakprimitive_from_vlak(VlakPrimitive *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr); + + + +/* + * Raytrace hints + */ typedef struct LCTSHint LCTSHint; struct LCTSHint { diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index dbd68fe8b8b..337f9ca3fdd 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -57,17 +57,18 @@ extern "C" { In order to allow a mixture of RayFace+RayObjects, all RayObjects must be 4byte aligned, allowing us to use the - 2 least significant bits (with the mask 0x02) to define the + 2 least significant bits (with the mask 0x03) to define the type of RayObject. - This leads to 4 possible types of RayObject, but at the moment - only 2 are used: + This leads to 4 possible types of RayObject: - addr&2 - type of object + addr&3 - type of object 0 Self (reserved for each structure) - 1 RayFace + 1 RayFace (tri/quad primitive) 2 RayObject (generic with API callbacks) - 3 RayObject_Vlak + 3 VlakPrimitive + (vlak primitive - to be used when we have a vlak describing the data + eg.: on render code) 0 means it's reserved and has it own meaning inside each ray acceleration structure (this way each structure can use the allign offset to determine if a node represents a @@ -83,25 +84,15 @@ extern "C" { /* used to unalign a given ray object */ #define RE_rayobject_unalignRayFace(o) ((RayObject*)(((intptr_t)o)|1)) #define RE_rayobject_unalignRayAPI(o) ((RayObject*)(((intptr_t)o)|2)) -#define RE_rayobject_unalignRayVlak(o) ((RayObject*)(((intptr_t)o)|3)) +#define RE_rayobject_unalignVlakPrimitive(o) ((RayObject*)(((intptr_t)o)|3)) /* used to test the type of ray object */ #define RE_rayobject_isAligned(o) ((((intptr_t)o)&3) == 0) #define RE_rayobject_isRayFace(o) ((((intptr_t)o)&3) == 1) #define RE_rayobject_isRayAPI(o) ((((intptr_t)o)&3) == 2) -#define RE_rayobject_isRayVlak(o) ((((intptr_t)o)&3) == 3) +#define RE_rayobject_isVlakPrimitive(o) ((((intptr_t)o)&3) == 3) -/* - * This ray object represents faces directly from a given VlakRen structure. - * Thus allowing to save memory, but making code dependant on render structures -typedef struct RayVlak -{ - struct ObjectInstanceRen *ob; - struct VlakRen *face; -} RayVlak; - */ - /* * This rayobject represents a generic object. With it's own callbacks for raytrace operations. * It's suitable to implement things like LOD. diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 67c69259213..8c106f60e1d 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -172,6 +172,7 @@ struct Render /* octree tables and variables for raytrace */ struct RayObject *raytree; struct RayFace *rayfaces; + struct VlakPrimitive *rayprimitives; float maxdist; /* needed for keeping an incorrect behaviour of SUN and HEMI lights (avoid breaking old scenes) */ /* occlusion tree */ @@ -289,6 +290,7 @@ typedef struct ObjectRen { /* used on makeraytree */ struct RayObject *raytree; struct RayFace *rayfaces; + struct VlakPrimitive *rayprimitives; struct ObjectInstanceRen *rayobi; } ObjectRen; @@ -313,6 +315,7 @@ typedef struct ObjectInstanceRen { /* used on makeraytree */ struct RayObject *raytree; + int transform_primitives; } ObjectInstanceRen; diff --git a/source/blender/render/intern/source/rayobject.c b/source/blender/render/intern/raytrace/rayobject.cpp similarity index 88% rename from source/blender/render/intern/source/rayobject.c rename to source/blender/render/intern/raytrace/rayobject.cpp index df457a37123..dc5128b2d1f 100644 --- a/source/blender/render/intern/source/rayobject.c +++ b/source/blender/render/intern/raytrace/rayobject.cpp @@ -30,6 +30,7 @@ #include "BKE_utildefines.h" #include "BLI_arithb.h" +#include "DNA_material_types.h" #include "RE_raytrace.h" #include "render_types.h" @@ -141,7 +142,6 @@ static int intersection2(VlakRen *face, float r0, float r1, float r2, float rx1, return 0; } -#include "DNA_material_types.h" static int vlr_check_intersect(Isect *is, ObjectInstanceRen *obi, VlakRen *vlr) { /* for baking selected to active non-traceable materials might still @@ -178,7 +178,7 @@ static int rayface_check_cullface(RayFace *face, Isect *is) /* ray - triangle or quad intersection */ /* this function shall only modify Isect if it detects an hit */ -static int intersect_rayface(RayFace *face, Isect *is) +static int intersect_rayface(RayObject *hit_obj, RayFace *face, Isect *is) { float co1[3],co2[3],co3[3],co4[3]; float x0,x1,x2,t00,t01,t02,t10,t11,t12,t20,t21,t22,r0,r1,r2; @@ -301,8 +301,8 @@ static int intersect_rayface(RayFace *face, Isect *is) { if(labda < 0.1f && is->orig.ob == face->ob) { - VlakRen * a = is->orig.face; - VlakRen * b = face->face; + VlakRen * a = (VlakRen*)is->orig.face; + VlakRen * b = (VlakRen*)face->face; /* so there's a shared edge or vertex, let's intersect ray with face itself, if that's true we can safely return 1, otherwise we assume @@ -327,7 +327,7 @@ static int intersect_rayface(RayFace *face, Isect *is) is->hit.ob = face->ob; is->hit.face = face->face; #ifdef RT_USE_LAST_HIT - is->last_hit = (RayObject*) RE_rayobject_unalignRayFace(face); + is->last_hit = hit_obj; #endif return 1; } @@ -361,6 +361,14 @@ RayObject* RE_rayface_from_coords(RayFace *rayface, void *ob, void *face, float return RE_rayobject_unalignRayFace(rayface); } +RayObject* RE_vlakprimitive_from_vlak(VlakPrimitive *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr) +{ + face->ob = obi; + face->face = vlr; + return RE_rayobject_unalignVlakPrimitive(face); +} + + int RE_rayobject_raycast(RayObject *r, Isect *isec) { int i; @@ -416,7 +424,25 @@ int RE_rayobject_intersect(RayObject *r, Isect *i) { if(RE_rayobject_isRayFace(r)) { - return intersect_rayface( (RayFace*) RE_rayobject_align(r), i); + return intersect_rayface(r, (RayFace*) RE_rayobject_align(r), i); + } + else if(RE_rayobject_isVlakPrimitive(r)) + { + //TODO optimize (useless copy to RayFace to avoid duplicate code) + VlakPrimitive *face = (VlakPrimitive*) RE_rayobject_align(r); + RayFace nface; + RE_rayface_from_vlak(&nface, face->ob, face->face); + + if(face->ob->transform_primitives) + { + Mat4MulVecfl(face->ob->mat, nface.v1); + Mat4MulVecfl(face->ob->mat, nface.v2); + Mat4MulVecfl(face->ob->mat, nface.v3); + if(RE_rayface_isQuad(&nface)) + Mat4MulVecfl(face->ob->mat, nface.v4); + } + + return intersect_rayface(r, &nface, i); } else if(RE_rayobject_isRayAPI(r)) { @@ -455,6 +481,16 @@ void RE_rayobject_merge_bb(RayObject *r, float *min, float *max) DO_MINMAX( face->v3, min, max ); if(RE_rayface_isQuad(face)) DO_MINMAX( face->v4, min, max ); } + else if(RE_rayobject_isVlakPrimitive(r)) + { + VlakPrimitive *face = (VlakPrimitive*) RE_rayobject_align(r); + VlakRen *vlr = face->face; + + DO_MINMAX( vlr->v1->co, min, max ); + DO_MINMAX( vlr->v2->co, min, max ); + DO_MINMAX( vlr->v3->co, min, max ); + if(vlr->v4) DO_MINMAX( vlr->v4->co, min, max ); + } else if(RE_rayobject_isRayAPI(r)) { r = RE_rayobject_align( r ); @@ -465,7 +501,7 @@ void RE_rayobject_merge_bb(RayObject *r, float *min, float *max) float RE_rayobject_cost(RayObject *r) { - if(RE_rayobject_isRayFace(r)) + if(RE_rayobject_isRayFace(r) || RE_rayobject_isVlakPrimitive(r)) { return 1.0; } @@ -479,7 +515,7 @@ float RE_rayobject_cost(RayObject *r) void RE_rayobject_hint_bb(RayObject *r, RayHint *hint, float *min, float *max) { - if(RE_rayobject_isRayFace(r)) + if(RE_rayobject_isRayFace(r) || RE_rayobject_isVlakPrimitive(r)) { return; } diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 8cb11d11762..18278d90e72 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -61,6 +61,8 @@ #include "rayobject.h" #include "raycounter.h" + +#define USE_VLAK_PRIMITIVES 1 #define RAY_TRA 1 #define RAY_TRAFLIP 2 @@ -133,6 +135,11 @@ void freeraytree(Render *re) MEM_freeN(re->rayfaces); re->rayfaces = NULL; } + if(re->rayprimitives) + { + MEM_freeN(re->rayprimitives); + re->rayprimitives = NULL; + } for(obi=re->instancetable.first; obi; obi=obi->next) { @@ -203,6 +210,7 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) { RayObject *raytree; RayFace *face; + VlakPrimitive *vlakprimitive; int v; //Count faces @@ -217,7 +225,11 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) //Create Ray cast accelaration structure raytree = obr->raytree = RE_rayobject_create( re->r.raytrace_tree_type, faces ); - face = obr->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "ObjectRen faces"); + if(USE_VLAK_PRIMITIVES) + vlakprimitive = obr->rayprimitives = (VlakPrimitive*)MEM_callocN(faces*sizeof(VlakPrimitive), "ObjectRen primitives"); + else + face = obr->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "ObjectRen faces"); + obr->rayobi = obi; for(v=0;vtotvlak;v++) @@ -225,17 +237,26 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); if(is_raytraceable_vlr(re, vlr)) { - RE_rayface_from_vlak( face, obi, vlr ); - RE_rayobject_add( raytree, RE_rayobject_unalignRayFace(face) ); - face++; + if(USE_VLAK_PRIMITIVES) + { + RE_rayobject_add( raytree, RE_vlakprimitive_from_vlak( vlakprimitive, obi, vlr ) ); + vlakprimitive++; + } + else + { + RE_rayface_from_vlak( face, obi, vlr ); + RE_rayobject_add( raytree, RE_rayobject_unalignRayFace(face) ); + face++; + } } } RE_rayobject_done( raytree ); } - if(obi->flag & R_TRANSFORMED) + if((obi->flag & R_TRANSFORMED) && obi->raytree == NULL) { + obi->transform_primitives = 0; obi->raytree = RE_rayobject_instance_create( obr->raytree, obi->mat, obi, obi->obr->rayobi ); } @@ -271,7 +292,8 @@ static void makeraytree_single(Render *re) ObjectInstanceRen *obi; RayObject *raytree; RayFace *face; - int faces = 0, obs = 0; + VlakPrimitive *vlakprimitive; + int faces = 0, obs = 0, special = 0; for(obi=re->instancetable.first; obi; obi=obi->next) if(is_raytraceable(re, obi)) @@ -282,7 +304,7 @@ static void makeraytree_single(Render *re) if(has_special_rayobject(re, obi)) { - faces++; + special++; } else { @@ -296,9 +318,16 @@ static void makeraytree_single(Render *re) } //Create raytree - raytree = re->raytree = RE_rayobject_create( re->r.raytrace_tree_type, faces ); + raytree = re->raytree = RE_rayobject_create( re->r.raytrace_tree_type, faces+special ); - face = re->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces"); + if(USE_VLAK_PRIMITIVES) + { + vlakprimitive = re->rayprimitives = (VlakPrimitive*)MEM_callocN(faces*sizeof(VlakPrimitive), "Raytrace vlak-primitives"); + } + else + { + face = re->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces"); + } for(obi=re->instancetable.first; obi; obi=obi->next) if(is_raytraceable(re, obi)) @@ -312,28 +341,46 @@ static void makeraytree_single(Render *re) { int v; ObjectRen *obr = obi->obr; + + if(obi->flag & R_TRANSFORMED) + { + obi->transform_primitives = 1; + } for(v=0;vtotvlak;v++) { VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); if(is_raytraceable_vlr(re, vlr)) { - RE_rayface_from_vlak(face, obi, vlr); - if((obi->flag & R_TRANSFORMED)) + if(USE_VLAK_PRIMITIVES) { - Mat4MulVecfl(obi->mat, face->v1); - Mat4MulVecfl(obi->mat, face->v2); - Mat4MulVecfl(obi->mat, face->v3); - if(RE_rayface_isQuad(face)) - Mat4MulVecfl(obi->mat, face->v4); + RayObject *obj = RE_vlakprimitive_from_vlak( vlakprimitive, obi, vlr ); + RE_rayobject_add( raytree, obj ); + vlakprimitive++; } + else + { + RE_rayface_from_vlak(face, obi, vlr); + if((obi->flag & R_TRANSFORMED)) + { + Mat4MulVecfl(obi->mat, face->v1); + Mat4MulVecfl(obi->mat, face->v2); + Mat4MulVecfl(obi->mat, face->v3); + if(RE_rayface_isQuad(face)) + Mat4MulVecfl(obi->mat, face->v4); + } - RE_rayobject_add( raytree, RE_rayobject_unalignRayFace(face) ); - face++; + RE_rayobject_add( raytree, RE_rayobject_unalignRayFace(face) ); + face++; + } } } } } + + re->i.infostr= "Raytree.. building"; + re->stats_draw(re->sdh, &re->i); + RE_rayobject_done( raytree ); } @@ -342,7 +389,7 @@ void makeraytree(Render *re) float min[3], max[3], sub[3]; int i; - re->i.infostr= "Make raytree"; + re->i.infostr= "Raytree.. preparing"; re->stats_draw(re->sdh, &re->i); BENCH(makeraytree_single(re), tree_build); @@ -359,6 +406,7 @@ void makeraytree(Render *re) re->maxdist = sqrt( sub[0]*sub[0] + sub[1]*sub[1] + sub[2]*sub[2] ); re->i.infostr= "Raytree finished"; + re->stats_draw(re->sdh, &re->i); } void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr) diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 5f21a0e2e1a..784e42685b7 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -879,6 +879,11 @@ void free_renderdata_tables(Render *re) MEM_freeN(obr->rayfaces); obr->rayfaces = NULL; } + if(obr->rayprimitives) + { + MEM_freeN(obr->rayprimitives); + obr->rayprimitives = NULL; + } if(obr->raytree) { RE_rayobject_free(obr->raytree); From 82198721d6996d03df5d384fde2c155e998bc56e Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 28 Sep 2009 10:25:12 +0000 Subject: [PATCH 093/138] Raycounters fix --- .../blender/render/extern/include/RE_raytrace.h | 15 +++++++++++++-- source/blender/render/intern/include/raycounter.h | 11 ----------- .../blender/render/intern/raytrace/rayobject.cpp | 3 ++- source/blender/render/intern/source/shadeinput.c | 2 +- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index f868e06d27c..edf343b6be7 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -35,20 +35,31 @@ extern "C" { #endif -//#define RE_RAYCOUNTER /* enable counters per ray, usefull for measuring raytrace structures performance */ +#define RE_RAYCOUNTER /* enable counters per ray, usefull for measuring raytrace structures performance */ #define RE_RAY_LCTS_MAX_SIZE 256 #define RT_USE_LAST_HIT /* last shadow hit is reused before raycasting on whole tree */ //#define RT_USE_HINT /* last hit object is reused before raycasting on whole tree */ +#ifdef RE_RAYCOUNTER +typedef struct RayCounter RayCounter; +struct RayCounter +{ + + struct + { + unsigned long long test, hit; + + } faces, bb, simd_bb, raycast, raytrace_hint, rayshadow_last_hit; +}; +#endif /* Internals about raycasting structures can be found on intern/raytree.h */ typedef struct RayObject RayObject; typedef struct Isect Isect; typedef struct RayHint RayHint; typedef struct RayTraceHint RayTraceHint; -typedef struct RayCounter RayCounter; struct DerivedMesh; struct Mesh; diff --git a/source/blender/render/intern/include/raycounter.h b/source/blender/render/intern/include/raycounter.h index 06579b366ee..dea6d63d001 100644 --- a/source/blender/render/intern/include/raycounter.h +++ b/source/blender/render/intern/include/raycounter.h @@ -34,17 +34,6 @@ #ifdef RE_RAYCOUNTER -typedef struct RayCounter RayCounter; -struct RayCounter -{ - - struct - { - unsigned long long test, hit; - - } faces, bb, simd_bb, raycast, raytrace_hint, rayshadow_last_hit; -}; - /* #define RE_RC_INIT(isec, shi) (isec).count = re_rc_counter+(shi).thread */ #define RE_RC_INIT(isec, shi) (isec).raycounter = &((shi).raycounter) void RE_RC_INFO (RayCounter *rc); diff --git a/source/blender/render/intern/raytrace/rayobject.cpp b/source/blender/render/intern/raytrace/rayobject.cpp index dc5128b2d1f..c32f61e8f0a 100644 --- a/source/blender/render/intern/raytrace/rayobject.cpp +++ b/source/blender/render/intern/raytrace/rayobject.cpp @@ -189,6 +189,7 @@ static int intersect_rayface(RayObject *hit_obj, RayFace *face, Isect *is) if(is->orig.ob == face->ob && is->orig.face == face->face) return 0; +/* if(is->skip & RE_SKIP_VLR_RENDER_CHECK) { if(vlr_check_intersect(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face ) == 0) @@ -204,7 +205,7 @@ static int intersect_rayface(RayObject *hit_obj, RayFace *face, Isect *is) if(rayface_check_cullface(face, is) == 0) return 0; } - +*/ RE_RC_COUNT(is->raycounter->faces.test); //Load coords diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index 0d3c5772d8a..e5684e2ebe9 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -243,9 +243,9 @@ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr) shr->rayhits[1] = (float)shi->raycounter.bb.hit; shr->rayhits[2] = 0.0; shr->rayhits[3] = 1.0; - RE_RC_MERGE(&re_rc_counter[shi->thread], &shi->raycounter); } */ + RE_RC_MERGE(&re_rc_counter[shi->thread], &shi->raycounter); } /* **************************************************************************** */ From 8da55763b541075dae4b1f7713c43af2b609e332 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Thu, 1 Oct 2009 18:30:59 +0000 Subject: [PATCH 094/138] *Updated UI options and added UI options to: control whether instances are used or not control whether vertexs are stored localy or not *Removed unsused code --- release/scripts/ui/buttons_scene.py | 7 +- source/blender/makesdna/DNA_scene_types.h | 27 +- source/blender/makesrna/intern/rna_scene.c | 14 +- source/blender/render/SConscript | 4 +- .../render/extern/include/RE_raytrace.h | 4 +- .../render/intern/raytrace/rayobject.cpp | 10 +- .../render/intern/raytrace/rayobject_bih.cpp | 248 ------------------ .../render/intern/raytrace/rayobject_bvh.cpp | 233 ---------------- .../render/intern/raytrace/rayobject_qbvh.cpp | 31 +-- .../intern/raytrace/rayobject_svbvh.cpp | 38 ++- .../render/intern/raytrace/rayobject_vbvh.cpp | 44 +++- .../render/intern/source/rayobject_blibvh.c | 15 +- .../render/intern/source/rayobject_octree.c | 17 +- .../blender/render/intern/source/rayshade.c | 46 ++-- 14 files changed, 169 insertions(+), 569 deletions(-) delete mode 100644 source/blender/render/intern/raytrace/rayobject_bih.cpp delete mode 100644 source/blender/render/intern/raytrace/rayobject_bvh.cpp diff --git a/release/scripts/ui/buttons_scene.py b/release/scripts/ui/buttons_scene.py index 88947aac86c..10a0efae33d 100644 --- a/release/scripts/ui/buttons_scene.py +++ b/release/scripts/ui/buttons_scene.py @@ -171,8 +171,11 @@ class SCENE_PT_performance(RenderButtonsPanel): sub.itemR(rd, "free_image_textures") sub = col.column() sub.active = rd.render_raytracing - sub.itemL(text="Ray Tracing Octree:") - sub.itemR(rd, "octree_resolution", text="") + sub.itemL(text="Acceleration structure:") + sub.itemR(rd, "raytrace_structure", text="") + sub.itemR(rd, "use_instances", text="Instance support") + sub.itemR(rd, "use_local_coords", text="Local coords") + sub.itemR(rd, "octree_resolution", text="Octree resolution") class SCENE_PT_post_processing(RenderButtonsPanel): __label__ = "Post Processing" diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 09e9f599d03..27ee5d47133 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -242,12 +242,23 @@ typedef struct RenderData { */ int mode; - /* render engine (deprecated), octree resolution */ - short renderer, ocres; - short raystructure; - short raytrace_tree_type; - short pad4[2]; + /** + * Flags for raytrace settings. Use bit-masking to access the settings. + */ + int raytrace_options; + + /** + * Raytrace acceleration structure + */ + short raytrace_structure; + /* renderer (deprecated) */ + short renderer; + + /* octree resolution */ + short ocres; + short pad4; + /** * What to do with the sky/background. Picks sky/premul/key * blending for the background @@ -260,6 +271,7 @@ typedef struct RenderData { short osa; short frs_sec, edgeint; + /* safety, border and display rect */ rctf safety, border; @@ -808,7 +820,10 @@ typedef struct Scene { #define R_RAYSTRUCTURE_VBVH 3 #define R_RAYSTRUCTURE_SIMD_SVBVH 4 /* needs SIMD */ #define R_RAYSTRUCTURE_SIMD_QBVH 5 /* needs SIMD */ -#define R_RAYSTRUCTURE_BIH 6 + +/* raytrace_options */ +#define R_RAYTRACE_USE_LOCAL_COORDS 0x0001 +#define R_RAYTRACE_USE_INSTANCES 0x0002 /* scemode (int now) */ #define R_DOSEQ 0x0001 diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index ffe07d4de62..267e29d7018 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1185,7 +1185,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna) {R_RAYSTRUCTURE_VBVH, "R_RAYSTRUCTURE_VBVH", 0, "vBVH", ""}, {R_RAYSTRUCTURE_SIMD_SVBVH, "R_RAYSTRUCTURE_SIMD_SVBVH", 0, "SIMD SVBVH", "Requires SIMD"}, {R_RAYSTRUCTURE_SIMD_QBVH, "R_RAYSTRUCTURE_SIMD_QBVH", 0, "SIMD QBVH", "Requires SIMD"}, - {R_RAYSTRUCTURE_BIH, "R_RAYSTRUCTURE_BIH", 0, "BIH", ""}, {0, NULL, 0, NULL, NULL} }; @@ -1618,11 +1617,22 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); prop= RNA_def_property(srna, "raytrace_structure", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "raystructure"); + RNA_def_property_enum_sdna(prop, NULL, "raytrace_structure"); RNA_def_property_enum_items(prop, raytrace_structure_items); RNA_def_property_ui_text(prop, "Raytrace Acceleration Structure", "Type of raytrace accelerator structure."); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + prop= RNA_def_property(srna, "use_instances", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "raytrace_options", R_RAYTRACE_USE_INSTANCES); + RNA_def_property_ui_text(prop, "Use Instances", "Instance support leads to effective memory reduction when using duplicates."); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + + prop= RNA_def_property(srna, "use_local_coords", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "raytrace_options", R_RAYTRACE_USE_LOCAL_COORDS); + RNA_def_property_ui_text(prop, "Use Local Coords", "Vertex coordinates are stored localy on each primitive. Increases memory usage, but may have impact on speed."); + RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); + + prop= RNA_def_property(srna, "antialiasing", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_OSA); RNA_def_property_ui_text(prop, "Anti-Aliasing", "Render and combine multiple samples per pixel to prevent jagged edges."); diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript index a15dada1bec..4ad7694cbbf 100644 --- a/source/blender/render/SConscript +++ b/source/blender/render/SConscript @@ -1,8 +1,8 @@ #!/usr/bin/python Import ('env') -cflags = ['-msse2','-mfpmath=sse'] -cxxflags = ['-msse2','-mfpmath=sse'] +cflags = ['-O2','-msse2','-mfpmath=sse'] +cxxflags = ['-O2','-msse2','-mfpmath=sse'] sources = env.Glob('intern/source/*.c') raysources = env.Glob('intern/raytrace/*.cpp') diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index edf343b6be7..6a171a98f12 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -85,11 +85,9 @@ RayObject* RE_rayobject_octree_create(int ocres, int size); RayObject* RE_rayobject_instance_create(RayObject *target, float transform[][4], void *ob, void *target_ob); RayObject* RE_rayobject_blibvh_create(int size); /* BLI_kdopbvh.c */ -RayObject* RE_rayobject_bvh_create(int size); /* raytrace/rayobject_bvh.c */ RayObject* RE_rayobject_vbvh_create(int size); /* raytrace/rayobject_vbvh.c */ -RayObject* RE_rayobject_qbvh_create(int size); /* raytrace/rayobject_qbvh.c */ RayObject* RE_rayobject_svbvh_create(int size); /* raytrace/rayobject_svbvh.c */ -RayObject* RE_rayobject_bih_create(int size); /* rayobject_bih.c */ +RayObject* RE_rayobject_qbvh_create(int size); /* raytrace/rayobject_qbvh.c */ /* diff --git a/source/blender/render/intern/raytrace/rayobject.cpp b/source/blender/render/intern/raytrace/rayobject.cpp index c32f61e8f0a..34faa2951ce 100644 --- a/source/blender/render/intern/raytrace/rayobject.cpp +++ b/source/blender/render/intern/raytrace/rayobject.cpp @@ -142,7 +142,7 @@ static int intersection2(VlakRen *face, float r0, float r1, float r2, float rx1, return 0; } -static int vlr_check_intersect(Isect *is, ObjectInstanceRen *obi, VlakRen *vlr) +static inline int vlr_check_intersect(Isect *is, ObjectInstanceRen *obi, VlakRen *vlr) { /* for baking selected to active non-traceable materials might still * be in the raytree */ @@ -156,7 +156,7 @@ static int vlr_check_intersect(Isect *is, ObjectInstanceRen *obi, VlakRen *vlr) return (is->lay & obi->lay); } -static int vlr_check_intersect_solid(Isect *is, ObjectInstanceRen* obi, VlakRen *vlr) +static inline int vlr_check_intersect_solid(Isect *is, ObjectInstanceRen* obi, VlakRen *vlr) { /* solid material types only */ if (vlr->mat->material_type == MA_TYPE_SURFACE) @@ -165,7 +165,7 @@ static int vlr_check_intersect_solid(Isect *is, ObjectInstanceRen* obi, VlakRen return 0; } -static int rayface_check_cullface(RayFace *face, Isect *is) +static inline int rayface_check_cullface(RayFace *face, Isect *is) { float nor[3]; @@ -189,7 +189,7 @@ static int intersect_rayface(RayObject *hit_obj, RayFace *face, Isect *is) if(is->orig.ob == face->ob && is->orig.face == face->face) return 0; -/* + if(is->skip & RE_SKIP_VLR_RENDER_CHECK) { if(vlr_check_intersect(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face ) == 0) @@ -205,7 +205,7 @@ static int intersect_rayface(RayObject *hit_obj, RayFace *face, Isect *is) if(rayface_check_cullface(face, is) == 0) return 0; } -*/ + RE_RC_COUNT(is->raycounter->faces.test); //Load coords diff --git a/source/blender/render/intern/raytrace/rayobject_bih.cpp b/source/blender/render/intern/raytrace/rayobject_bih.cpp deleted file mode 100644 index efbf70616b7..00000000000 --- a/source/blender/render/intern/raytrace/rayobject_bih.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/** - * $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) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#include -#include - -#include "MEM_guardedalloc.h" -#include "BKE_utildefines.h" -#include "BLI_arithb.h" -#include "RE_raytrace.h" -#include "rayobject_rtbuild.h" -#include "rayobject.h" - -#define BIH_NCHILDS 4 -typedef struct BIHTree BIHTree; - -static int bih_intersect(BIHTree *obj, Isect *isec); -static void bih_add(BIHTree *o, RayObject *ob); -static void bih_done(BIHTree *o); -static void bih_free(BIHTree *o); -static void bih_bb(BIHTree *o, float *min, float *max); - -static RayObjectAPI bih_api = -{ - (RE_rayobject_raycast_callback) bih_intersect, - (RE_rayobject_add_callback) bih_add, - (RE_rayobject_done_callback) bih_done, - (RE_rayobject_free_callback) bih_free, - (RE_rayobject_merge_bb_callback)bih_bb -}; - -typedef struct BIHNode BIHNode; -struct BIHNode -{ - BIHNode *child[BIH_NCHILDS]; - float bi[BIH_NCHILDS][2]; - int split_axis; -}; - -struct BIHTree -{ - RayObject rayobj; - - BIHNode *root; - - BIHNode *node_alloc, *node_next; - RTBuilder *builder; - - float bb[2][3]; -}; - - -RayObject *RE_rayobject_bih_create(int size) -{ - BIHTree *obj= (BIHTree*)MEM_callocN(sizeof(BIHTree), "BIHTree"); - assert( RE_rayobject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ - - obj->rayobj.api = &bih_api; - obj->root = NULL; - - obj->node_alloc = obj->node_next = NULL; - obj->builder = rtbuild_create( size ); - - return RE_rayobject_unalignRayAPI((RayObject*) obj); -} - -static void bih_free(BIHTree *obj) -{ - if(obj->builder) - rtbuild_free(obj->builder); - - if(obj->node_alloc) - MEM_freeN(obj->node_alloc); - - MEM_freeN(obj); -} - -static void bih_bb(BIHTree *obj, float *min, float *max) -{ - DO_MIN(obj->bb[0], min); - DO_MAX(obj->bb[1], max); -} - -/* - * Tree transverse - */ -static int dfs_raycast(const BIHNode *const node, Isect *isec, float tmin, float tmax) -{ - int i; - int hit = 0; - - const int *const offset = isec->bv_index + node->split_axis*2; - - //TODO diving heuristic - for(i=0; ibi[i][offset[0]] - isec->start[node->split_axis]) * isec->idot_axis[node->split_axis]; - float t2 = (node->bi[i][offset[1]] - isec->start[node->split_axis]) * isec->idot_axis[node->split_axis]; - - if(t1 < tmin) t1 = tmin; //t1 = MAX2(t1, tmin); - if(t2 > tmax) t2 = tmax; //t2 = MIN2(t2, tmax); - - if(t1 <= t2) - { - if(RE_rayobject_isAligned(node->child[i])) - { - if(node->child[i] == 0) break; - - hit |= dfs_raycast(node->child[i], isec, t1, t2); - if(hit && isec->mode == RE_RAY_SHADOW) return hit; - } - else - { - hit |= RE_rayobject_intersect( (RayObject*)node->child[i], isec); - if(hit && isec->mode == RE_RAY_SHADOW) return hit; - } - - if(tmax > isec->labda) - tmax = isec->labda; - } - } - - return hit; -} - -static int bih_intersect(BIHTree *obj, Isect *isec) -{ - if(RE_rayobject_isAligned(obj->root)) - return dfs_raycast(obj->root, isec, 0, isec->labda); - else - return RE_rayobject_intersect( (RayObject*)obj->root, isec); -} - - -/* - * Builds a BIH tree from builder object - */ -static void bih_add(BIHTree *obj, RayObject *ob) -{ - rtbuild_add( obj->builder, ob ); -} - -static BIHNode *bih_new_node(BIHTree *tree, int nid) -{ - BIHNode *node = tree->node_alloc + nid - 1; - assert(RE_rayobject_isAligned(node)); - if(node+1 > tree->node_next) - tree->node_next = node+1; - - return node; -} - -static int child_id(int pid, int nchild) -{ - //N child of node A = A * K + (2 - K) + N, (0 <= N < K) - return pid*BIH_NCHILDS+(2-BIH_NCHILDS)+nchild; -} - -static BIHNode *bih_rearrange(BIHTree *tree, RTBuilder *builder, int nid, float *bb) -{ - if(rtbuild_size(builder) == 1) - { - RayObject *child = rtbuild_get_primitive( builder, 0 ); - assert(!RE_rayobject_isAligned(child)); - - INIT_MINMAX(bb, bb+3); - RE_rayobject_merge_bb( (RayObject*)child, bb, bb+3); - - return (BIHNode*)child; - } - else - { - int i; - int nc = rtbuild_mean_split_largest_axis(builder, BIH_NCHILDS); - RTBuilder tmp; - - BIHNode *parent = bih_new_node(tree, nid); - - INIT_MINMAX(bb, bb+3); - parent->split_axis = builder->split_axis; - for(i=0; ichild[i] = bih_rearrange( tree, rtbuild_get_child(builder, i, &tmp), child_id(nid,i), cbb ); - - parent->bi[i][0] = cbb[parent->split_axis]; - parent->bi[i][1] = cbb[parent->split_axis+3]; - - DO_MIN(cbb , bb); - DO_MAX(cbb+3, bb+3); - } - for(; ibi[i][0] = 1.0; - parent->bi[i][1] = -1.0; - parent->child[i] = 0; - } - - return parent; - } -} - -static void bih_done(BIHTree *obj) -{ - int needed_nodes; - assert(obj->root == NULL && obj->node_alloc == NULL && obj->builder); - - //TODO exact calculate needed nodes - needed_nodes = (rtbuild_size(obj->builder)+1)*2; - assert(needed_nodes > 0); - - obj->node_alloc = (BIHNode*)MEM_mallocN( sizeof(BIHNode)*needed_nodes, "BIHTree.Nodes"); - obj->node_next = obj->node_alloc; - - obj->root = bih_rearrange( obj, obj->builder, 1, (float*)obj->bb ); - - rtbuild_free( obj->builder ); - obj->builder = NULL; - - assert(obj->node_alloc+needed_nodes >= obj->node_next); -} - diff --git a/source/blender/render/intern/raytrace/rayobject_bvh.cpp b/source/blender/render/intern/raytrace/rayobject_bvh.cpp deleted file mode 100644 index a7e96f6d3fc..00000000000 --- a/source/blender/render/intern/raytrace/rayobject_bvh.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/** - * $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) 2009 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): André Pinto. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#include - -#include "RE_raytrace.h" -#include "rayobject_rtbuild.h" -#include "rayobject.h" -#include "MEM_guardedalloc.h" -#include "BKE_utildefines.h" -#include "BLI_arithb.h" -#include "BLI_memarena.h" -#include "bvh.h" - -#define BVH_NCHILDS 2 -#define RAY_BB_TEST_COST (0.2f) -#define DFS_STACK_SIZE 64 -#define DYNAMIC_ALLOC - -//#define rtbuild_split rtbuild_mean_split_largest_axis /* objects mean split on the longest axis, childs BB are allowed to overlap */ -//#define rtbuild_split rtbuild_median_split_largest_axis /* space median split on the longest axis, childs BB are allowed to overlap */ -#define rtbuild_split rtbuild_heuristic_object_split /* split objects using heuristic */ - -struct BVHNode -{ - BVHNode *child[BVH_NCHILDS]; - float bb[6]; - int split_axis; -}; - -struct BVHTree -{ - RayObject rayobj; - - BVHNode *root; - - MemArena *node_arena; - - float cost; - RTBuilder *builder; -}; - -/* - * Push nodes (used on dfs) - */ -template -inline static void bvh_node_push_childs(Node *node, Isect *isec, Node **stack, int &stack_pos) -{ - //push nodes in reverse visit order - if(isec->idot_axis[node->split_axis] < 0.0f) - { - int i; - for(i=0; ichild[i] == 0) - break; - else - stack[stack_pos++] = node->child[i]; - } - else - { - int i; - for(i=BVH_NCHILDS-1; i>=0; i--) - if(node->child[i] != 0) - stack[stack_pos++] = node->child[i]; - } -} - -/* - * BVH done - */ -static BVHNode *bvh_new_node(BVHTree *tree, int nid) -{ - BVHNode *node = (BVHNode*)BLI_memarena_alloc(tree->node_arena, sizeof(BVHNode)); - return node; -} - -static int child_id(int pid, int nchild) -{ - //N child of node A = A * K + (2 - K) + N, (0 <= N < K) - return pid*BVH_NCHILDS+(2-BVH_NCHILDS)+nchild; -} - - -static BVHNode *bvh_rearrange(BVHTree *tree, RTBuilder *builder, int nid, float *cost) -{ - *cost = 0; - if(rtbuild_size(builder) == 0) - return 0; - - if(rtbuild_size(builder) == 1) - { - RayObject *child = rtbuild_get_primitive( builder, 0 ); - - if(RE_rayobject_isRayFace(child)) - { - int i; - BVHNode *parent = bvh_new_node(tree, nid); - parent->split_axis = 0; - - INIT_MINMAX(parent->bb, parent->bb+3); - - for(i=0; i<1; i++) - { - parent->child[i] = (BVHNode*)rtbuild_get_primitive( builder, i ); - bvh_node_merge_bb(parent->child[i], parent->bb, parent->bb+3); - } - for(; ichild[i] = 0; - - *cost = RE_rayobject_cost(child)+RAY_BB_TEST_COST; - return parent; - } - else - { - assert(!RE_rayobject_isAligned(child)); - //Its a sub-raytrace structure, assume it has it own raycast - //methods and adding a Bounding Box arround is unnecessary - - *cost = RE_rayobject_cost(child); - return (BVHNode*)child; - } - } - else - { - int i; - RTBuilder tmp; - BVHNode *parent = bvh_new_node(tree, nid); - int nc = rtbuild_split(builder, BVH_NCHILDS); - - - INIT_MINMAX(parent->bb, parent->bb+3); - parent->split_axis = builder->split_axis; - for(i=0; ichild[i] = bvh_rearrange( tree, rtbuild_get_child(builder, i, &tmp), child_id(nid,i), &tcost ); - - INIT_MINMAX(cbb, cbb+3); - bvh_node_merge_bb(parent->child[i], cbb, cbb+3); - DO_MIN(cbb, parent->bb); - DO_MAX(cbb+3, parent->bb+3); - - *cost += tcost*bb_area(cbb, cbb+3); - } - for(; ichild[i] = 0; - - *cost /= bb_area(parent->bb, parent->bb+3); - *cost += nc*RAY_BB_TEST_COST; - return parent; - } - - assert(false); -} - -template<> -void bvh_done(BVHTree *obj) -{ - int needed_nodes = (rtbuild_size(obj->builder)+1)*2; - if(needed_nodes > BLI_MEMARENA_STD_BUFSIZE) - needed_nodes = BLI_MEMARENA_STD_BUFSIZE; - - obj->node_arena = BLI_memarena_new(needed_nodes); - BLI_memarena_use_malloc(obj->node_arena); - - - obj->root = bvh_rearrange( obj, obj->builder, 1, &obj->cost ); - - rtbuild_free( obj->builder ); - obj->builder = NULL; -} - -template<> -int bvh_intersect(BVHTree *obj, Isect* isec) -{ - if(RE_rayobject_isAligned(obj->root)) - return bvh_node_stack_raycast(obj->root, isec); - else - return RE_rayobject_intersect( (RayObject*) obj->root, isec ); -} - - -/* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */ -static RayObjectAPI bvh_api = -{ - (RE_rayobject_raycast_callback) ((int(*)(BVHTree*,Isect*)) &bvh_intersect), - (RE_rayobject_add_callback) ((void(*)(BVHTree*,RayObject*)) &bvh_add), - (RE_rayobject_done_callback) ((void(*)(BVHTree*)) &bvh_done), - (RE_rayobject_free_callback) ((void(*)(BVHTree*)) &bvh_free), - (RE_rayobject_merge_bb_callback)((void(*)(BVHTree*,float*,float*)) &bvh_bb), - (RE_rayobject_cost_callback) ((float(*)(BVHTree*)) &bvh_cost) -}; - - -RayObject *RE_rayobject_bvh_create(int size) -{ - BVHTree *obj= (BVHTree*)MEM_callocN(sizeof(BVHTree), "BVHTree"); - assert( RE_rayobject_isAligned(obj) ); /* RayObject API assumes real data to be 4-byte aligned */ - - obj->rayobj.api = &bvh_api; - obj->root = NULL; - - obj->node_arena = NULL; - obj->builder = rtbuild_create( size ); - - return RE_rayobject_unalignRayAPI((RayObject*) obj); -} diff --git a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp index 53579d2915f..59daf9dc962 100644 --- a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp @@ -44,17 +44,6 @@ struct QBVHTree }; -/* - * Cost to test N childs - */ -struct PackCost -{ - float operator()(int n) - { - return (n / 4) + ((n % 4) > 2 ? 1 : n%4); - } -}; - template<> void bvh_done(QBVHTree *obj) { @@ -68,21 +57,11 @@ void bvh_done(QBVHTree *obj) BLI_memarena_use_malloc(arena2); BLI_memarena_use_align(arena2, 16); - //Build and optimize the tree - - if(0) - { - VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); - pushup_simd(root); - obj->root = Reorganize_SVBVH(arena2).transform(root); - } - else - { - //Finds the optimal packing of this tree using a given cost model - OVBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); - VBVH_optimalPackSIMD(PackCost()).transform(root); - obj->root = Reorganize_SVBVH(arena2).transform(root); - } + //Build and optimize the tree + //TODO do this in 1 pass (half memory usage during building) + VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); + pushup_simd(root); + obj->root = Reorganize_SVBVH(arena2).transform(root); //Cleanup BLI_memarena_free(arena1); diff --git a/source/blender/render/intern/raytrace/rayobject_svbvh.cpp b/source/blender/render/intern/raytrace/rayobject_svbvh.cpp index 1bcffddd0ac..f806fcf93ef 100644 --- a/source/blender/render/intern/raytrace/rayobject_svbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_svbvh.cpp @@ -43,6 +43,17 @@ struct SVBVHTree RTBuilder *builder; }; +/* + * Cost to test N childs + */ +struct PackCost +{ + float operator()(int n) + { + return (n / 4) + ((n % 4) > 2 ? 1 : n%4); + } +}; + template<> void bvh_done(SVBVHTree *obj) @@ -58,16 +69,27 @@ void bvh_done(SVBVHTree *obj) BLI_memarena_use_align(arena2, 16); //Build and optimize the tree - VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); - reorganize(root); - remove_useless(root, &root); - bvh_refit(root); + if(0) + { + VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); + reorganize(root); + remove_useless(root, &root); + bvh_refit(root); - pushup(root); - pushdown(root); - pushup_simd(root); + pushup(root); + pushdown(root); + pushup_simd(root); - obj->root = Reorganize_SVBVH(arena2).transform(root); + obj->root = Reorganize_SVBVH(arena2).transform(root); + } + else + { + //Finds the optimal packing of this tree using a given cost model + //TODO this uses quite a lot of memory, find ways to reduce memory usage during building + OVBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); + VBVH_optimalPackSIMD(PackCost()).transform(root); + obj->root = Reorganize_SVBVH(arena2).transform(root); + } //Free data diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index 4e51de0da07..5260abf67ae 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -58,6 +58,16 @@ struct VBVHTree RTBuilder *builder; }; +/* + * Cost to test N childs + */ +struct PackCost +{ + float operator()(int n) + { + return n; + } +}; template<> void bvh_done(VBVHTree *obj) @@ -67,24 +77,42 @@ void bvh_done(VBVHTree *obj) //TODO find a away to exactly calculate the needed memory MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); BLI_memarena_use_malloc(arena1); - //Build and optimize the tree - VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); + if(1) + { + VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); - reorganize(root); - remove_useless(root, &root); - bvh_refit(root); + reorganize(root); + remove_useless(root, &root); + bvh_refit(root); - pushup(root); - pushdown(root); + pushup(root); + pushdown(root); + obj->root = root; + } + else + { +/* + TODO + MemArena *arena2 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); + BLI_memarena_use_malloc(arena2); + + //Finds the optimal packing of this tree using a given cost model + //TODO this uses quite a lot of memory, find ways to reduce memory usage during building + OVBVHNode *root = BuildBinaryVBVH(arena2).transform(obj->builder); + VBVH_optimalPackSIMD(PackCost()).transform(root); + obj->root = Reorganize_VBVH(arena1).transform(root); + + BLI_memarena_free(arena2); + */ + } //Cleanup rtbuild_free( obj->builder ); obj->builder = NULL; obj->node_arena = arena1; - obj->root = root; obj->cost = 1.0; } diff --git a/source/blender/render/intern/source/rayobject_blibvh.c b/source/blender/render/intern/source/rayobject_blibvh.c index 6e789862207..487193ef1f2 100644 --- a/source/blender/render/intern/source/rayobject_blibvh.c +++ b/source/blender/render/intern/source/rayobject_blibvh.c @@ -42,13 +42,26 @@ static void RE_rayobject_blibvh_done(RayObject *o); static void RE_rayobject_blibvh_free(RayObject *o); static void RE_rayobject_blibvh_bb(RayObject *o, float *min, float *max); +static float RE_rayobject_blibvh_cost(RayObject *o) +{ + //TODO calculate the expected cost to raycast on this structure + return 1.0; +} + +static void RE_rayobject_blibvh_hint_bb(RayObject *o, RayHint *hint, float *min, float *max) +{ + return; +} + static RayObjectAPI bvh_api = { RE_rayobject_blibvh_intersect, RE_rayobject_blibvh_add, RE_rayobject_blibvh_done, RE_rayobject_blibvh_free, - RE_rayobject_blibvh_bb + RE_rayobject_blibvh_bb, + RE_rayobject_blibvh_cost, + RE_rayobject_blibvh_hint_bb }; typedef struct BVHObject diff --git a/source/blender/render/intern/source/rayobject_octree.c b/source/blender/render/intern/source/rayobject_octree.c index 4246dd522db..2f0a1a3f53b 100644 --- a/source/blender/render/intern/source/rayobject_octree.c +++ b/source/blender/render/intern/source/rayobject_octree.c @@ -90,13 +90,28 @@ static void RE_rayobject_octree_done(RayObject *o); static void RE_rayobject_octree_free(RayObject *o); static void RE_rayobject_octree_bb(RayObject *o, float *min, float *max); +/* + * This function is not expected to be called by current code state. + */ +static float RE_rayobject_octree_cost(RayObject *o) +{ + return 1.0; +} + +static void RE_rayobject_octree_hint_bb(RayObject *o, RayHint *hint, float *min, float *max) +{ + return; +} + static RayObjectAPI octree_api = { RE_rayobject_octree_intersect, RE_rayobject_octree_add, RE_rayobject_octree_done, RE_rayobject_octree_free, - RE_rayobject_octree_bb + RE_rayobject_octree_bb, + RE_rayobject_octree_cost, + RE_rayobject_octree_hint_bb }; /* **************** ocval method ******************* */ diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index d84a2d9210a..641085d8cd6 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -62,7 +62,6 @@ #include "raycounter.h" -#define USE_VLAK_PRIMITIVES 1 #define RAY_TRA 1 #define RAY_TRAFLIP 2 @@ -78,15 +77,12 @@ RayObject * RE_rayobject_create(int type, int size) if(type == R_RAYSTRUCTURE_AUTO) { //TODO -// if(detect_simd()) -// type = R_RAYSTRUCTURE_SIMD_SVBVH; -// else -// type = R_RAYSTRUCTURE_VBVH; - - type = R_RAYSTRUCTURE_SIMD_QBVH; + //if(detect_simd()) + type = R_RAYSTRUCTURE_SIMD_SVBVH; + //else + // type = R_RAYSTRUCTURE_VBVH; } - - + if(type == R_RAYSTRUCTURE_OCTREE) { //TODO dynamic ocres @@ -108,10 +104,7 @@ RayObject * RE_rayobject_create(int type, int size) { return RE_rayobject_qbvh_create(size); } - if(type == R_RAYSTRUCTURE_BIH) - { -// return RE_rayobject_bih_create(size); - } + assert( NULL ); return NULL; } @@ -209,8 +202,8 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) if(obr->raytree == NULL) { RayObject *raytree; - RayFace *face; - VlakPrimitive *vlakprimitive; + RayFace *face = NULL; + VlakPrimitive *vlakprimitive = NULL; int v; //Count faces @@ -224,8 +217,8 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) assert( faces > 0 ); //Create Ray cast accelaration structure - raytree = obr->raytree = RE_rayobject_create( re->r.raytrace_tree_type, faces ); - if(USE_VLAK_PRIMITIVES) + raytree = obr->raytree = RE_rayobject_create( re->r.raytrace_structure, faces ); + if( (re->r.raytrace_options & R_RAYTRACE_USE_LOCAL_COORDS) ) vlakprimitive = obr->rayprimitives = (VlakPrimitive*)MEM_callocN(faces*sizeof(VlakPrimitive), "ObjectRen primitives"); else face = obr->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "ObjectRen faces"); @@ -237,7 +230,7 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); if(is_raytraceable_vlr(re, vlr)) { - if(USE_VLAK_PRIMITIVES) + if( (re->r.raytrace_options & R_RAYTRACE_USE_LOCAL_COORDS) ) { RE_rayobject_add( raytree, RE_vlakprimitive_from_vlak( vlakprimitive, obi, vlr ) ); vlakprimitive++; @@ -266,7 +259,7 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) static int has_special_rayobject(Render *re, ObjectInstanceRen *obi) { - if( (obi->flag & R_TRANSFORMED) ) + if( (obi->flag & R_TRANSFORMED) && (re->r.raytrace_options & R_RAYTRACE_USE_INSTANCES) ) { ObjectRen *obr = obi->obr; int v, faces = 0; @@ -291,8 +284,8 @@ static void makeraytree_single(Render *re) { ObjectInstanceRen *obi; RayObject *raytree; - RayFace *face; - VlakPrimitive *vlakprimitive; + RayFace *face = NULL; + VlakPrimitive *vlakprimitive = NULL; int faces = 0, obs = 0, special = 0; for(obi=re->instancetable.first; obi; obi=obi->next) @@ -318,9 +311,9 @@ static void makeraytree_single(Render *re) } //Create raytree - raytree = re->raytree = RE_rayobject_create( re->r.raytrace_tree_type, faces+special ); + raytree = re->raytree = RE_rayobject_create( re->r.raytrace_structure, faces+special ); - if(USE_VLAK_PRIMITIVES) + if( (re->r.raytrace_options & R_RAYTRACE_USE_LOCAL_COORDS) ) { vlakprimitive = re->rayprimitives = (VlakPrimitive*)MEM_callocN(faces*sizeof(VlakPrimitive), "Raytrace vlak-primitives"); } @@ -352,7 +345,7 @@ static void makeraytree_single(Render *re) VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255); if(is_raytraceable_vlr(re, vlr)) { - if(USE_VLAK_PRIMITIVES) + if( (re->r.raytrace_options & R_RAYTRACE_USE_LOCAL_COORDS) ) { RayObject *obj = RE_vlakprimitive_from_vlak( vlakprimitive, obi, vlr ); RE_rayobject_add( raytree, obj ); @@ -392,6 +385,11 @@ void makeraytree(Render *re) re->i.infostr= "Raytree.. preparing"; re->stats_draw(re->sdh, &re->i); + /* disable options not yet suported by octree, + they might actually never be supported (unless people really need it) */ + if(re->r.raytrace_structure == R_RAYSTRUCTURE_OCTREE) + re->r.raytrace_options &= ~( R_RAYTRACE_USE_INSTANCES | R_RAYTRACE_USE_LOCAL_COORDS); + BENCH(makeraytree_single(re), tree_build); //Calculate raytree max_size From 55541d8a8143b97ce0d452caf4ececa8903c31a0 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Sun, 4 Oct 2009 16:56:00 +0000 Subject: [PATCH 095/138] Added some test_break during the build process. (Maybe later this should be done with some thread_cancel function instead of doing variable/callbacks tests) --- .../blender/render/intern/include/rayobject.h | 24 ++++ .../render/intern/raytrace/rayobject.cpp | 7 ++ .../render/intern/raytrace/rayobject_qbvh.cpp | 12 +- .../intern/raytrace/rayobject_rtbuild.cpp | 5 +- .../intern/raytrace/rayobject_rtbuild.h | 2 +- .../intern/raytrace/rayobject_svbvh.cpp | 20 +++- .../render/intern/raytrace/rayobject_vbvh.cpp | 9 +- source/blender/render/intern/raytrace/vbvh.h | 26 ++++- .../blender/render/intern/source/rayshade.c | 106 +++++++++++------- 9 files changed, 159 insertions(+), 52 deletions(-) diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index 337f9ca3fdd..9e35c0feac5 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -93,6 +93,21 @@ extern "C" { #define RE_rayobject_isVlakPrimitive(o) ((((intptr_t)o)&3) == 3) + +/* + * This class is intended as a place holder for control, configuration of the rayobject like: + * - stop building (TODO maybe when porting build to threads this could be implemented with some thread_cancel function) + * - max number of threads and threads callback to use during build + * ... + */ +typedef int (*RE_rayobjectcontrol_test_break_callback)(void *data); +typedef struct RayObjectControl RayObjectControl; +struct RayObjectControl +{ + void *data; + RE_rayobjectcontrol_test_break_callback test_break; +}; + /* * This rayobject represents a generic object. With it's own callbacks for raytrace operations. * It's suitable to implement things like LOD. @@ -100,9 +115,13 @@ extern "C" { struct RayObject { struct RayObjectAPI *api; + + struct RayObjectControl control; }; + + typedef int (*RE_rayobject_raycast_callback)(RayObject *, Isect *); typedef void (*RE_rayobject_add_callback)(RayObject *raytree, RayObject *rayobject); typedef void (*RE_rayobject_done_callback)(RayObject *); @@ -144,6 +163,11 @@ int RE_rayobject_bb_intersect_test(const Isect *i, const float *bb); /* same as float RE_rayobject_cost(RayObject *r); +/* + * Returns true if for some reason a heavy processing function should stop + * (eg.: user asked to stop during a tree a build) + */ +int RE_rayobjectcontrol_test_break(RayObjectControl *c); #define ISECT_EPSILON ((float)FLT_EPSILON) diff --git a/source/blender/render/intern/raytrace/rayobject.cpp b/source/blender/render/intern/raytrace/rayobject.cpp index 34faa2951ce..95387cf1ee4 100644 --- a/source/blender/render/intern/raytrace/rayobject.cpp +++ b/source/blender/render/intern/raytrace/rayobject.cpp @@ -528,3 +528,10 @@ void RE_rayobject_hint_bb(RayObject *r, RayHint *hint, float *min, float *max) else assert(0); } +int RE_rayobjectcontrol_test_break(RayObjectControl *control) +{ + if(control->test_break) + return control->test_break( control->data ); + + return 0; +} diff --git a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp index 59daf9dc962..b18ee0824cf 100644 --- a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp @@ -47,7 +47,7 @@ struct QBVHTree template<> void bvh_done(QBVHTree *obj) { - rtbuild_done(obj->builder); + rtbuild_done(obj->builder, &obj->rayobj.control); //TODO find a away to exactly calculate the needed memory MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); @@ -59,7 +59,15 @@ void bvh_done(QBVHTree *obj) //Build and optimize the tree //TODO do this in 1 pass (half memory usage during building) - VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); + VBVHNode *root = BuildBinaryVBVH(arena1, &obj->rayobj.control).transform(obj->builder); + + if(RE_rayobjectcontrol_test_break(&obj->rayobj.control)) + { + BLI_memarena_free(arena1); + BLI_memarena_free(arena2); + return; + } + pushup_simd(root); obj->root = Reorganize_SVBVH(arena2).transform(root); diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp index 430045b56b6..9523e725893 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp @@ -130,11 +130,14 @@ static void object_sort(Item *begin, Item *end, int axis) assert(false); } -void rtbuild_done(RTBuilder *b) +void rtbuild_done(RTBuilder *b, RayObjectControl* ctrl) { for(int i=0; i<3; i++) if(b->sorted_begin[i]) + { + if(RE_rayobjectcontrol_test_break(ctrl)) break; object_sort( b->sorted_begin[i], b->sorted_end[i], i ); + } } RayObject* rtbuild_get_primitive(RTBuilder *b, int index) diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.h b/source/blender/render/intern/raytrace/rayobject_rtbuild.h index 8f471f095e2..71665681586 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.h +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.h @@ -85,7 +85,7 @@ typedef struct RTBuilder RTBuilder* rtbuild_create(int size); void rtbuild_free(RTBuilder *b); void rtbuild_add(RTBuilder *b, RayObject *o); -void rtbuild_done(RTBuilder *b); +void rtbuild_done(RTBuilder *b, RayObjectControl *c); void rtbuild_merge_bb(RTBuilder *b, float *min, float *max); int rtbuild_size(RTBuilder *b); diff --git a/source/blender/render/intern/raytrace/rayobject_svbvh.cpp b/source/blender/render/intern/raytrace/rayobject_svbvh.cpp index f806fcf93ef..229e82dfa68 100644 --- a/source/blender/render/intern/raytrace/rayobject_svbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_svbvh.cpp @@ -58,7 +58,7 @@ struct PackCost template<> void bvh_done(SVBVHTree *obj) { - rtbuild_done(obj->builder); + rtbuild_done(obj->builder, &obj->rayobj.control); //TODO find a away to exactly calculate the needed memory MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); @@ -71,7 +71,14 @@ void bvh_done(SVBVHTree *obj) //Build and optimize the tree if(0) { - VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); + VBVHNode *root = BuildBinaryVBVH(arena1,&obj->rayobj.control).transform(obj->builder); + if(RE_rayobjectcontrol_test_break(&obj->rayobj.control)) + { + BLI_memarena_free(arena1); + BLI_memarena_free(arena2); + return; + } + reorganize(root); remove_useless(root, &root); bvh_refit(root); @@ -86,7 +93,14 @@ void bvh_done(SVBVHTree *obj) { //Finds the optimal packing of this tree using a given cost model //TODO this uses quite a lot of memory, find ways to reduce memory usage during building - OVBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); + OVBVHNode *root = BuildBinaryVBVH(arena1,&obj->rayobj.control).transform(obj->builder); + if(RE_rayobjectcontrol_test_break(&obj->rayobj.control)) + { + BLI_memarena_free(arena1); + BLI_memarena_free(arena2); + return; + } + VBVH_optimalPackSIMD(PackCost()).transform(root); obj->root = Reorganize_SVBVH(arena2).transform(root); } diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index 5260abf67ae..11f04c04141 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -72,7 +72,7 @@ struct PackCost template<> void bvh_done(VBVHTree *obj) { - rtbuild_done(obj->builder); + rtbuild_done(obj->builder, &obj->rayobj.control); //TODO find a away to exactly calculate the needed memory MemArena *arena1 = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); @@ -81,7 +81,12 @@ void bvh_done(VBVHTree *obj) //Build and optimize the tree if(1) { - VBVHNode *root = BuildBinaryVBVH(arena1).transform(obj->builder); + VBVHNode *root = BuildBinaryVBVH(arena1,&obj->rayobj.control).transform(obj->builder); + if(RE_rayobjectcontrol_test_break(&obj->rayobj.control)) + { + BLI_memarena_free(arena1); + return; + } reorganize(root); remove_useless(root, &root); diff --git a/source/blender/render/intern/raytrace/vbvh.h b/source/blender/render/intern/raytrace/vbvh.h index db1df43f665..1ff51786e52 100644 --- a/source/blender/render/intern/raytrace/vbvh.h +++ b/source/blender/render/intern/raytrace/vbvh.h @@ -107,10 +107,18 @@ template struct BuildBinaryVBVH { MemArena *arena; + RayObjectControl *control; - BuildBinaryVBVH(MemArena *a) + void test_break() + { + if(RE_rayobjectcontrol_test_break(control)) + throw "Stop"; + } + + BuildBinaryVBVH(MemArena *a, RayObjectControl *c) { arena = a; + control = c; } Node *create_node() @@ -130,6 +138,18 @@ struct BuildBinaryVBVH } Node *transform(RTBuilder *builder) + { + try + { + return _transform(builder); + + } catch(...) + { + } + return NULL; + } + + Node *_transform(RTBuilder *builder) { int size = rtbuild_size(builder); @@ -143,6 +163,8 @@ struct BuildBinaryVBVH } else { + test_break(); + Node *node = create_node(); INIT_MINMAX(node->bb, node->bb+3); @@ -157,7 +179,7 @@ struct BuildBinaryVBVH RTBuilder tmp; rtbuild_get_child(builder, i, &tmp); - *child = transform(&tmp); + *child = _transform(&tmp); child = &((*child)->sibling); } diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 641085d8cd6..9ef8aa3aba2 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -72,8 +72,26 @@ /* only to be used here in this file, it's for speed */ extern struct Render R; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -RayObject * RE_rayobject_create(int type, int size) +static int test_break(void *data) { + Render *re = (Render*)data; + return re->test_break(re->tbh); +} + +static RE_rayobject_config_control(RayObject *r, Render *re) +{ + if(RE_rayobject_isRayAPI(r)) + { + r = RE_rayobject_align( r ); + r->control.data = re; + r->control.test_break = test_break; + } +} + +RayObject* RE_rayobject_create(Render *re, int type, int size) +{ + RayObject * res = NULL; + if(type == R_RAYSTRUCTURE_AUTO) { //TODO @@ -83,30 +101,21 @@ RayObject * RE_rayobject_create(int type, int size) // type = R_RAYSTRUCTURE_VBVH; } - if(type == R_RAYSTRUCTURE_OCTREE) - { - //TODO dynamic ocres - return RE_rayobject_octree_create(R.r.ocres, size); - } - if(type == R_RAYSTRUCTURE_BLIBVH) - { - return RE_rayobject_blibvh_create(size); - } - if(type == R_RAYSTRUCTURE_VBVH) - { - return RE_rayobject_vbvh_create(size); - } - if(type == R_RAYSTRUCTURE_SIMD_SVBVH) - { - return RE_rayobject_svbvh_create(size); - } - if(type == R_RAYSTRUCTURE_SIMD_QBVH) - { - return RE_rayobject_qbvh_create(size); - } - assert( NULL ); + if(type == R_RAYSTRUCTURE_OCTREE) //TODO dynamic ocres + res = RE_rayobject_octree_create(re->r.ocres, size); + else if(type == R_RAYSTRUCTURE_BLIBVH) + res = RE_rayobject_blibvh_create(size); + else if(type == R_RAYSTRUCTURE_VBVH) + res = RE_rayobject_vbvh_create(size); + else if(type == R_RAYSTRUCTURE_SIMD_SVBVH) + res = RE_rayobject_svbvh_create(size); + else if(type == R_RAYSTRUCTURE_SIMD_QBVH) + res = RE_rayobject_qbvh_create(size); - return NULL; + if(res) + RE_rayobject_config_control( res, re ); + + return res; } #ifdef RE_RAYCOUNTER @@ -217,7 +226,7 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) assert( faces > 0 ); //Create Ray cast accelaration structure - raytree = obr->raytree = RE_rayobject_create( re->r.raytrace_structure, faces ); + raytree = obr->raytree = RE_rayobject_create( re, re->r.raytrace_structure, faces ); if( (re->r.raytrace_options & R_RAYTRACE_USE_LOCAL_COORDS) ) vlakprimitive = obr->rayprimitives = (VlakPrimitive*)MEM_callocN(faces*sizeof(VlakPrimitive), "ObjectRen primitives"); else @@ -311,7 +320,7 @@ static void makeraytree_single(Render *re) } //Create raytree - raytree = re->raytree = RE_rayobject_create( re->r.raytrace_structure, faces+special ); + raytree = re->raytree = RE_rayobject_create( re, re->r.raytrace_structure, faces+special ); if( (re->r.raytrace_options & R_RAYTRACE_USE_LOCAL_COORDS) ) { @@ -325,6 +334,9 @@ static void makeraytree_single(Render *re) for(obi=re->instancetable.first; obi; obi=obi->next) if(is_raytraceable(re, obi)) { + if(test_break(re)) + break; + if(has_special_rayobject(re, obi)) { RayObject *obj = makeraytree_object(re, obi); @@ -371,10 +383,13 @@ static void makeraytree_single(Render *re) } } - re->i.infostr= "Raytree.. building"; - re->stats_draw(re->sdh, &re->i); + if(!test_break(re)) + { + re->i.infostr= "Raytree.. building"; + re->stats_draw(re->sdh, &re->i); - RE_rayobject_done( raytree ); + RE_rayobject_done( raytree ); + } } void makeraytree(Render *re) @@ -391,20 +406,29 @@ void makeraytree(Render *re) re->r.raytrace_options &= ~( R_RAYTRACE_USE_INSTANCES | R_RAYTRACE_USE_LOCAL_COORDS); BENCH(makeraytree_single(re), tree_build); - - //Calculate raytree max_size - //This is ONLY needed to kept a bogus behaviour of SUN and HEMI lights - RE_rayobject_merge_bb( re->raytree, min, max ); - for(i=0; i<3; i++) + if(test_break(re)) { - min[i] += 0.01f; - max[i] += 0.01f; - sub[i] = max[i]-min[i]; - } - re->maxdist = sqrt( sub[0]*sub[0] + sub[1]*sub[1] + sub[2]*sub[2] ); + freeraytree(re); - re->i.infostr= "Raytree finished"; - re->stats_draw(re->sdh, &re->i); + re->i.infostr= "Raytree building canceled"; + re->stats_draw(re->sdh, &re->i); + } + else + { + //Calculate raytree max_size + //This is ONLY needed to kept a bogus behaviour of SUN and HEMI lights + RE_rayobject_merge_bb( re->raytree, min, max ); + for(i=0; i<3; i++) + { + min[i] += 0.01f; + max[i] += 0.01f; + sub[i] = max[i]-min[i]; + } + re->maxdist = sqrt( sub[0]*sub[0] + sub[1]*sub[1] + sub[2]*sub[2] ); + + re->i.infostr= "Raytree finished"; + re->stats_draw(re->sdh, &re->i); + } } void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr) From 729a63bbb6ba89ac32b3cef3291f28e990032cde Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Sun, 4 Oct 2009 19:53:06 +0000 Subject: [PATCH 096/138] * update default physics settings for jahka --- source/blender/editors/datafiles/B.blend.c | 5391 ++++++++++---------- 1 file changed, 2727 insertions(+), 2664 deletions(-) diff --git a/source/blender/editors/datafiles/B.blend.c b/source/blender/editors/datafiles/B.blend.c index b469f0c24cb..b22ef5b3053 100644 --- a/source/blender/editors/datafiles/B.blend.c +++ b/source/blender/editors/datafiles/B.blend.c @@ -1,586 +1,253 @@ /* DataToC output of file */ -int datatoc_B_blend_size= 100360; +int datatoc_B_blend_size= 102392; char datatoc_B_blend[]= { - 66, 76, 69, 78, 68, 69, 82, 95, -118, 50, 53, 48, 82, 69, 78, 68, 32, 0, 0, 0,208,245, 18, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0, - 83, 99,101,110,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 76, 79, 66, 32, 0, 0, 0, -200,245, 18, 0,192, 0, 0, 0, 1, 0, 0, 0, 32, 32, 32, 51, 3, 0, 0, 0,250, 0, 0, 0, 1, 0, 0, 1, 72, 22, 11, 7, -160, 33, 10, 7, 0, 16, 0, 0,128, 32, 4, 0, 87, 77, 0, 0,140, 0, 0, 0,192, 75, 10, 7, 86, 1, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 77, 87,105,110, 77, 97,110, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160,254, 14, 7,160,147,103, 2,160,254, 14, 7, -160,254, 14, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,224,183,102, 2,216, 85, 5, 7, 68, 65, 84, 65,148, 0, 0, 0,160,254, 14, 7, 87, 1, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 99, 2, 1, 0, 0, 0, 0, 0, 0, 0, 72, 22, 11, 7, 0, 0, 0, 0,115, 99,114,101, -101,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 34, 0, -186, 4,254, 2, 0, 0, 0, 0, 1, 0,238, 3, 0, 0, 1, 0, 0, 0, 0, 0,232, 44, 99, 2, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,144, 76, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0,208,229, 25, 7,176,202, 25, 7,152, 43, 99, 2, -184,231, 9, 7,200, 45, 5, 7, 56, 90, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 83, 78, 0, 0,140, 0, 0, 0, 72, 22, 11, 7, -186, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 82, 83, 99,114,101,101,110, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,208, 79, 10, 7, -176,183, 3, 7,232,192, 3, 7, 96,201, 2, 7,120,255, 14, 7, 72,136, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0,160, 33, 10, 7, - 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,111, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,208, 79, 10, 7, -187, 0, 0, 0, 1, 0, 0, 0,120, 63, 11, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 20, 0, 0, 0,120, 63, 11, 7,187, 0, 0, 0, 1, 0, 0, 0, 8, 11, 11, 7,208, 79, 10, 7, 0, 0, 0, 0, 0, 0,254, 2, - 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 8, 11, 11, 7,187, 0, 0, 0, 1, 0, 0, 0,200, 32, 4, 7,120, 63, 11, 7, - 0, 0, 0, 0,186, 4,254, 2, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,200, 32, 4, 7,187, 0, 0, 0, 1, 0, 0, 0, -232,251, 3, 7, 8, 11, 11, 7, 0, 0, 0, 0,186, 4, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,232,251, 3, 7, -187, 0, 0, 0, 1, 0, 0, 0, 48, 16, 4, 7,200, 32, 4, 7, 0, 0, 0, 0, 0, 0,227, 2, 1, 0, 0, 0, 68, 65, 84, 65, - 20, 0, 0, 0, 48, 16, 4, 7,187, 0, 0, 0, 1, 0, 0, 0,216, 43, 4, 7,232,251, 3, 7, 0, 0, 0, 0,186, 4,227, 2, - 1, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,216, 43, 4, 7,187, 0, 0, 0, 1, 0, 0, 0,160, 34, 4, 7, 48, 16, 4, 7, - 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,160, 34, 4, 7,187, 0, 0, 0, 1, 0, 0, 0, - 88,147, 4, 7,216, 43, 4, 7, 0, 0, 0, 0,186, 4, 60, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 88,147, 4, 7, -187, 0, 0, 0, 1, 0, 0, 0,136,121, 4, 7,160, 34, 4, 7, 0, 0, 0, 0,216, 3, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 20, 0, 0, 0,136,121, 4, 7,187, 0, 0, 0, 1, 0, 0, 0,104, 25, 4, 7, 88,147, 4, 7, 0, 0, 0, 0,216, 3,227, 2, - 1, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,104, 25, 4, 7,187, 0, 0, 0, 1, 0, 0, 0, 64,160, 4, 7,136,121, 4, 7, - 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 64,160, 4, 7,187, 0, 0, 0, 1, 0, 0, 0, - 32, 26, 15, 7,104, 25, 4, 7, 0, 0, 0, 0,216, 3, 72, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 32, 26, 15, 7, -187, 0, 0, 0, 1, 0, 0, 0,176,183, 3, 7, 64,160, 4, 7, 0, 0, 0, 0,216, 3, 72, 2, 0, 0, 0, 0, 68, 65, 84, 65, - 20, 0, 0, 0,176,183, 3, 7,187, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 32, 26, 15, 7, 0, 0, 0, 0,186, 4, 72, 2, - 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,232,192, 3, 7,188, 0, 0, 0, 1, 0, 0, 0, 24,226, 3, 7, 0, 0, 0, 0, - 8, 11, 11, 7,120, 63, 11, 7, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 24,226, 3, 7,188, 0, 0, 0, - 1, 0, 0, 0, 88, 14, 4, 7,232,192, 3, 7,232,251, 3, 7,120, 63, 11, 7, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 24, 0, 0, 0, 88, 14, 4, 7,188, 0, 0, 0, 1, 0, 0, 0, 0,180, 3, 7, 24,226, 3, 7, 48, 16, 4, 7, 8, 11, 11, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 0,180, 3, 7,188, 0, 0, 0, 1, 0, 0, 0,104,163, 3, 7, - 88, 14, 4, 7,232,251, 3, 7, 48, 16, 4, 7, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,104,163, 3, 7, -188, 0, 0, 0, 1, 0, 0, 0,248,203, 3, 7, 0,180, 3, 7, 88,147, 4, 7,208, 79, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 24, 0, 0, 0,248,203, 3, 7,188, 0, 0, 0, 1, 0, 0, 0, 16,191, 3, 7,104,163, 3, 7,200, 32, 4, 7, - 88,147, 4, 7, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 16,191, 3, 7,188, 0, 0, 0, 1, 0, 0, 0, -144, 23, 4, 7,248,203, 3, 7,232,251, 3, 7,136,121, 4, 7, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, -144, 23, 4, 7,188, 0, 0, 0, 1, 0, 0, 0, 0,118, 4, 7, 16,191, 3, 7, 48, 16, 4, 7,136,121, 4, 7, 0, 0, 0, 0, - 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 0,118, 4, 7,188, 0, 0, 0, 1, 0, 0, 0,144,109, 4, 7,144, 23, 4, 7, -104, 25, 4, 7,208, 79, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,144,109, 4, 7,188, 0, 0, 0, - 1, 0, 0, 0, 40,178, 3, 7, 0,118, 4, 7,232,251, 3, 7,104, 25, 4, 7, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 24, 0, 0, 0, 40,178, 3, 7,188, 0, 0, 0, 1, 0, 0, 0,200,170, 3, 7,144,109, 4, 7,136,121, 4, 7, 64,160, 4, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,200,170, 3, 7,188, 0, 0, 0, 1, 0, 0, 0,176,242, 3, 7, - 40,178, 3, 7, 88,147, 4, 7, 64,160, 4, 7, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,176,242, 3, 7, -188, 0, 0, 0, 1, 0, 0, 0, 56,248, 3, 7,200,170, 3, 7,104, 25, 4, 7, 64,160, 4, 7, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 24, 0, 0, 0, 56,248, 3, 7,188, 0, 0, 0, 1, 0, 0, 0, 80, 38, 4, 7,176,242, 3, 7, 88,147, 4, 7, - 32, 26, 15, 7, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 80, 38, 4, 7,188, 0, 0, 0, 1, 0, 0, 0, -232,133, 3, 7, 56,248, 3, 7,136,121, 4, 7, 32, 26, 15, 7, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, -232,133, 3, 7,188, 0, 0, 0, 1, 0, 0, 0,160,210, 2, 7, 80, 38, 4, 7,176,183, 3, 7, 48, 16, 4, 7, 0, 0, 0, 0, - 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,160,210, 2, 7,188, 0, 0, 0, 1, 0, 0, 0, 96,201, 2, 7,232,133, 3, 7, -176,183, 3, 7,200, 32, 4, 7, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 96,201, 2, 7,188, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0,160,210, 2, 7,176,183, 3, 7, 32, 26, 15, 7, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 96, 0, 0, 0,120,255, 14, 7,190, 0, 0, 0, 1, 0, 0, 0, 24, 23, 11, 7, 0, 0, 0, 0,232,251, 3, 7,120, 63, 11, 7, - 8, 11, 11, 7, 48, 16, 4, 7, 0, 0, 0, 0, 0, 0, 0, 0,186, 4, 0, 0,228, 2, 0, 0,254, 2, 0, 0, 7, 7,187, 4, - 27, 0, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 56,150, 92, 2,152,180,102, 2,152,180,102, 2, 32,173, 11, 7,112,158, 24, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 40, 47, 5, 7, 8, 48, 5, 7, 68, 65, 84, 65,248, 0, 0, 0, 32,173, 11, 7,191, 0, 0, 0, - 1, 0, 0, 0,112,158, 24, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,157, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, - 0, 96,151, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,186, 4, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,237, 68, - 0, 0,200, 65, 0,128,237, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 4, - 10, 0,187, 4, 26, 0,187, 4, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,186, 4, 0, 0,228, 2, 0, 0,253, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -187, 4, 26, 0, 2, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,151, 92, 2,184,191, 25, 7, -184,191, 25, 7, 0, 0, 0, 0, 0, 0, 0, 0,216, 49, 5, 7, 96, 50, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, -248, 0, 0, 0,112,158, 24, 7,191, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 32,173, 11, 7, 0, 0, 0, 0, 0, 32,240, 68, - 0, 0, 0,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,110, 69, 0, 0, 0,192, 0, 0, 0, 0,112, 7, 0, 0,129, 7, 0, 0, - 18, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,111, 7, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,111, 7, 0, 0, - 18, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, - 10, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 4, 6, 0,129, 7, 2, 0,112, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254, 2, 0, 0,254, 2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0,224,150, 92, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 96, 0, 0, 0, 24, 23, 11, 7,190, 0, 0, 0, 1, 0, 0, 0,200, 33, 11, 7, -120,255, 14, 7, 88,147, 4, 7, 32, 26, 15, 7,176,183, 3, 7,200, 32, 4, 7, 0, 0, 0, 0,217, 3, 0, 0,186, 4, 0, 0, - 0, 0, 0, 0, 71, 2, 0, 0, 4, 4,226, 0, 72, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,147, 92, 2,192,160, 9, 7, -120,148, 10, 7,128,237, 11, 7,184,238, 11, 7, 0, 0, 0, 0, 0, 0, 0, 0,232, 50, 5, 7,200, 51, 5, 7, 68, 65, 84, 65, -248, 0, 0, 0,128,237, 11, 7,191, 0, 0, 0, 1, 0, 0, 0,184,238, 11, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,193, 67, - 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 98, 67, 0, 0, 0, 0, 0, 0,248, 65, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,225, 0, 0, 0, - 0, 0, 0, 0, 30, 0, 0, 0, 0,128,137, 67, 0, 0,200, 65, 0,128,137, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 4, 10, 0,226, 0, 31, 0,226, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,217, 3, 0, 0,186, 4, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,226, 0, 31, 0, 3, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,152,149, 92, 2,160,145,246, 6,160,145,246, 6, 0, 0, 0, 0, 0, 0, 0, 0,152, 53, 5, 7,168, 54, 5, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0,184,238, 11, 7,191, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -128,237, 11, 7, 0, 0, 0, 0, 0, 0, 80, 67, 0, 0, 68,196, 0, 0, 0, 0, 0, 0, 0, 0,254,255, 80, 67,255,191, 5,196, - 0, 0, 0, 0,209, 0, 0, 0,226, 0, 0, 0, 18, 0, 0, 0, 40, 2, 0, 0, 0, 0, 0, 0,208, 0, 0, 0, 0, 0, 0, 0, - 17, 0, 0, 0, 0, 0, 0, 0,208, 0, 0, 0, 18, 0, 0, 0, 40, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,226, 0, 41, 2,209, 0, - 23, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,176, 63,100, 2, 1, 0, 0, 0, 0, 0, 0, 0,217, 3, 0, 0,186, 4, 0, 0, - 31, 0, 0, 0, 71, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,226, 0, 41, 2, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40,148, 92, 2, 88, 22, 6, 7, 16,102, 5, 7,248, 24, 11, 7, - 72,159, 9, 7,144, 56, 5, 7, 40, 58, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,248, 24, 11, 7, -189, 0, 0, 0, 1, 0, 0, 0,112, 26, 11, 7, 0, 0, 0, 0,200,148, 92, 2, 0, 0, 0, 0, 66, 85, 84, 84, 79, 78, 83, 95, - 80, 84, 95, 99,111,110,116,101,120,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 85, 84, 84, 79, 78, 83, 95, - 80, 84, 95, 99,111,110,116,101,120,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,111,110,116,101,120,116, 0, + 66, 76, 69, 78, 68, 69, 82, 95,118, 50, 53, 48, 82, 69, 78, 68, 32, 0, 0, 0, 36,246, 24, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0, 83, 99,101,110,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 71, 76, 79, 66, 32, 0, 0, 0, 20,246, 24, 0,195, 0, 0, 0, 1, 0, 0, 0, 32, 32, 32, 52, + 4, 0, 0, 0,250, 0, 0, 0, 1, 0, 0, 1, 56, 79,201, 2,216,194,213, 2, 0, 16, 0, 0,128, 32, 4, 0, 87, 77, 0, 0, +140, 0, 0, 0,120, 78,201, 2, 93, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 87, 77, 87,105,110, 77, 97,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,240, 49,213, 2,240, 49,213, 2,240, 49,213, 2,240, 49,213, 2, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,123,207, 2, 16,203,131, 3, 68, 65, 84, 65, +156, 0, 0, 0,240, 49,213, 2, 94, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,255,213, 2, 1, 0, 0, 0, + 0, 0, 0, 0, 56, 79,201, 2, 0, 0, 0, 0,115, 99,114,101,101,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0,110, 7,219, 3, 0, 0, 0, 0, 1, 0,238, 3, 0, 0, 1, 0, + 0, 0, 0, 0,208, 64,210, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,103,210, 2, 0, 0, 0, 0, + 0, 0, 0, 0,160, 65,210, 2,160, 65,210, 2,136, 68,207, 2, 0, 69,207, 2,120, 69,207, 2,120, 69,207, 2, 96, 80,201, 2, + 40,174,210, 2, 0, 0, 0, 0, 0, 0, 0, 0, 83, 78, 0, 0,140, 0, 0, 0, 56, 79,201, 2,189, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 82, 83, 99,114,101,101,110, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,187,200, 2,240,190,200, 2, 56,191,200, 2, +176, 51,213, 2,168,120,207, 2,232,122,207, 2, 0, 0, 0, 0, 0, 0, 0, 0,216,194,213, 2, 0, 0, 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0,144,166, 83, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 72,187,200, 2,190, 0, 0, 0, 1, 0, 0, 0, +144,187,200, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,144,187,200, 2, +190, 0, 0, 0, 1, 0, 0, 0,216,187,200, 2, 72,187,200, 2, 0, 0, 0, 0, 0, 0,219, 3, 0, 0, 0, 0, 68, 65, 84, 65, + 20, 0, 0, 0,216,187,200, 2,190, 0, 0, 0, 1, 0, 0, 0, 32,188,200, 2,144,187,200, 2, 0, 0, 0, 0,110, 7,219, 3, + 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 32,188,200, 2,190, 0, 0, 0, 1, 0, 0, 0,104,188,200, 2,216,187,200, 2, + 0, 0, 0, 0,110, 7, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,104,188,200, 2,190, 0, 0, 0, 1, 0, 0, 0, +176,188,200, 2, 32,188,200, 2, 0, 0, 0, 0, 0, 0,188, 3, 1, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,176,188,200, 2, +190, 0, 0, 0, 1, 0, 0, 0,248,188,200, 2,104,188,200, 2, 0, 0, 0, 0,110, 7,188, 3, 1, 0, 0, 0, 68, 65, 84, 65, + 20, 0, 0, 0,248,188,200, 2,190, 0, 0, 0, 1, 0, 0, 0, 64,189,200, 2,176,188,200, 2, 0, 0, 0, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 64,189,200, 2,190, 0, 0, 0, 1, 0, 0, 0,136,189,200, 2,248,188,200, 2, + 0, 0, 0, 0,110, 7, 80, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,136,189,200, 2,190, 0, 0, 0, 1, 0, 0, 0, +208,189,200, 2, 64,189,200, 2, 0, 0, 0, 0, 16, 6, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,208,189,200, 2, +190, 0, 0, 0, 1, 0, 0, 0, 24,190,200, 2,136,189,200, 2, 0, 0, 0, 0, 16, 6,188, 3, 1, 0, 0, 0, 68, 65, 84, 65, + 20, 0, 0, 0, 24,190,200, 2,190, 0, 0, 0, 1, 0, 0, 0, 96,190,200, 2,208,189,200, 2, 0, 0, 0, 0, 0, 0, 96, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0, 96,190,200, 2,190, 0, 0, 0, 1, 0, 0, 0,168,190,200, 2, 24,190,200, 2, + 0, 0, 0, 0, 16, 6, 96, 0, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,168,190,200, 2,190, 0, 0, 0, 1, 0, 0, 0, +240,190,200, 2, 96,190,200, 2, 0, 0, 0, 0, 16, 6,244, 2, 0, 0, 0, 0, 68, 65, 84, 65, 20, 0, 0, 0,240,190,200, 2, +190, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,168,190,200, 2, 0, 0, 0, 0,110, 7,244, 2, 0, 0, 0, 0, 68, 65, 84, 65, + 24, 0, 0, 0, 56,191,200, 2,191, 0, 0, 0, 1, 0, 0, 0,128,191,200, 2, 0, 0, 0, 0,144,187,200, 2,216,187,200, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,128,191,200, 2,191, 0, 0, 0, 1, 0, 0, 0,200,191,200, 2, + 56,191,200, 2,144,187,200, 2,104,188,200, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,200,191,200, 2, +191, 0, 0, 0, 1, 0, 0, 0, 16,192,200, 2,128,191,200, 2,216,187,200, 2,176,188,200, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 24, 0, 0, 0, 16,192,200, 2,191, 0, 0, 0, 1, 0, 0, 0, 88,192,200, 2,200,191,200, 2,104,188,200, 2, +176,188,200, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 88,192,200, 2,191, 0, 0, 0, 1, 0, 0, 0, +160,192,200, 2, 16,192,200, 2, 72,187,200, 2,136,189,200, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, +160,192,200, 2,191, 0, 0, 0, 1, 0, 0, 0,232,192,200, 2, 88,192,200, 2, 32,188,200, 2,136,189,200, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,232,192,200, 2,191, 0, 0, 0, 1, 0, 0, 0, 48,193,200, 2,160,192,200, 2, +104,188,200, 2,208,189,200, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 48,193,200, 2,191, 0, 0, 0, + 1, 0, 0, 0,120,193,200, 2,232,192,200, 2,176,188,200, 2,208,189,200, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 24, 0, 0, 0,120,193,200, 2,191, 0, 0, 0, 1, 0, 0, 0,192,193,200, 2, 48,193,200, 2, 72,187,200, 2, 24,190,200, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,192,193,200, 2,191, 0, 0, 0, 1, 0, 0, 0, 8,194,200, 2, +120,193,200, 2,104,188,200, 2, 24,190,200, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 8,194,200, 2, +191, 0, 0, 0, 1, 0, 0, 0, 80,194,200, 2,192,193,200, 2,208,189,200, 2, 96,190,200, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 24, 0, 0, 0, 80,194,200, 2,191, 0, 0, 0, 1, 0, 0, 0,152,194,200, 2, 8,194,200, 2,136,189,200, 2, + 96,190,200, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,152,194,200, 2,191, 0, 0, 0, 1, 0, 0, 0, +224,194,200, 2, 80,194,200, 2, 24,190,200, 2, 96,190,200, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, +224,194,200, 2,191, 0, 0, 0, 1, 0, 0, 0,216, 50,213, 2,152,194,200, 2,136,189,200, 2,168,190,200, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,216, 50,213, 2,191, 0, 0, 0, 1, 0, 0, 0, 32, 51,213, 2,224,194,200, 2, +208,189,200, 2,168,190,200, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0, 32, 51,213, 2,191, 0, 0, 0, + 1, 0, 0, 0,104, 51,213, 2,216, 50,213, 2,176,188,200, 2,240,190,200, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 24, 0, 0, 0,104, 51,213, 2,191, 0, 0, 0, 1, 0, 0, 0,176, 51,213, 2, 32, 51,213, 2, 32,188,200, 2,240,190,200, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,176, 51,213, 2,191, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, +104, 51,213, 2,168,190,200, 2,240,190,200, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 96, 0, 0, 0,168,120,207, 2, +193, 0, 0, 0, 1, 0, 0, 0, 56,121,207, 2, 0, 0, 0, 0,104,188,200, 2,144,187,200, 2,216,187,200, 2,176,188,200, 2, + 0, 0, 0, 0, 0, 0, 0, 0,110, 7, 0, 0,189, 3, 0, 0,219, 3, 0, 0, 7, 7,111, 7, 31, 0, 1, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 64,202,201, 2, 32, 42,210, 2, 32, 42,210, 2,192, 66,213, 2,232, 67,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 41,210, 2,192, 41,210, 2, 68, 65, 84, 65,248, 0, 0, 0,192, 66,213, 2,194, 0, 0, 0, 1, 0, 0, 0,232, 67,213, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 96,158, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0,224,237, 68, 0, 0, 0, 0, + 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,110, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,237, 68, 0, 0,200, 65, 0,128,237, 68, + 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 4, 10, 0,111, 7, 26, 0,111, 7, + 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,110, 7, 0, 0, +189, 3, 0, 0,214, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111, 7, 26, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88,177,201, 2, 96,181,131, 3, 96,181,131, 3, 0, 0, 0, 0, + 0, 0, 0, 0,240, 69,207, 2,104, 70,207, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0,232, 67,213, 2, +194, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,192, 66,213, 2, 0, 0, 0, 0, 0,192,107, 69, 0, 0,128,192, 0, 0, 0, 0, + 0, 0, 0, 0,255,191,107, 69, 0, 0, 0,192, 0, 0, 0, 0, 94, 7, 0, 0,111, 7, 0, 0, 18, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 93, 7, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 93, 7, 0, 0, 18, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, + 18, 0, 0, 4, 6, 0,111, 7, 5, 0, 94, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,110, 7, 0, 0,215, 3, 0, 0,219, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,111, 7, 5, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200,176,201, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,224, 70,207, 2,208, 71,207, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 96, 0, 0, 0, 56,121,207, 2,193, 0, 0, 0, 1, 0, 0, 0,200,121,207, 2,168,120,207, 2,136,189,200, 2, +168,190,200, 2,240,190,200, 2, 32,188,200, 2, 0, 0, 0, 0, 17, 6, 0, 0,110, 7, 0, 0, 0, 0, 0, 0,243, 2, 0, 0, + 4, 4, 94, 1,244, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,201,201, 2,216, 86,213, 2, 64, 93,213, 2, 16, 69,213, 2, + 56, 70,213, 2, 0, 0, 0, 0, 0, 0, 0, 0,224, 39,210, 2,160, 40,210, 2, 68, 65, 84, 65,248, 0, 0, 0, 16, 69,213, 2, +194, 0, 0, 0, 1, 0, 0, 0, 56, 70,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,193, 67, 0, 0, 0, 0, 0, 0,208, 65, + 0, 0, 0, 0, 0, 0,175, 67, 0, 0, 0, 0, 0, 0,248, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 1, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, + 0,128,137, 67, 0, 0,200, 65, 0,128,137, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, + 4, 0, 12, 4, 10, 0, 94, 1, 31, 0, 94, 1, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 6, 0, 0,110, 7, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 94, 1, 31, 0, 4, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,176,201, 2, +232, 29,139, 3,232, 29,139, 3, 0, 0, 0, 0, 0, 0, 0, 0, 72, 72,207, 2, 56, 73,207, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65,248, 0, 0, 0, 56, 70,213, 2,194, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 16, 69,213, 2, 0, 0, 0, 0, + 0, 0,166, 67, 0, 0, 89,196, 0, 0, 0, 0, 0, 0, 0, 0,253,127,166, 67,253,191, 48,196, 0, 0, 0, 0, 77, 1, 0, 0, + 94, 1, 0, 0, 18, 0, 0, 0,212, 2, 0, 0, 0, 0, 0, 0, 76, 1, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, + 76, 1, 0, 0, 18, 0, 0, 0,212, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0, 94, 1,213, 2, 77, 1,195, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,136, 36,210, 2, 1, 0, 0, 0, 0, 0, 0, 0, 17, 6, 0, 0,110, 7, 0, 0, 31, 0, 0, 0,243, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 1,213, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,168,175,201, 2,240,161,133, 3,120,181,138, 3, 96, 71,213, 2, 8,165,138, 3,176, 73,207, 2, + 24, 75,207, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 96, 71,213, 2,192, 0, 0, 0, 1, 0, 0, 0, +200, 72,213, 2, 0, 0, 0, 0, 56, 70,201, 2, 0, 0, 0, 0, 66, 85, 84, 84, 79, 78, 83, 95, 80, 84, 95, 99,111,110,116,101, +120,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 85, 84, 84, 79, 78, 83, 95, 80, 84, 95, 99,111,110,116,101, +120,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,111,110,116,101,120,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,220,255,208, 0, 36, 0, - 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,220,255, 76, 1, 36, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0,112, 26, 11, 7,189, 0, 0, 0, 1, 0, 0, 0,232, 27, 11, 7,248, 24, 11, 7,232,164, 2, 7, - 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,114,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,114,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 82,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,135,255,208, 0, 61, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,232, 27, 11, 7,189, 0, 0, 0, 1, 0, 0, 0, - 96, 29, 11, 7,112, 26, 11, 7,192,166, 2, 7, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,108, 97,121,101,114,115, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,108, 97,121,101,114,115, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111,255,208, 0, 0, 0, 0, 0, 0, 0, 4, 0, 2, 0, - 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, - 96, 29, 11, 7,189, 0, 0, 0, 1, 0, 0, 0,216, 30, 11, 7,232, 27, 11, 7,152,168, 2, 7, 0, 0, 0, 0, 83, 67, 69, 78, - 69, 95, 80, 84, 95,100,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +200, 72,213, 2,192, 0, 0, 0, 1, 0, 0, 0, 48, 74,213, 2, 96, 71,213, 2,248, 91,137, 3, 0, 0, 0, 0, 83, 67, 69, 78, + 69, 95, 80, 84, 95,114,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, - 69, 95, 80, 84, 95,100,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68,105,109,101, -110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,165,254, -208, 0,178, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 69, 95, 80, 84, 95,114,101,110,100,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,101,110,100, +101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,135,255, + 76, 1, 61, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,216, 30, 11, 7,189, 0, 0, 0, 1, 0, 0, 0, 80, 32, 11, 7, 96, 29, 11, 7, -112,170, 2, 7, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95, 97,110,116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 48, 74,213, 2,192, 0, 0, 0, 1, 0, 0, 0,152, 75,213, 2,200, 72,213, 2, +184, 92,137, 3, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,108, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95, 97,110,116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,108, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 65,110,116,105, 45, 65,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 76, 97,121,101,114,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,254,208, 0, 58, 0, 20, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111,255, 76, 1, 0, 0, 0, 0, 0, 0, 4, 0, 10, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 80, 32, 11, 7,189, 0, 0, 0, - 1, 0, 0, 0,104,153, 9, 7,216, 30, 11, 7, 72,172, 2, 7, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,115,104, 97, -100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,115,104, 97, -100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,104, 97,100,105,110,103, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,152, 75,213, 2,192, 0, 0, 0, + 1, 0, 0, 0, 0, 77,213, 2, 48, 74,213, 2,120, 93,137, 3, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,100,105,109, +101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,100,105,109, +101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68,105,109,101,110,115,105,111,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,213,253,208, 0,102, 0, 0, 0, 0, 0, - 0, 0, 2, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,165,254, 76, 1,178, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 56, 1, 0, 0,104,153, 9, 7,189, 0, 0, 0, 1, 0, 0, 0,224,154, 9, 7, 80, 32, 11, 7, 32,174, 2, 7, 0, 0, 0, 0, - 83, 67, 69, 78, 69, 95, 80, 84, 95,111,117,116,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 56, 1, 0, 0, 0, 77,213, 2,192, 0, 0, 0, 1, 0, 0, 0,104, 78,213, 2,152, 75,213, 2, 56, 94,137, 3, 0, 0, 0, 0, + 83, 67, 69, 78, 69, 95, 80, 84, 95, 97,110,116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 83, 67, 69, 78, 69, 95, 80, 84, 95,111,117,116,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 83, 67, 69, 78, 69, 95, 80, 84, 95, 97,110,116,105, 97,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 79,117,116,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 65,110,116,105, 45, 65,108,105, 97,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 84,253,208, 0,105, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 83,254, 76, 1, 58, 0, 20, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,224,154, 9, 7,189, 0, 0, 0, 1, 0, 0, 0, 88,156, 9, 7, -104,153, 9, 7,208,177, 2, 7, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,112,101,114,102,111,114,109, 97,110, 99,101, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,104, 78,213, 2,192, 0, 0, 0, 1, 0, 0, 0,208, 79,213, 2, + 0, 77,213, 2,248, 94,137, 3, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,115,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,112,101,114,102,111,114,109, 97,110, 99,101, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,115,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,104, 97,100,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60,253,208, 0, 0, 0, 0, 0, 0, 0, 4, 0, 2, 0, 0, 0, 0, 0, - 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,213,253, 76, 1,102, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 88,156, 9, 7, -189, 0, 0, 0, 1, 0, 0, 0,208,157, 9, 7,224,154, 9, 7,168,179, 2, 7, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, - 95,112,111,115,116, 95,112,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,208, 79,213, 2, +192, 0, 0, 0, 1, 0, 0, 0, 56, 81,213, 2,104, 78,213, 2,184, 95,137, 3, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, + 95,111,117,116,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, - 95,112,111,115,116, 95,112,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,111,115,116, 32, 80,114,111, - 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36,253,208, 0, 0, 0, - 0, 0, 0, 0, 4, 0, 2, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 95,111,117,116,112,117,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79,117,116,112,117,116, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84,253, 76, 1,105, 0, + 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0,208,157, 9, 7,189, 0, 0, 0, 1, 0, 0, 0, 72,159, 9, 7, 88,156, 9, 7,128,181, 2, 7, - 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,115,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 56, 1, 0, 0, 56, 81,213, 2,192, 0, 0, 0, 1, 0, 0, 0,160, 82,213, 2,208, 79,213, 2, 56, 97,137, 3, + 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,112,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,115,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,112,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 83,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 80,101,114,102,111,114,109, 97,110, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 12,253,208, 0, 0, 0, 20, 0, 0, 0, 4, 0, 2, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 60,253, 76, 1, 0, 0, 0, 0, 0, 0, 4, 0, 10, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 72,159, 9, 7,189, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0,208,157, 9, 7, 88,183, 2, 7, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,117,110,105,116, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,160, 82,213, 2,192, 0, 0, 0, 1, 0, 0, 0, + 8, 84,213, 2, 56, 81,213, 2,248, 97,137, 3, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,112,111,115,116, 95,112,114, +111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,112,111,115,116, 95,112,114, +111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,111,115,116, 32, 80,114,111, 99,101,115,115,105,110,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,117,110,105,116, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36,253, 76, 1, 0, 0, 0, 0, 0, 0, 4, 0, 10, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85,110,105,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,244,252,208, 0, 0, 0, 0, 0, 0, 0, 4, 0, 3, 0, - 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,224, 0, 0, 0, -192,160, 9, 7,158, 0, 0, 0, 1, 0, 0, 0,120,148, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, + 8, 84,213, 2,192, 0, 0, 0, 1, 0, 0, 0,112, 85,213, 2,160, 82,213, 2,184, 98,137, 3, 0, 0, 0, 0, 83, 67, 69, 78, + 69, 95, 80, 84, 95,115,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, + 69, 95, 80, 84, 95,115,116, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83,116, 97,109, +112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12,253, + 76, 1, 0, 0, 20, 0, 0, 0, 4, 0, 10, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,112, 85,213, 2,192, 0, 0, 0, 1, 0, 0, 0,112,166,138, 3, 8, 84,213, 2, +120, 99,137, 3, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,117,110,105,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,117,110,105,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 85,110,105,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,244,252, 76, 1, 0, 0, 0, 0, 0, 0, 4, 0, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,112,166,138, 3,192, 0, 0, 0, + 1, 0, 0, 0, 8,165,138, 3,112, 85,213, 2, 56,100,137, 3, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,107,101,121, +105,110,103, 95,115,101,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 69, 78, 69, 95, 80, 84, 95,107,101,121, +105,110,103, 95,115,101,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75,101,121,105,110,103, 32, 83,101,116,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 80,175, 11, 7, -255, 20, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0,224,161, 9, 7,191, 0, 0, 0, 1, 0, 0, 0, - 40,144, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,138, 67, - 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,237, 68, 0, 0,200, 65, - 0,128,237, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 4, 10, 0, 20, 1, - 26, 0, 20, 1, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 6, 0, 0, -108, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 1, 26, 0, - 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0, - 40,144, 10, 7,191, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,224,161, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 89, 6, 0, 0,108, 7, 0, 0, 26, 0, 0, 0, 80, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 20, 1, 55, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 96,145, 10, 7, 68, 65, 84, 65,216, 2, 0, 0, 96,145, 10, 7,152, 0, 0, 0, 1, 0, 0, 0,103,212,136, 64, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 80, 1,128,191, 0, 0,128,191, 0, 0, 0,128, 0, 0, 0,128,226,215,163,188, 0, 0, 0,128, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,193, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, 0, 0,128, 63,103,212,136, 64, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 80, 1,128,191, 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0,184,175, 31, 65, 0, 0, 32, 65,237,122,111, 62, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,161, 14,106, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -209,252,249,195,115,253, 71,194, 0, 0, 0, 0, 0, 0, 0, 0, 98,127,249, 67,129,255, 71, 66, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,193, 0, 0,128, 63,103,212,136, 64, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 80, 1,128,191, 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0,184,175, 31, 65, 0, 0, 32, 65, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100, 32,222, 58, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,240, 0, 0, 0,120,148, 10, 7,153, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0,192,160, 9, 7,224,161, 9, 7, 40,144, 10, 7, 1, 0, 0, 0, 51, 51, 51, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, - 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0, 56,192, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 12, 66, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 10,215, 35, 60, 0, 0,250, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, 10, 0,159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 96, 0, 0, 0,200, 33, 11, 7, -190, 0, 0, 0, 1, 0, 0, 0, 48,124, 9, 7, 24, 23, 11, 7,208, 79, 10, 7,104, 25, 4, 7, 64,160, 4, 7, 88,147, 4, 7, - 0, 0, 0, 0, 0, 0, 0, 0,215, 3, 0, 0, 0, 0, 0, 0, 71, 0, 0, 0, 15, 15,216, 3, 72, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0,123, 92, 2, 24,152, 10, 7, 0,123, 9, 7,168,149, 10, 7,224,150, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, -176, 58, 5, 7,144, 59, 5, 7, 68, 65, 84, 65,248, 0, 0, 0,168,149, 10, 7,191, 0, 0, 0, 1, 0, 0, 0,224,150, 10, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,128, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 56, 0, 0,118, 68, 0, 0, 0, 0, - 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,215, 3, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,224,202, 68, 0, 0,200, 65, 0,224,202, 68, - 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 4, 10, 0,216, 3, 26, 0,216, 3, - 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,215, 3, 0, 0, - 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 3, 26, 0, 5, 0, 1, 0, - 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,124, 92, 2,248, 23, 6, 7,248, 23, 6, 7, 0, 0, 0, 0, - 0, 0, 0, 0, 96, 61, 5, 7,112, 62, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0,224,150, 10, 7, -191, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,168,149, 10, 7, 0, 0, 64,192, 0, 0,126, 67, 0, 0, 0, 0, 0, 0, 72, 66, -112,189, 17,192,246, 70,125, 67, 0, 0, 0, 0, 0, 0, 72, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,215, 3, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,215, 3, 0, 0, 18, 0, 0, 0, 45, 0, 0, 0, - 0, 0,128, 63, 0, 0, 72, 66, 0,124,146, 72, 0, 0, 72, 66,205,204,204, 61, 0, 0, 32, 65, 72, 0, 0, 0, 0, 0, 0, 2, - 4, 0, 0, 4, 8, 0,216, 3, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,215, 3, 0, 0, 26, 0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,216, 3, 46, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,123, 92, 2, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 64, 5, 7,120, 66, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65,180, 0, 0, 0, 24,152, 10, 7,168, 0, 0, 0, 1, 0, 0, 0, 0,123, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 6, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0, 16,153, 10, 7,191, 0, 0, 0, 1, 0, 0, 0,176,118, 9, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,203, 68, 0, 0, 0, 0, - 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 87, 6, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,237, 68, 0, 0,200, 65, 0,128,237, 68, - 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 4, 10, 0, 88, 6, 26, 0, 88, 6, - 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 6, 0, 0, - 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 6, 26, 0, 0, 0, 1, 0, - 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0,176,118, 9, 7, -191, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 16,153, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 87, 6, 0, 0, 26, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 88, 6, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,119, 9, 7, - 68, 65, 84, 65,216, 2, 0, 0,232,119, 9, 7,152, 0, 0, 0, 1, 0, 0, 0, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 87,213,108, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 1,128,191, - 0, 0,128,191, 0, 0, 0,128, 0, 0, 0,128,226,215,163,188, 0, 0, 0,128, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,193, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, 0, 0,128, 63, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 87,213,108, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 1,128,191, - 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0,184,175, 31, 65, 0, 0, 32, 65,161, 14,106, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,224, 91,138, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,209,252,249,195, -115,253, 71,194, 0, 0, 0, 0, 0, 0, 0, 0, 98,127,249, 67,129,255, 71, 66, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,193, 0, 0,128, 63, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 87,213,108, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 1,128,191, - 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0,184,175, 31, 65, 0, 0, 32, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 32, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52,149,147, 58, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,240, 0, 0, 0, 0,123, 9, 7,153, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 24,152, 10, 7, 16,153, 10, 7,176,118, 9, 7, 1, 0, 0, 0, 51, 51, 51, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, 0, 0, 0, 0, - 1, 0, 0, 0, 1, 0, 7, 0, 56,192, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, - 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 12, 66, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 10,215, 35, 60, 0, 0,250, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16, 0, 0, 0, 7, 0, 10, 0,159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 96, 0, 0, 0, 48,124, 9, 7,190, 0, 0, 0, - 1, 0, 0, 0, 72,136, 9, 7,200, 33, 11, 7,104, 25, 4, 7,232,251, 3, 7,136,121, 4, 7, 64,160, 4, 7, 0, 0, 0, 0, - 0, 0, 0, 0,215, 3, 0, 0, 73, 0, 0, 0,226, 2, 0, 0, 1, 1,216, 3,154, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -232,124, 92, 2, 24,135, 9, 7, 24,135, 9, 7,208,124, 9, 7,160,229, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 5, 7, - 48, 69, 5, 7, 68, 65, 84, 65,248, 0, 0, 0,208,124, 9, 7,191, 0, 0, 0, 1, 0, 0, 0, 8,126, 9, 7, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 64, 90, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,118, 68, 0, 0, 0, 0, 0, 0,208, 65, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,215, 3, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,237, 68, 0, 0,200, 65, 0,128,237, 68, 0, 0,200, 65, - 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 4, 10, 0,216, 3, 26, 0,216, 3, 26, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,215, 3, 0, 0, 73, 0, 0, 0, - 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 3, 26, 0, 7, 0, 1, 0, 2, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,132, 92, 2, 32, 77,104, 2, 32, 77,104, 2, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 71, 5, 7,152, 72, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0, 8,126, 9, 7,191, 0, 0, 0, - 1, 0, 0, 0, 48,130, 9, 7,208,124, 9, 7, 0, 0, 0, 0, 0, 0, 15, 67, 0, 0,251,195, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 15, 67, 0, 0,251,195, 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, 18, 0, 0, 0, 7, 2, 0, 0, 0, 0, 0, 0, -142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 18, 0, 0, 0, 7, 2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, - 6, 0,160, 0, 8, 2,143, 0,246, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,159, 0, 0, 0,219, 0, 0, 0,226, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -160, 0, 8, 2, 8, 0, 5, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,129, 92, 2, 72,117,101, 2, -136, 52,102, 2, 64,127, 9, 7,184,128, 9, 7,128, 74, 5, 7, 24, 76, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 56, 1, 0, 0, 64,127, 9, 7,189, 0, 0, 0, 1, 0, 0, 0,184,128, 9, 7, 0, 0, 0, 0,224,129, 92, 2, 0, 0, 0, 0, - 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108, 95,115,104,101,108,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108, 95,115,104,101,108,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 84,111,111,108, 32, 83,104,101,108,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,196,255,143, 0, 36, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,184,128, 9, 7,189, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 64,127, 9, 7, 80,129, 4, 7, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95,111, 98,106,101, - 99,116,109,111,100,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95,111, 98,106,101, - 99,116,109,111,100,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 98,106,101, 99,116, 32, 84,111,111,108,115, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27,254,143, 0,145, 1, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0, 48,130, 9, 7, -191, 0, 0, 0, 1, 0, 0, 0,152,219, 10, 7, 8,126, 9, 7, 0, 0, 0, 0, 0, 0, 16, 67, 0, 0,206,194, 0, 0, 0, 0, - 0, 0, 0, 0,231,102, 16, 67, 0, 0,206,194, 0, 0, 0, 0,143, 0, 0, 0,160, 0, 0, 0, 18, 0, 0, 0,119, 0, 0, 0, - 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 18, 0, 0, 0,119, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, - 18, 0, 0, 4, 6, 0,160, 0,120, 0,143, 0,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,159, 0, 0, 0, 99, 0, 0, 0,218, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,160, 0,120, 0, 9, 0, 6, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,176,130, 92, 2, -120, 73, 25, 7,120, 73, 25, 7, 32,218, 10, 7, 32,218, 10, 7, 0, 78, 5, 7,152, 79, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 56, 1, 0, 0, 32,218, 10, 7,189, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,131, 92, 2, - 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,108, 97,115,116, 95,111,112,101,114, 97,116,111,114, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,108, 97,115,116, 95,111,112,101,114, 97,116,111,114, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 79,112,101,114, 97,116,111,114, 0,105,116,109,111,100,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,216,255,144, 0, 16, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0,152,219, 10, 7,191, 0, 0, 0, 1, 0, 0, 0, -160,229, 10, 7, 48,130, 9, 7, 0, 0, 0, 0, 0, 0, 75, 67, 0,128,118,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 67, - 0,128, 27,196, 0, 0, 0, 0,203, 0, 0, 0,220, 0, 0, 0, 18, 0, 0, 0,127, 2, 0, 0, 0, 0, 0, 0,202, 0, 0, 0, - 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,202, 0, 0, 0, 18, 0, 0, 0,127, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,220, 0, -128, 2,203, 0,110, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,215, 3, 0, 0, -215, 3, 0, 0, 99, 0, 0, 0,226, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, - 0, 0, 4, 0, 4, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 48,126, 92, 2, 0, 0, 0, 0, 0, 0, 0, 0, -208,220, 10, 7, 40,228, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, -208,220, 10, 7,189, 0, 0, 0, 1, 0, 0, 0, 72,222, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, - 51, 68, 95, 80, 84, 95,111, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, - 51, 68, 95, 80, 84, 95,111, 98,106,101, 99,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84,114, 97,110, -115,102,111,114,109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26,255, -203, 0,206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 72,222, 10, 7,189, 0, 0, 0, 1, 0, 0, 0,192,223, 10, 7,208,220, 10, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,103,112,101,110, 99,105,108, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,103,112,101,110, 99,105,108, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 71,114,101, 97,115,101, 32, 80,101,110, 99,105,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200,254,203, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,192,223, 10, 7,189, 0, 0, 0, - 1, 0, 0, 0, 56,225, 10, 7, 72,222, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95, 51,100, -118,105,101,119, 95,112,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95, 51,100, -118,105,101,119, 95,112,114,111,112,101,114,116,105,101,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86,105,101,119, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,129,253,203, 0, 47, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,220,252, 76, 1, 0, 0, 0, 0, 0, 0, + 4, 0, 2, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 56, 1, 0, 0, 56,225, 10, 7,189, 0, 0, 0, 1, 0, 0, 0,176,226, 10, 7,192,223, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, - 86, 73, 69, 87, 51, 68, 95, 80, 84, 95, 51,100,118,105,101,119, 95,100,105,115,112,108, 97,121, 0, 0, 0, 0, 0, 0, 0, 0, + 56, 1, 0, 0, 8,165,138, 3,192, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,112,166,138, 3,184,101,137, 3, 0, 0, 0, 0, + 83, 67, 69, 78, 69, 95, 80, 84, 95,112,104,121,115,105, 99,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 86, 73, 69, 87, 51, 68, 95, 80, 84, 95, 51,100,118,105,101,119, 95,100,105,115,112,108, 97,121, 0, 0, 0, 0, 0, 0, 0, 0, + 83, 67, 69, 78, 69, 95, 80, 84, 95,112,104,121,115,105, 99,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68,105,115,112,108, 97,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 71,114, 97,118,105,116,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 66,252,203, 0, 39, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,160,252, 76, 1, 36, 0, 20, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,176,226, 10, 7,189, 0, 0, 0, 1, 0, 0, 0, 40,228, 10, 7, - 56,225, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95, 51,100,118,105,101,119, 95,109,101,115, -104,100,105,115,112,108, 97,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95, 51,100,118,105,101,119, 95,109,101,115, -104,100,105,115,112,108, 97,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77,101,115,104, 32, 68,105,115,112,108, 97,121, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254,250,203, 0,104, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 40,228, 10, 7, -189, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,176,226, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, - 84, 95, 98, 97, 99,107,103,114,111,117,110,100, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, - 84, 95, 98, 97, 99,107,103,114,111,117,110,100, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 97, 99,107,103,114,111,117, -110,100, 32, 73,109, 97,103,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42,252,203, 0, 0, 0, - 20, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65,248, 0, 0, 0,160,229, 10, 7,191, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,152,219, 10, 7, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,215, 3, 0, 0, 99, 0, 0, 0,226, 2, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216, 3,128, 2, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,144,125, 92, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 81, 5, 7, - 40, 84, 5, 7, 0, 0, 0, 0, 0,132, 9, 7, 68, 65, 84, 65,216, 2, 0, 0, 0,132, 9, 7,152, 0, 0, 0, 1, 0, 0, 0, - 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 64,215, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 28, 13,128,191, 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0, 74,215, 76,190, 0, 0, 0, 0, -238, 4, 53, 63,186,103, 59,190,247,217, 46, 63, 0, 0, 0, 0,255, 4, 53, 63,126,103, 59, 62,244,217, 46,191, 0, 0, 0, 0, -228, 3, 52, 50,248, 70,119, 63,217,131,132, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 60,138,193, 0, 0,128, 63, -236, 4, 53, 63,244, 4, 53, 63, 0, 0, 24, 53, 0, 0, 0, 0,137,103, 59,190,118,103, 59, 62,227, 70,119, 63, 0, 0, 0, 0, -238,217, 46, 63,221,217, 46,191,213,131,132, 62, 0, 0, 0, 0,186,213, 60, 65,168,213, 60,193,221, 28,143, 64, 0, 0,128, 63, -100,253, 69, 63,248,146,157,190,223,235, 46,191,247,217, 46,191,119,253, 69, 63,197,146,157, 62,220,235, 46, 63,244,217, 46, 63, - 65,228, 68, 50,109,234,207, 63,107,145,132,190,217,131,132,190, 0, 0, 0, 0, 0, 0, 0, 0, 18,177,136, 65,152, 60,138, 65, -252,128, 37, 63,186,128, 37, 63, 0, 0,180, 53, 0, 0, 60, 52,154,225,222,189,131,225,222, 61,139, 11, 19, 63, 0, 0,144, 51, - 25,255,107,194, 1,255,107, 66,239,218,178,193,208,247,159,192,220, 91,105, 66,197, 91,105,194, 49,219,176, 65, 50, 8,160, 64, -238, 4, 53, 63,186,103, 59,190,247,217, 46, 63, 0, 0, 0, 0,255, 4, 53, 63,126,103, 59, 62,244,217, 46,191, 0, 0, 0, 0, -228, 3, 52, 50,248, 70,119, 63,217,131,132, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 60,138,193, 0, 0,128, 63, -100,253, 69, 63,248,146,157,190,223,235, 46,191,247,217, 46,191,119,253, 69, 63,197,146,157, 62,220,235, 46, 63,244,217, 46, 63, - 65,228, 68, 50,109,234,207, 63,107,145,132,190,217,131,132,190, 0, 0, 0, 0, 0, 0, 0, 0, 18,177,136, 65,152, 60,138, 65, -166, 33, 26, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,166, 33, 26, 64, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,166, 33, 26, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, -122,163, 59, 63,235,250, 15,191,221,141,110,190,230,113,155,190,152, 60,138, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 83,146,243, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,240, 0, 0, 0, - 24,135, 9, 7,153, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 51, 51, 51, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 32, 65, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0, 56,192, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 12, 66, - 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,205,204,204, 61, 0, 0,250, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, 10, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0,255,255, - 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 96, 0, 0, 0, 72,136, 9, 7,190, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 48,124, 9, 7, 32, 26, 15, 7,136,121, 4, 7, - 48, 16, 4, 7,176,183, 3, 7, 0, 0, 0, 0,217, 3, 0, 0,186, 4, 0, 0, 73, 2, 0, 0,226, 2, 0, 0, 3, 3,226, 0, -154, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24,121, 92, 2, 88,139, 9, 7, 24,238, 10, 7,232,136, 9, 7, 32,138, 9, 7, - 0, 0, 0, 0, 0, 0, 0, 0,120, 86, 5, 7, 88, 87, 5, 7, 68, 65, 84, 65,248, 0, 0, 0,232,136, 9, 7,191, 0, 0, 0, - 1, 0, 0, 0, 32,138, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,190, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, - 0, 0, 98, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,225, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 66, 67, - 0, 0,200, 65, 0, 0, 66, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 4, - 10, 0,226, 0, 26, 0,226, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -217, 3, 0, 0,186, 4, 0, 0, 73, 2, 0, 0, 98, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -226, 0, 26, 0, 11, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96,122, 92, 2, 96,150, 25, 7, - 96,150, 25, 7, 0, 0, 0, 0, 0, 0, 0, 0, 40, 89, 5, 7,176, 89, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, -248, 0, 0, 0, 32,138, 9, 7,191, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,232,136, 9, 7, 0, 0, 0, 0, 0,128,131, 67, - 0, 0,228,194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 67, 0, 0,220,194, 0, 0, 0, 0,209, 0, 0, 0,226, 0, 0, 0, - 18, 0, 0, 0,127, 0, 0, 0, 0, 0, 0, 0,208, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,208, 0, 0, 0, - 18, 0, 0, 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 18, 0, 0, 0, 2, 0, 3, 3, 0, 0, 0, 4, 6, 0,226, 0,128, 0,209, 0,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,217, 3, 0, 0,186, 4, 0, 0, 99, 2, 0, 0,226, 2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,226, 0,128, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,192,121, 92, 2,200,170, 25, 7,200,170, 25, 7, 0, 0, 0, 0, 0, 0, 0, 0,152, 91, 5, 7,168, 92, 5, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 4, 1, 0, 0, 88,139, 9, 7,162, 0, 0, 0, 1, 0, 0, 0,112,231, 10, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,176,125, 25, 7,176,125, 25, 7, -216,143, 12, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 68, 65, 84, 65, 12, 0, 0, 0,216,143, 12, 7,214, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0,160,140, 9, 7, - 68, 65, 84, 65,156, 0, 0, 0,160,140, 9, 7,213, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,160, 33, 10, 7, - 19, 0, 0, 0, 1, 0, 1, 0,160, 33, 10, 7, 20, 0, 0, 0, 1, 0, 1, 0,160, 33, 10, 7, 21, 0, 1, 0, 1, 0, 1, 0, -160, 33, 10, 7, 0, 0, 0, 0, 1, 0, 1, 0, 64, 39, 10, 7, 0, 0, 0, 0, 1, 0, 1, 0,224,195, 9, 7, 0, 0, 0, 0, - 1, 0, 1, 0, 48, 21, 12, 7, 0, 0, 0, 0, 1, 0, 1, 0, 48,203, 9, 7, 0, 0, 0, 0, 1, 0, 1, 0,224, 45, 10, 7, - 0, 0, 0, 0, 1, 0, 1, 0,136,199, 9, 7, 0, 0, 0, 0, 1, 0, 1, 0,208,240, 10, 7, 0, 0, 0, 0, 1, 0, 1, 0, - 56,192, 9, 7, 0, 0, 0, 0, 1, 0, 1, 0,240,143, 9, 7, 68, 65, 84, 65,248, 0, 0, 0,128,141, 9, 7,191, 0, 0, 0, - 1, 0, 0, 0,184,142, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 55, - 0, 0, 67, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,194, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,137, 67, - 0, 0,200, 65, 0,128,137, 67, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 4, - 10, 0,195, 0, 26, 0,195, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 53, 4, 0, 0,247, 4, 0, 0, 69, 2, 0, 0, 94, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -195, 0, 26, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, -248, 0, 0, 0,184,142, 9, 7,191, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,128,141, 9, 7, 0, 0, 0, 0, 0, 0,150, 67, - 0,192,116,196, 0, 0, 0, 0, 0, 0, 0, 0,205, 85,150, 67,223,204, 35,196, 26, 85,207,195, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,194, 0, 0, 0, - 0, 0, 0, 0,155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, - 0, 0, 0, 0, 1, 0, 3, 0, 2, 0, 0, 4, 6, 0,195, 0,156, 0,195, 0,156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 4, 0, 0,247, 4, 0, 0, 95, 2, 0, 0,250, 2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,195, 0,156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,224, 0, 0, 0,112,231, 10, 7,158, 0, 0, 0, 1, 0, 0, 0, 24,238, 10, 7, - 88,139, 9, 7,128,141, 9, 7,184,142, 9, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,224, 0, 0, 0,216, 86,213, 2,161, 0, 0, 0, 1, 0, 0, 0, 64, 93,213, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, -248, 0, 0, 0,144,232, 10, 7,191, 0, 0, 0, 1, 0, 0, 0,200,233, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 68, + 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 32,153,136, 3,255, 20, 0, 0,160, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, +248, 0, 0, 0,232, 87,213, 2,194, 0, 0, 0, 1, 0, 0, 0, 16, 89,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,138, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,237, 68, 0, 0,200, 65, 0,128,237, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, @@ -588,16 +255,16 @@ char datatoc_B_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 6, 0, 0,108, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 1, 26, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0,200,233, 10, 7,191, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -144,232, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0, 16, 89,213, 2,194, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, +232, 87,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 6, 0, 0,108, 7, 0, 0, 26, 0, 0, 0, 80, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 1, 55, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,235, 10, 7, 68, 65, 84, 65,216, 2, 0, 0, 0,235, 10, 7, -152, 0, 0, 0, 1, 0, 0, 0,103,212,136, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 90,213, 2, 68, 65, 84, 65,216, 2, 0, 0, 56, 90,213, 2, +155, 0, 0, 0, 1, 0, 0, 0,103,212,136, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 1,128,191, 0, 0,128,191, 0, 0, 0,128, 0, 0, 0,128, 226,215,163,188, 0, 0, 0,128, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -620,63 +287,417 @@ char datatoc_B_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65,240, 0, 0, 0, 24,238, 10, 7,153, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,112,231, 10, 7,144,232, 10, 7, -200,233, 10, 7, 1, 0, 0, 0, 51, 51, 51, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0, 56,192, 9, 7, + 68, 65, 84, 65,240, 0, 0, 0, 64, 93,213, 2,156, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,216, 86,213, 2,232, 87,213, 2, + 16, 89,213, 2, 1, 0, 0, 0, 51, 51, 51, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0,240,211,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 12, 66, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 10,215, 35, 60, 0, 0,250, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, 10, 0,159, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 83, 67, 0, 0, 92, 5, 0, 0,160, 33, 10, 7,150, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 83, 99,101,110,101, 0,116, 97,103,101, 0, 97,105,110, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56,192, 9, 7, 64, 39, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, -120,188, 2, 7, 48,241, 2, 7,120,188, 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,239, 10, 7,152,230,101, 2, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68,172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100, 0, 0, 0,100, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 2, -224, 1, 60, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 6, 0, 25, 0,141, 0,128, 7, 56, 4, 8, 0, 8, 0, 0, 0, - 24, 0, 17, 0, 0, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 23, 0, 33, 0, 0, 0,128, 0, 0, 0, 8, 0, - 24, 0, 10, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48,231, 9, 7, 48,231, 9, 7, 0, 0, 0, 0, - 0, 0,200, 66, 0, 0,200, 66, 0, 0,128, 63, 0, 0,128, 63, 1, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 5, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 98, 97, - 99,107, 98,117,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 96, 0, 0, 0,200,121,207, 2,193, 0, 0, 0, 1, 0, 0, 0, 88,122,207, 2, 56,121,207, 2, + 72,187,200, 2, 24,190,200, 2, 96,190,200, 2,136,189,200, 2, 0, 0, 0, 0, 0, 0, 0, 0, 15, 6, 0, 0, 0, 0, 0, 0, + 95, 0, 0, 0, 15, 15, 16, 6, 96, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,198,201, 2,176, 96,213, 2,240,102,213, 2, + 96, 94,213, 2,136, 95,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 64, 43,210, 2,128, 42,210, 2, 68, 65, 84, 65,248, 0, 0, 0, + 96, 94,213, 2,194, 0, 0, 0, 1, 0, 0, 0,136, 95,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64,129, 68, 0, 0, 0, 0, + 0, 0,208, 65, 0, 0, 0, 0, 0, 0,194, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 6, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 0,224,202, 68, 0, 0,200, 65, 0,224,202, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, + 2, 0, 3, 3, 4, 0, 12, 4, 10, 0, 16, 6, 26, 0, 16, 6, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 6, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 16, 6, 26, 0, 6, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 56,167,201, 2,136,163,133, 3,136,163,133, 3, 0, 0, 0, 0, 0, 0, 0, 0,144, 75,207, 2,128, 76,207, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0,136, 95,213, 2,194, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 96, 94,213, 2, + 0, 0, 64,192, 0, 0,126, 67, 0, 0, 0, 0, 0, 0, 72, 66,112,189, 17,192,246, 70,125, 67, 0, 0, 0, 0, 0, 0, 72, 66, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 6, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, + 0, 0, 0, 0, 15, 6, 0, 0, 18, 0, 0, 0, 69, 0, 0, 0, 0, 0,128, 63, 0, 0, 72, 66, 0,124,146, 72, 0, 0, 72, 66, +205,204,204, 61, 0, 0, 32, 65, 72, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 4, 8, 0, 16, 6, 70, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 6, 0, 0, 26, 0, 0, 0, + 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 6, 70, 0, 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,166,201, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +248, 76,207, 2,216, 78,207, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,180, 0, 0, 0,176, 96,213, 2,171, 0, 0, 0, + 1, 0, 0, 0,240,102,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47,116,109,112, - 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0, +152, 97,213, 2,194, 0, 0, 0, 1, 0, 0, 0,192, 98,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 68, 0, 0, 0, 0, + 0, 0,208, 65, 0, 0, 0, 0, 0, 0,203, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 6, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 0,128,237, 68, 0, 0,200, 65, 0,128,237, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, + 2, 0, 3, 3, 4, 0, 12, 4, 10, 0, 88, 6, 26, 0, 88, 6, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 6, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 88, 6, 26, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0,192, 98,213, 2,194, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,152, 97,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 6, 0, 0, 26, 0, 0, 0, + 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 6, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232, 99,213, 2, 68, 65, 84, 65,216, 2, 0, 0,232, 99,213, 2,155, 0, 0, 0, + 1, 0, 0, 0, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87,213,108, 66, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 1,128,191, 0, 0,128,191, 0, 0, 0,128, 0, 0, 0,128,226,215,163,188, + 0, 0, 0,128, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,193, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, + 0, 0,128, 63, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87,213,108, 66, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 1,128,191, 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0,184,175, 31, 65, + 0, 0, 32, 65,161, 14,106, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,224, 91,138, 60, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,209,252,249,195,115,253, 71,194, 0, 0, 0, 0, 0, 0, 0, 0, 98,127,249, 67, +129,255, 71, 66, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,193, + 0, 0,128, 63, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87,213,108, 66, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 1,128,191, 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0,184,175, 31, 65, + 0, 0, 32, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 52,149,147, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, +240, 0, 0, 0,240,102,213, 2,156, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,176, 96,213, 2,152, 97,213, 2,192, 98,213, 2, + 1, 0, 0, 0, 51, 51, 51, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0,240,211,213, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, + 0, 0, 12, 66, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 10,215, 35, 60, 0, 0,250, 67, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, 10, 0,159, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 96, 0, 0, 0, 88,122,207, 2,193, 0, 0, 0, 1, 0, 0, 0,232,122,207, 2,200,121,207, 2, 24,190,200, 2, +104,188,200, 2,208,189,200, 2, 96,190,200, 2, 0, 0, 0, 0, 0, 0, 0, 0, 15, 6, 0, 0, 97, 0, 0, 0,187, 3, 0, 0, + 1, 1, 16, 6, 91, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,152,198,201, 2,232,151,213, 2,232,151,213, 2, 16,104,213, 2, +184,147,213, 2, 0, 0, 0, 0, 0, 0, 0, 0,128, 45,210, 2,160, 43,210, 2, 68, 65, 84, 65,248, 0, 0, 0, 16,104,213, 2, +194, 0, 0, 0, 1, 0, 0, 0, 56,105,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 68, 0, 0, 0, 0, 0, 0,208, 65, + 0, 0, 0, 0, 0, 0,194, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 6, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, + 0,128,237, 68, 0, 0,200, 65, 0,128,237, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, + 4, 0, 12, 4, 10, 0, 16, 6, 26, 0, 16, 6, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 15, 6, 0, 0, 97, 0, 0, 0,122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 16, 6, 26, 0, 8, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8,170,201, 2, + 32,165,133, 3, 32,165,133, 3, 0, 0, 0, 0, 0, 0, 0, 0, 80, 79,207, 2,184, 80,207, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65,248, 0, 0, 0, 56,105,213, 2,194, 0, 0, 0, 1, 0, 0, 0, 48,109,213, 2, 16,104,213, 2, 0, 0, 0, 0, + 0, 0, 15, 67, 0,192, 45,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 67, 0,192, 45,196, 0, 0, 0, 0,143, 0, 0, 0, +160, 0, 0, 0, 18, 0, 0, 0,200, 2, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, +142, 0, 0, 0, 18, 0, 0, 0,200, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, + 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0,201, 2,143, 0,183, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,159, 0, 0, 0,243, 0, 0, 0,187, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 0,201, 2, 9, 0, 5, 0, 11, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,232,168,201, 2, 80,168,133, 3,184,166,133, 3, 96,106,213, 2,200,107,213, 2, 48, 81,207, 2, +232, 78,210, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 96,106,213, 2,192, 0, 0, 0, 1, 0, 0, 0, +200,107,213, 2, 0, 0, 0, 0, 56, 64,201, 2, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108, 95,115, +104,101,108,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,116,111,111,108, 95,115, +104,101,108,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84,111,111,108, 32, 83,104,101,108,102, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,196,255,143, 0, 36, 0, 0, 0, 0, 0, 0, 0, 34, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, +200,107,213, 2,192, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 96,106,213, 2,112,160,135, 3, 0, 0, 0, 0, 86, 73, 69, 87, + 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95,111, 98,106,101, 99,116,109,111,100,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, + 51, 68, 95, 80, 84, 95,116,111,111,108,115, 95,111, 98,106,101, 99,116,109,111,100,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 98,106,101, + 99,116, 32, 84,111,111,108,115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52,254, +143, 0,120, 1, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0, 48,109,213, 2,194, 0, 0, 0, 1, 0, 0, 0,192,111,213, 2, 56,105,213, 2, + 0, 0, 0, 0, 0, 0, 16, 67, 0, 0,206,194, 0, 0, 0, 0, 0, 0, 0, 0,231,102, 16, 67, 0, 0,206,194, 0, 0, 0, 0, +143, 0, 0, 0,160, 0, 0, 0, 18, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0,142, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, + 0, 0, 0, 0,142, 0, 0, 0, 18, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 63, 0, 0, 0, 64, 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 4, 6, 0,160, 0,120, 0,143, 0,102, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,159, 0, 0, 0,123, 0, 0, 0, +242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 0,120, 0, 10, 0, 6, 0, 34, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,169,201, 2,232,169,133, 3,232,169,133, 3, 88,110,213, 2, 88,110,213, 2, + 96, 79,210, 2,200, 80,210, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 88,110,213, 2,192, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 64,201, 2, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,108, 97, +115,116, 95,111,112,101,114, 97,116,111,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,108, 97, +115,116, 95,111,112,101,114, 97,116,111,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79,112,101,114, 97,116,111,114, 0,105,116,109, +111,100,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,216,255,144, 0, 16, 0, 0, 0, 0, 0, + 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, +248, 0, 0, 0,192,111,213, 2,194, 0, 0, 0, 1, 0, 0, 0,184,147,213, 2, 48,109,213, 2, 0, 0, 0, 0, 0, 0, 75, 67, + 0,128,118,196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 67, 0,128, 27,196, 0, 0, 0, 0,203, 0, 0, 0,220, 0, 0, 0, + 18, 0, 0, 0,127, 2, 0, 0, 0, 0, 0, 0,202, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,202, 0, 0, 0, + 18, 0, 0, 0,127, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, + 10, 0, 0, 0, 1, 0, 7, 0, 18, 0, 0, 0, 6, 0,220, 0,128, 2,203, 0,110, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 6, 0, 0, 15, 6, 0, 0,123, 0, 0, 0,187, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 4, 0, 4, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 88,168,201, 2, 0, 0, 0, 0, 0, 0, 0, 0,232,112,213, 2, 8,120,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0,232,112,213, 2,192, 0, 0, 0, 1, 0, 0, 0, 80,114,213, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,111, 98,106,101, 99,116, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95,111, 98,106,101, 99,116, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84,114, 97,110,115,102,111,114,109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26,255,203, 0,206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 80,114,213, 2, +192, 0, 0, 0, 1, 0, 0, 0,208,115,213, 2,232,112,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, + 84, 95,103,112,101,110, 99,105,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, + 84, 95,103,112,101,110, 99,105,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71,114,101, 97,115,101, 32, 80, +101,110, 99,105,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200,254,203, 0, 58, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 56, 1, 0, 0,208,115,213, 2,192, 0, 0, 0, 1, 0, 0, 0, 56,117,213, 2, 80,114,213, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95, 51,100,118,105,101,119, 95,112,114,111,112,101,114,116,105,101,115, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95, 51,100,118,105,101,119, 95,112,114,111,112,101,114,116,105,101,115, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86,105,101,119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,129,253,203, 0, 47, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 56,117,213, 2,192, 0, 0, 0, 1, 0, 0, 0, +160,118,213, 2,208,115,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95, 51,100,118,105,101,119, + 95,100,105,115,112,108, 97,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95, 51,100,118,105,101,119, + 95,100,105,115,112,108, 97,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68,105,115,112,108, 97,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,252,203, 0, 39, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, +160,118,213, 2,192, 0, 0, 0, 1, 0, 0, 0, 8,120,213, 2, 56,117,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, + 51, 68, 95, 80, 84, 95, 51,100,118,105,101,119, 95,109,101,115,104,100,105,115,112,108, 97,121, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, + 51, 68, 95, 80, 84, 95, 51,100,118,105,101,119, 95,109,101,115,104,100,105,115,112,108, 97,121, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77,101,115,104, + 32, 68,105,115,112,108, 97,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254,250, +203, 0,104, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68, 65, 84, 65, 56, 1, 0, 0, 8,120,213, 2,192, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,160,118,213, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95, 98, 97, 99,107,103,114,111,117,110,100, 95,105,109, 97, +103,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 86, 73, 69, 87, 51, 68, 95, 80, 84, 95, 98, 97, 99,107,103,114,111,117,110,100, 95,105,109, 97, +103,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 66, 97, 99,107,103,114,111,117,110,100, 32, 73,109, 97,103,101, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42,252,203, 0, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0,184,147,213, 2,194, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0,192,111,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15, 6, 0, 0,123, 0, 0, 0,187, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 6, 65, 3, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,200,167,201, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 81,210, 2,176, 89,210, 2, 0, 0, 0, 0,224,148,213, 2, 68, 65, 84, 65, +216, 2, 0, 0,224,148,213, 2,155, 0, 0, 0, 1, 0, 0, 0,255,255,139, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,144,107, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 13,128,191, 0, 0,128,191, + 0, 0, 0, 0, 0, 0, 0, 0, 74,215, 76,190, 0, 0, 0, 0,238, 4, 53, 63,186,103, 59,190,247,217, 46, 63, 0, 0, 0, 0, +255, 4, 53, 63,126,103, 59, 62,244,217, 46,191, 0, 0, 0, 0,228, 3, 52, 50,248, 70,119, 63,217,131,132, 62, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,152, 60,138,193, 0, 0,128, 63,236, 4, 53, 63,244, 4, 53, 63, 0, 0, 24, 53, 0, 0, 0, 0, +137,103, 59,190,118,103, 59, 62,227, 70,119, 63, 0, 0, 0, 0,238,217, 46, 63,221,217, 46,191,213,131,132, 62, 0, 0, 0, 0, +186,213, 60, 65,168,213, 60,193,221, 28,143, 64, 0, 0,128, 63, 99,253, 69, 63,212,242,190,190,223,235, 46,191,247,217, 46,191, +117,253, 69, 63,151,242,190, 62,220,235, 46, 63,244,217, 46, 63, 64,228, 68, 50,223,243,251, 63,107,145,132,190,217,131,132,190, + 0, 0, 0, 0, 0, 0, 0, 0, 18,177,136, 65,152, 60,138, 65,252,128, 37, 63,190,128, 37, 63, 0, 0,172, 53, 0, 0, 52, 52, + 40,237,183,189, 22,237,183, 61, 53,176,242, 62, 0, 0,160, 50, 25,255,107,194, 2,255,107, 66,239,218,178,193,209,247,159,192, +220, 91,105, 66,198, 91,105,194, 49,219,176, 65, 51, 8,160, 64,238, 4, 53, 63,186,103, 59,190,247,217, 46, 63, 0, 0, 0, 0, +255, 4, 53, 63,126,103, 59, 62,244,217, 46,191, 0, 0, 0, 0,228, 3, 52, 50,248, 70,119, 63,217,131,132, 62, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,152, 60,138,193, 0, 0,128, 63, 99,253, 69, 63,212,242,190,190,223,235, 46,191,247,217, 46,191, +117,253, 69, 63,151,242,190, 62,220,235, 46, 63,244,217, 46, 63, 64,228, 68, 50,223,243,251, 63,107,145,132,190,217,131,132,190, + 0, 0, 0, 0, 0, 0, 0, 0, 18,177,136, 65,152, 60,138, 65,240,113,195, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,240,113,195, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,113,195, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63,122,163, 59, 63,235,250, 15,191,221,141,110,190,230,113,155,190, +152, 60,138, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,109,154, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,240, 0, 0, 0,232,151,213, 2,156, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 51, 51, 51, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, 0, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 7, 0,240,211,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 12, 66, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,205,204,204, 61, + 0, 0,250, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, + 7, 0, 10, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0,255,255, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 96, 0, 0, 0,232,122,207, 2,193, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 88,122,207, 2,168,190,200, 2,208,189,200, 2,176,188,200, 2,240,190,200, 2, 0, 0, 0, 0, 17, 6, 0, 0, +110, 7, 0, 0,245, 2, 0, 0,187, 3, 0, 0, 3, 3, 94, 1,199, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,216,164,201, 2, + 88,155,213, 2,184,193,213, 2, 8,153,213, 2, 48,154,213, 2, 0, 0, 0, 0, 0, 0, 0, 0,160, 46,210, 2,224, 45,210, 2, + 68, 65, 84, 65,248, 0, 0, 0, 8,153,213, 2,194, 0, 0, 0, 1, 0, 0, 0, 48,154,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0,128,180, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,175, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 93, 1, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 66, 67, 0, 0,200, 65, 0, 0, 66, 67, 0, 0,200, 65, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 4, 10, 0, 94, 1, 26, 0, 94, 1, 26, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 6, 0, 0,110, 7, 0, 0,245, 2, 0, 0, 14, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 1, 26, 0, 12, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 24,166,201, 2,128,171,133, 3,128,171,133, 3, 0, 0, 0, 0, 0, 0, 0, 0, 40, 90,210, 2, +160, 90,210, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0, 48,154,213, 2,194, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 8,153,213, 2, 0, 0, 0, 0, 0,128,131, 67, 0, 0,228,194, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,166, 67, + 0, 0, 27,195, 0, 0, 0, 0, 77, 1, 0, 0, 94, 1, 0, 0, 18, 0, 0, 0,172, 0, 0, 0, 0, 0, 0, 0, 76, 1, 0, 0, + 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 76, 1, 0, 0, 18, 0, 0, 0,172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 18, 0, 0, 0, 2, 0, 3, 3, 0, 0, 0, 4, 6, 0, 94, 1, +173, 0, 77, 1,155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 6, 0, 0, +110, 7, 0, 0, 15, 3, 0, 0,187, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 1,173, 0, + 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,112,165,201, 2, 96, 83,133, 3, 96, 83,133, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 24, 91,210, 2, 8, 92,210, 2, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 4, 1, 0, 0, + 88,155,213, 2,165, 0, 0, 0, 1, 0, 0, 0,160,189,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,205,204, 76, 63,205,204, 76, 63,205,204, 76, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 62, 6, 0, 0, 0, 16, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63,173, 2, 95, 0,154,153,217, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 4, 0, 1, 0,180, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68,172, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 24, 6,139, 3, 24, 6,139, 3,144,156,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -152, 24, 11, 7, 1, 0, 0, 0, 1, 0, 10, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,205,204, 28, 65, 0, 0, 0, 0, 32, 0, 32, 0, 1, 0, 0, 0, 0, 0, 0, 0, -128, 0, 5, 0, 60, 0, 5, 0, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 2, -224, 1, 60, 0, 32, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 0,180, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 5, 0,128, 7, 56, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 28, 0, 0, 0,120,188, 2, 7, -128, 0, 0, 0, 1, 0, 0, 0,136,223, 2, 7, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,236, 1, 64, 1, -224,195, 9, 7, 68, 65, 84, 65, 28, 0, 0, 0,136,223, 2, 7,128, 0, 0, 0, 1, 0, 0, 0, 48,241, 2, 7,120,188, 2, 7, - 1, 0, 0, 0, 2, 0, 0, 0, 0, 4, 0, 0,121, 2, 10, 2,136,199, 9, 7, 68, 65, 84, 65, 28, 0, 0, 0, 48,241, 2, 7, -128, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,136,223, 2, 7, 1, 0, 0, 0, 3, 0, 0, 0, 0, 4, 0, 0, 38, 2, 28, 2, - 56,192, 9, 7, 68, 65, 84, 65, 72, 1, 0, 0, 72,239, 10, 7,147, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 68, 65, 84, 65, 12, 0, 0, 0,144,156,213, 2,217, 0, 0, 0, + 1, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0,208,156,213, 2, 68, 65, 84, 65,156, 0, 0, 0,208,156,213, 2,216, 0, 0, 0, + 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,216,194,213, 2, 19, 0, 0, 0, 1, 0, 1, 0,216,194,213, 2, 20, 0, 0, 0, + 1, 0, 1, 0,216,194,213, 2, 21, 0, 1, 0, 1, 0, 1, 0,216,194,213, 2, 0, 0, 0, 0, 1, 0, 1, 0,128,205,213, 2, + 0, 0, 0, 0, 1, 0, 1, 0,168,215,213, 2, 0, 0, 0, 0, 1, 0, 1, 0, 80,184,210, 2, 0, 0, 0, 0, 1, 0, 1, 0, + 24,223,213, 2, 0, 0, 0, 0, 1, 0, 1, 0, 32,227,213, 2, 0, 0, 0, 0, 1, 0, 1, 0, 96,219,213, 2, 0, 0, 0, 0, + 1, 0, 1, 0,152,202,213, 2, 0, 0, 0, 0, 1, 0, 1, 0,240,211,213, 2, 0, 0, 0, 0, 1, 0, 1, 0,240,201,213, 2, + 68, 65, 84, 65,248, 0, 0, 0,184,157,213, 2,194, 0, 0, 0, 1, 0, 0, 0,224,158,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,240, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 55, 0, 0, 67, 67, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +194, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,137, 67, 0, 0,200, 65, 0,128,137, 67, 0, 0,200, 65, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 4, 10, 0,195, 0, 26, 0,195, 0, 26, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 4, 0, 0,247, 4, 0, 0, 69, 2, 0, 0, 94, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,195, 0, 26, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0,224,158,213, 2,194, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0,184,157,213, 2, 0, 0, 0, 0, 0, 0,150, 67, 0,192,116,196, 0, 0, 0, 0, 0, 0, 0, 0,205, 85,150, 67, +223,204, 35,196, 26, 85,207,195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,194, 0, 0, 0, 0, 0, 0, 0,155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 64, 0, 0, 0, 0, 1, 0, 3, 0, 2, 0, 0, 4, 6, 0,195, 0, +156, 0,195, 0,156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 4, 0, 0, +247, 4, 0, 0, 95, 2, 0, 0,250, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,195, 0,156, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,224, 0, 0, 0, +160,189,213, 2,161, 0, 0, 0, 1, 0, 0, 0,184,193,213, 2, 88,155,213, 2,184,157,213, 2,224,158,213, 2, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0, 8,160,213, 2,194, 0, 0, 0, 1, 0, 0, 0, + 48,161,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 68, 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0,138, 67, + 0, 0, 0, 0, 0, 0,208, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0,128,237, 68, 0, 0,200, 65, + 0,128,237, 68, 0, 0,200, 65, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 2, 0, 3, 3, 4, 0, 12, 4, 10, 0, 20, 1, + 26, 0, 20, 1, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 6, 0, 0, +108, 7, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 1, 26, 0, + 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,248, 0, 0, 0, + 48,161,213, 2,194, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 8,160,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 89, 6, 0, 0,108, 7, 0, 0, 26, 0, 0, 0, 80, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 20, 1, 55, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +176,190,213, 2, 68, 65, 84, 65,216, 2, 0, 0,176,190,213, 2,155, 0, 0, 0, 1, 0, 0, 0,103,212,136, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 80, 1,128,191, 0, 0,128,191, 0, 0, 0,128, 0, 0, 0,128,226,215,163,188, 0, 0, 0,128, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,193, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, 0, 0,128, 63,103,212,136, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 80, 1,128,191, 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0,184,175, 31, 65, 0, 0, 32, 65,237,122,111, 62, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,161, 14,106, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +209,252,249,195,115,253, 71,194, 0, 0, 0, 0, 0, 0, 0, 0, 98,127,249, 67,129,255, 71, 66, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,193, 0, 0,128, 63,103,212,136, 64, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,140, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 80, 1,128,191, 0, 0,128,191, 0, 0, 0, 0, 0, 0, 0, 0,184,175, 31, 65, 0, 0, 32, 65, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100, 32,222, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,240, 0, 0, 0,184,193,213, 2,156, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0,160,189,213, 2, 8,160,213, 2, 48,161,213, 2, 1, 0, 0, 0, 51, 51, 51, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 65, + 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0,240,211,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 12, 66, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 10,215, 35, 60, 0, 0,250, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, 10, 0,159, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 0, 0,108, 5, 0, 0,216,194,213, 2, +153, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 67, 83, 99,101,110,101, 0, +116, 97,103,101, 0, 97,105,110, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +240,211,213, 2,128,205,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 48, 74,208, 2,208, 74,208, 2, 48, 74,208, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +120,200,213, 2,232,140,138, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 68,172, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +100, 0, 0, 0,100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 2,224, 1, 60, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 6, 0, 25, 0,141, 0,128, 7, + 56, 4, 8, 0, 8, 0, 0, 0, 24, 0, 17, 0, 0, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 23, 0, 33, 0, + 0, 0,128, 0, 0, 0, 8, 0, 24, 0, 10, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 66,207, 2, + 48, 66,207, 2, 0, 0, 0, 0, 0, 0,200, 66, 0, 0,200, 66, 0, 0,128, 63, 0, 0,128, 63, 1, 0, 0, 0, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 5, 0, 2, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 47, 47, 98, 97, 99,107, 98,117,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 47,116,109,112, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,205,204, 76, 63,205,204, 76, 63,205,204, 76, 63, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 62, 6, 0, 0, 0, 16, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63,173, 2, 95, 0, +154,153,217, 63, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 0,180, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 68,172, 0, 0, 0, 0,128, 63,102,166,171, 67, 0, 0,128, 63, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,187,200, 2, 1, 0, 0, 0, 1, 0, 10, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,205,204, 28, 65, + 0, 0, 0, 0, 32, 0, 32, 0, 1, 0, 0, 0, 0, 0, 0, 0,128, 0, 5, 0, 60, 0, 5, 0, 1, 0, 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 2,224, 1, 60, 0, 32, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 0, +180, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 5, 0,128, 7, 56, 4, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,195,245, 28,193, 1, 0, 0, 0, 68, 65, 84, 65, 28, 0, 0, 0, 48, 74,208, 2, +130, 0, 0, 0, 1, 0, 0, 0,128, 74,208, 2, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 8, 3,160, 1, +168,215,213, 2, 68, 65, 84, 65, 28, 0, 0, 0,128, 74,208, 2,130, 0, 0, 0, 1, 0, 0, 0,208, 74,208, 2, 48, 74,208, 2, + 1, 0, 0, 0, 2, 0, 0, 0, 0, 4, 0, 0,231, 3,223, 2, 96,219,213, 2, 68, 65, 84, 65, 28, 0, 0, 0,208, 74,208, 2, +130, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,128, 74,208, 2, 1, 0, 0, 0, 3, 0, 0, 0, 0, 4, 0, 0,100, 3,251, 2, +240,211,213, 2, 68, 65, 84, 65, 72, 1, 0, 0,120,200,213, 2,149, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 1, 0, 1, 0,205,204, 76, 63, 0, 0,180, 66, 9, 0, 1, 0, 0, 0,128, 63,111, 18,131, 58, 205,204,204, 61, 0, 0, 1, 0, 32, 0, 32, 0, 32, 0, 1, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -687,18 +708,18 @@ char datatoc_B_blend[]= { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,250, 0,205,204,204, 61,205,204,204, 61,102,102,166, 63, 0, 0,192, 63, 0, 0,240, 65, 72,225,122, 63,205,204,204, 61, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 67, 2, 0, 3, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 72, 0, 0, 0, 48,231, 9, 7,133, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 32, 82,101, + 68, 65, 84, 65, 72, 0, 0, 0, 48, 66,207, 2,135, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 32, 82,101, 110,100,101,114, 76, 97,121,101,114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255, 15, 0, 0, 0, 0, 0,255,127, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 67, 65, 0, 0, -120, 0, 0, 0,240,143, 9, 7, 29, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +120, 0, 0, 0,240,201,213, 2, 29, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 65, 67, 97,109,101,114, 97, 0, 97,109,101,114, 97, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 63,145,137, 68, 66,205,204,204, 61, 0, 0,200, 66, 0, 0, 12, 66, 161, 14,234, 64, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 0, 0,124, 1, 0, 0,208,240, 10, 7, 41, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 0, 0,124, 1, 0, 0,152,202,213, 2, 41, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 65, 83,112,111,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63,247,255,239, 65, 0, 0,150, 66,154,153, 25, 62, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63,144,242, 10, 7, + 0, 0,128, 63,247,255,239, 65, 0, 0,150, 66,154,153, 25, 62, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 72,204,213, 2, 2, 0, 0, 0, 46, 26,128, 63, 25, 4,240, 65, 0, 0, 52, 66, 0, 0,128, 63, 0, 0, 64, 64, 64, 11, 3, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,111, 18,131, 58, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, @@ -706,20 +727,20 @@ char datatoc_B_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 4, 7, 68, 65, 84, 65, 8, 1, 0, 0, -144,242, 10, 7, 64, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 75,208, 2, 68, 65, 84, 65, 8, 1, 0, 0, + 72,204,213, 2, 71, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 2, 0, 1, 0, 0, 0,128, 67, 0, 0, 0, 0, - 0, 0,128, 63,243, 4, 53,191,242, 4, 53, 63,242, 4, 53,191,243, 4, 53, 63,112,236, 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63,243, 4, 53,191,242, 4, 53, 63,242, 4, 53,191,243, 4, 53, 63,248, 51,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,112,236, 2, 7, - 62, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65, 32, 0, 0, 0, 0, 42, 4, 7, 19, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 79, 0, 0,104, 1, 0, 0, 64, 39, 10, 7, -127, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 79, 87,111,114,108,100, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 24, 0, 0, 0,248, 51,213, 2, + 69, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 68, 65, 84, 65, 32, 0, 0, 0, 32, 75,208, 2, 19, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 79, 0, 0,104, 1, 0, 0,128,205,213, 2, +129, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, 79, 87,111,114,108,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 62, 0, 0,128, 62, 0, 0,128, 62, 0, 0, 0, 0,205,204,204, 61,205,204,204, 61, 205,204,204, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, @@ -730,23 +751,24 @@ char datatoc_B_blend[]= { 0, 0,128, 62, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 88, 0, 0,120, 0, 0, 0,232, 40, 10, 7, 27, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 88, 0, 0,120, 0, 0, 0, 24,207,213, 2, 27, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 88, 84,101,120,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, - 1, 0, 0, 0, 96,142, 2, 7, 96,142, 2, 7, 96,142, 2, 7, 96,142, 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,160, 41, 10, 7,255,255,255,255, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, - 24, 0, 0, 0, 96,142, 2, 7, 25, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104,248, 11, 7, 0, 0, 0, 0, - 0, 0, 0, 0, 69, 69, 82, 70, 68, 65, 84, 65, 4, 0, 0, 0,104,248, 11, 7, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, - 79, 66, 0, 0,100, 3, 0, 0, 56,192, 9, 7,118, 0, 0, 0, 1, 0, 0, 0,224,195, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 64, 52,213, 2, 64, 52,213, 2, 64, 52,213, 2, 64, 52,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,192,207,213, 2,255,255,255,255, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, + 24, 0, 0, 0, 64, 52,213, 2, 25, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,180,207, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 69, 69, 82, 70, 68, 65, 84, 65, 4, 0, 0, 0, 80,180,207, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, + 79, 66, 0, 0,136, 3, 0, 0,240,211,213, 2,118, 0, 0, 0, 1, 0, 0, 0,168,215,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 67, 97,109,101,114, 97, 0, 97,109,101,114, 97, 46, 48, 48, 49, 0, 0, 0, 0, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,143, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,201,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,110,101,239, 64,150, 62,208,192, 78,255,170, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42,254,141, 63,192, 57, 49, 60, 34,159, 80, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,222,149, 47, 63, 53, 70, 58, 63,222, 56, 49,188, 0, 0, 0, 0, 86,126,162,190,227,251,159, 62, 55, 53,101, 63, 0, 0, 0, 0, 7,165, 39, 63,149, 84, 28,191, 51,247,227, 62, 0, 0, 0, 0,110,101,239, 64,150, 62,208,192, 78,255,170, 64, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, @@ -758,122 +780,128 @@ char datatoc_B_blend[]= { 0, 0,128, 53, 0, 0,128, 63, 1, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 5, 0, 1, 0, 0, 0, 0, 0, 79, 66, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0, 0, 0, 0, 56,180,150,201, 0, 0,128, 63, 187,225, 16, 63, 0, 0,128, 63,205,204,204, 62,237, 54, 32, 63, 0, 0, 0, 0,143,194,117, 61, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0,100, 3, 0, 0, -224,195, 9, 7,118, 0, 0, 0, 1, 0, 0, 0,136,199, 9, 7, 56,192, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 67,117, - 98,101, 0,112,104,101,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184,149, 25, 7, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 48, 21, 12, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,224,127, 10, 7, -168,144, 9, 7, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, -222,149, 47, 63, 52, 70, 58, 63,179, 56, 49,188, 0, 0, 0,128, 86,126,162,190,227,251,159, 62, 56, 53,101, 63, 0, 0, 0,128, - 7,165, 39, 63,149, 84, 28,191, 50,247,227, 62, 0, 0, 0,128,110,101,239, 64,151, 62,208,192, 77,255,170, 64, 0, 0,128, 63, - 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 68, 0, 79, 66, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0, 0, 0, 0, 56,180,150,201, 0, 0,128, 63,169, 19,208, 60, 0, 0,128, 63, -205,204,204, 62,229,208, 34, 62, 0, 0, 0, 0,143,194,117, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 64, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,120,137, 25, 7,152,143, 25, 7, 25, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 4, 0, 0, 0,224,127, 10, 7, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 4, 0, 0, 0,168,144, 9, 7, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 79, 66, 0, 0,100, 3, 0, 0,136,199, 9, 7,118, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,224,195, 9, 7, 0, 0, 0, 0, - 0, 0, 0, 0, 79, 66, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 4, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,208,240, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,154,112,130, 64,183,178,128, 63,112,236,188, 64, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,229,123, 38, 63, 87, 43, 98, 61,229,229,238, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 54,236,148,190, 25,134,116, 63,236, 13, 98,189, 0, 0, 0, 0,221,102, 69,191, 57,174, 76,190, - 34,194, 26, 63, 0, 0, 0, 0, 37,255, 16, 63,241,161, 95, 62,164,111, 75, 63, 0, 0, 0, 0,154,112,130, 64,183,178,128, 63, -112,236,188, 64, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 35,233,134, 49,251,110, 17,179, 0, 0, 0, 0, 49,158,141, 50, 1, 0,128, 63, -126,214,237, 50, 0, 0, 0, 0,155,248, 28,178,199,139, 96,177,254,255,127, 63, 0, 0, 0, 0, 80,136,159,178,192, 4,158,178, -209,114,143,179, 0, 0,128, 63, 53,236,148,190,222,102, 69,191, 37,255, 16, 63, 0, 0, 0,128, 24,134,116, 63, 57,174, 76,190, -240,161, 95, 62, 0, 0, 0,128,235, 13, 98,189, 34,194, 26, 63,166,111, 75, 63, 0, 0, 0,128,208, 19, 13, 63,234, 65,102,190, - 10, 10,231,192, 0, 0,128, 63, 1, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 5, 0, 1, 0, 0, 0, 68, 0, 79, 66, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0, 0, 0, 0, 56,180,150,201, 0, 0,128, 63, -169, 19,208, 60, 0, 0,128, 63,205,204,204, 62,229,208, 34, 62, 0, 0, 0, 0,143,194,117, 61, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0, +136, 3, 0, 0,168,215,213, 2,118, 0, 0, 0, 1, 0, 0, 0, 96,219,213, 2,240,211,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 79, 66, 67,117, 98,101, 0,112,104,101,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,232,154,136, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 80,184,210, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +136,180,207, 2,192,180,207, 2, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63,222,149, 47, 63, 52, 70, 58, 63,179, 56, 49,188, 0, 0, 0,128, 86,126,162,190,227,251,159, 62, 56, 53,101, 63, + 0, 0, 0,128, 7,165, 39, 63,149, 84, 28,191, 50,247,227, 62, 0, 0, 0,128,110,101,239, 64,151, 62,208,192, 77,255,170, 64, + 0, 0,128, 63, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 68, 0, 79, 66, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0, 0, 0, 0, 56,180,150,201, 0, 0,128, 63,169, 19,208, 60, + 0, 0,128, 63,205,204,204, 62,229,208, 34, 62, 0, 0, 0, 0,143,194,117, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 4, 0, 1, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 64, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48,179,210, 2,120,180,210, 2, 25, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 4, 0, 0, 0, +136,180,207, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 4, 0, 0, 0,192,180,207, 2, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 79, 66, 0, 0,136, 3, 0, 0, 96,219,213, 2,118, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, +168,215,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 79, 66, 76, 97,109,112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152,202,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,154,112,130, 64, +183,178,128, 63,112,236,188, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,229,123, 38, 63, 87, 43, 98, 61, +229,229,238, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54,236,148,190, 25,134,116, 63,236, 13, 98,189, 0, 0, 0, 0, +221,102, 69,191, 57,174, 76,190, 34,194, 26, 63, 0, 0, 0, 0, 37,255, 16, 63,241,161, 95, 62,164,111, 75, 63, 0, 0, 0, 0, +154,112,130, 64,183,178,128, 63,112,236,188, 64, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 35,233,134, 49,251,110, 17,179, 0, 0, 0, 0, + 49,158,141, 50, 1, 0,128, 63,126,214,237, 50, 0, 0, 0, 0,155,248, 28,178,199,139, 96,177,254,255,127, 63, 0, 0, 0, 0, + 80,136,159,178,192, 4,158,178,209,114,143,179, 0, 0,128, 63, 53,236,148,190,222,102, 69,191, 37,255, 16, 63, 0, 0, 0,128, + 24,134,116, 63, 57,174, 76,190,240,161, 95, 62, 0, 0, 0,128,235, 13, 98,189, 34,194, 26, 63,166,111, 75, 63, 0, 0, 0,128, +208, 19, 13, 63,234, 65,102,190, 10, 10,231,192, 0, 0,128, 63, 1, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 5, 0, 1, 0, + 0, 0, 68, 0, 79, 66, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,100, 0, 0, 0, 0, 0, 0, 0, + 56,180,150,201, 0, 0,128, 63,169, 19,208, 60, 0, 0,128, 63,205,204,204, 62,229,208, 34, 62, 0, 0, 0, 0,143,194,117, 61, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, 0, 1, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 65, 0, 0,184, 2, 0, 0, - 48,203, 9, 7, 44, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 65, 77, 97, -116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,205,204, 76, 63,205,204, 76, 63,205,204, 76, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63,205,204, 76, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 10,215, 35, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -205,204, 76, 62,205,204, 76, 62, 0, 0, 8, 0, 1, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,160, 63, 0, 0, 0, 0, 0, 0,160, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 2, 0, 2, 0, 50, 0, 0, 6, - 0, 0,128, 63, 0, 0,128, 63, 18, 0, 18, 0, 10,215,163, 59, 10,215,163, 59, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 67, 0, 0, 3, 3, 0, 1, 3, 1, 0, 4, 0, 12, 0, 4, 0, 0, 0, 0, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0,128, 64, - 0, 0, 0, 63,205,204,204, 61, 0, 0, 0, 63,205,204,204, 61,205,204,204, 61, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 40,206, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 77, 65, 0, 0,160, 2, 0, 0, 24,223,213, 2, 44, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 77, 65, 77, 97,116,101,114,105, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,205,204, 76, 63,205,204, 76, 63,205,204, 76, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63,205,204, 76, 63, + 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 10,215, 35, 60, 0, 0, 0, 0, 0, 0, 8, 0, 1, 0, 50, 0,205,204, 76, 62, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 63, 0, 0, 0, 0, 0, 0,160, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 2, 0, 2, 0, 50, 0, 0, 6, 0, 0,128, 63, 0, 0,128, 63, 18, 0, 18, 0, 10,215,163, 59, 10,215,163, 59, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 3, 3, 0, 1, 3, 1, 0, 4, 0, 12, 0, 4, 0, 0, 0, 0, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 63, 0, 0,128, 64, 0, 0, 0, 63,205,204,204, 61, 0, 0, 0, 63,205,204,204, 61,205,204,204, 61, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, +232,225,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 56,144, 2, 7, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 63,205,204, 76, 63,205,204, 76, 63,205,204, 76, 61, -205,204,204, 61,102,102,166, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,112, 75,208, 2, 0, 0, 0, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63,205,204, 76, 63, +205,204, 76, 63,205,204, 76, 63,205,204, 76, 61,205,204,204, 61,102,102,166, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 8, 1, 0, 0, +232,225,213, 2, 32, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,227,213, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0,144, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 63,205,204, 76, 62, 0, 0, 0, 0, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 68, 65, 84, 65, 32, 0, 0, 0,112, 75,208, 2, + 19, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 84, 69, 0, 0, 40, 1, 0, 0, 32,227,213, 2, 39, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 69, 84,101,120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 62, 0, 0,160, 64, 0, 0,128, 63, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 64, 0, 0, 0, 64, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 32, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 8, 0, 0, 0, 1, 0, 1, 0, 3, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,205,204,204, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 68, 65, 84, 65,144, 0, 0, 0, 40,206, 9, 7, 32, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0,224, 45, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0, 0, 0,144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, - 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 63, 0, 0,128, 63, -205,204, 76, 62, 0, 0, 0, 0, 68, 65, 84, 65, 32, 0, 0, 0, 56,144, 2, 7, 19, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 69, 0, 0, - 40, 1, 0, 0,224, 45, 10, 7, 39, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 84, 69, 84,101,120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 62, 0, 0,160, 64, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 64, 0, 0, 0, 64, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 64, 0, 0, 0, 0, 2, 0, 0, 0, - 0, 0, 0, 0, 5, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 8, 0, 0, 0, 1, 0, 1, 0, 3, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -205,204,204, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 77, 69, 0, 0, 24, 1, 0, 0, 80,184,210, 2, 54, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 77, 69, 67,117, 98,101, 0,112,104,101,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +248,180,207, 2,104, 32,131, 3, 0, 0, 0, 0, 0, 0, 0, 0,120,228,213, 2,128, 0,131, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,140,210, 2, 1, 0, 0, 0, 5, 0, 0, 0, 24, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,208,141,210, 2, 1, 0, 0, 0, 5, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 88,143,210, 2, 1, 0, 0, 0, 5, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 12, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,128, 51, 0, 0, 0,180, 0, 0, 0, 0, 4, 0,128, 63, + 4, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 30, 0, 4, 0, + 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65, 4, 0, 0, 0,248,180,207, 2, 0, 0, 0, 0, + 1, 0, 0, 0, 24,223,213, 2, 68, 65, 84, 65, 84, 1, 0, 0, 72,140,210, 2, 74, 1, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 69, 0, 0, 24, 1, 0, 0, - 48, 21, 12, 7, 54, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 69, 67,117, - 98,101, 0,112,104,101,114,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,131, 2, 7, 80, 27, 12, 7, 0, 0, 0, 0, - 0, 0, 0, 0,248,206, 9, 7, 72, 47, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,136, 22, 12, 7, 1, 0, 0, 0, 5, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 24, 12, 7, - 1, 0, 0, 0, 5, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,184, 25, 12, 7, 1, 0, 0, 0, 5, 0, 0, 0, - 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 12, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0,128, 51, 0, 0, 0,180, 0, 0, 0, 0, 4, 0,128, 63, 4, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 30, 0, 4, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 68, 65, 84, 65, 4, 0, 0, 0, 80,131, 2, 7, 0, 0, 0, 0, 1, 0, 0, 0, 48,203, 9, 7, 68, 65, 84, 65, - 84, 1, 0, 0,136, 22, 12, 7, 67, 1, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,228,213, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248,206, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -881,17 +909,17 @@ char datatoc_B_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,192, 0, 0, 0,120,228,213, 2, 60, 0, 0, 0, + 8, 0, 0, 0, 0, 0,128, 63,255,255,127, 63, 0, 0,128,191,230, 73,230, 73, 26,182,255,127, 1, 0, 0, 0, 0, 0,128, 63, + 0, 0,128,191, 0, 0,128,191,230, 73, 26,182, 26,182,255,127, 1, 0, 0, 0, 1, 0,128,191,253,255,127,191, 0, 0,128,191, + 26,182, 26,182, 26,182,255,127, 1, 0, 0, 0,250,255,127,191, 3, 0,128, 63, 0, 0,128,191, 26,182,230, 73, 26,182,255,127, + 1, 0, 0, 0, 4, 0,128, 63,247,255,127, 63, 0, 0,128, 63,230, 73,230, 73,230, 73,255,127, 1, 0, 0, 0,245,255,127, 63, + 5, 0,128,191, 0, 0,128, 63,230, 73, 26,182,230, 73,255,127, 1, 0, 0, 0, 3, 0,128,191,250,255,127,191, 0, 0,128, 63, + 26,182, 26,182,230, 73,255,127, 1, 0, 0, 0,255,255,127,191, 0, 0,128, 63, 0, 0,128, 63, 26,182,230, 73,230, 73,255,127, + 1, 0, 0, 0, 68, 65, 84, 65, 84, 1, 0, 0,208,141,210, 2, 74, 1, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 68, 65, 84, 65,192, 0, 0, 0,248,206, 9, 7, 60, 0, 0, 0, 8, 0, 0, 0, 0, 0,128, 63,255,255,127, 63, - 0, 0,128,191,230, 73,230, 73, 26,182,255,127, 1, 0, 0, 0, 0, 0,128, 63, 0, 0,128,191, 0, 0,128,191,230, 73, 26,182, - 26,182,255,127, 1, 0, 0, 0, 1, 0,128,191,253,255,127,191, 0, 0,128,191, 26,182, 26,182, 26,182,255,127, 1, 0, 0, 0, -250,255,127,191, 3, 0,128, 63, 0, 0,128,191, 26,182,230, 73, 26,182,255,127, 1, 0, 0, 0, 4, 0,128, 63,247,255,127, 63, - 0, 0,128, 63,230, 73,230, 73,230, 73,255,127, 1, 0, 0, 0,245,255,127, 63, 5, 0,128,191, 0, 0,128, 63,230, 73, 26,182, -230, 73,255,127, 1, 0, 0, 0, 3, 0,128,191,250,255,127,191, 0, 0,128, 63, 26,182, 26,182,230, 73,255,127, 1, 0, 0, 0, -255,255,127,191, 0, 0,128, 63, 0, 0,128, 63, 26,182,230, 73,230, 73,255,127, 1, 0, 0, 0, 68, 65, 84, 65, 84, 1, 0, 0, - 32, 24, 12, 7, 67, 1, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 0,131, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 47, 10, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -899,44 +927,46 @@ char datatoc_B_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,144, 0, 0, 0,128, 0,131, 3, 57, 0, 0, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 35, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 35, 0, 1, 0, 0, 0, 5, 0, 0, 0, 0, 0, 35, 0, 2, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 35, 0, 2, 0, 0, 0, 6, 0, 0, 0, 0, 0, 35, 0, 3, 0, 0, 0, 7, 0, 0, 0, 0, 0, 35, 0, + 4, 0, 0, 0, 5, 0, 0, 0, 0, 0, 35, 0, 4, 0, 0, 0, 7, 0, 0, 0, 0, 0, 35, 0, 5, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 35, 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 35, 0, 68, 65, 84, 65, 84, 1, 0, 0, 88,143,210, 2, 74, 1, 0, 0, + 5, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65,144, 0, 0, 0, 72, 47, 10, 7, 57, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 35, 0, - 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 35, 0, 1, 0, 0, 0, 2, 0, 0, 0, - 0, 0, 35, 0, 1, 0, 0, 0, 5, 0, 0, 0, 0, 0, 35, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 35, 0, 2, 0, 0, 0, - 6, 0, 0, 0, 0, 0, 35, 0, 3, 0, 0, 0, 7, 0, 0, 0, 0, 0, 35, 0, 4, 0, 0, 0, 5, 0, 0, 0, 0, 0, 35, 0, - 4, 0, 0, 0, 7, 0, 0, 0, 0, 0, 35, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 35, 0, 6, 0, 0, 0, 7, 0, 0, 0, - 0, 0, 35, 0, 68, 65, 84, 65, 84, 1, 0, 0,184, 25, 12, 7, 67, 1, 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,104, 32,131, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 27, 12, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,120, 0, 0, 0, +104, 32,131, 3, 56, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 2, + 4, 0, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, + 6, 0, 0, 0, 7, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 2, 85, 83, 69, 82, 56, 11, 0, 0, 0, 94,252, 0,188, 0, 0, 0, 1, 0, 0, 0, 33,152, 1, 0, 63, 2, 0, 0, + 5, 0, 0, 0, 47,116,109,112, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,120, 0, 0, 0, 80, 27, 12, 7, 56, 0, 0, 0, 6, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, - 5, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, - 5, 0, 0, 0, 6, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 3, 0, 0, 0, - 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 2, 85, 83, 69, 82, 56, 11, 0, 0, - 0, 2, 68, 1,185, 0, 0, 0, 1, 0, 0, 0, 33,152, 1, 0, 63, 2, 0, 0, 5, 0, 0, 0, 47,116,109,112, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 47, 47, 0, 85,115,101,114,115, 47,116,111,110, 47, 68,101,115,107,116,111,112, 47, 0, 45,112,111,119,101,114, +112, 99, 47, 98,105,110, 47, 98,108,101,110,100,101,114, 46, 97,112,112, 47, 67,111,110,116,101,110,116,115, 47, 82,101,115,111, +117,114, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 0, 85,115,101,114,115, - 47,116,111,110, 47, 68,101,115,107,116,111,112, 47, 0, 45,112,111,119,101,114,112, 99, 47, 98,105,110, 47, 98,108,101,110,100, -101,114, 46, 97,112,112, 47, 67,111,110,116,101,110,116,115, 47, 82,101,115,111,117,114, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -954,9 +984,9 @@ char datatoc_B_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -964,19 +994,18 @@ char datatoc_B_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 48, 52, 6, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 8, 0, 0, + 2, 0, 0, 0, 68,172, 0, 0, 36, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 64, 0, 5, 0, 2, 0, +104,229,213, 2,120, 44,131, 3,120,175,210, 2,120,175,210, 2, 24, 76,131, 3, 24, 76,131, 3, 32, 0, 0, 0, 1, 0, 2, 0, + 25, 0, 0, 0, 20, 0, 20, 0, 1, 0, 0, 0, 0, 0, 0, 0,205,204, 76, 63,205,204, 76, 63,205,204, 76, 63, 0, 0, 0, 0, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 30, 90,100,191,154,153,153, 62,102,102,102, 63, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 31,250,254, 62, 9, 0, 0, 63,156,153, 25, 63, 0, 0, 0, 0,205,204, 76, 62,205,204, 76, 62, +205,204, 76, 62, 0, 0,128, 63, 44,135, 22, 63, 32,133,235, 62,184,243,125, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +195, 73, 76, 63, 42,135, 86, 63, 0, 0,128, 63, 0, 0, 0, 0, 1, 43,135, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, + 16, 47, 93, 62, 58,180,200,190, 24, 47, 93,190, 0, 0, 0, 0, 14, 0, 0, 0, 25, 0, 15, 0,120, 0, 60, 0, 0, 0, 0, 0, +128, 0, 0, 0, 0, 0, 0, 0,144, 31, 15, 0, 6, 0, 15, 0, 8, 0, 10, 0,250, 0, 0, 0,100, 0,100, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 48, 52, 6, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 8, 0, 0, 2, 0, 0, 0, 68,172, 0, 0, 36, 0, 0, 0, - 2, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 64, 0, 5, 0, 2, 0,168, 3, 10, 7, 40,207, 13, 7, 48, 93, 5, 7, - 48, 93, 5, 7,128, 94, 5, 7,128, 94, 5, 7, 32, 0, 0, 0, 1, 0, 2, 0, 25, 0, 0, 0, 20, 0, 20, 0, 1, 0, 0, 0, - 0, 0, 0, 0,205,204, 76, 63,205,204, 76, 63,205,204, 76, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, - 0, 0,128, 63, 30, 90,100,191,154,153,153, 62,102,102,102, 63, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 31,250,254, 62, - 9, 0, 0, 63,156,153, 25, 63, 0, 0, 0, 0,205,204, 76, 62,205,204, 76, 62,205,204, 76, 62, 0, 0,128, 63, 44,135, 22, 63, - 32,133,235, 62,184,243,125, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,195, 73, 76, 63, 42,135, 86, 63, 0, 0,128, 63, - 0, 0, 0, 0, 1, 43,135, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 16, 47, 93, 62, 58,180,200,190, 24, 47, 93,190, - 0, 0, 0, 0, 14, 0, 0, 0, 25, 0, 15, 0,120, 0, 60, 0, 0, 0, 0, 0,128, 0, 0, 0, 0, 0, 0, 0,144, 31, 15, 0, - 6, 0, 15, 0, 8, 0, 10, 0,250, 0, 0, 0,100, 0,100, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -984,818 +1013,830 @@ char datatoc_B_blend[]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, + 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, + 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, + 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, + 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, + 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, + 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, + 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, + 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,200, 21, 0, 0,104,229,213, 2,186, 0, 0, 0, + 1, 0, 0, 0,120, 44,131, 3, 0, 0, 0, 0, 68,101,102, 97,117,108,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25,255,153,153,153,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255, +255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25,255,153,153,153,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255, +255,255,255,255, 1, 0, 15, 0,241,255, 0, 0, 25, 25, 25,255,153,153,153,255,153,153,153,255, 90, 90, 90,255, 0, 0, 0,255, +255,255,255,255, 1, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0,255, 70, 70, 70,255, 86,128,194,255,255,255,255,255,255,255,255,255, + 0, 0, 0,255, 1, 0, 15, 0,241,255, 0, 0, 0, 0, 0,255, 70, 70, 70,255, 70, 70, 70,255,255,255,255,255, 0, 0, 0,255, +255,255,255,255, 1, 0, 15, 0,241,255, 0, 0, 25, 25, 25,255,153,153,153,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255, +255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25,255,180,180,180,255,153,153,153,255, 90, 90, 90,255, 0, 0, 0,255, +255,255,255,255, 1, 0,236,255, 0, 0, 0, 0, 25, 25, 25,255,180,180,180,255,153,153,153,255,128,128,128,255, 0, 0, 0,255, +255,255,255,255, 1, 0,236,255, 0, 0, 0, 0, 0, 0, 0,255, 70, 70, 70,255, 70, 70, 70,255,255,255,255,255,255,255,255,255, +204,204,204,255, 1, 0, 15, 0,241,255, 0, 0, 0, 0, 0,255, 63, 63, 63,255, 86,128,194,255,255,255,255,255, 0, 0, 0,255, + 0, 0, 0,255, 0, 0, 25, 0,236,255, 0, 0, 0, 0, 0,255, 25, 25, 25,230, 45, 45, 45,230,100,100,100,255,160,160,160,255, +255,255,255,255, 0, 0, 25, 0,236,255, 0, 0, 0, 0, 0,255, 0, 0, 0, 0, 86,128,194,255,255,255,255,255,255,255,255,255, + 0, 0, 0,255, 0, 0, 38, 0, 0, 0, 0, 0, 25, 25, 25,255,128,128,128,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255, +255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50,180, 80, 80, 80,180,100,100,100,180,128,128,128,255, 0, 0, 0,255, +255,255,255,255, 1, 0, 5, 0,251,255, 0, 0, 0, 0, 0,255, 0, 0, 0, 0, 86,128,194,255, 0, 0, 0,255, 0, 0, 0,255, + 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0,115,190, 76,255, 90,166, 51,255,240,235,100,255,215,211, 75,255,180, 0,255,255, +153, 0,230,255, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 63, 0, 0,128, 63, 0, 0,128, 63, - 0, 0,128, 63, 0, 0,128, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, - 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, - 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, - 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, - 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, - 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, - 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, - 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, - 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, - 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, - 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, - 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, - 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, - 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, - 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, - 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, - 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, - 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, - 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, - 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, - 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, - 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, - 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0,128, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 68, 65, 84, 65,200, 21, 0, 0,168, 3, 10, 7,183, 0, 0, 0, 1, 0, 0, 0, 40,207, 13, 7, 0, 0, 0, 0, - 68,101,102, 97,117,108,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 25, 25, 25,255,153,153,153,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, - 25, 25, 25,255,153,153,153,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255,255,255,255,255, 1, 0, 15, 0,241,255, 0, 0, - 25, 25, 25,255,153,153,153,255,153,153,153,255, 90, 90, 90,255, 0, 0, 0,255,255,255,255,255, 1, 0, 0, 0, 25, 0, 0, 0, - 0, 0, 0,255, 70, 70, 70,255, 86,128,194,255,255,255,255,255,255,255,255,255, 0, 0, 0,255, 1, 0, 15, 0,241,255, 0, 0, - 0, 0, 0,255, 70, 70, 70,255, 70, 70, 70,255,255,255,255,255, 0, 0, 0,255,255,255,255,255, 1, 0, 15, 0,241,255, 0, 0, - 25, 25, 25,255,153,153,153,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, - 25, 25, 25,255,180,180,180,255,153,153,153,255, 90, 90, 90,255, 0, 0, 0,255,255,255,255,255, 1, 0,236,255, 0, 0, 0, 0, - 25, 25, 25,255,180,180,180,255,153,153,153,255,128,128,128,255, 0, 0, 0,255,255,255,255,255, 1, 0,236,255, 0, 0, 0, 0, - 0, 0, 0,255, 70, 70, 70,255, 70, 70, 70,255,255,255,255,255,255,255,255,255,204,204,204,255, 1, 0, 15, 0,241,255, 0, 0, - 0, 0, 0,255, 63, 63, 63,255, 86,128,194,255,255,255,255,255, 0, 0, 0,255, 0, 0, 0,255, 0, 0, 25, 0,236,255, 0, 0, - 0, 0, 0,255, 25, 25, 25,230, 45, 45, 45,230,100,100,100,255,160,160,160,255,255,255,255,255, 0, 0, 25, 0,236,255, 0, 0, - 0, 0, 0,255, 0, 0, 0, 0, 86,128,194,255,255,255,255,255,255,255,255,255, 0, 0, 0,255, 0, 0, 38, 0, 0, 0, 0, 0, - 25, 25, 25,255,128,128,128,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, - 50, 50, 50,180, 80, 80, 80,180,100,100,100,180,128,128,128,255, 0, 0, 0,255,255,255,255,255, 1, 0, 5, 0,251,255, 0, 0, - 0, 0, 0,255, 0, 0, 0, 0, 86,128,194,255, 0, 0, 0,255, 0, 0, 0,255, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, -115,190, 76,255, 90,166, 51,255,240,235,100,255,215,211, 75,255,180, 0,255,255,153, 0,230,255, 0, 0, 0, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,114,114,114,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,130,130,130,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, - 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, -255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, - 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 57, 57, 57,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, - 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255, -255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60, -255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 90, 90,255, 0, 0, 0, 0,250,250,250,255, 15, 15, 15,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,180,180,180,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100,255,140, 25,255,250,250,250,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,130,130,130,255, - 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, -255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, - 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,250,250,250,255,250,250,250,255,250,250,250,255, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -107,107,107,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,102,102,102,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -255,255,255,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,150,150,150,100,112,112,112,100, 96,192, 64,255, 94, 94, 94,255, - 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 79,101, 73,255,135,177,125,255,255,255,255,255, 0, 0, 0,255, -255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60, -255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 82, 96,110,255, -124,137,150,255, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, - 0, 0, 0,255,255,133, 0,255, 3, 0, 0, 0, 0, 0, 0, 0,114,114,114,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, - 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, -255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, - 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -114,114,114,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,173,173,173,255,127,112,112,100, 0, 0, 0, 0, 91, 91, 91,255, - 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255, -255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60, -255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -102,102,102,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,255,255,255,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -150,150,150,100,112,112,112,100, 96,192, 64,255, 94, 94, 94,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, - 79,101, 73,255,135,177,125,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, -255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, - 12, 10, 10,128,255,140, 0,255, 96,192, 64,255, 82, 96,110,255,124,137,150,255, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0,255,255,133, 0,255, 3, 0, 0, 0, 0, 0, 0, 0, -107,107,107,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,102,102,102,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -255,255,255,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,150,150,150,100,112,112,112,100, 96,192, 64,255, 94, 94, 94,255, - 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 79,101, 73,255,135,177,125,255,255,255,255,255, 0, 0, 0,255, -255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60, -255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 12, 10, 10,128,255,140, 0,255, 96,192, 64,255, 82, 96,110,255, -124,137,150,255, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, - 0, 0, 0,255,255,133, 0,255, 3, 0, 0, 0, 0, 0, 0, 0,116,116,116,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, - 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, -255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, - 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81,105,135,255,109, 88,129,255, 78,152, 62,255, 46,143,143,255,169, 84,124,255, -126,126, 80,255,162, 95,111,255,109,145,131,255,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 53, 53, 53,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, - 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255, -255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255,255,255,255, 10,255,133, 0, 60, -255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,110,110,110,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,132,132,132,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, - 94, 94, 94,255,172,172,172,255, 17, 27, 60,100, 94, 94, 94,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,195,195,195,255, - 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, -255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, - 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -153,153,153,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,143,143,143,255,198,119,119,255,255, 0, 0,255, 64, 64, 64,255, - 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255, -255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60, -255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 4, 0, 0,100, 0, 0,255, 0, 0,200,255,128, 0, 80,255, 95, 95, 0,255, 0,100, 50,255, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,114,114,114,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, - 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, -255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, - 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -114,114,114,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,173,173,173,255,127,112,112,100, 0, 0, 0, 0, 91, 91, 91,255, - 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255, -255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60, -255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 57, 57,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, - 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,255,255,255,219, 37, 18,255, -255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, - 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0,150,150,150,255,129,131,144,255, -127,127,127,255,142,138,145,255,120,145,120,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -100,100,100,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, - 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255, -255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60, -255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,114,114,114,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255, -114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, -160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, - 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255, -255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, - 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -154, 0, 0,255,189, 17, 17,255,247, 10, 10,255, 0, 0, 0, 0,247, 64, 24,255,246,105, 19,255,250,153, 0,255, 0, 0, 0, 0, - 30,145, 9,255, 89,183, 11,255,131,239, 29,255, 0, 0, 0, 0, 10, 54,148,255, 54,103,223,255, 94,193,239,255, 0, 0, 0, 0, -169, 41, 78,255,193, 65,106,255,240, 93,145,255, 0, 0, 0, 0, 67, 12,120,255, 84, 58,163,255,135,100,213,255, 0, 0, 0, 0, - 36,120, 90,255, 60,149,121,255,111,182,171,255, 0, 0, 0, 0, 75,112,124,255,106,134,145,255,155,194,205,255, 0, 0, 0, 0, -244,201, 12,255,238,194, 54,255,243,255, 0,255, 0, 0, 0, 0, 30, 32, 36,255, 72, 76, 86,255,255,255,255,255, 0, 0, 0, 0, -111, 47,106,255,152, 69,190,255,211, 48,214,255, 0, 0, 0, 0,108,142, 34,255,127,176, 34,255,187,239, 91,255, 0, 0, 0, 0, -141,141,141,255,176,176,176,255,222,222,222,255, 0, 0, 0, 0,131, 67, 38,255,139, 88, 17,255,189,106, 17,255, 0, 0, 0, 0, - 8, 49, 14,255, 28, 67, 11,255, 52, 98, 43,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 68, 65, 84, 65,200, 21, 0, 0, 40,207, 13, 7,183, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,168, 3, 10, 7, 82,111,117,110, -100,101,100, 0, 0,101,119, 32, 85,115,101,114, 32, 84,104,101,109,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25,255, -153,153,153,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25,255, -153,153,153,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255,255,255,255,255, 1, 0, 25, 0,231,255, 0, 0, 25, 25, 25,255, -153,153,153,255,153,153,153,255, 90, 90, 90,255, 0, 0, 0,255,255,255,255,255, 1, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0,255, - 70, 70, 70,255, 86,128,194,255,255,255,255,255,255,255,255,255, 0, 0, 0,255, 1, 0, 15, 0,241,255, 0, 0, 0, 0, 0,255, - 70, 70, 70,255, 70, 70, 70,255,255,255,255,255, 0, 0, 0,255,255,255,255,255, 1, 0, 15, 0,241,255, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25,255, -180,180,180,255,153,153,153,255, 90, 90, 90,255, 0, 0, 0,255,255,255,255,255, 1, 0,236,255, 0, 0, 0, 0, 25, 25, 25,255, -180,180,180,255,153,153,153,255,128,128,128,255, 0, 0, 0,255,255,255,255,255, 1, 0,236,255, 0, 0, 0, 0, 0, 0, 0,255, - 70, 70, 70,255, 70, 70, 70,255,255,255,255,255,255,255,255,255,204,204,204,255, 1, 0, 15, 0,241,255, 0, 0, 0, 0, 0,255, - 63, 63, 63,255, 86,128,194,255,255,255,255,255, 0, 0, 0,255, 0, 0, 0,255, 0, 0, 25, 0,236,255, 0, 0, 0, 0, 0,255, - 25, 25, 25,230, 46,124,217,204,255,255,255,255,255,255,255,255, 0, 0, 0,255, 0, 0, 25, 0,236,255, 0, 0, 0, 0, 0,255, - 0, 0, 0, 0, 86,128,194,255,255,255,255,255,255,255,255,255, 0, 0, 0,255, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,107,107,107,255, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,175,175,175, 51, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100, -127,112,112,100, 0, 0, 0, 0, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, - 0, 0, 0, 0,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, - 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,107,107,107,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, 0, 0, 0, 51, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0,143,143,143,255, 0, 0, 0,255, -217,217,217,255, 0, 0, 0, 40,255,255,255,255, 16, 64, 16,255,102,255,102,255,255,130, 0,255, 0, 0, 0,255,255,130, 0,255, - 0, 0, 0,255,255,255,255,255,230,150, 50,255,255, 32, 32,255, 0, 0, 0, 0,255,255,255, 10,255,130, 0, 60,255,138, 48,255, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,114,114,114,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,130,130,130,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, + 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,107,107,107,255, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100, -127,112,112,100,255,130, 0,255, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, - 0, 0, 0, 0,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 57, 57,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100, +127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 16, 64, 16,255, + 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, + 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, + 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, - 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,107,107,107,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,107,107,107,150, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,107,107,107,100,143,143,143,100, 96,192, 64,255, 94, 94, 94,255, 0, 0, 0,255, -255,136,255,255, 0, 0, 0, 0,255,187,255,255, 79,101, 73,255,135,177,125,255,255,255,255,255,255,255,255,255,255,130, 0,255, - 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 82, 96,110,255,124,137,150,255, - 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,255, -255,130, 0,255, 2, 0, 0, 0, 0, 0, 0, 0,114,114,114,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,107,107,107,255, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100, -127,112,112,100, 0, 0, 0, 0, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, - 0, 0, 0, 0,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 76, 76,255, + 0, 0, 0, 0,250,250,250,255, 15, 15, 15,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,102,102,102,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100,255,140, 25,255,250,250,250,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40,130,130,130,255, 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, + 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, + 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,250,250,250,255,250,250,250,255, +250,250,250,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,102,102,102,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,255,255,255,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,150,150,150,100, +112,112,112,100, 96,192, 64,255, 94, 94, 94,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 79,101, 73,255, +135,177,125,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, + 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, + 0, 0, 0, 0, 96,192, 64,255, 82, 96,110,255,124,137,150,255, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,158,158,158,255, - 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,158,158,158,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,150, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,140,140,140,255,127,112,112,100, 0, 0, 0, 0,112,112, 96,255, 0, 0, 0,255, -255,136,255,255, 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,112,255,255,255,255,112,255, - 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,107,107,107,255, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,107,107,107,255, -178,178,178,100,255,130, 0,100, 94, 94, 94,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255, 79,101, 73,255, -135,177,125,255,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0,143,143,143,255,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,228,156,198,204, -255,255,170,204, 96,192, 64,255, 82, 96,110,255,124,137,150,255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, - 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,143,143,143,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,150, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,107,107,107,255,178,178,178,100,255,130, 0,100, 94, 94, 94,255, 0, 0, 0,255, -255,136,255,255, 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,112,255,255,255,255,112,255, - 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,228,156,198,255,255,255,170,255, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,107,107,107,255, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100, -127,112,112,100, 0, 0, 0, 0, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, - 0, 0, 0, 0,255,255,255,255,255,112,255,255,255,130, 0,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80,200,255,255, 0, 0, 0, 0, - 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 81,105,135,255,109, 88,129,255, 78,152, 62,255, 46,143,143,255,169, 84,124,255,126,126, 80,255, -162, 95,111,255,109,145,131,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 53, 53,255, - 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,195,195,195,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,150, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 88, 88, 88,255, 0, 0, 0,255, -255,136,255,255, 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,112,255,255,255,255,112,255, - 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60,255,133, 0,255, - 0, 0, 0, 0, 0, 0, 0, 0, 80,200,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,195,195,195,255, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,143,143,143,255, -127,112,112,100, 0, 0, 0, 0, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, - 0, 0, 0, 0,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,153,153,153,255, - 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,153,153,153,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,150, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,143,143,143,255,198,119,119,255,255, 0, 0,255, 88, 88, 88,255, 0, 0, 0,255, -255,136,255,255, 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,112,255,255,255,255,112,255, - 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 0, 0, 0,100, 0, 0,255, 0, 0,200,255,128, 0, 80,255, 95, 95, 0,255, 0,100, 50,255, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,107,107,107,255, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100, -127,112,112,100, 0, 0, 0, 0, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, - 0, 0, 0, 0,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,158,158,158,255, - 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,158,158,158,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,150, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,140,140,140,255,127,112,112,100, 0, 0, 0, 0,112,112, 96,255, 0, 0, 0,255, -255,136,255,255, 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,112,255,255,255,255,112,255, - 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,107,107,107,255, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, 0, 0, 0, 51, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100, -127,112,112,100, 0, 0, 0, 0,143,143,143,255, 0, 0, 0,255,217,217,217,255, 0, 0, 0, 40,255,255,255,255, 0, 0, 0, 0, - 0, 0, 0, 0,255,130, 0,255, 0, 0, 0,255,255,130, 0,255, 0, 0, 0,255,255,255,255,255,230,150, 50,255, 0, 0, 0, 0, - 0, 0, 0, 0,255,255,255, 10,255,130, 0, 60,255,138, 48,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0,150,150,150,255,129,131,144,255,127,127,127,255, -142,138,145,255,120,145,120,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100,100,100,255, - 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,107,107,107,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, 0, 0, 0, 51, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0,143,143,143,255, 0, 0, 0,255, -217,217,217,255, 0, 0, 0, 40,255,255,255,255, 16, 64, 16,255,102,255,102,255,255,130, 0,255, 0, 0, 0,255,255,130, 0,255, - 0, 0, 0,255,255,255,255,255,230,150, 50,255,255, 32, 32,255, 0, 0, 0, 0,255,255,255, 10,255,130, 0, 60,255,138, 48,255, + 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0,255,255,133, 0,255, 3, 0, 0, 0, 0, 0, 0, 0,114,114,114,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, + 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,114,114,114,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, - 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, 0, 0, 0, 0, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,114,114,114,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,173,173,173,255, +127,112,112,100, 0, 0, 0, 0, 91, 91, 91,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 16, 64, 16,255, + 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, + 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, + 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,102,102,102,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,255,255,255,150, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,150,150,150,100,112,112,112,100, 96,192, 64,255, 94, 94, 94,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 79,101, 73,255,135,177,125,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, + 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, + 34,221,221,255,200,200,200,255, 80,200,255, 80, 12, 10, 10,128,255,140, 0,255, 96,192, 64,255, 82, 96,110,255,124,137,150,255, + 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0,255, +255,133, 0,255, 3, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,102,102,102,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,255,255,255,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,150,150,150,100, +112,112,112,100, 96,192, 64,255, 94, 94, 94,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 79,101, 73,255, +135,177,125,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, + 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 12, 10, 10,128, +255,140, 0,255, 96,192, 64,255, 82, 96,110,255,124,137,150,255, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0,255,255,133, 0,255, 3, 0, 0, 0, 0, 0, 0, 0,116,116,116,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, + 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, + 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81,105,135,255,109, 88,129,255, + 78,152, 62,255, 46,143,143,255,169, 84,124,255,126,126, 80,255,162, 95,111,255,109,145,131,255,255,255,255,128, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 53, 53,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100, +127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 16, 64, 16,255, + 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, + 75, 75, 75,255,255,255,255, 10,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, + 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,110,110,110,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,132,132,132,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, 94, 94, 94,255,172,172,172,255, 17, 27, 60,100, 94, 94, 94,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40,195,195,195,255, 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, + 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, + 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,153,153,153,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,143,143,143,255, +198,119,119,255,255, 0, 0,255, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 16, 64, 16,255, + 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, + 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, + 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0,100, 0, 0,255, 0, 0,200,255,128, 0, 80,255, + 95, 95, 0,255, 0,100, 50,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,114,114,114,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, + 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, + 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,114,114,114,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,173,173,173,255, +127,112,112,100, 0, 0, 0, 0, 91, 91, 91,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 16, 64, 16,255, + 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, + 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, + 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 57, 57,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, + 0, 0, 0,255,255,255,255,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, + 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 4, 0, 0,155,155,155,160,100,100,100,255,108,105,111,255,104,106,117,255,105,117,110,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,100,100,100,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100, +127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255,241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 16, 64, 16,255, + 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, + 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, + 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,114,114,114,255, + 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, + 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255, +241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 16, 64, 16,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, + 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255, 0, 0, 0, 18,255,133, 0, 60,255,133, 0,255, + 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,154, 0, 0,255,189, 17, 17,255,247, 10, 10,255, 0, 0, 0, 0,247, 64, 24,255, +246,105, 19,255,250,153, 0,255, 0, 0, 0, 0, 30,145, 9,255, 89,183, 11,255,131,239, 29,255, 0, 0, 0, 0, 10, 54,148,255, + 54,103,223,255, 94,193,239,255, 0, 0, 0, 0,169, 41, 78,255,193, 65,106,255,240, 93,145,255, 0, 0, 0, 0, 67, 12,120,255, + 84, 58,163,255,135,100,213,255, 0, 0, 0, 0, 36,120, 90,255, 60,149,121,255,111,182,171,255, 0, 0, 0, 0, 75,112,124,255, +106,134,145,255,155,194,205,255, 0, 0, 0, 0,244,201, 12,255,238,194, 54,255,243,255, 0,255, 0, 0, 0, 0, 30, 32, 36,255, + 72, 76, 86,255,255,255,255,255, 0, 0, 0, 0,111, 47,106,255,152, 69,190,255,211, 48,214,255, 0, 0, 0, 0,108,142, 34,255, +127,176, 34,255,187,239, 91,255, 0, 0, 0, 0,141,141,141,255,176,176,176,255,222,222,222,255, 0, 0, 0, 0,131, 67, 38,255, +139, 88, 17,255,189,106, 17,255, 0, 0, 0, 0, 8, 49, 14,255, 28, 67, 11,255, 52, 98, 43,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 65, 84, 65,200, 21, 0, 0,120, 44,131, 3,186, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0,104,229,213, 2, 82,111,117,110,100,101,100, 0, 0,101,119, 32, 85,115,101,114, 32, 84,104,101,109,101, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25,255,153,153,153,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255,255,255,255,255, + 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25,255,153,153,153,255,100,100,100,255, 25, 25, 25,255, 0, 0, 0,255,255,255,255,255, + 1, 0, 25, 0,231,255, 0, 0, 25, 25, 25,255,153,153,153,255,153,153,153,255, 90, 90, 90,255, 0, 0, 0,255,255,255,255,255, + 1, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0,255, 70, 70, 70,255, 86,128,194,255,255,255,255,255,255,255,255,255, 0, 0, 0,255, + 1, 0, 15, 0,241,255, 0, 0, 0, 0, 0,255, 70, 70, 70,255, 70, 70, 70,255,255,255,255,255, 0, 0, 0,255,255,255,255,255, + 1, 0, 15, 0,241,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25,255,180,180,180,255,153,153,153,255, 90, 90, 90,255, 0, 0, 0,255,255,255,255,255, + 1, 0,236,255, 0, 0, 0, 0, 25, 25, 25,255,180,180,180,255,153,153,153,255,128,128,128,255, 0, 0, 0,255,255,255,255,255, + 1, 0,236,255, 0, 0, 0, 0, 0, 0, 0,255, 70, 70, 70,255, 70, 70, 70,255,255,255,255,255,255,255,255,255,204,204,204,255, + 1, 0, 15, 0,241,255, 0, 0, 0, 0, 0,255, 63, 63, 63,255, 86,128,194,255,255,255,255,255, 0, 0, 0,255, 0, 0, 0,255, + 0, 0, 25, 0,236,255, 0, 0, 0, 0, 0,255, 25, 25, 25,230, 46,124,217,204,255,255,255,255,255,255,255,255, 0, 0, 0,255, + 0, 0, 25, 0,236,255, 0, 0, 0, 0, 0,255, 0, 0, 0, 0, 86,128,194,255,255,255,255,255,255,255,255,255, 0, 0, 0,255, + 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,154, 0, 0,255, -189, 17, 17,255,247, 10, 10,255, 0, 0, 0, 0,247, 64, 24,255,246,105, 19,255,250,153, 0,255, 0, 0, 0, 0, 30,145, 9,255, - 89,183, 11,255,131,239, 29,255, 0, 0, 0, 0, 10, 54,148,255, 54,103,223,255, 94,193,239,255, 0, 0, 0, 0,169, 41, 78,255, -193, 65,106,255,240, 93,145,255, 0, 0, 0, 0, 67, 12,120,255, 84, 58,163,255,135,100,213,255, 0, 0, 0, 0, 36,120, 90,255, - 60,149,121,255,111,182,171,255, 0, 0, 0, 0, 75,112,124,255,106,134,145,255,155,194,205,255, 0, 0, 0, 0,244,201, 12,255, -238,194, 54,255,243,255, 0,255, 0, 0, 0, 0, 30, 32, 36,255, 72, 76, 86,255,255,255,255,255, 0, 0, 0, 0,111, 47,106,255, -152, 69,190,255,211, 48,214,255, 0, 0, 0, 0,108,142, 34,255,127,176, 34,255,187,239, 91,255, 0, 0, 0, 0,141,141,141,255, -176,176,176,255,222,222,222,255, 0, 0, 0, 0,131, 67, 38,255,139, 88, 17,255,189,106, 17,255, 0, 0, 0, 0, 8, 49, 14,255, - 28, 67, 11,255, 52, 98, 43,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, + 0, 0, 0,255,255,255,255,255,107,107,107,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,175,175,175, 51, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, + 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255, +144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 78, 65, 49, - 28,222, 0, 0, 32, 80, 6, 7, 0, 0, 0, 0, 1, 0, 0, 0, 83, 68, 78, 65, 78, 65, 77, 69,212, 10, 0, 0, 42,110,101,120, -116, 0, 42,112,114,101,118, 0, 42,100, 97,116, 97, 0, 42,102,105,114,115,116, 0, 42,108, 97,115,116, 0,120, 0,121, 0,122, - 0,119, 0,120,109,105,110, 0,120,109, 97,120, 0,121,109,105,110, 0,121,109, 97,120, 0, 42,112,111,105,110,116,101,114, 0, -103,114,111,117,112, 0,118, 97,108, 0,118, 97,108, 50, 0,116,121,112,101, 0,115,117, 98,116,121,112,101, 0,102,108, 97,103, - 0,110, 97,109,101, 91, 51, 50, 93, 0,115, 97,118,101,100, 0,100, 97,116, 97, 0,108,101,110, 0,116,111,116, 97,108,108,101, -110, 0, 42,110,101,119,105,100, 0, 42,108,105, 98, 0,110, 97,109,101, 91, 50, 52, 93, 0,117,115, 0,105, 99,111,110, 95,105, -100, 0, 42,112,114,111,112,101,114,116,105,101,115, 0,105,100, 0, 42,105,100, 98,108,111, 99,107, 0, 42,102,105,108,101,100, - 97,116, 97, 0,110, 97,109,101, 91, 50, 52, 48, 93, 0,102,105,108,101,110, 97,109,101, 91, 50, 52, 48, 93, 0,116,111,116, 0, -112, 97,100, 0, 42,112, 97,114,101,110,116, 0,119, 91, 50, 93, 0,104, 91, 50, 93, 0, 99,104, 97,110,103,101,100, 91, 50, 93, - 0,112, 97,100, 48, 0,112, 97,100, 49, 0, 42,114,101, 99,116, 91, 50, 93, 0, 42,111, 98, 0, 98,108,111, 99,107,116,121,112, -101, 0, 97,100,114, 99,111,100,101, 0,110, 97,109,101, 91, 49, 50, 56, 93, 0, 42, 98,112, 0, 42, 98,101,122,116, 0,109, 97, -120,114, 99,116, 0,116,111,116,114, 99,116, 0,118, 97,114,116,121,112,101, 0,116,111,116,118,101,114,116, 0,105,112,111, 0, -101,120,116,114, 97,112, 0,114,116, 0, 98,105,116,109, 97,115,107, 0,115,108,105,100,101, 95,109,105,110, 0,115,108,105,100, -101, 95,109, 97,120, 0, 99,117,114,118, 97,108, 0, 42,100,114,105,118,101,114, 0, 99,117,114,118,101, 0, 99,117,114, 0,115, -104,111,119,107,101,121, 0,109,117,116,101,105,112,111, 0,112,111,115, 0,114,101,108, 97,116,105,118,101, 0,116,111,116,101, -108,101,109, 0,112, 97,100, 50, 0, 42,119,101,105,103,104,116,115, 0,118,103,114,111,117,112, 91, 51, 50, 93, 0,115,108,105, -100,101,114,109,105,110, 0,115,108,105,100,101,114,109, 97,120, 0, 42, 97,100,116, 0, 42,114,101,102,107,101,121, 0,101,108, -101,109,115,116,114, 91, 51, 50, 93, 0,101,108,101,109,115,105,122,101, 0, 98,108,111, 99,107, 0, 42,105,112,111, 0, 42,102, -114,111,109, 0,116,111,116,107,101,121, 0,115,108,117,114,112,104, 0, 42,108,105,110,101, 0, 42,102,111,114,109, 97,116, 0, - 98,108,101,110, 0,108,105,110,101,110,111, 0,115,116, 97,114,116, 0,101,110,100, 0,102,108, 97,103,115, 0, 99,111,108,111, -114, 91, 52, 93, 0,112, 97,100, 91, 52, 93, 0, 42,110, 97,109,101, 0,110,108,105,110,101,115, 0,108,105,110,101,115, 0, 42, - 99,117,114,108, 0, 42,115,101,108,108, 0, 99,117,114, 99, 0,115,101,108, 99, 0,109, 97,114,107,101,114,115, 0, 42,117,110, -100,111, 95, 98,117,102, 0,117,110,100,111, 95,112,111,115, 0,117,110,100,111, 95,108,101,110, 0, 42, 99,111,109,112,105,108, -101,100, 0,109,116,105,109,101, 0,115,105,122,101, 0,115,101,101,107, 0,112, 97,115,115,101,112, 97,114,116, 97,108,112,104, - 97, 0, 97,110,103,108,101, 0, 99,108,105,112,115,116, 97, 0, 99,108,105,112,101,110,100, 0,108,101,110,115, 0,111,114,116, -104,111, 95,115, 99, 97,108,101, 0,100,114, 97,119,115,105,122,101, 0,115,104,105,102,116,120, 0,115,104,105,102,116,121, 0, - 89, 70, 95,100,111,102,100,105,115,116, 0, 89, 70, 95, 97,112,101,114,116,117,114,101, 0, 89, 70, 95, 98,107,104,116,121,112, -101, 0, 89, 70, 95, 98,107,104, 98,105, 97,115, 0, 89, 70, 95, 98,107,104,114,111,116, 0, 42,100,111,102, 95,111, 98, 0,102, -114, 97,109,101,110,114, 0,102,114, 97,109,101,115, 0,111,102,102,115,101,116, 0,115,102,114, 97, 0,102,105,101, 95,105,109, - 97, 0, 99,121, 99,108, 0,111,107, 0,109,117,108,116,105, 95,105,110,100,101,120, 0,108, 97,121,101,114, 0,112, 97,115,115, - 0,109,101,110,117,110,114, 0, 42,115, 99,101,110,101, 0,105, 98,117,102,115, 0, 42,103,112,117,116,101,120,116,117,114,101, - 0, 42, 97,110,105,109, 0, 42,114,114, 0,115,111,117,114, 99,101, 0,108, 97,115,116,102,114, 97,109,101, 0,116,112, 97,103, -101,102,108, 97,103, 0,116,111,116, 98,105,110,100, 0,120,114,101,112, 0,121,114,101,112, 0,116,119,115,116, 97, 0,116,119, -101,110,100, 0, 98,105,110,100, 99,111,100,101, 0, 42,114,101,112, 98,105,110,100, 0, 42,112, 97, 99,107,101,100,102,105,108, -101, 0, 42,112,114,101,118,105,101,119, 0, 42,114,101,110,100,101,114, 95,116,101,120,116, 0,108, 97,115,116,117,112,100, 97, -116,101, 0,108, 97,115,116,117,115,101,100, 0, 97,110,105,109,115,112,101,101,100, 0,103,101,110, 95,120, 0,103,101,110, 95, -121, 0,103,101,110, 95,116,121,112,101, 0, 97,115,112,120, 0, 97,115,112,121, 0,116,101,120, 99,111, 0,109, 97,112,116,111, - 0,109, 97,112,116,111,110,101,103, 0, 98,108,101,110,100,116,121,112,101, 0, 42,111, 98,106,101, 99,116, 0, 42,116,101,120, - 0,117,118,110, 97,109,101, 91, 51, 50, 93, 0,112,114,111,106,120, 0,112,114,111,106,121, 0,112,114,111,106,122, 0,109, 97, -112,112,105,110,103, 0,111,102,115, 91, 51, 93, 0,115,105,122,101, 91, 51, 93, 0,114,111,116, 0,116,101,120,102,108, 97,103, - 0, 99,111,108,111,114,109,111,100,101,108, 0,112,109, 97,112,116,111, 0,112,109, 97,112,116,111,110,101,103, 0,110,111,114, -109, 97,112,115,112, 97, 99,101, 0,119,104,105, 99,104, 95,111,117,116,112,117,116, 0, 98,114,117,115,104, 95,109, 97,112, 95, -109,111,100,101, 0,112, 97,100, 91, 55, 93, 0,114, 0,103, 0, 98, 0,107, 0,100,101,102, 95,118, 97,114, 0, 99,111,108,102, - 97, 99, 0,110,111,114,102, 97, 99, 0,118, 97,114,102, 97, 99, 0,100,105,115,112,102, 97, 99, 0,119, 97,114,112,102, 97, 99, - 0,110, 97,109,101, 91, 49, 54, 48, 93, 0, 42,104, 97,110,100,108,101, 0, 42,112,110, 97,109,101, 0, 42,115,116,110, 97,109, -101,115, 0,115,116,121,112,101,115, 0,118, 97,114,115, 0, 42,118, 97,114,115,116,114, 0, 42,114,101,115,117,108,116, 0, 42, - 99,102,114, 97, 0,100, 97,116, 97, 91, 51, 50, 93, 0, 40, 42,100,111,105,116, 41, 40, 41, 0, 40, 42,105,110,115,116, 97,110, - 99,101, 95,105,110,105,116, 41, 40, 41, 0, 40, 42, 99, 97,108,108, 98, 97, 99,107, 41, 40, 41, 0,118,101,114,115,105,111,110, - 0, 97, 0,105,112,111,116,121,112,101, 0, 42,105,109, 97, 0, 42, 99,117, 98,101, 91, 54, 93, 0,105,109, 97,116, 91, 52, 93, - 91, 52, 93, 0,111, 98,105,109, 97,116, 91, 51, 93, 91, 51, 93, 0,115,116,121,112,101, 0,118,105,101,119,115, 99, 97,108,101, - 0,110,111,116,108, 97,121, 0, 99,117, 98,101,114,101,115, 0,100,101,112,116,104, 0,114,101, 99, 97,108, 99, 0,108, 97,115, -116,115,105,122,101, 0,102, 97,108,108,111,102,102, 95,116,121,112,101, 0,102, 97,108,108,111,102,102, 95,115,111,102,116,110, -101,115,115, 0,114, 97,100,105,117,115, 0, 99,111,108,111,114, 95,115,111,117,114, 99,101, 0,116,111,116,112,111,105,110,116, -115, 0,112,100,112, 97,100, 0, 42,112,115,121,115, 0,112,115,121,115, 95, 99, 97, 99,104,101, 95,115,112, 97, 99,101, 0,111, - 98, 95, 99, 97, 99,104,101, 95,115,112, 97, 99,101, 0,112,100,112, 97,100, 50, 91, 50, 93, 0, 42,112,111,105,110,116, 95,116, -114,101,101, 0, 42,112,111,105,110,116, 95,100, 97,116, 97, 0,110,111,105,115,101, 95,115,105,122,101, 0,110,111,105,115,101, - 95,100,101,112,116,104, 0,110,111,105,115,101, 95,105,110,102,108,117,101,110, 99,101, 0,110,111,105,115,101, 95, 98, 97,115, -105,115, 0,112,100,112, 97,100, 51, 91, 51, 93, 0,110,111,105,115,101, 95,102, 97, 99, 0,115,112,101,101,100, 95,115, 99, 97, -108,101, 0, 42, 99,111, 98, 97, 0,114,101,115,111,108, 91, 51, 93, 0,105,110,116,101,114,112, 95,116,121,112,101, 0,102,105, -108,101, 95,102,111,114,109, 97,116, 0,105,110,116, 95,109,117,108,116,105,112,108,105,101,114, 0,115,116,105,108,108, 95,102, -114, 97,109,101, 0,115,111,117,114, 99,101, 95,112, 97,116,104, 91, 50, 52, 48, 93, 0, 42,100, 97,116, 97,115,101,116, 0,110, -111,105,115,101,115,105,122,101, 0,116,117,114, 98,117,108, 0, 98,114,105,103,104,116, 0, 99,111,110,116,114, 97,115,116, 0, -114,102, 97, 99, 0,103,102, 97, 99, 0, 98,102, 97, 99, 0,102,105,108,116,101,114,115,105,122,101, 0,109,103, 95, 72, 0,109, -103, 95,108, 97, 99,117,110, 97,114,105,116,121, 0,109,103, 95,111, 99,116, 97,118,101,115, 0,109,103, 95,111,102,102,115,101, -116, 0,109,103, 95,103, 97,105,110, 0,100,105,115,116, 95, 97,109,111,117,110,116, 0,110,115, 95,111,117,116,115, 99, 97,108, -101, 0,118,110, 95,119, 49, 0,118,110, 95,119, 50, 0,118,110, 95,119, 51, 0,118,110, 95,119, 52, 0,118,110, 95,109,101,120, -112, 0,118,110, 95,100,105,115,116,109, 0,118,110, 95, 99,111,108,116,121,112,101, 0,110,111,105,115,101,100,101,112,116,104, - 0,110,111,105,115,101,116,121,112,101, 0,110,111,105,115,101, 98, 97,115,105,115, 0,110,111,105,115,101, 98, 97,115,105,115, - 50, 0,105,109, 97,102,108, 97,103, 0, 99,114,111,112,120,109,105,110, 0, 99,114,111,112,121,109,105,110, 0, 99,114,111,112, -120,109, 97,120, 0, 99,114,111,112,121,109, 97,120, 0,116,101,120,102,105,108,116,101,114, 0, 97,102,109, 97,120, 0,120,114, -101,112,101, 97,116, 0,121,114,101,112,101, 97,116, 0,101,120,116,101,110,100, 0, 99,104,101, 99,107,101,114,100,105,115,116, - 0,110, 97, 98,108, 97, 0,105,117,115,101,114, 0, 42,110,111,100,101,116,114,101,101, 0, 42,112,108,117,103,105,110, 0, 42, -101,110,118, 0, 42,112,100, 0, 42,118,100, 0,117,115,101, 95,110,111,100,101,115, 0,108,111, 99, 91, 51, 93, 0,114,111,116, - 91, 51, 93, 0,109, 97,116, 91, 52, 93, 91, 52, 93, 0,109,105,110, 91, 51, 93, 0,109, 97,120, 91, 51, 93, 0,109,111,100,101, - 0,116,111,116,101,120, 0,115,104,100,119,114, 0,115,104,100,119,103, 0,115,104,100,119, 98, 0,115,104,100,119,112, 97,100, - 0,101,110,101,114,103,121, 0,100,105,115,116, 0,115,112,111,116,115,105,122,101, 0,115,112,111,116, 98,108,101,110,100, 0, -104, 97,105,110,116, 0, 97,116,116, 49, 0, 97,116,116, 50, 0, 42, 99,117,114,102, 97,108,108,111,102,102, 0,115,104, 97,100, -115,112,111,116,115,105,122,101, 0, 98,105, 97,115, 0,115,111,102,116, 0, 98,117,102,115,105,122,101, 0,115, 97,109,112, 0, - 98,117,102,102,101,114,115, 0,102,105,108,116,101,114,116,121,112,101, 0, 98,117,102,102,108, 97,103, 0, 98,117,102,116,121, -112,101, 0,114, 97,121, 95,115, 97,109,112, 0,114, 97,121, 95,115, 97,109,112,121, 0,114, 97,121, 95,115, 97,109,112,122, 0, -114, 97,121, 95,115, 97,109,112, 95,116,121,112,101, 0, 97,114,101, 97, 95,115,104, 97,112,101, 0, 97,114,101, 97, 95,115,105, -122,101, 0, 97,114,101, 97, 95,115,105,122,101,121, 0, 97,114,101, 97, 95,115,105,122,101,122, 0, 97,100, 97,112,116, 95,116, -104,114,101,115,104, 0,114, 97,121, 95,115, 97,109,112, 95,109,101,116,104,111,100, 0,116,101,120, 97, 99,116, 0,115,104, 97, -100,104, 97,108,111,115,116,101,112, 0,115,117,110, 95,101,102,102,101, 99,116, 95,116,121,112,101, 0,115,107,121, 98,108,101, -110,100,116,121,112,101, 0,104,111,114,105,122,111,110, 95, 98,114,105,103,104,116,110,101,115,115, 0,115,112,114,101, 97,100, - 0,115,117,110, 95, 98,114,105,103,104,116,110,101,115,115, 0,115,117,110, 95,115,105,122,101, 0, 98, 97, 99,107,115, 99, 97, -116,116,101,114,101,100, 95,108,105,103,104,116, 0,115,117,110, 95,105,110,116,101,110,115,105,116,121, 0, 97,116,109, 95,116, -117,114, 98,105,100,105,116,121, 0, 97,116,109, 95,105,110,115, 99, 97,116,116,101,114,105,110,103, 95,102, 97, 99,116,111,114, - 0, 97,116,109, 95,101,120,116,105,110, 99,116,105,111,110, 95,102, 97, 99,116,111,114, 0, 97,116,109, 95,100,105,115,116, 97, -110, 99,101, 95,102, 97, 99,116,111,114, 0,115,107,121, 98,108,101,110,100,102, 97, 99, 0,115,107,121, 95,101,120,112,111,115, -117,114,101, 0,115,107,121, 95, 99,111,108,111,114,115,112, 97, 99,101, 0,112, 97,100, 52, 0, 89, 70, 95,110,117,109,112,104, -111,116,111,110,115, 0, 89, 70, 95,110,117,109,115,101, 97,114, 99,104, 0, 89, 70, 95,112,104,100,101,112,116,104, 0, 89, 70, - 95,117,115,101,113,109, 99, 0, 89, 70, 95, 98,117,102,115,105,122,101, 0, 89, 70, 95,112, 97,100, 0, 89, 70, 95, 99, 97,117, -115,116,105, 99, 98,108,117,114, 0, 89, 70, 95,108,116,114, 97,100,105,117,115, 0, 89, 70, 95,103,108,111,119,105,110,116, 0, - 89, 70, 95,103,108,111,119,111,102,115, 0, 89, 70, 95,103,108,111,119,116,121,112,101, 0, 89, 70, 95,112, 97,100, 50, 0, 42, -109,116,101,120, 91, 49, 56, 93, 0,112,114, 95,116,101,120,116,117,114,101, 0,112, 97,100, 91, 51, 93, 0,100,101,110,115,105, -116,121, 0,101,109,105,115,115,105,111,110, 0, 97, 98,115,111,114,112,116,105,111,110, 0,115, 99, 97,116,116,101,114,105,110, -103, 0,101,109,105,115,115,105,111,110, 95, 99,111,108, 91, 51, 93, 0, 97, 98,115,111,114,112,116,105,111,110, 95, 99,111,108, - 91, 51, 93, 0,100,101,110,115,105,116,121, 95,115, 99, 97,108,101, 0,100,101,112,116,104, 95, 99,117,116,111,102,102, 0,112, -104, 97,115,101,102,117,110, 99, 95,116,121,112,101, 0,118,112, 97,100, 91, 51, 93, 0,112,104, 97,115,101,102,117,110, 99, 95, -103, 0,115,116,101,112,115,105,122,101, 0,115,104, 97,100,101, 95,115,116,101,112,115,105,122,101, 0,115,116,101,112,115,105, -122,101, 95,116,121,112,101, 0,115,104, 97,100,101,102,108, 97,103, 0,115,104, 97,100,101, 95,116,121,112,101, 0,112,114,101, - 99, 97, 99,104,101, 95,114,101,115,111,108,117,116,105,111,110, 0,109,115, 95,100,105,102,102, 0,109,115, 95,105,110,116,101, -110,115,105,116,121, 0,109,115, 95,115,116,101,112,115, 0,109, 97,116,101,114,105, 97,108, 95,116,121,112,101, 0,115,112,101, - 99,114, 0,115,112,101, 99,103, 0,115,112,101, 99, 98, 0,109,105,114,114, 0,109,105,114,103, 0,109,105,114, 98, 0, 97,109, - 98,114, 0, 97,109, 98, 98, 0, 97,109, 98,103, 0, 97,109, 98, 0,101,109,105,116, 0, 97,110,103, 0,115,112,101, 99,116,114, - 97, 0,114, 97,121, 95,109,105,114,114,111,114, 0, 97,108,112,104, 97, 0,114,101,102, 0,115,112,101, 99, 0,122,111,102,102, -115, 0, 97,100,100, 0,116,114, 97,110,115,108,117, 99,101,110, 99,121, 0,118,111,108, 0,102,114,101,115,110,101,108, 95,109, -105,114, 0,102,114,101,115,110,101,108, 95,109,105,114, 95,105, 0,102,114,101,115,110,101,108, 95,116,114, 97, 0,102,114,101, -115,110,101,108, 95,116,114, 97, 95,105, 0,102,105,108,116,101,114, 0,116,120, 95,108,105,109,105,116, 0,116,120, 95,102, 97, -108,108,111,102,102, 0,114, 97,121, 95,100,101,112,116,104, 0,114, 97,121, 95,100,101,112,116,104, 95,116,114, 97, 0,104, 97, -114, 0,115,101,101,100, 49, 0,115,101,101,100, 50, 0,103,108,111,115,115, 95,109,105,114, 0,103,108,111,115,115, 95,116,114, - 97, 0,115, 97,109,112, 95,103,108,111,115,115, 95,109,105,114, 0,115, 97,109,112, 95,103,108,111,115,115, 95,116,114, 97, 0, - 97,100, 97,112,116, 95,116,104,114,101,115,104, 95,109,105,114, 0, 97,100, 97,112,116, 95,116,104,114,101,115,104, 95,116,114, - 97, 0, 97,110,105,115,111, 95,103,108,111,115,115, 95,109,105,114, 0,100,105,115,116, 95,109,105,114, 0,102, 97,100,101,116, -111, 95,109,105,114, 0,115,104, 97,100,101, 95,102,108, 97,103, 0,109,111,100,101, 95,108, 0,102,108, 97,114,101, 99, 0,115, -116, 97,114, 99, 0,108,105,110,101, 99, 0,114,105,110,103, 99, 0,104, 97,115,105,122,101, 0,102,108, 97,114,101,115,105,122, -101, 0,115,117, 98,115,105,122,101, 0,102,108, 97,114,101, 98,111,111,115,116, 0,115,116,114, 97,110,100, 95,115,116, 97, 0, -115,116,114, 97,110,100, 95,101,110,100, 0,115,116,114, 97,110,100, 95,101, 97,115,101, 0,115,116,114, 97,110,100, 95,115,117, -114,102,110,111,114, 0,115,116,114, 97,110,100, 95,109,105,110, 0,115,116,114, 97,110,100, 95,119,105,100,116,104,102, 97,100, -101, 0,115,116,114, 97,110,100, 95,117,118,110, 97,109,101, 91, 51, 50, 93, 0,115, 98,105, 97,115, 0,108, 98,105, 97,115, 0, -115,104, 97,100, 95, 97,108,112,104, 97, 0,115,101,112,116,101,120, 0,114,103, 98,115,101,108, 0,112,114, 95,116,121,112,101, - 0,112,114, 95, 98, 97, 99,107, 0,112,114, 95,108, 97,109,112, 0,109,108, 95,102,108, 97,103, 0,100,105,102,102, 95,115,104, - 97,100,101,114, 0,115,112,101, 99, 95,115,104, 97,100,101,114, 0,114,111,117,103,104,110,101,115,115, 0,114,101,102,114, 97, - 99, 0,112, 97,114, 97,109, 91, 52, 93, 0,114,109,115, 0,100, 97,114,107,110,101,115,115, 0, 42,114, 97,109,112, 95, 99,111, -108, 0, 42,114, 97,109,112, 95,115,112,101, 99, 0,114, 97,109,112,105,110, 95, 99,111,108, 0,114, 97,109,112,105,110, 95,115, -112,101, 99, 0,114, 97,109,112, 98,108,101,110,100, 95, 99,111,108, 0,114, 97,109,112, 98,108,101,110,100, 95,115,112,101, 99, - 0,114, 97,109,112, 95,115,104,111,119, 0,112, 97,100, 51, 0,114, 97,109,112,102, 97, 99, 95, 99,111,108, 0,114, 97,109,112, -102, 97, 99, 95,115,112,101, 99, 0, 42,103,114,111,117,112, 0,102,114,105, 99,116,105,111,110, 0,102,104, 0,114,101,102,108, -101, 99,116, 0,102,104,100,105,115,116, 0,120,121,102,114,105, 99,116, 0,100,121,110, 97,109,111,100,101, 0,115,115,115, 95, -114, 97,100,105,117,115, 91, 51, 93, 0,115,115,115, 95, 99,111,108, 91, 51, 93, 0,115,115,115, 95,101,114,114,111,114, 0,115, -115,115, 95,115, 99, 97,108,101, 0,115,115,115, 95,105,111,114, 0,115,115,115, 95, 99,111,108,102, 97, 99, 0,115,115,115, 95, -116,101,120,102, 97, 99, 0,115,115,115, 95,102,114,111,110,116, 0,115,115,115, 95, 98, 97, 99,107, 0,115,115,115, 95,102,108, - 97,103, 0,115,115,115, 95,112,114,101,115,101,116, 0, 89, 70, 95, 97,114, 0, 89, 70, 95, 97,103, 0, 89, 70, 95, 97, 98, 0, - 89, 70, 95,100,115, 99, 97,108,101, 0, 89, 70, 95,100,112,119,114, 0, 89, 70, 95,100,115,109,112, 0, 89, 70, 95,112,114,101, -115,101,116, 0, 89, 70, 95,100,106,105,116, 0,103,112,117,109, 97,116,101,114,105, 97,108, 0,110, 97,109,101, 91, 50, 53, 54, - 93, 0, 42, 98, 98, 0,105, 49, 0,106, 49, 0,107, 49, 0,105, 50, 0,106, 50, 0,107, 50, 0,115,101,108, 99,111,108, 49, 0, -115,101,108, 99,111,108, 50, 0,113,117, 97,116, 91, 52, 93, 0,101,120,112,120, 0,101,120,112,121, 0,101,120,112,122, 0,114, - 97,100, 0,114, 97,100, 50, 0,115, 0, 42,109, 97,116, 0, 42,105,109, 97,116, 0,101,108,101,109,115, 0,100,105,115,112, 0, - 42,101,100,105,116,101,108,101,109,115, 0, 42, 42,109, 97,116, 0,102,108, 97,103, 50, 0,116,111,116, 99,111,108, 0,119,105, -114,101,115,105,122,101, 0,114,101,110,100,101,114,115,105,122,101, 0,116,104,114,101,115,104, 0, 42,108, 97,115,116,101,108, -101,109, 0,118,101, 99, 91, 51, 93, 91, 51, 93, 0, 97,108,102, 97, 0,119,101,105,103,104,116, 0,104, 49, 0,104, 50, 0,102, - 49, 0,102, 50, 0,102, 51, 0,104,105,100,101, 0,118,101, 99, 91, 52, 93, 0,109, 97,116, 95,110,114, 0,112,110,116,115,117, - 0,112,110,116,115,118, 0,114,101,115,111,108,117, 0,114,101,115,111,108,118, 0,111,114,100,101,114,117, 0,111,114,100,101, -114,118, 0,102,108, 97,103,117, 0,102,108, 97,103,118, 0, 42,107,110,111,116,115,117, 0, 42,107,110,111,116,115,118, 0,116, -105,108,116, 95,105,110,116,101,114,112, 0,114, 97,100,105,117,115, 95,105,110,116,101,114,112, 0, 99,104, 97,114,105,100,120, - 0,107,101,114,110, 0,104, 0,110,117,114, 98, 0, 42,101,100,105,116,110,117,114, 98, 0, 42, 98,101,118,111, 98,106, 0, 42, -116, 97,112,101,114,111, 98,106, 0, 42,116,101,120,116,111,110, 99,117,114,118,101, 0, 42,112, 97,116,104, 0, 42,107,101,121, - 0, 98,101,118, 0,100,114, 97,119,102,108, 97,103, 0,116,119,105,115,116, 95,109,111,100,101, 0,112, 97,100, 91, 50, 93, 0, -116,119,105,115,116, 95,115,109,111,111,116,104, 0,112, 97,116,104,108,101,110, 0, 98,101,118,114,101,115,111,108, 0,119,105, -100,116,104, 0,101,120,116, 49, 0,101,120,116, 50, 0,114,101,115,111,108,117, 95,114,101,110, 0,114,101,115,111,108,118, 95, -114,101,110, 0, 97, 99,116,110,117, 0, 42,108, 97,115,116,115,101,108, 98,112, 0,115,112, 97, 99,101,109,111,100,101, 0,115, -112, 97, 99,105,110,103, 0,108,105,110,101,100,105,115,116, 0,115,104,101, 97,114, 0,102,115,105,122,101, 0,119,111,114,100, -115,112, 97, 99,101, 0,117,108,112,111,115, 0,117,108,104,101,105,103,104,116, 0,120,111,102, 0,121,111,102, 0,108,105,110, -101,119,105,100,116,104, 0, 42,115,116,114, 0, 42,115,101,108, 98,111,120,101,115, 0, 42,101,100,105,116,102,111,110,116, 0, -102, 97,109,105,108,121, 91, 50, 52, 93, 0, 42,118,102,111,110,116, 0, 42,118,102,111,110,116, 98, 0, 42,118,102,111,110,116, -105, 0, 42,118,102,111,110,116, 98,105, 0,115,101,112, 99,104, 97,114, 0, 99,116,105,109,101, 0,116,111,116, 98,111,120, 0, - 97, 99,116, 98,111,120, 0, 42,116, 98, 0,115,101,108,115,116, 97,114,116, 0,115,101,108,101,110,100, 0, 42,115,116,114,105, -110,102,111, 0, 99,117,114,105,110,102,111, 0,101,102,102,101, 99,116, 0, 42,109,102, 97, 99,101, 0, 42,109,116,102, 97, 99, -101, 0, 42,116,102, 97, 99,101, 0, 42,109,118,101,114,116, 0, 42,109,101,100,103,101, 0, 42,100,118,101,114,116, 0, 42,109, - 99,111,108, 0, 42,109,115,116,105, 99,107,121, 0, 42,116,101,120, 99,111,109,101,115,104, 0, 42,109,115,101,108,101, 99,116, - 0, 42,101,100,105,116, 95,109,101,115,104, 0,118,100, 97,116, 97, 0,101,100, 97,116, 97, 0,102,100, 97,116, 97, 0,116,111, -116,101,100,103,101, 0,116,111,116,102, 97, 99,101, 0,116,111,116,115,101,108,101, 99,116, 0, 97, 99,116, 95,102, 97, 99,101, - 0, 99,117, 98,101,109, 97,112,115,105,122,101, 0,115,109,111,111,116,104,114,101,115,104, 0,115,117, 98,100,105,118, 0,115, -117, 98,100,105,118,114, 0,115,117, 98,115,117,114,102,116,121,112,101, 0, 42,109,114, 0, 42,112,118, 0, 42,116,112, 97,103, -101, 0,117,118, 91, 52, 93, 91, 50, 93, 0, 99,111,108, 91, 52, 93, 0,116,114, 97,110,115,112, 0,116,105,108,101, 0,117,110, -119,114, 97,112, 0,118, 49, 0,118, 50, 0,118, 51, 0,118, 52, 0,101,100, 99,111,100,101, 0, 99,114,101, 97,115,101, 0, 98, -119,101,105,103,104,116, 0,100,101,102, 95,110,114, 0, 42,100,119, 0,116,111,116,119,101,105,103,104,116, 0, 99,111, 91, 51, - 93, 0,110,111, 91, 51, 93, 0,117,118, 91, 50, 93, 0, 99,111, 91, 50, 93, 0,105,110,100,101,120, 0,102, 0,105, 0,115, 91, - 50, 53, 54, 93, 0,116,111,116,100,105,115,112, 0, 40, 42,100,105,115,112,115, 41, 40, 41, 0,118, 91, 52, 93, 0,109,105,100, - 0,118, 91, 50, 93, 0, 42,102, 97, 99,101,115, 0, 42, 99,111,108,102, 97, 99,101,115, 0, 42,101,100,103,101,115, 0, 42,118, -101,114,116,115, 0,108,101,118,101,108,115, 0,108,101,118,101,108, 95, 99,111,117,110,116, 0, 99,117,114,114,101,110,116, 0, -110,101,119,108,118,108, 0,101,100,103,101,108,118,108, 0,112,105,110,108,118,108, 0,114,101,110,100,101,114,108,118,108, 0, -117,115,101, 95, 99,111,108, 0, 42,101,100,103,101, 95,102,108, 97,103,115, 0, 42,101,100,103,101, 95, 99,114,101, 97,115,101, -115, 0, 42,118,101,114,116, 95,109, 97,112, 0, 42,101,100,103,101, 95,109, 97,112, 0, 42,111,108,100, 95,102, 97, 99,101,115, - 0, 42,111,108,100, 95,101,100,103,101,115, 0, 42,101,114,114,111,114, 0,109,111,100,105,102,105,101,114, 0,115,117, 98,100, -105,118, 84,121,112,101, 0,114,101,110,100,101,114, 76,101,118,101,108,115, 0, 42,101,109, 67, 97, 99,104,101, 0, 42,109, 67, - 97, 99,104,101, 0,100,101,102, 97,120,105,115, 0,112, 97,100, 91, 54, 93, 0,108,101,110,103,116,104, 0,114, 97,110,100,111, -109,105,122,101, 0,115,101,101,100, 0, 42,111, 98, 95, 97,114,109, 0, 42,115,116, 97,114,116, 95, 99, 97,112, 0, 42,101,110, -100, 95, 99, 97,112, 0, 42, 99,117,114,118,101, 95,111, 98, 0, 42,111,102,102,115,101,116, 95,111, 98, 0,111,102,102,115,101, -116, 91, 51, 93, 0,115, 99, 97,108,101, 91, 51, 93, 0,109,101,114,103,101, 95,100,105,115,116, 0,102,105,116, 95,116,121,112, -101, 0,111,102,102,115,101,116, 95,116,121,112,101, 0, 99,111,117,110,116, 0, 97,120,105,115, 0,116,111,108,101,114, 97,110, - 99,101, 0, 42,109,105,114,114,111,114, 95,111, 98, 0,115,112,108,105,116, 95, 97,110,103,108,101, 0,118, 97,108,117,101, 0, -114,101,115, 0,118, 97,108, 95,102,108, 97,103,115, 0,108,105,109, 95,102,108, 97,103,115, 0,101, 95,102,108, 97,103,115, 0, - 98,101,118,101,108, 95, 97,110,103,108,101, 0,100,101,102,103,114,112, 95,110, 97,109,101, 91, 51, 50, 93, 0, 42,100,111,109, - 97,105,110, 0, 42,102,108,111,119, 0, 42, 99,111,108,108, 0,116,105,109,101, 0, 42,116,101,120,116,117,114,101, 0,115,116, -114,101,110,103,116,104, 0,100,105,114,101, 99,116,105,111,110, 0,109,105,100,108,101,118,101,108, 0,116,101,120,109, 97,112, -112,105,110,103, 0, 42,109, 97,112, 95,111, 98,106,101, 99,116, 0,117,118,108, 97,121,101,114, 95,110, 97,109,101, 91, 51, 50, - 93, 0,117,118,108, 97,121,101,114, 95,116,109,112, 0, 42,112,114,111,106,101, 99,116,111,114,115, 91, 49, 48, 93, 0, 42,105, -109, 97,103,101, 0,110,117,109, 95,112,114,111,106,101, 99,116,111,114,115, 0, 97,115,112,101, 99,116,120, 0, 97,115,112,101, - 99,116,121, 0,112,101,114, 99,101,110,116, 0,102, 97, 99,101, 67,111,117,110,116, 0,102, 97, 99, 0,114,101,112,101, 97,116, - 0, 42,111, 98,106,101, 99,116, 99,101,110,116,101,114, 0,115,116, 97,114,116,120, 0,115,116, 97,114,116,121, 0,104,101,105, -103,104,116, 0,110, 97,114,114,111,119, 0,115,112,101,101,100, 0,100, 97,109,112, 0,102, 97,108,108,111,102,102, 0,116,105, -109,101,111,102,102,115, 0,108,105,102,101,116,105,109,101, 0,100,101,102,111,114,109,102,108, 97,103, 0,109,117,108,116,105, - 0, 42,112,114,101,118, 67,111,115, 0,115,117, 98,116, 97,114,103,101,116, 91, 51, 50, 93, 0,112, 97,114,101,110,116,105,110, -118, 91, 52, 93, 91, 52, 93, 0, 99,101,110,116, 91, 51, 93, 0, 42,105,110,100,101,120, 97,114, 0,116,111,116,105,110,100,101, -120, 0,102,111,114, 99,101, 0, 42, 99,108,111,116,104, 79, 98,106,101, 99,116, 0, 42,115,105,109, 95,112, 97,114,109,115, 0, - 42, 99,111,108,108, 95,112, 97,114,109,115, 0, 42,112,111,105,110,116, 95, 99, 97, 99,104,101, 0,112,116, 99, 97, 99,104,101, -115, 0, 42,120, 0, 42,120,110,101,119, 0, 42,120,111,108,100, 0, 42, 99,117,114,114,101,110,116, 95,120,110,101,119, 0, 42, - 99,117,114,114,101,110,116, 95,120, 0, 42, 99,117,114,114,101,110,116, 95,118, 0, 42,109,102, 97, 99,101,115, 0,110,117,109, -118,101,114,116,115, 0,110,117,109,102, 97, 99,101,115, 0, 42, 98,118,104,116,114,101,101, 0, 42,118, 0, 42,100,109, 0, 99, -102,114, 97, 0,111,112,101,114, 97,116,105,111,110, 0,118,101,114,116,101,120, 0,116,111,116,105,110,102,108,117,101,110, 99, -101, 0,103,114,105,100,115,105,122,101, 0,110,101,101,100, 98,105,110,100, 0, 42, 98,105,110,100,119,101,105,103,104,116,115, - 0, 42, 98,105,110,100, 99,111,115, 0,116,111,116, 99, 97,103,101,118,101,114,116, 0, 42,100,121,110,103,114,105,100, 0, 42, -100,121,110,105,110,102,108,117,101,110, 99,101,115, 0, 42,100,121,110,118,101,114,116,115, 0, 42,112, 97,100, 50, 0,100,121, -110,103,114,105,100,115,105,122,101, 0,100,121,110, 99,101,108,108,109,105,110, 91, 51, 93, 0,100,121,110, 99,101,108,108,119, -105,100,116,104, 0, 98,105,110,100,109, 97,116, 91, 52, 93, 91, 52, 93, 0,116,111,116,100,109,118,101,114,116, 0,116,111,116, -100,109,101,100,103,101, 0,116,111,116,100,109,102, 97, 99,101, 0,112,115,121,115, 0,112,111,115,105,116,105,111,110, 0,114, - 97,110,100,111,109, 95,112,111,115,105,116,105,111,110, 0, 42,102, 97, 99,101,112, 97, 0,118,103,114,111,117,112, 0,112,114, -111,116,101, 99,116, 0, 42,117,110,100,111, 95,118,101,114,116,115, 0,117,110,100,111, 95,118,101,114,116,115, 95,116,111,116, - 0,117,110,100,111, 95,115,105,103,110, 97,108, 0,108,118,108, 0,116,111,116,108,118,108, 0,115,105,109,112,108,101, 0, 42, -102,115,115, 0, 42,116, 97,114,103,101,116, 0, 42, 97,117,120, 84, 97,114,103,101,116, 0,118,103,114,111,117,112, 95,110, 97, -109,101, 91, 51, 50, 93, 0,107,101,101,112, 68,105,115,116, 0,115,104,114,105,110,107, 84,121,112,101, 0,115,104,114,105,110, -107, 79,112,116,115, 0,112,114,111,106, 65,120,105,115, 0,115,117, 98,115,117,114,102, 76,101,118,101,108,115, 0, 42,111,114, -105,103,105,110, 0,102, 97, 99,116,111,114, 0,108,105,109,105,116, 91, 50, 93, 0,111,114,105,103,105,110, 79,112,116,115, 0, -112,110,116,115,119, 0,111,112,110,116,115,117, 0,111,112,110,116,115,118, 0,111,112,110,116,115,119, 0,116,121,112,101,117, - 0,116,121,112,101,118, 0,116,121,112,101,119, 0,102,117, 0,102,118, 0,102,119, 0,100,117, 0,100,118, 0,100,119, 0, 42, -100,101,102, 0, 42,108, 97,116,116,105, 99,101,100, 97,116, 97, 0,108, 97,116,109, 97,116, 91, 52, 93, 91, 52, 93, 0, 42,101, -100,105,116,108, 97,116,116, 0,118,101, 99, 91, 56, 93, 91, 51, 93, 0, 42,115, 99,117,108,112,116, 0,112, 97,114,116,121,112, -101, 0,112, 97,114, 49, 0,112, 97,114, 50, 0,112, 97,114, 51, 0,112, 97,114,115,117, 98,115,116,114, 91, 51, 50, 93, 0, 42, -116,114, 97, 99,107, 0, 42,112,114,111,120,121, 0, 42,112,114,111,120,121, 95,103,114,111,117,112, 0, 42,112,114,111,120,121, - 95,102,114,111,109, 0, 42, 97, 99,116,105,111,110, 0, 42,112,111,115,101,108,105, 98, 0, 42,112,111,115,101, 0, 42,103,112, -100, 0, 99,111,110,115,116,114, 97,105,110,116, 67,104, 97,110,110,101,108,115, 0,100,101,102, 98, 97,115,101, 0,109,111,100, -105,102,105,101,114,115, 0,114,101,115,116,111,114,101, 95,109,111,100,101, 0, 42,109, 97,116, 98,105,116,115, 0, 97, 99,116, - 99,111,108, 0,100,108,111, 99, 91, 51, 93, 0,111,114,105,103, 91, 51, 93, 0,100,115,105,122,101, 91, 51, 93, 0,100,114,111, -116, 91, 51, 93, 0,111, 98,109, 97,116, 91, 52, 93, 91, 52, 93, 0, 99,111,110,115,116,105,110,118, 91, 52, 93, 91, 52, 93, 0, -108, 97,121, 0, 99,111,108, 98,105,116,115, 0,116,114, 97,110,115,102,108, 97,103, 0,112,114,111,116,101, 99,116,102,108, 97, -103, 0,116,114, 97, 99,107,102,108, 97,103, 0,117,112,102,108, 97,103, 0,110,108, 97,102,108, 97,103, 0,105,112,111,102,108, - 97,103, 0,105,112,111,119,105,110, 0,115, 99, 97,102,108, 97,103, 0,115, 99, 97,118,105,115,102,108, 97,103, 0, 98,111,117, -110,100,116,121,112,101, 0,100,117,112,111,110, 0,100,117,112,111,102,102, 0,100,117,112,115,116, 97, 0,100,117,112,101,110, -100, 0,115,102, 0,109, 97,115,115, 0,100, 97,109,112,105,110,103, 0,105,110,101,114,116,105, 97, 0,102,111,114,109,102, 97, - 99,116,111,114, 0,114,100, 97,109,112,105,110,103, 0,115,105,122,101,102, 97, 99, 0,109, 97,114,103,105,110, 0,109, 97,120, - 95,118,101,108, 0,109,105,110, 95,118,101,108, 0,109, 95, 99,111,110,116, 97, 99,116, 80,114,111, 99,101,115,115,105,110,103, - 84,104,114,101,115,104,111,108,100, 0,100,116, 0,100,116,120, 0,101,109,112,116,121, 95,100,114, 97,119,116,121,112,101, 0, -112, 97,100, 49, 91, 53, 93, 0,101,109,112,116,121, 95,100,114, 97,119,115,105,122,101, 0,100,117,112,102, 97, 99,101,115, 99, - 97, 0,112,114,111,112, 0,115,101,110,115,111,114,115, 0, 99,111,110,116,114,111,108,108,101,114,115, 0, 97, 99,116,117, 97, -116,111,114,115, 0, 98, 98,115,105,122,101, 91, 51, 93, 0, 97, 99,116,100,101,102, 0,103, 97,109,101,102,108, 97,103, 0,103, - 97,109,101,102,108, 97,103, 50, 0, 42, 98,115,111,102,116, 0,115,111,102,116,102,108, 97,103, 0, 97,110,105,115,111,116,114, -111,112,105, 99, 70,114,105, 99,116,105,111,110, 91, 51, 93, 0, 99,111,110,115,116,114, 97,105,110,116,115, 0,110,108, 97,115, -116,114,105,112,115, 0,104,111,111,107,115, 0,112, 97,114,116,105, 99,108,101,115,121,115,116,101,109, 0, 42,115,111,102,116, - 0, 42,100,117,112, 95,103,114,111,117,112, 0,102,108,117,105,100,115,105,109, 70,108, 97,103, 0,114,101,115,116,114,105, 99, -116,102,108, 97,103, 0,115,104, 97,112,101,110,114, 0,115,104, 97,112,101,102,108, 97,103, 0,114,101, 99, 97,108, 99,111, 0, - 98,111,100,121, 95,116,121,112,101, 0, 42,102,108,117,105,100,115,105,109, 83,101,116,116,105,110,103,115, 0, 42,100,101,114, -105,118,101,100, 68,101,102,111,114,109, 0, 42,100,101,114,105,118,101,100, 70,105,110, 97,108, 0,108, 97,115,116, 68, 97,116, - 97, 77, 97,115,107, 0,115,116, 97,116,101, 0,105,110,105,116, 95,115,116, 97,116,101, 0,103,112,117,108, 97,109,112, 0,112, - 99, 95,105,100,115, 0, 99,117,114,105,110,100,101,120, 0, 97, 99,116,105,118,101, 0,100,101,102,108,101, 99,116, 0,102,111, -114, 99,101,102,105,101,108,100, 0,112,100,101,102, 95,100, 97,109,112, 0,112,100,101,102, 95,114,100, 97,109,112, 0,112,100, -101,102, 95,112,101,114,109, 0,112,100,101,102, 95,102,114,105, 99,116, 0,112,100,101,102, 95,114,102,114,105, 99,116, 0,102, - 95,115,116,114,101,110,103,116,104, 0,102, 95,112,111,119,101,114, 0,102, 95,100,105,115,116, 0,102, 95,100, 97,109,112, 0, -109, 97,120,100,105,115,116, 0,109,105,110,100,105,115,116, 0,109, 97,120,114, 97,100, 0,109,105,110,114, 97,100, 0,102, 95, -112,111,119,101,114, 95,114, 0,112,100,101,102, 95,115, 98,100, 97,109,112, 0,112,100,101,102, 95,115, 98,105,102,116, 0,112, -100,101,102, 95,115, 98,111,102,116, 0, 99,108,117,109,112, 95,102, 97, 99, 0, 99,108,117,109,112, 95,112,111,119, 0,107,105, -110,107, 95,102,114,101,113, 0,107,105,110,107, 95,115,104, 97,112,101, 0,107,105,110,107, 95, 97,109,112, 0,102,114,101,101, - 95,101,110,100, 0,116,101,120, 95,110, 97, 98,108, 97, 0,116,101,120, 95,109,111,100,101, 0,107,105,110,107, 0,107,105,110, -107, 95, 97,120,105,115, 0,114,116, 50, 0, 42,114,110,103, 0,102, 95,110,111,105,115,101, 0,102,114, 97,109,101, 0,116,111, -116,112,111,105,110,116, 0,100, 97,116, 97, 95,116,121,112,101,115, 0, 42,105,110,100,101,120, 95, 97,114,114, 97,121, 0, 42, -100, 97,116, 97, 91, 56, 93, 0, 42, 99,117,114, 91, 56, 93, 0,115,116,101,112, 0,115,105,109,102,114, 97,109,101, 0,115,116, - 97,114,116,102,114, 97,109,101, 0,101,110,100,102,114, 97,109,101, 0,101,100,105,116,102,114, 97,109,101, 0,108, 97,115,116, - 95,101,120, 97, 99,116, 0,110, 97,109,101, 91, 54, 52, 93, 0,112,114,101,118, 95,110, 97,109,101, 91, 54, 52, 93, 0,105,110, -102,111, 91, 54, 52, 93, 0,112, 97,116,104, 91, 50, 52, 48, 93, 0,109,101,109, 95, 99, 97, 99,104,101, 0, 42,101,100,105,116, - 0, 40, 42,102,114,101,101, 95,101,100,105,116, 41, 40, 41, 0,108,105,110, 83,116,105,102,102, 0, 97,110,103, 83,116,105,102, -102, 0,118,111,108,117,109,101, 0,118,105,116,101,114, 97,116,105,111,110,115, 0,112,105,116,101,114, 97,116,105,111,110,115, - 0,100,105,116,101,114, 97,116,105,111,110,115, 0, 99,105,116,101,114, 97,116,105,111,110,115, 0,107, 83, 82, 72, 82, 95, 67, - 76, 0,107, 83, 75, 72, 82, 95, 67, 76, 0,107, 83, 83, 72, 82, 95, 67, 76, 0,107, 83, 82, 95, 83, 80, 76, 84, 95, 67, 76, 0, -107, 83, 75, 95, 83, 80, 76, 84, 95, 67, 76, 0,107, 83, 83, 95, 83, 80, 76, 84, 95, 67, 76, 0,107, 86, 67, 70, 0,107, 68, 80, - 0,107, 68, 71, 0,107, 76, 70, 0,107, 80, 82, 0,107, 86, 67, 0,107, 68, 70, 0,107, 77, 84, 0,107, 67, 72, 82, 0,107, 75, - 72, 82, 0,107, 83, 72, 82, 0,107, 65, 72, 82, 0, 99,111,108,108,105,115,105,111,110,102,108, 97,103,115, 0,110,117,109, 99, -108,117,115,116,101,114,105,116,101,114, 97,116,105,111,110,115, 0,119,101,108,100,105,110,103, 0,116,111,116,115,112,114,105, -110,103, 0, 42, 98,112,111,105,110,116, 0, 42, 98,115,112,114,105,110,103, 0,109,115,103, 95,108,111, 99,107, 0,109,115,103, - 95,118, 97,108,117,101, 0,110,111,100,101,109, 97,115,115, 0,110, 97,109,101,100, 86, 71, 95, 77, 97,115,115, 91, 51, 50, 93, - 0,103,114, 97,118, 0,109,101,100,105, 97,102,114,105, 99,116, 0,114,107,108,105,109,105,116, 0,112,104,121,115,105, 99,115, - 95,115,112,101,101,100, 0,103,111, 97,108,115,112,114,105,110,103, 0,103,111, 97,108,102,114,105, 99,116, 0,109,105,110,103, -111, 97,108, 0,109, 97,120,103,111, 97,108, 0,100,101,102,103,111, 97,108, 0,118,101,114,116,103,114,111,117,112, 0,110, 97, -109,101,100, 86, 71, 95, 83,111,102,116,103,111, 97,108, 91, 51, 50, 93, 0,102,117,122,122,121,110,101,115,115, 0,105,110,115, -112,114,105,110,103, 0,105,110,102,114,105, 99,116, 0,110, 97,109,101,100, 86, 71, 95, 83,112,114,105,110,103, 95, 75, 91, 51, - 50, 93, 0,101,102,114, 97, 0,105,110,116,101,114,118, 97,108, 0,108,111, 99, 97,108, 0,115,111,108,118,101,114,102,108, 97, -103,115, 0, 42, 42,107,101,121,115, 0,116,111,116,112,111,105,110,116,107,101,121, 0,115,101, 99,111,110,100,115,112,114,105, -110,103, 0, 99,111,108, 98, 97,108,108, 0, 98, 97,108,108,100, 97,109,112, 0, 98, 97,108,108,115,116,105,102,102, 0,115, 98, - 99, 95,109,111,100,101, 0, 97,101,114,111,101,100,103,101, 0,109,105,110,108,111,111,112,115, 0,109, 97,120,108,111,111,112, -115, 0, 99,104,111,107,101, 0,115,111,108,118,101,114, 95, 73, 68, 0,112,108, 97,115,116,105, 99, 0,115,112,114,105,110,103, -112,114,101,108,111, 97,100, 0, 42,115, 99,114, 97,116, 99,104, 0,115,104,101, 97,114,115,116,105,102,102, 0,105,110,112,117, -115,104, 0, 42,112,111,105,110,116, 99, 97, 99,104,101, 0,115,104,111,119, 95, 97,100,118, 97,110, 99,101,100,111,112,116,105, -111,110,115, 0,114,101,115,111,108,117,116,105,111,110,120,121,122, 0,112,114,101,118,105,101,119,114,101,115,120,121,122, 0, -114,101, 97,108,115,105,122,101, 0,103,117,105, 68,105,115,112,108, 97,121, 77,111,100,101, 0,114,101,110,100,101,114, 68,105, -115,112,108, 97,121, 77,111,100,101, 0,118,105,115, 99,111,115,105,116,121, 86, 97,108,117,101, 0,118,105,115, 99,111,115,105, -116,121, 77,111,100,101, 0,118,105,115, 99,111,115,105,116,121, 69,120,112,111,110,101,110,116, 0,103,114, 97,118,120, 0,103, -114, 97,118,121, 0,103,114, 97,118,122, 0, 97,110,105,109, 83,116, 97,114,116, 0, 97,110,105,109, 69,110,100, 0,103,115,116, - 97,114, 0,109, 97,120, 82,101,102,105,110,101, 0,105,110,105, 86,101,108,120, 0,105,110,105, 86,101,108,121, 0,105,110,105, - 86,101,108,122, 0, 42,111,114,103, 77,101,115,104, 0, 42,109,101,115,104, 83,117,114,102, 97, 99,101, 0, 42,109,101,115,104, - 66, 66, 0,115,117,114,102,100, 97,116, 97, 80, 97,116,104, 91, 50, 52, 48, 93, 0, 98, 98, 83,116, 97,114,116, 91, 51, 93, 0, - 98, 98, 83,105,122,101, 91, 51, 93, 0,116,121,112,101, 70,108, 97,103,115, 0,100,111,109, 97,105,110, 78,111,118,101, 99,103, -101,110, 0,118,111,108,117,109,101, 73,110,105,116, 84,121,112,101, 0,112, 97,114,116, 83,108,105,112, 86, 97,108,117,101, 0, -103,101,110,101,114, 97,116,101, 84,114, 97, 99,101,114,115, 0,103,101,110,101,114, 97,116,101, 80, 97,114,116,105, 99,108,101, -115, 0,115,117,114,102, 97, 99,101, 83,109,111,111,116,104,105,110,103, 0,115,117,114,102, 97, 99,101, 83,117, 98,100,105,118, -115, 0,112, 97,114,116,105, 99,108,101, 73,110,102, 83,105,122,101, 0,112, 97,114,116,105, 99,108,101, 73,110,102, 65,108,112, -104, 97, 0,102, 97,114, 70,105,101,108,100, 83,105,122,101, 0, 42,109,101,115,104, 83,117,114,102, 78,111,114,109, 97,108,115, - 0, 99,112,115, 84,105,109,101, 83,116, 97,114,116, 0, 99,112,115, 84,105,109,101, 69,110,100, 0, 99,112,115, 81,117, 97,108, -105,116,121, 0, 97,116,116,114, 97, 99,116,102,111,114, 99,101, 83,116,114,101,110,103,116,104, 0, 97,116,116,114, 97, 99,116, -102,111,114, 99,101, 82, 97,100,105,117,115, 0,118,101,108,111, 99,105,116,121,102,111,114, 99,101, 83,116,114,101,110,103,116, -104, 0,118,101,108,111, 99,105,116,121,102,111,114, 99,101, 82, 97,100,105,117,115, 0,108, 97,115,116,103,111,111,100,102,114, - 97,109,101, 0,109,105,115,116,121,112,101, 0,104,111,114,114, 0,104,111,114,103, 0,104,111,114, 98, 0,104,111,114,107, 0, -122,101,110,114, 0,122,101,110,103, 0,122,101,110, 98, 0,122,101,110,107, 0, 97,109, 98,107, 0,102, 97,115,116, 99,111,108, - 0,101,120,112,111,115,117,114,101, 0,101,120,112, 0,114, 97,110,103,101, 0,108,105,110,102, 97, 99, 0,108,111,103,102, 97, - 99, 0,103,114, 97,118,105,116,121, 0, 97, 99,116,105,118,105,116,121, 66,111,120, 82, 97,100,105,117,115, 0,115,107,121,116, -121,112,101, 0,111, 99, 99,108,117,115,105,111,110, 82,101,115, 0,112,104,121,115,105, 99,115, 69,110,103,105,110,101, 0,116, -105, 99,114, 97,116,101, 0,109, 97,120,108,111,103,105, 99,115,116,101,112, 0,112,104,121,115,117, 98,115,116,101,112, 0,109, - 97,120,112,104,121,115,116,101,112, 0,109,105,115,105, 0,109,105,115,116,115,116, 97, 0,109,105,115,116,100,105,115,116, 0, -109,105,115,116,104,105, 0,115,116, 97,114,114, 0,115,116, 97,114,103, 0,115,116, 97,114, 98, 0,115,116, 97,114,107, 0,115, -116, 97,114,115,105,122,101, 0,115,116, 97,114,109,105,110,100,105,115,116, 0,115,116, 97,114,100,105,115,116, 0,115,116, 97, -114, 99,111,108,110,111,105,115,101, 0,100,111,102,115,116, 97, 0,100,111,102,101,110,100, 0,100,111,102,109,105,110, 0,100, -111,102,109, 97,120, 0, 97,111,100,105,115,116, 0, 97,111,100,105,115,116,102, 97, 99, 0, 97,111,101,110,101,114,103,121, 0, - 97,111, 98,105, 97,115, 0, 97,111,109,111,100,101, 0, 97,111,115, 97,109,112, 0, 97,111,109,105,120, 0, 97,111, 99,111,108, -111,114, 0, 97,111, 95, 97,100, 97,112,116, 95,116,104,114,101,115,104, 0, 97,111, 95, 97,100, 97,112,116, 95,115,112,101,101, -100, 95,102, 97, 99, 0, 97,111, 95, 97,112,112,114,111,120, 95,101,114,114,111,114, 0, 97,111, 95, 97,112,112,114,111,120, 95, - 99,111,114,114,101, 99,116,105,111,110, 0, 97,111, 95,115, 97,109,112, 95,109,101,116,104,111,100, 0, 97,111, 95,103, 97,116, -104,101,114, 95,109,101,116,104,111,100, 0, 97,111, 95, 97,112,112,114,111,120, 95,112, 97,115,115,101,115, 0, 42, 97,111,115, -112,104,101,114,101, 0, 42, 97,111,116, 97, 98,108,101,115, 0,115,101,108, 99,111,108, 0,115,120, 0,115,121, 0, 42,108,112, - 70,111,114,109, 97,116, 0, 42,108,112, 80, 97,114,109,115, 0, 99, 98, 70,111,114,109, 97,116, 0, 99, 98, 80, 97,114,109,115, - 0,102, 99, 99, 84,121,112,101, 0,102, 99, 99, 72, 97,110,100,108,101,114, 0,100,119, 75,101,121, 70,114, 97,109,101, 69,118, -101,114,121, 0,100,119, 81,117, 97,108,105,116,121, 0,100,119, 66,121,116,101,115, 80,101,114, 83,101, 99,111,110,100, 0,100, -119, 70,108, 97,103,115, 0,100,119, 73,110,116,101,114,108,101, 97,118,101, 69,118,101,114,121, 0, 97,118,105, 99,111,100,101, - 99,110, 97,109,101, 91, 49, 50, 56, 93, 0, 42, 99,100, 80, 97,114,109,115, 0, 42,112, 97,100, 0, 99,100, 83,105,122,101, 0, -113,116, 99,111,100,101, 99,110, 97,109,101, 91, 49, 50, 56, 93, 0, 99,111,100,101, 99, 0, 97,117,100,105,111, 95, 99,111,100, -101, 99, 0,118,105,100,101,111, 95, 98,105,116,114, 97,116,101, 0, 97,117,100,105,111, 95, 98,105,116,114, 97,116,101, 0,103, -111,112, 95,115,105,122,101, 0,114, 99, 95,109,105,110, 95,114, 97,116,101, 0,114, 99, 95,109, 97,120, 95,114, 97,116,101, 0, -114, 99, 95, 98,117,102,102,101,114, 95,115,105,122,101, 0,109,117,120, 95,112, 97, 99,107,101,116, 95,115,105,122,101, 0,109, -117,120, 95,114, 97,116,101, 0,109,105,120,114, 97,116,101, 0,109, 97,105,110, 0, 42,109, 97,116, 95,111,118,101,114,114,105, -100,101, 0, 42,108,105,103,104,116, 95,111,118,101,114,114,105,100,101, 0,108, 97,121, 95,122,109, 97,115,107, 0,108, 97,121, -102,108, 97,103, 0,112, 97,115,115,102,108, 97,103, 0,112, 97,115,115, 95,120,111,114, 0, 42, 97,118,105, 99,111,100,101, 99, -100, 97,116, 97, 0, 42,113,116, 99,111,100,101, 99,100, 97,116, 97, 0,102,102, 99,111,100,101, 99,100, 97,116, 97, 0, 97,117, -100,105,111, 0,112,115,102,114, 97, 0,112,101,102,114, 97, 0,105,109, 97,103,101,115, 0,102,114, 97,109, 97,112,116,111, 0, -116,104,114,101, 97,100,115, 0,102,114, 97,109,101,108,101,110, 0, 98,108,117,114,102, 97, 99, 0,101,100,103,101, 82, 0,101, -100,103,101, 71, 0,101,100,103,101, 66, 0,102,117,108,108,115, 99,114,101,101,110, 0,120,112,108, 97,121, 0,121,112,108, 97, -121, 0,102,114,101,113,112,108, 97,121, 0, 97,116,116,114,105, 98, 0,114,116, 49, 0,115,116,101,114,101,111,109,111,100,101, - 0,100,105,109,101,110,115,105,111,110,115,112,114,101,115,101,116, 0,109, 97,120,105,109,115,105,122,101, 0,120,115, 99,104, - 0,121,115, 99,104, 0,120,112, 97,114,116,115, 0,121,112, 97,114,116,115, 0,119,105,110,112,111,115, 0,112,108, 97,110,101, -115, 0,105,109,116,121,112,101, 0,115,117, 98,105,109,116,121,112,101, 0,113,117, 97,108,105,116,121, 0,100,105,115,112,108, - 97,121,109,111,100,101, 0,114,112, 97,100, 49, 0,114,112, 97,100, 50, 0,115, 99,101,109,111,100,101, 0,114,101,110,100,101, -114,101,114, 0,111, 99,114,101,115, 0, 97,108,112,104, 97,109,111,100,101, 0,111,115, 97, 0,102,114,115, 95,115,101, 99, 0, -101,100,103,101,105,110,116, 0,115, 97,102,101,116,121, 0, 98,111,114,100,101,114, 0,100,105,115,112,114,101, 99,116, 0,108, - 97,121,101,114,115, 0, 97, 99,116,108, 97,121, 0,120, 97,115,112, 0,121, 97,115,112, 0,102,114,115, 95,115,101, 99, 95, 98, - 97,115,101, 0,103, 97,117,115,115, 0, 99,111,108,111,114, 95,109,103,116, 95,102,108, 97,103, 0,112,111,115,116,103, 97,109, -109, 97, 0,112,111,115,116,104,117,101, 0,112,111,115,116,115, 97,116, 0,100,105,116,104,101,114, 95,105,110,116,101,110,115, -105,116,121, 0, 98, 97,107,101, 95,111,115, 97, 0, 98, 97,107,101, 95,102,105,108,116,101,114, 0, 98, 97,107,101, 95,109,111, -100,101, 0, 98, 97,107,101, 95,102,108, 97,103, 0, 98, 97,107,101, 95,110,111,114,109, 97,108, 95,115,112, 97, 99,101, 0, 98, - 97,107,101, 95,113,117, 97,100, 95,115,112,108,105,116, 0, 98, 97,107,101, 95,109, 97,120,100,105,115,116, 0, 98, 97,107,101, - 95, 98,105, 97,115,100,105,115,116, 0, 98, 97,107,101, 95,112, 97,100, 0, 71, 73,113,117, 97,108,105,116,121, 0, 71, 73, 99, - 97, 99,104,101, 0, 71, 73,109,101,116,104,111,100, 0, 71, 73,112,104,111,116,111,110,115, 0, 71, 73,100,105,114,101, 99,116, - 0, 89, 70, 95, 65, 65, 0, 89, 70,101,120,112,111,114,116,120,109,108, 0, 89, 70, 95,110,111, 98,117,109,112, 0, 89, 70, 95, - 99,108, 97,109,112,114,103, 98, 0,121,102,112, 97,100, 49, 0, 71, 73,100,101,112,116,104, 0, 71, 73, 99, 97,117,115,100,101, -112,116,104, 0, 71, 73,112,105,120,101,108,115,112,101,114,115, 97,109,112,108,101, 0, 71, 73,112,104,111,116,111,110, 99,111, -117,110,116, 0, 71, 73,109,105,120,112,104,111,116,111,110,115, 0, 71, 73,112,104,111,116,111,110,114, 97,100,105,117,115, 0, - 89, 70, 95,114, 97,121,100,101,112,116,104, 0, 89, 70, 95, 65, 65,112, 97,115,115,101,115, 0, 89, 70, 95, 65, 65,115, 97,109, -112,108,101,115, 0,121,102,112, 97,100, 50, 0, 71, 73,115,104, 97,100,111,119,113,117, 97,108,105,116,121, 0, 71, 73,114,101, -102,105,110,101,109,101,110,116, 0, 71, 73,112,111,119,101,114, 0, 71, 73,105,110,100,105,114,112,111,119,101,114, 0, 89, 70, - 95,103, 97,109,109, 97, 0, 89, 70, 95,101,120,112,111,115,117,114,101, 0, 89, 70, 95,114, 97,121, 98,105, 97,115, 0, 89, 70, - 95, 65, 65,112,105,120,101,108,115,105,122,101, 0, 89, 70, 95, 65, 65,116,104,114,101,115,104,111,108,100, 0, 98, 97, 99,107, - 98,117,102, 91, 49, 54, 48, 93, 0,112,105, 99, 91, 49, 54, 48, 93, 0,115,116, 97,109,112, 0,115,116, 97,109,112, 95,102,111, -110,116, 95,105,100, 0,115,116, 97,109,112, 95,117,100, 97,116, 97, 91, 49, 54, 48, 93, 0,102,103, 95,115,116, 97,109,112, 91, - 52, 93, 0, 98,103, 95,115,116, 97,109,112, 91, 52, 93, 0,115,105,109,112,108,105,102,121, 95,115,117, 98,115,117,114,102, 0, -115,105,109,112,108,105,102,121, 95,115,104, 97,100,111,119,115, 97,109,112,108,101,115, 0,115,105,109,112,108,105,102,121, 95, -112, 97,114,116,105, 99,108,101,115, 0,115,105,109,112,108,105,102,121, 95, 97,111,115,115,115, 0, 99,105,110,101,111,110,119, -104,105,116,101, 0, 99,105,110,101,111,110, 98,108, 97, 99,107, 0, 99,105,110,101,111,110,103, 97,109,109, 97, 0,106,112, 50, - 95,112,114,101,115,101,116, 0,106,112, 50, 95,100,101,112,116,104, 0,114,112, 97,100, 51, 0,100,111,109,101,114,101,115, 0, -100,111,109,101,109,111,100,101, 0,100,111,109,101, 97,110,103,108,101, 0,100,111,109,101,116,105,108,116, 0,100,111,109,101, -114,101,115, 98,117,102, 0, 42,100,111,109,101,116,101,120,116, 0,101,110,103,105,110,101, 91, 51, 50, 93, 0,112, 97,114,116, -105, 99,108,101, 95,112,101,114, 99, 0,115,117, 98,115,117,114,102, 95,109, 97,120, 0,115,104, 97,100, 98,117,102,115, 97,109, -112,108,101, 95,109, 97,120, 0, 97,111, 95,101,114,114,111,114, 0,116,105,108,116, 0,114,101,115, 98,117,102, 0, 42,119, 97, -114,112,116,101,120,116, 0, 99,111,108, 91, 51, 93, 0,109, 97,116,109,111,100,101, 0,102,114, 97,109,105,110,103, 0,100,111, -109,101, 0,115,116,101,114,101,111,102,108, 97,103, 0, 42, 42, 98,114,117,115,104,101,115, 0, 97, 99,116,105,118,101, 95, 98, -114,117,115,104, 95,105,110,100,101,120, 0, 98,114,117,115,104, 95, 99,111,117,110,116, 0, 42,112, 97,105,110,116, 95, 99,117, -114,115,111,114, 0,112, 97,105,110,116, 95, 99,117,114,115,111,114, 95, 99,111,108, 91, 52, 93, 0,112, 97,105,110,116, 0,116, -111,111,108, 0,115,101, 97,109, 95, 98,108,101,101,100, 0,110,111,114,109, 97,108, 95, 97,110,103,108,101, 0, 42,112, 97,105, -110,116, 99,117,114,115,111,114, 0,105,110,118,101,114,116, 0,116,111,116,114,101,107,101,121, 0,116,111,116, 97,100,100,107, -101,121, 0, 98,114,117,115,104,116,121,112,101, 0, 98,114,117,115,104, 91, 55, 93, 0,101,109,105,116,116,101,114,100,105,115, -116, 0,115,101,108,101, 99,116,109,111,100,101, 0,101,100,105,116,116,121,112,101, 0,100,114, 97,119, 95,115,116,101,112, 0, -102, 97,100,101, 95,102,114, 97,109,101,115, 0,110, 97,109,101, 91, 51, 54, 93, 0,109, 97,116, 91, 51, 93, 91, 51, 93, 0,112, -105,118,111,116, 91, 51, 93, 0,116, 97, 98,108,101,116, 95,115,105,122,101, 0,116, 97, 98,108,101,116, 95,115,116,114,101,110, -103,116,104, 0,103, 97,109,109, 97, 0,109,117,108, 0, 42,118,112, 97,105,110,116, 95,112,114,101,118, 0, 42,119,112, 97,105, -110,116, 95,112,114,101,118, 0, 42,118,112, 97,105,110,116, 0, 42,119,112, 97,105,110,116, 0,118,103,114,111,117,112, 95,119, -101,105,103,104,116, 0, 99,111,114,110,101,114,116,121,112,101, 0,101,100,105,116, 98,117,116,102,108, 97,103, 0,106,111,105, -110,116,114,105,108,105,109,105,116, 0,100,101,103,114, 0,116,117,114,110, 0,101,120,116,114, 95,111,102,102,115, 0,100,111, -117, 98,108,105,109,105,116, 0,110,111,114,109, 97,108,115,105,122,101, 0, 97,117,116,111,109,101,114,103,101, 0,115,101,103, -109,101,110,116,115, 0,114,105,110,103,115, 0,118,101,114,116,105, 99,101,115, 0,117,110,119,114, 97,112,112,101,114, 0,117, -118, 99, 97,108, 99, 95,114, 97,100,105,117,115, 0,117,118, 99, 97,108, 99, 95, 99,117, 98,101,115,105,122,101, 0,117,118, 99, - 97,108, 99, 95,109, 97,114,103,105,110, 0,117,118, 99, 97,108, 99, 95,109, 97,112,100,105,114, 0,117,118, 99, 97,108, 99, 95, -109, 97,112, 97,108,105,103,110, 0,117,118, 99, 97,108, 99, 95,102,108, 97,103, 0,117,118, 95,102,108, 97,103, 0,117,118, 95, -115,101,108,101, 99,116,109,111,100,101, 0,117,118, 95,112, 97,100, 91, 50, 93, 0, 97,117,116,111,105,107, 95, 99,104, 97,105, -110,108,101,110, 0,105,109, 97,112, 97,105,110,116, 0,112, 97,114,116,105, 99,108,101, 0,112,114,111,112,111,114,116,105,111, -110, 97,108, 95,115,105,122,101, 0,115,101,108,101, 99,116, 95,116,104,114,101,115,104, 0, 99,108,101, 97,110, 95,116,104,114, -101,115,104, 0, 97,117,116,111,107,101,121, 95,109,111,100,101, 0, 97,117,116,111,107,101,121, 95,102,108, 97,103, 0,114,101, -116,111,112,111, 95,109,111,100,101, 0,114,101,116,111,112,111, 95,112, 97,105,110,116, 95,116,111,111,108, 0,108,105,110,101, - 95,100,105,118, 0,101,108,108,105,112,115,101, 95,100,105,118, 0,114,101,116,111,112,111, 95,104,111,116,115,112,111,116, 0, -109,117,108,116,105,114,101,115, 95,115,117, 98,100,105,118, 95,116,121,112,101, 0,115,107,103,101,110, 95,114,101,115,111,108, -117,116,105,111,110, 0,115,107,103,101,110, 95,116,104,114,101,115,104,111,108,100, 95,105,110,116,101,114,110, 97,108, 0,115, -107,103,101,110, 95,116,104,114,101,115,104,111,108,100, 95,101,120,116,101,114,110, 97,108, 0,115,107,103,101,110, 95,108,101, -110,103,116,104, 95,114, 97,116,105,111, 0,115,107,103,101,110, 95,108,101,110,103,116,104, 95,108,105,109,105,116, 0,115,107, -103,101,110, 95, 97,110,103,108,101, 95,108,105,109,105,116, 0,115,107,103,101,110, 95, 99,111,114,114,101,108, 97,116,105,111, -110, 95,108,105,109,105,116, 0,115,107,103,101,110, 95,115,121,109,109,101,116,114,121, 95,108,105,109,105,116, 0,115,107,103, -101,110, 95,114,101,116, 97,114,103,101,116, 95, 97,110,103,108,101, 95,119,101,105,103,104,116, 0,115,107,103,101,110, 95,114, -101,116, 97,114,103,101,116, 95,108,101,110,103,116,104, 95,119,101,105,103,104,116, 0,115,107,103,101,110, 95,114,101,116, 97, -114,103,101,116, 95,100,105,115,116, 97,110, 99,101, 95,119,101,105,103,104,116, 0,115,107,103,101,110, 95,111,112,116,105,111, -110,115, 0,115,107,103,101,110, 95,112,111,115,116,112,114,111, 0,115,107,103,101,110, 95,112,111,115,116,112,114,111, 95,112, - 97,115,115,101,115, 0,115,107,103,101,110, 95,115,117, 98,100,105,118,105,115,105,111,110,115, 91, 51, 93, 0,115,107,103,101, -110, 95,109,117,108,116,105, 95,108,101,118,101,108, 0, 42,115,107,103,101,110, 95,116,101,109,112,108, 97,116,101, 0, 98,111, -110,101, 95,115,107,101,116, 99,104,105,110,103, 0, 98,111,110,101, 95,115,107,101,116, 99,104,105,110,103, 95, 99,111,110,118, -101,114,116, 0,115,107,103,101,110, 95,115,117, 98,100,105,118,105,115,105,111,110, 95,110,117,109, 98,101,114, 0,115,107,103, -101,110, 95,114,101,116, 97,114,103,101,116, 95,111,112,116,105,111,110,115, 0,115,107,103,101,110, 95,114,101,116, 97,114,103, -101,116, 95,114,111,108,108, 0,115,107,103,101,110, 95,115,105,100,101, 95,115,116,114,105,110,103, 91, 56, 93, 0,115,107,103, -101,110, 95,110,117,109, 95,115,116,114,105,110,103, 91, 56, 93, 0,101,100,103,101, 95,109,111,100,101, 0,115,110, 97,112, 95, -109,111,100,101, 0,115,110, 97,112, 95,102,108, 97,103, 0,115,110, 97,112, 95,116, 97,114,103,101,116, 0,112,114,111,112,111, -114,116,105,111,110, 97,108, 0,112,114,111,112, 95,109,111,100,101, 0,116,111,116,111, 98,106, 0,116,111,116,108, 97,109,112, - 0,116,111,116,111, 98,106,115,101,108, 0,116,111,116, 99,117,114,118,101, 0,116,111,116,109,101,115,104, 0,116,111,116, 97, -114,109, 97,116,117,114,101, 0,115, 99, 97,108,101, 95,108,101,110,103,116,104, 0,115,121,115,116,101,109, 0, 42, 99, 97,109, -101,114, 97, 0, 42,119,111,114,108,100, 0, 42,115,101,116, 0, 98, 97,115,101, 0, 42, 98, 97,115, 97, 99,116, 0, 42,111, 98, -101,100,105,116, 0, 99,117,114,115,111,114, 91, 51, 93, 0,116,119, 99,101,110,116, 91, 51, 93, 0,116,119,109,105,110, 91, 51, - 93, 0,116,119,109, 97,120, 91, 51, 93, 0, 42,101,100, 0, 42,116,111,111,108,115,101,116,116,105,110,103,115, 0, 42,115,116, - 97,116,115, 0,116,114, 97,110,115,102,111,114,109, 95,115,112, 97, 99,101,115, 0,115,111,117,110,100, 95,104, 97,110,100,108, -101,115, 0, 42,116,104,101, 68, 97,103, 0,100, 97,103,105,115,118, 97,108,105,100, 0,100, 97,103,102,108, 97,103,115, 0,106, -117,109,112,102,114, 97,109,101, 0,102,114, 97,109,101, 95,115,116,101,112, 0, 97, 99,116,105,118,101, 95,107,101,121,105,110, -103,115,101,116, 0,107,101,121,105,110,103,115,101,116,115, 0,103,109, 0,117,110,105,116, 0, 98,108,101,110,100, 0,119,105, -110,109, 97,116, 91, 52, 93, 91, 52, 93, 0,118,105,101,119,109, 97,116, 91, 52, 93, 91, 52, 93, 0,118,105,101,119,105,110,118, - 91, 52, 93, 91, 52, 93, 0,112,101,114,115,109, 97,116, 91, 52, 93, 91, 52, 93, 0,112,101,114,115,105,110,118, 91, 52, 93, 91, - 52, 93, 0,118,105,101,119,109, 97,116,111, 98, 91, 52, 93, 91, 52, 93, 0,112,101,114,115,109, 97,116,111, 98, 91, 52, 93, 91, - 52, 93, 0,116,119,109, 97,116, 91, 52, 93, 91, 52, 93, 0,118,105,101,119,113,117, 97,116, 91, 52, 93, 0,122,102, 97, 99, 0, - 99, 97,109,100,120, 0, 99, 97,109,100,121, 0,112,105,120,115,105,122,101, 0, 99, 97,109,122,111,111,109, 0,118,105,101,119, - 98,117,116, 0,108, 97,115,116,109,111,100,101, 0,114,102,108, 97,103, 0,118,105,101,119,108,111, 99,107, 0,112,101,114,115, -112, 0,118,105,101,119, 0, 99,108,105,112, 91, 54, 93, 91, 52, 93, 0, 42, 99,108,105,112, 98, 98, 0, 42,108,111, 99, 97,108, -118,100, 0, 42,114,105, 0, 42,114,101,116,111,112,111, 95,118,105,101,119, 95,100, 97,116, 97, 0, 42,100,101,112,116,104,115, - 0, 42,115,109,115, 0, 42,115,109,111,111,116,104, 95,116,105,109,101,114, 0,108,118,105,101,119,113,117, 97,116, 91, 52, 93, - 0,108,112,101,114,115,112, 0,108,118,105,101,119, 0,114,101,103,105,111,110, 98, 97,115,101, 0,115,112, 97, 99,101,116,121, -112,101, 0, 98,108,111, 99,107,115, 99, 97,108,101, 0, 98,108,111, 99,107,104, 97,110,100,108,101,114, 91, 56, 93, 0,108, 97, -121, 95,117,115,101,100, 0, 42,111, 98, 95, 99,101,110,116,114,101, 0, 42, 98,103,112,105, 99, 0,111, 98, 95, 99,101,110,116, -114,101, 95, 98,111,110,101, 91, 51, 50, 93, 0,108, 97,121, 97, 99,116, 0,100,114, 97,119,116,121,112,101, 0,108,111, 99, 97, -108,118,105,101,119, 0,115, 99,101,110,101,108,111, 99,107, 0, 97,114,111,117,110,100, 0,112,105,118,111,116, 95,108, 97,115, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,107,107,107,255, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255, 0, 0, 0, 51, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, + 0, 0, 0, 0,143,143,143,255, 0, 0, 0,255,217,217,217,255, 0, 0, 0, 40,255,255,255,255, 16, 64, 16,255,102,255,102,255, +255,130, 0,255, 0, 0, 0,255,255,130, 0,255, 0, 0, 0,255,255,255,255,255,230,150, 50,255,255, 32, 32,255, 0, 0, 0, 0, +255,255,255, 10,255,130, 0, 60,255,138, 48,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, + 0, 0, 0,255,255,255,255,255,107,107,107,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,150, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100,255,130, 0,255, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, + 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255, +144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,107,107,107,255, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,107,107,107,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,107,107,107,100,143,143,143,100, + 96,192, 64,255, 94, 94, 94,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255, 79,101, 73,255,135,177,125,255, +255,255,255,255,255,255,255,255,255,130, 0,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255, 82, 96,110,255,124,137,150,255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,130, 0,255, 2, 0, 0, 0, 0, 0, 0, 0,114,114,114,255, 0, 0, 0, 0, + 0, 0, 0,255,255,255,255,255,107,107,107,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,150, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, + 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255, +144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,158,158,158,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,158,158,158,255, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,165,165,165,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,140,140,140,255,127,112,112,100, + 0, 0, 0, 0,112,112, 96,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, 0, 0, 0, 0, +255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, + 0, 0, 0,255,255,255,255,255,107,107,107,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,150, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,107,107,107,255,178,178,178,100,255,130, 0,100, 94, 94, 94,255, 0, 0, 0,255,255,136,255,255, + 0, 0, 0, 0,255,187,255,255, 79,101, 73,255,135,177,125,255,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255, +144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,143,143,143,255,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,228,156,198,204,255,255,170,204, 96,192, 64,255, 82, 96,110,255,124,137,150,255, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,143,143,143,255, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,165,165,165,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,107,107,107,255,178,178,178,100, +255,130, 0,100, 94, 94, 94,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, 0, 0, 0, 0, +255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,228,156,198,255,255,255,170,255, + 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, + 0, 0, 0,255,255,255,255,255,107,107,107,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,150, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, + 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,112,255,255,255,130, 0,255, 0, 0, 0,255, +144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 80,200,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81,105,135,255,109, 88,129,255, 78,152, 62,255, + 46,143,143,255,169, 84,124,255,126,126, 80,255,162, 95,111,255,109,145,131,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 53, 53, 53,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,195,195,195,255, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,165,165,165,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, + 0, 0, 0, 0, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, 0, 0, 0, 0, +255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 50,150, 30,200,100,200, 60,255,133, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 80,200,255,255, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, + 0, 0, 0,255,255,255,255,255,195,195,195,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,150, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,143,143,143,255,127,112,112,100, 0, 0, 0, 0, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, + 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255, +144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,153,153,153,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,153,153,153,255, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,165,165,165,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,143,143,143,255,198,119,119,255, +255, 0, 0,255, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, 0, 0, 0, 0, +255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,100, 0, 0,255, 0, 0,200,255,128, 0, 80,255, 95, 95, 0,255, + 0,100, 50,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, + 0, 0, 0,255,255,255,255,255,107,107,107,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,150, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 88, 88, 88,255, 0, 0, 0,255,255,136,255,255, + 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255, +144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,158,158,158,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,158,158,158,255, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,165,165,165,150, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,140,140,140,255,127,112,112,100, + 0, 0, 0, 0,112,112, 96,255, 0, 0, 0,255,255,136,255,255, 0, 0, 0, 0,255,187,255,255, 0, 0, 0, 0, 0, 0, 0, 0, +255,255,255,255,255,112,255,255,255,255,112,255, 0, 0, 0,255,144,144, 48,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 50,150, 30,200,100,200, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107,107,107,255, 0, 0, 0, 0, + 0, 0, 0,255,255,255,255,255,107,107,107,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, 0, 0, 0, 51, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0,143,143,143,255, 0, 0, 0,255,217,217,217,255, + 0, 0, 0, 40,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0,255,130, 0,255, 0, 0, 0,255,255,130, 0,255, 0, 0, 0,255, +255,255,255,255,230,150, 50,255, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255, 10,255,130, 0, 60,255,138, 48,255, 34,221,221,255, +200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, +150,150,150,255,129,131,144,255,127,127,127,255,142,138,145,255,120,145,120,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,100,100,100,255, 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,107,107,107,255, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255, 0, 0, 0, 51, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, + 0, 0, 0, 0,143,143,143,255, 0, 0, 0,255,217,217,217,255, 0, 0, 0, 40,255,255,255,255, 16, 64, 16,255,102,255,102,255, +255,130, 0,255, 0, 0, 0,255,255,130, 0,255, 0, 0, 0,255,255,255,255,255,230,150, 50,255,255, 32, 32,255, 0, 0, 0, 0, +255,255,255, 10,255,130, 0, 60,255,138, 48,255, 34,221,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, + 96,192, 64,255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,255,255,255,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,114,114,114,255, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,145,145,145,245, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255, 0, 0, 0, 0, 0, 0, 0,255, + 0, 0, 0,255,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,154, 0, 0,255,189, 17, 17,255,247, 10, 10,255, 0, 0, 0, 0,247, 64, 24,255,246,105, 19,255, +250,153, 0,255, 0, 0, 0, 0, 30,145, 9,255, 89,183, 11,255,131,239, 29,255, 0, 0, 0, 0, 10, 54,148,255, 54,103,223,255, + 94,193,239,255, 0, 0, 0, 0,169, 41, 78,255,193, 65,106,255,240, 93,145,255, 0, 0, 0, 0, 67, 12,120,255, 84, 58,163,255, +135,100,213,255, 0, 0, 0, 0, 36,120, 90,255, 60,149,121,255,111,182,171,255, 0, 0, 0, 0, 75,112,124,255,106,134,145,255, +155,194,205,255, 0, 0, 0, 0,244,201, 12,255,238,194, 54,255,243,255, 0,255, 0, 0, 0, 0, 30, 32, 36,255, 72, 76, 86,255, +255,255,255,255, 0, 0, 0, 0,111, 47,106,255,152, 69,190,255,211, 48,214,255, 0, 0, 0, 0,108,142, 34,255,127,176, 34,255, +187,239, 91,255, 0, 0, 0, 0,141,141,141,255,176,176,176,255,222,222,222,255, 0, 0, 0, 0,131, 67, 38,255,139, 88, 17,255, +189,106, 17,255, 0, 0, 0, 0, 8, 49, 14,255, 28, 67, 11,255, 52, 98, 43,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 68, 78, 65, 49,144,226, 0, 0,184,251,141, 3, 0, 0, 0, 0, 1, 0, 0, 0, 83, 68, 78, 65, + 78, 65, 77, 69, 17, 11, 0, 0, 42,110,101,120,116, 0, 42,112,114,101,118, 0, 42,100, 97,116, 97, 0, 42,102,105,114,115,116, + 0, 42,108, 97,115,116, 0,120, 0,121, 0,122, 0,119, 0,120,109,105,110, 0,120,109, 97,120, 0,121,109,105,110, 0,121,109, + 97,120, 0, 42,112,111,105,110,116,101,114, 0,103,114,111,117,112, 0,118, 97,108, 0,118, 97,108, 50, 0,116,121,112,101, 0, +115,117, 98,116,121,112,101, 0,102,108, 97,103, 0,110, 97,109,101, 91, 51, 50, 93, 0,115, 97,118,101,100, 0,100, 97,116, 97, + 0,108,101,110, 0,116,111,116, 97,108,108,101,110, 0, 42,110,101,119,105,100, 0, 42,108,105, 98, 0,110, 97,109,101, 91, 50, + 52, 93, 0,117,115, 0,105, 99,111,110, 95,105,100, 0, 42,112,114,111,112,101,114,116,105,101,115, 0,105,100, 0, 42,105,100, + 98,108,111, 99,107, 0, 42,102,105,108,101,100, 97,116, 97, 0,110, 97,109,101, 91, 50, 52, 48, 93, 0,102,105,108,101,110, 97, +109,101, 91, 50, 52, 48, 93, 0,116,111,116, 0,112, 97,100, 0, 42,112, 97,114,101,110,116, 0,119, 91, 50, 93, 0,104, 91, 50, + 93, 0, 99,104, 97,110,103,101,100, 91, 50, 93, 0,112, 97,100, 48, 0,112, 97,100, 49, 0, 42,114,101, 99,116, 91, 50, 93, 0, + 42,111, 98, 0, 98,108,111, 99,107,116,121,112,101, 0, 97,100,114, 99,111,100,101, 0,110, 97,109,101, 91, 49, 50, 56, 93, 0, + 42, 98,112, 0, 42, 98,101,122,116, 0,109, 97,120,114, 99,116, 0,116,111,116,114, 99,116, 0,118, 97,114,116,121,112,101, 0, +116,111,116,118,101,114,116, 0,105,112,111, 0,101,120,116,114, 97,112, 0,114,116, 0, 98,105,116,109, 97,115,107, 0,115,108, +105,100,101, 95,109,105,110, 0,115,108,105,100,101, 95,109, 97,120, 0, 99,117,114,118, 97,108, 0, 42,100,114,105,118,101,114, + 0, 99,117,114,118,101, 0, 99,117,114, 0,115,104,111,119,107,101,121, 0,109,117,116,101,105,112,111, 0,112,111,115, 0,114, +101,108, 97,116,105,118,101, 0,116,111,116,101,108,101,109, 0,112, 97,100, 50, 0, 42,119,101,105,103,104,116,115, 0,118,103, +114,111,117,112, 91, 51, 50, 93, 0,115,108,105,100,101,114,109,105,110, 0,115,108,105,100,101,114,109, 97,120, 0, 42, 97,100, +116, 0, 42,114,101,102,107,101,121, 0,101,108,101,109,115,116,114, 91, 51, 50, 93, 0,101,108,101,109,115,105,122,101, 0, 98, +108,111, 99,107, 0, 42,105,112,111, 0, 42,102,114,111,109, 0,116,111,116,107,101,121, 0,115,108,117,114,112,104, 0, 42,108, +105,110,101, 0, 42,102,111,114,109, 97,116, 0, 98,108,101,110, 0,108,105,110,101,110,111, 0,115,116, 97,114,116, 0,101,110, +100, 0,102,108, 97,103,115, 0, 99,111,108,111,114, 91, 52, 93, 0,112, 97,100, 91, 52, 93, 0, 42,110, 97,109,101, 0,110,108, +105,110,101,115, 0,108,105,110,101,115, 0, 42, 99,117,114,108, 0, 42,115,101,108,108, 0, 99,117,114, 99, 0,115,101,108, 99, + 0,109, 97,114,107,101,114,115, 0, 42,117,110,100,111, 95, 98,117,102, 0,117,110,100,111, 95,112,111,115, 0,117,110,100,111, + 95,108,101,110, 0, 42, 99,111,109,112,105,108,101,100, 0,109,116,105,109,101, 0,115,105,122,101, 0,115,101,101,107, 0,112, + 97,115,115,101,112, 97,114,116, 97,108,112,104, 97, 0, 97,110,103,108,101, 0, 99,108,105,112,115,116, 97, 0, 99,108,105,112, +101,110,100, 0,108,101,110,115, 0,111,114,116,104,111, 95,115, 99, 97,108,101, 0,100,114, 97,119,115,105,122,101, 0,115,104, +105,102,116,120, 0,115,104,105,102,116,121, 0, 89, 70, 95,100,111,102,100,105,115,116, 0, 89, 70, 95, 97,112,101,114,116,117, +114,101, 0, 89, 70, 95, 98,107,104,116,121,112,101, 0, 89, 70, 95, 98,107,104, 98,105, 97,115, 0, 89, 70, 95, 98,107,104,114, +111,116, 0, 42,100,111,102, 95,111, 98, 0,102,114, 97,109,101,110,114, 0,102,114, 97,109,101,115, 0,111,102,102,115,101,116, + 0,115,102,114, 97, 0,102,105,101, 95,105,109, 97, 0, 99,121, 99,108, 0,111,107, 0,109,117,108,116,105, 95,105,110,100,101, +120, 0,108, 97,121,101,114, 0,112, 97,115,115, 0,109,101,110,117,110,114, 0, 42,115, 99,101,110,101, 0,105, 98,117,102,115, + 0, 42,103,112,117,116,101,120,116,117,114,101, 0, 42, 97,110,105,109, 0, 42,114,114, 0,115,111,117,114, 99,101, 0,108, 97, +115,116,102,114, 97,109,101, 0,116,112, 97,103,101,102,108, 97,103, 0,116,111,116, 98,105,110,100, 0,120,114,101,112, 0,121, +114,101,112, 0,116,119,115,116, 97, 0,116,119,101,110,100, 0, 98,105,110,100, 99,111,100,101, 0, 42,114,101,112, 98,105,110, +100, 0, 42,112, 97, 99,107,101,100,102,105,108,101, 0, 42,112,114,101,118,105,101,119, 0, 42,114,101,110,100,101,114, 95,116, +101,120,116, 0,108, 97,115,116,117,112,100, 97,116,101, 0,108, 97,115,116,117,115,101,100, 0, 97,110,105,109,115,112,101,101, +100, 0,103,101,110, 95,120, 0,103,101,110, 95,121, 0,103,101,110, 95,116,121,112,101, 0, 97,115,112,120, 0, 97,115,112,121, + 0,116,101,120, 99,111, 0,109, 97,112,116,111, 0,109, 97,112,116,111,110,101,103, 0, 98,108,101,110,100,116,121,112,101, 0, + 42,111, 98,106,101, 99,116, 0, 42,116,101,120, 0,117,118,110, 97,109,101, 91, 51, 50, 93, 0,112,114,111,106,120, 0,112,114, +111,106,121, 0,112,114,111,106,122, 0,109, 97,112,112,105,110,103, 0,111,102,115, 91, 51, 93, 0,115,105,122,101, 91, 51, 93, + 0,114,111,116, 0,116,101,120,102,108, 97,103, 0, 99,111,108,111,114,109,111,100,101,108, 0,112,109, 97,112,116,111, 0,112, +109, 97,112,116,111,110,101,103, 0,110,111,114,109, 97,112,115,112, 97, 99,101, 0,119,104,105, 99,104, 95,111,117,116,112,117, +116, 0, 98,114,117,115,104, 95,109, 97,112, 95,109,111,100,101, 0,112, 97,100, 91, 55, 93, 0,114, 0,103, 0, 98, 0,107, 0, +100,101,102, 95,118, 97,114, 0, 99,111,108,102, 97, 99, 0,118, 97,114,102, 97, 99, 0,110,111,114,102, 97, 99, 0,100,105,115, +112,102, 97, 99, 0,119, 97,114,112,102, 97, 99, 0, 99,111,108,115,112,101, 99,102, 97, 99, 0,109,105,114,114,102, 97, 99, 0, + 97,108,112,104, 97,102, 97, 99, 0,100,105,102,102,102, 97, 99, 0,115,112,101, 99,102, 97, 99, 0,101,109,105,116,102, 97, 99, + 0,104, 97,114,100,102, 97, 99, 0,114, 97,121,109,105,114,114,102, 97, 99, 0,116,114, 97,110,115,108,102, 97, 99, 0, 97,109, + 98,102, 97, 99, 0, 99,111,108,101,109,105,116,102, 97, 99, 0, 99,111,108,114,101,102,108,102, 97, 99, 0, 99,111,108,116,114, + 97,110,115,102, 97, 99, 0,100,101,110,115,102, 97, 99, 0,115, 99, 97,116,116,101,114,102, 97, 99, 0,114,101,102,108,102, 97, + 99, 0,116,105,109,101,102, 97, 99, 0,108,101,110,103,116,104,102, 97, 99, 0, 99,108,117,109,112,102, 97, 99, 0,107,105,110, +107,102, 97, 99, 0,114,111,117,103,104,102, 97, 99, 0,112, 97,100,101,110,115,102, 97, 99, 0,108,105,102,101,102, 97, 99, 0, +115,105,122,101,102, 97, 99, 0,105,118,101,108,102, 97, 99, 0,112,118,101,108,102, 97, 99, 0,115,104, 97,100,111,119,102, 97, + 99, 0,122,101,110,117,112,102, 97, 99, 0,122,101,110,100,111,119,110,102, 97, 99, 0, 98,108,101,110,100,102, 97, 99, 0,110, + 97,109,101, 91, 49, 54, 48, 93, 0, 42,104, 97,110,100,108,101, 0, 42,112,110, 97,109,101, 0, 42,115,116,110, 97,109,101,115, + 0,115,116,121,112,101,115, 0,118, 97,114,115, 0, 42,118, 97,114,115,116,114, 0, 42,114,101,115,117,108,116, 0, 42, 99,102, +114, 97, 0,100, 97,116, 97, 91, 51, 50, 93, 0, 40, 42,100,111,105,116, 41, 40, 41, 0, 40, 42,105,110,115,116, 97,110, 99,101, + 95,105,110,105,116, 41, 40, 41, 0, 40, 42, 99, 97,108,108, 98, 97, 99,107, 41, 40, 41, 0,118,101,114,115,105,111,110, 0, 97, + 0,105,112,111,116,121,112,101, 0, 42,105,109, 97, 0, 42, 99,117, 98,101, 91, 54, 93, 0,105,109, 97,116, 91, 52, 93, 91, 52, + 93, 0,111, 98,105,109, 97,116, 91, 51, 93, 91, 51, 93, 0,115,116,121,112,101, 0,118,105,101,119,115, 99, 97,108,101, 0,110, +111,116,108, 97,121, 0, 99,117, 98,101,114,101,115, 0,100,101,112,116,104, 0,114,101, 99, 97,108, 99, 0,108, 97,115,116,115, +105,122,101, 0,102, 97,108,108,111,102,102, 95,116,121,112,101, 0,102, 97,108,108,111,102,102, 95,115,111,102,116,110,101,115, +115, 0,114, 97,100,105,117,115, 0, 99,111,108,111,114, 95,115,111,117,114, 99,101, 0,116,111,116,112,111,105,110,116,115, 0, +112,100,112, 97,100, 0, 42,112,115,121,115, 0,112,115,121,115, 95, 99, 97, 99,104,101, 95,115,112, 97, 99,101, 0,111, 98, 95, + 99, 97, 99,104,101, 95,115,112, 97, 99,101, 0,112,100,112, 97,100, 50, 91, 50, 93, 0, 42,112,111,105,110,116, 95,116,114,101, +101, 0, 42,112,111,105,110,116, 95,100, 97,116, 97, 0,110,111,105,115,101, 95,115,105,122,101, 0,110,111,105,115,101, 95,100, +101,112,116,104, 0,110,111,105,115,101, 95,105,110,102,108,117,101,110, 99,101, 0,110,111,105,115,101, 95, 98, 97,115,105,115, + 0,112,100,112, 97,100, 51, 91, 51, 93, 0,110,111,105,115,101, 95,102, 97, 99, 0,115,112,101,101,100, 95,115, 99, 97,108,101, + 0, 42, 99,111, 98, 97, 0,114,101,115,111,108, 91, 51, 93, 0,105,110,116,101,114,112, 95,116,121,112,101, 0,102,105,108,101, + 95,102,111,114,109, 97,116, 0,101,120,116,101,110,100, 0,105,110,116, 95,109,117,108,116,105,112,108,105,101,114, 0,115,116, +105,108,108, 95,102,114, 97,109,101, 0,115,111,117,114, 99,101, 95,112, 97,116,104, 91, 50, 52, 48, 93, 0, 42,100, 97,116, 97, +115,101,116, 0,110,111,105,115,101,115,105,122,101, 0,116,117,114, 98,117,108, 0, 98,114,105,103,104,116, 0, 99,111,110,116, +114, 97,115,116, 0,114,102, 97, 99, 0,103,102, 97, 99, 0, 98,102, 97, 99, 0,102,105,108,116,101,114,115,105,122,101, 0,109, +103, 95, 72, 0,109,103, 95,108, 97, 99,117,110, 97,114,105,116,121, 0,109,103, 95,111, 99,116, 97,118,101,115, 0,109,103, 95, +111,102,102,115,101,116, 0,109,103, 95,103, 97,105,110, 0,100,105,115,116, 95, 97,109,111,117,110,116, 0,110,115, 95,111,117, +116,115, 99, 97,108,101, 0,118,110, 95,119, 49, 0,118,110, 95,119, 50, 0,118,110, 95,119, 51, 0,118,110, 95,119, 52, 0,118, +110, 95,109,101,120,112, 0,118,110, 95,100,105,115,116,109, 0,118,110, 95, 99,111,108,116,121,112,101, 0,110,111,105,115,101, +100,101,112,116,104, 0,110,111,105,115,101,116,121,112,101, 0,110,111,105,115,101, 98, 97,115,105,115, 0,110,111,105,115,101, + 98, 97,115,105,115, 50, 0,105,109, 97,102,108, 97,103, 0, 99,114,111,112,120,109,105,110, 0, 99,114,111,112,121,109,105,110, + 0, 99,114,111,112,120,109, 97,120, 0, 99,114,111,112,121,109, 97,120, 0,116,101,120,102,105,108,116,101,114, 0, 97,102,109, + 97,120, 0,120,114,101,112,101, 97,116, 0,121,114,101,112,101, 97,116, 0, 99,104,101, 99,107,101,114,100,105,115,116, 0,110, + 97, 98,108, 97, 0,105,117,115,101,114, 0, 42,110,111,100,101,116,114,101,101, 0, 42,112,108,117,103,105,110, 0, 42,101,110, +118, 0, 42,112,100, 0, 42,118,100, 0,117,115,101, 95,110,111,100,101,115, 0,108,111, 99, 91, 51, 93, 0,114,111,116, 91, 51, + 93, 0,109, 97,116, 91, 52, 93, 91, 52, 93, 0,109,105,110, 91, 51, 93, 0,109, 97,120, 91, 51, 93, 0,109,111,100,101, 0,116, +111,116,101,120, 0,115,104,100,119,114, 0,115,104,100,119,103, 0,115,104,100,119, 98, 0,115,104,100,119,112, 97,100, 0,101, +110,101,114,103,121, 0,100,105,115,116, 0,115,112,111,116,115,105,122,101, 0,115,112,111,116, 98,108,101,110,100, 0,104, 97, +105,110,116, 0, 97,116,116, 49, 0, 97,116,116, 50, 0, 42, 99,117,114,102, 97,108,108,111,102,102, 0,115,104, 97,100,115,112, +111,116,115,105,122,101, 0, 98,105, 97,115, 0,115,111,102,116, 0, 98,117,102,115,105,122,101, 0,115, 97,109,112, 0, 98,117, +102,102,101,114,115, 0,102,105,108,116,101,114,116,121,112,101, 0, 98,117,102,102,108, 97,103, 0, 98,117,102,116,121,112,101, + 0,114, 97,121, 95,115, 97,109,112, 0,114, 97,121, 95,115, 97,109,112,121, 0,114, 97,121, 95,115, 97,109,112,122, 0,114, 97, +121, 95,115, 97,109,112, 95,116,121,112,101, 0, 97,114,101, 97, 95,115,104, 97,112,101, 0, 97,114,101, 97, 95,115,105,122,101, + 0, 97,114,101, 97, 95,115,105,122,101,121, 0, 97,114,101, 97, 95,115,105,122,101,122, 0, 97,100, 97,112,116, 95,116,104,114, +101,115,104, 0,114, 97,121, 95,115, 97,109,112, 95,109,101,116,104,111,100, 0,116,101,120, 97, 99,116, 0,115,104, 97,100,104, + 97,108,111,115,116,101,112, 0,115,117,110, 95,101,102,102,101, 99,116, 95,116,121,112,101, 0,115,107,121, 98,108,101,110,100, +116,121,112,101, 0,104,111,114,105,122,111,110, 95, 98,114,105,103,104,116,110,101,115,115, 0,115,112,114,101, 97,100, 0,115, +117,110, 95, 98,114,105,103,104,116,110,101,115,115, 0,115,117,110, 95,115,105,122,101, 0, 98, 97, 99,107,115, 99, 97,116,116, +101,114,101,100, 95,108,105,103,104,116, 0,115,117,110, 95,105,110,116,101,110,115,105,116,121, 0, 97,116,109, 95,116,117,114, + 98,105,100,105,116,121, 0, 97,116,109, 95,105,110,115, 99, 97,116,116,101,114,105,110,103, 95,102, 97, 99,116,111,114, 0, 97, +116,109, 95,101,120,116,105,110, 99,116,105,111,110, 95,102, 97, 99,116,111,114, 0, 97,116,109, 95,100,105,115,116, 97,110, 99, +101, 95,102, 97, 99,116,111,114, 0,115,107,121, 98,108,101,110,100,102, 97, 99, 0,115,107,121, 95,101,120,112,111,115,117,114, +101, 0,115,107,121, 95, 99,111,108,111,114,115,112, 97, 99,101, 0,112, 97,100, 52, 0, 89, 70, 95,110,117,109,112,104,111,116, +111,110,115, 0, 89, 70, 95,110,117,109,115,101, 97,114, 99,104, 0, 89, 70, 95,112,104,100,101,112,116,104, 0, 89, 70, 95,117, +115,101,113,109, 99, 0, 89, 70, 95, 98,117,102,115,105,122,101, 0, 89, 70, 95,112, 97,100, 0, 89, 70, 95, 99, 97,117,115,116, +105, 99, 98,108,117,114, 0, 89, 70, 95,108,116,114, 97,100,105,117,115, 0, 89, 70, 95,103,108,111,119,105,110,116, 0, 89, 70, + 95,103,108,111,119,111,102,115, 0, 89, 70, 95,103,108,111,119,116,121,112,101, 0, 89, 70, 95,112, 97,100, 50, 0, 42,109,116, +101,120, 91, 49, 56, 93, 0,112,114, 95,116,101,120,116,117,114,101, 0,112, 97,100, 91, 51, 93, 0,100,101,110,115,105,116,121, + 0,101,109,105,115,115,105,111,110, 0,115, 99, 97,116,116,101,114,105,110,103, 0,114,101,102,108,101, 99,116,105,111,110, 0, +101,109,105,115,115,105,111,110, 95, 99,111,108, 91, 51, 93, 0,116,114, 97,110,115,109,105,115,115,105,111,110, 95, 99,111,108, + 91, 51, 93, 0,114,101,102,108,101, 99,116,105,111,110, 95, 99,111,108, 91, 51, 93, 0,100,101,110,115,105,116,121, 95,115, 99, + 97,108,101, 0,100,101,112,116,104, 95, 99,117,116,111,102,102, 0, 97,115,121,109,109,101,116,114,121, 0,115,116,101,112,115, +105,122,101, 95,116,121,112,101, 0,115,104, 97,100,101,102,108, 97,103, 0,115,104, 97,100,101, 95,116,121,112,101, 0,112,114, +101, 99, 97, 99,104,101, 95,114,101,115,111,108,117,116,105,111,110, 0,115,116,101,112,115,105,122,101, 0,109,115, 95,100,105, +102,102, 0,109,115, 95,105,110,116,101,110,115,105,116,121, 0,109,115, 95,115,116,101,112,115, 0,109, 97,116,101,114,105, 97, +108, 95,116,121,112,101, 0,115,112,101, 99,114, 0,115,112,101, 99,103, 0,115,112,101, 99, 98, 0,109,105,114,114, 0,109,105, +114,103, 0,109,105,114, 98, 0, 97,109, 98,114, 0, 97,109, 98, 98, 0, 97,109, 98,103, 0, 97,109, 98, 0,101,109,105,116, 0, + 97,110,103, 0,115,112,101, 99,116,114, 97, 0,114, 97,121, 95,109,105,114,114,111,114, 0, 97,108,112,104, 97, 0,114,101,102, + 0,115,112,101, 99, 0,122,111,102,102,115, 0, 97,100,100, 0,116,114, 97,110,115,108,117, 99,101,110, 99,121, 0,118,111,108, + 0,102,114,101,115,110,101,108, 95,109,105,114, 0,102,114,101,115,110,101,108, 95,109,105,114, 95,105, 0,102,114,101,115,110, +101,108, 95,116,114, 97, 0,102,114,101,115,110,101,108, 95,116,114, 97, 95,105, 0,102,105,108,116,101,114, 0,116,120, 95,108, +105,109,105,116, 0,116,120, 95,102, 97,108,108,111,102,102, 0,114, 97,121, 95,100,101,112,116,104, 0,114, 97,121, 95,100,101, +112,116,104, 95,116,114, 97, 0,104, 97,114, 0,115,101,101,100, 49, 0,115,101,101,100, 50, 0,103,108,111,115,115, 95,109,105, +114, 0,103,108,111,115,115, 95,116,114, 97, 0,115, 97,109,112, 95,103,108,111,115,115, 95,109,105,114, 0,115, 97,109,112, 95, +103,108,111,115,115, 95,116,114, 97, 0, 97,100, 97,112,116, 95,116,104,114,101,115,104, 95,109,105,114, 0, 97,100, 97,112,116, + 95,116,104,114,101,115,104, 95,116,114, 97, 0, 97,110,105,115,111, 95,103,108,111,115,115, 95,109,105,114, 0,100,105,115,116, + 95,109,105,114, 0,102, 97,100,101,116,111, 95,109,105,114, 0,115,104, 97,100,101, 95,102,108, 97,103, 0,109,111,100,101, 95, +108, 0,102,108, 97,114,101, 99, 0,115,116, 97,114, 99, 0,108,105,110,101, 99, 0,114,105,110,103, 99, 0,104, 97,115,105,122, +101, 0,102,108, 97,114,101,115,105,122,101, 0,115,117, 98,115,105,122,101, 0,102,108, 97,114,101, 98,111,111,115,116, 0,115, +116,114, 97,110,100, 95,115,116, 97, 0,115,116,114, 97,110,100, 95,101,110,100, 0,115,116,114, 97,110,100, 95,101, 97,115,101, + 0,115,116,114, 97,110,100, 95,115,117,114,102,110,111,114, 0,115,116,114, 97,110,100, 95,109,105,110, 0,115,116,114, 97,110, +100, 95,119,105,100,116,104,102, 97,100,101, 0,115,116,114, 97,110,100, 95,117,118,110, 97,109,101, 91, 51, 50, 93, 0,115, 98, +105, 97,115, 0,108, 98,105, 97,115, 0,115,104, 97,100, 95, 97,108,112,104, 97, 0,115,101,112,116,101,120, 0,114,103, 98,115, +101,108, 0,112,114, 95,116,121,112,101, 0,112,114, 95, 98, 97, 99,107, 0,112,114, 95,108, 97,109,112, 0,109,108, 95,102,108, + 97,103, 0,100,105,102,102, 95,115,104, 97,100,101,114, 0,115,112,101, 99, 95,115,104, 97,100,101,114, 0,114,111,117,103,104, +110,101,115,115, 0,114,101,102,114, 97, 99, 0,112, 97,114, 97,109, 91, 52, 93, 0,114,109,115, 0,100, 97,114,107,110,101,115, +115, 0, 42,114, 97,109,112, 95, 99,111,108, 0, 42,114, 97,109,112, 95,115,112,101, 99, 0,114, 97,109,112,105,110, 95, 99,111, +108, 0,114, 97,109,112,105,110, 95,115,112,101, 99, 0,114, 97,109,112, 98,108,101,110,100, 95, 99,111,108, 0,114, 97,109,112, + 98,108,101,110,100, 95,115,112,101, 99, 0,114, 97,109,112, 95,115,104,111,119, 0,112, 97,100, 51, 0,114, 97,109,112,102, 97, + 99, 95, 99,111,108, 0,114, 97,109,112,102, 97, 99, 95,115,112,101, 99, 0, 42,103,114,111,117,112, 0,102,114,105, 99,116,105, +111,110, 0,102,104, 0,114,101,102,108,101, 99,116, 0,102,104,100,105,115,116, 0,120,121,102,114,105, 99,116, 0,100,121,110, + 97,109,111,100,101, 0,115,115,115, 95,114, 97,100,105,117,115, 91, 51, 93, 0,115,115,115, 95, 99,111,108, 91, 51, 93, 0,115, +115,115, 95,101,114,114,111,114, 0,115,115,115, 95,115, 99, 97,108,101, 0,115,115,115, 95,105,111,114, 0,115,115,115, 95, 99, +111,108,102, 97, 99, 0,115,115,115, 95,116,101,120,102, 97, 99, 0,115,115,115, 95,102,114,111,110,116, 0,115,115,115, 95, 98, + 97, 99,107, 0,115,115,115, 95,102,108, 97,103, 0,115,115,115, 95,112,114,101,115,101,116, 0,109, 97,112,116,111, 95,116,101, +120,116,117,114,101,100, 0,103,112,117,109, 97,116,101,114,105, 97,108, 0,110, 97,109,101, 91, 50, 53, 54, 93, 0, 42, 98, 98, + 0,105, 49, 0,106, 49, 0,107, 49, 0,105, 50, 0,106, 50, 0,107, 50, 0,115,101,108, 99,111,108, 49, 0,115,101,108, 99,111, +108, 50, 0,113,117, 97,116, 91, 52, 93, 0,101,120,112,120, 0,101,120,112,121, 0,101,120,112,122, 0,114, 97,100, 0,114, 97, +100, 50, 0,115, 0, 42,109, 97,116, 0, 42,105,109, 97,116, 0,101,108,101,109,115, 0,100,105,115,112, 0, 42,101,100,105,116, +101,108,101,109,115, 0, 42, 42,109, 97,116, 0,102,108, 97,103, 50, 0,116,111,116, 99,111,108, 0,119,105,114,101,115,105,122, +101, 0,114,101,110,100,101,114,115,105,122,101, 0,116,104,114,101,115,104, 0, 42,108, 97,115,116,101,108,101,109, 0,118,101, + 99, 91, 51, 93, 91, 51, 93, 0, 97,108,102, 97, 0,119,101,105,103,104,116, 0,104, 49, 0,104, 50, 0,102, 49, 0,102, 50, 0, +102, 51, 0,104,105,100,101, 0,118,101, 99, 91, 52, 93, 0,109, 97,116, 95,110,114, 0,112,110,116,115,117, 0,112,110,116,115, +118, 0,114,101,115,111,108,117, 0,114,101,115,111,108,118, 0,111,114,100,101,114,117, 0,111,114,100,101,114,118, 0,102,108, + 97,103,117, 0,102,108, 97,103,118, 0, 42,107,110,111,116,115,117, 0, 42,107,110,111,116,115,118, 0,116,105,108,116, 95,105, +110,116,101,114,112, 0,114, 97,100,105,117,115, 95,105,110,116,101,114,112, 0, 99,104, 97,114,105,100,120, 0,107,101,114,110, + 0,104, 0,110,117,114, 98, 0, 42,101,100,105,116,110,117,114, 98, 0, 42, 98,101,118,111, 98,106, 0, 42,116, 97,112,101,114, +111, 98,106, 0, 42,116,101,120,116,111,110, 99,117,114,118,101, 0, 42,112, 97,116,104, 0, 42,107,101,121, 0, 98,101,118, 0, +100,114, 97,119,102,108, 97,103, 0,116,119,105,115,116, 95,109,111,100,101, 0,112, 97,100, 91, 50, 93, 0,116,119,105,115,116, + 95,115,109,111,111,116,104, 0,112, 97,116,104,108,101,110, 0, 98,101,118,114,101,115,111,108, 0,119,105,100,116,104, 0,101, +120,116, 49, 0,101,120,116, 50, 0,114,101,115,111,108,117, 95,114,101,110, 0,114,101,115,111,108,118, 95,114,101,110, 0, 97, + 99,116,110,117, 0, 42,108, 97,115,116,115,101,108, 98,112, 0,115,112, 97, 99,101,109,111,100,101, 0,115,112, 97, 99,105,110, +103, 0,108,105,110,101,100,105,115,116, 0,115,104,101, 97,114, 0,102,115,105,122,101, 0,119,111,114,100,115,112, 97, 99,101, + 0,117,108,112,111,115, 0,117,108,104,101,105,103,104,116, 0,120,111,102, 0,121,111,102, 0,108,105,110,101,119,105,100,116, +104, 0, 42,115,116,114, 0, 42,115,101,108, 98,111,120,101,115, 0, 42,101,100,105,116,102,111,110,116, 0,102, 97,109,105,108, +121, 91, 50, 52, 93, 0, 42,118,102,111,110,116, 0, 42,118,102,111,110,116, 98, 0, 42,118,102,111,110,116,105, 0, 42,118,102, +111,110,116, 98,105, 0,115,101,112, 99,104, 97,114, 0, 99,116,105,109,101, 0,116,111,116, 98,111,120, 0, 97, 99,116, 98,111, +120, 0, 42,116, 98, 0,115,101,108,115,116, 97,114,116, 0,115,101,108,101,110,100, 0, 42,115,116,114,105,110,102,111, 0, 99, +117,114,105,110,102,111, 0,101,102,102,101, 99,116, 0, 42,109,102, 97, 99,101, 0, 42,109,116,102, 97, 99,101, 0, 42,116,102, + 97, 99,101, 0, 42,109,118,101,114,116, 0, 42,109,101,100,103,101, 0, 42,100,118,101,114,116, 0, 42,109, 99,111,108, 0, 42, +109,115,116,105, 99,107,121, 0, 42,116,101,120, 99,111,109,101,115,104, 0, 42,109,115,101,108,101, 99,116, 0, 42,101,100,105, +116, 95,109,101,115,104, 0,118,100, 97,116, 97, 0,101,100, 97,116, 97, 0,102,100, 97,116, 97, 0,116,111,116,101,100,103,101, + 0,116,111,116,102, 97, 99,101, 0,116,111,116,115,101,108,101, 99,116, 0, 97, 99,116, 95,102, 97, 99,101, 0, 99,117, 98,101, +109, 97,112,115,105,122,101, 0,115,109,111,111,116,104,114,101,115,104, 0,115,117, 98,100,105,118, 0,115,117, 98,100,105,118, +114, 0,115,117, 98,115,117,114,102,116,121,112,101, 0, 42,109,114, 0, 42,112,118, 0, 42,116,112, 97,103,101, 0,117,118, 91, + 52, 93, 91, 50, 93, 0, 99,111,108, 91, 52, 93, 0,116,114, 97,110,115,112, 0,116,105,108,101, 0,117,110,119,114, 97,112, 0, +118, 49, 0,118, 50, 0,118, 51, 0,118, 52, 0,101,100, 99,111,100,101, 0, 99,114,101, 97,115,101, 0, 98,119,101,105,103,104, +116, 0,100,101,102, 95,110,114, 0, 42,100,119, 0,116,111,116,119,101,105,103,104,116, 0, 99,111, 91, 51, 93, 0,110,111, 91, + 51, 93, 0,117,118, 91, 50, 93, 0, 99,111, 91, 50, 93, 0,105,110,100,101,120, 0,102, 0,105, 0,115, 91, 50, 53, 54, 93, 0, +116,111,116,100,105,115,112, 0, 40, 42,100,105,115,112,115, 41, 40, 41, 0,118, 91, 52, 93, 0,109,105,100, 0,118, 91, 50, 93, + 0, 42,102, 97, 99,101,115, 0, 42, 99,111,108,102, 97, 99,101,115, 0, 42,101,100,103,101,115, 0, 42,118,101,114,116,115, 0, +108,101,118,101,108,115, 0,108,101,118,101,108, 95, 99,111,117,110,116, 0, 99,117,114,114,101,110,116, 0,110,101,119,108,118, +108, 0,101,100,103,101,108,118,108, 0,112,105,110,108,118,108, 0,114,101,110,100,101,114,108,118,108, 0,117,115,101, 95, 99, +111,108, 0, 42,101,100,103,101, 95,102,108, 97,103,115, 0, 42,101,100,103,101, 95, 99,114,101, 97,115,101,115, 0, 42,118,101, +114,116, 95,109, 97,112, 0, 42,101,100,103,101, 95,109, 97,112, 0, 42,111,108,100, 95,102, 97, 99,101,115, 0, 42,111,108,100, + 95,101,100,103,101,115, 0, 42,101,114,114,111,114, 0,109,111,100,105,102,105,101,114, 0,115,117, 98,100,105,118, 84,121,112, +101, 0,114,101,110,100,101,114, 76,101,118,101,108,115, 0, 42,101,109, 67, 97, 99,104,101, 0, 42,109, 67, 97, 99,104,101, 0, +100,101,102, 97,120,105,115, 0,112, 97,100, 91, 54, 93, 0,108,101,110,103,116,104, 0,114, 97,110,100,111,109,105,122,101, 0, +115,101,101,100, 0, 42,111, 98, 95, 97,114,109, 0, 42,115,116, 97,114,116, 95, 99, 97,112, 0, 42,101,110,100, 95, 99, 97,112, + 0, 42, 99,117,114,118,101, 95,111, 98, 0, 42,111,102,102,115,101,116, 95,111, 98, 0,111,102,102,115,101,116, 91, 51, 93, 0, +115, 99, 97,108,101, 91, 51, 93, 0,109,101,114,103,101, 95,100,105,115,116, 0,102,105,116, 95,116,121,112,101, 0,111,102,102, +115,101,116, 95,116,121,112,101, 0, 99,111,117,110,116, 0, 97,120,105,115, 0,116,111,108,101,114, 97,110, 99,101, 0, 42,109, +105,114,114,111,114, 95,111, 98, 0,115,112,108,105,116, 95, 97,110,103,108,101, 0,118, 97,108,117,101, 0,114,101,115, 0,118, + 97,108, 95,102,108, 97,103,115, 0,108,105,109, 95,102,108, 97,103,115, 0,101, 95,102,108, 97,103,115, 0, 98,101,118,101,108, + 95, 97,110,103,108,101, 0,100,101,102,103,114,112, 95,110, 97,109,101, 91, 51, 50, 93, 0, 42,100,111,109, 97,105,110, 0, 42, +102,108,111,119, 0, 42, 99,111,108,108, 0,116,105,109,101, 0, 42,116,101,120,116,117,114,101, 0,115,116,114,101,110,103,116, +104, 0,100,105,114,101, 99,116,105,111,110, 0,109,105,100,108,101,118,101,108, 0,116,101,120,109, 97,112,112,105,110,103, 0, + 42,109, 97,112, 95,111, 98,106,101, 99,116, 0,117,118,108, 97,121,101,114, 95,110, 97,109,101, 91, 51, 50, 93, 0,117,118,108, + 97,121,101,114, 95,116,109,112, 0, 42,112,114,111,106,101, 99,116,111,114,115, 91, 49, 48, 93, 0, 42,105,109, 97,103,101, 0, +110,117,109, 95,112,114,111,106,101, 99,116,111,114,115, 0, 97,115,112,101, 99,116,120, 0, 97,115,112,101, 99,116,121, 0,112, +101,114, 99,101,110,116, 0,102, 97, 99,101, 67,111,117,110,116, 0,102, 97, 99, 0,114,101,112,101, 97,116, 0, 42,111, 98,106, +101, 99,116, 99,101,110,116,101,114, 0,115,116, 97,114,116,120, 0,115,116, 97,114,116,121, 0,104,101,105,103,104,116, 0,110, + 97,114,114,111,119, 0,115,112,101,101,100, 0,100, 97,109,112, 0,102, 97,108,108,111,102,102, 0,116,105,109,101,111,102,102, +115, 0,108,105,102,101,116,105,109,101, 0,100,101,102,111,114,109,102,108, 97,103, 0,109,117,108,116,105, 0, 42,112,114,101, +118, 67,111,115, 0,115,117, 98,116, 97,114,103,101,116, 91, 51, 50, 93, 0,112, 97,114,101,110,116,105,110,118, 91, 52, 93, 91, + 52, 93, 0, 99,101,110,116, 91, 51, 93, 0, 42,105,110,100,101,120, 97,114, 0,116,111,116,105,110,100,101,120, 0,102,111,114, + 99,101, 0, 42, 99,108,111,116,104, 79, 98,106,101, 99,116, 0, 42,115,105,109, 95,112, 97,114,109,115, 0, 42, 99,111,108,108, + 95,112, 97,114,109,115, 0, 42,112,111,105,110,116, 95, 99, 97, 99,104,101, 0,112,116, 99, 97, 99,104,101,115, 0, 42,120, 0, + 42,120,110,101,119, 0, 42,120,111,108,100, 0, 42, 99,117,114,114,101,110,116, 95,120,110,101,119, 0, 42, 99,117,114,114,101, +110,116, 95,120, 0, 42, 99,117,114,114,101,110,116, 95,118, 0, 42,109,102, 97, 99,101,115, 0,110,117,109,118,101,114,116,115, + 0,110,117,109,102, 97, 99,101,115, 0, 42, 98,118,104,116,114,101,101, 0, 42,118, 0, 42,100,109, 0, 99,102,114, 97, 0,111, +112,101,114, 97,116,105,111,110, 0,118,101,114,116,101,120, 0,116,111,116,105,110,102,108,117,101,110, 99,101, 0,103,114,105, +100,115,105,122,101, 0,110,101,101,100, 98,105,110,100, 0, 42, 98,105,110,100,119,101,105,103,104,116,115, 0, 42, 98,105,110, +100, 99,111,115, 0,116,111,116, 99, 97,103,101,118,101,114,116, 0, 42,100,121,110,103,114,105,100, 0, 42,100,121,110,105,110, +102,108,117,101,110, 99,101,115, 0, 42,100,121,110,118,101,114,116,115, 0, 42,112, 97,100, 50, 0,100,121,110,103,114,105,100, +115,105,122,101, 0,100,121,110, 99,101,108,108,109,105,110, 91, 51, 93, 0,100,121,110, 99,101,108,108,119,105,100,116,104, 0, + 98,105,110,100,109, 97,116, 91, 52, 93, 91, 52, 93, 0,116,111,116,100,109,118,101,114,116, 0,116,111,116,100,109,101,100,103, +101, 0,116,111,116,100,109,102, 97, 99,101, 0,112,115,121,115, 0,112,111,115,105,116,105,111,110, 0,114, 97,110,100,111,109, + 95,112,111,115,105,116,105,111,110, 0, 42,102, 97, 99,101,112, 97, 0,118,103,114,111,117,112, 0,112,114,111,116,101, 99,116, + 0, 42,117,110,100,111, 95,118,101,114,116,115, 0,117,110,100,111, 95,118,101,114,116,115, 95,116,111,116, 0,117,110,100,111, + 95,115,105,103,110, 97,108, 0,108,118,108, 0,116,111,116,108,118,108, 0,115,105,109,112,108,101, 0, 42,102,115,115, 0, 42, +116, 97,114,103,101,116, 0, 42, 97,117,120, 84, 97,114,103,101,116, 0,118,103,114,111,117,112, 95,110, 97,109,101, 91, 51, 50, + 93, 0,107,101,101,112, 68,105,115,116, 0,115,104,114,105,110,107, 84,121,112,101, 0,115,104,114,105,110,107, 79,112,116,115, + 0,112,114,111,106, 65,120,105,115, 0,115,117, 98,115,117,114,102, 76,101,118,101,108,115, 0, 42,111,114,105,103,105,110, 0, +102, 97, 99,116,111,114, 0,108,105,109,105,116, 91, 50, 93, 0,111,114,105,103,105,110, 79,112,116,115, 0,112,110,116,115,119, + 0,111,112,110,116,115,117, 0,111,112,110,116,115,118, 0,111,112,110,116,115,119, 0,116,121,112,101,117, 0,116,121,112,101, +118, 0,116,121,112,101,119, 0,102,117, 0,102,118, 0,102,119, 0,100,117, 0,100,118, 0,100,119, 0, 42,100,101,102, 0, 42, +108, 97,116,116,105, 99,101,100, 97,116, 97, 0,108, 97,116,109, 97,116, 91, 52, 93, 91, 52, 93, 0, 42,101,100,105,116,108, 97, +116,116, 0,118,101, 99, 91, 56, 93, 91, 51, 93, 0, 42,115, 99,117,108,112,116, 0,112, 97,114,116,121,112,101, 0,112, 97,114, + 49, 0,112, 97,114, 50, 0,112, 97,114, 51, 0,112, 97,114,115,117, 98,115,116,114, 91, 51, 50, 93, 0, 42,116,114, 97, 99,107, + 0, 42,112,114,111,120,121, 0, 42,112,114,111,120,121, 95,103,114,111,117,112, 0, 42,112,114,111,120,121, 95,102,114,111,109, + 0, 42, 97, 99,116,105,111,110, 0, 42,112,111,115,101,108,105, 98, 0, 42,112,111,115,101, 0, 42,103,112,100, 0, 99,111,110, +115,116,114, 97,105,110,116, 67,104, 97,110,110,101,108,115, 0,100,101,102, 98, 97,115,101, 0,109,111,100,105,102,105,101,114, +115, 0,114,101,115,116,111,114,101, 95,109,111,100,101, 0, 42,109, 97,116, 98,105,116,115, 0, 97, 99,116, 99,111,108, 0,100, +108,111, 99, 91, 51, 93, 0,111,114,105,103, 91, 51, 93, 0,100,115,105,122,101, 91, 51, 93, 0,100,114,111,116, 91, 51, 93, 0, +100,113,117, 97,116, 91, 52, 93, 0,111, 98,109, 97,116, 91, 52, 93, 91, 52, 93, 0, 99,111,110,115,116,105,110,118, 91, 52, 93, + 91, 52, 93, 0,108, 97,121, 0, 99,111,108, 98,105,116,115, 0,116,114, 97,110,115,102,108, 97,103, 0,112,114,111,116,101, 99, +116,102,108, 97,103, 0,116,114, 97, 99,107,102,108, 97,103, 0,117,112,102,108, 97,103, 0,110,108, 97,102,108, 97,103, 0,105, +112,111,102,108, 97,103, 0,105,112,111,119,105,110, 0,115, 99, 97,102,108, 97,103, 0,115, 99, 97,118,105,115,102,108, 97,103, + 0, 98,111,117,110,100,116,121,112,101, 0,100,117,112,111,110, 0,100,117,112,111,102,102, 0,100,117,112,115,116, 97, 0,100, +117,112,101,110,100, 0,115,102, 0,109, 97,115,115, 0,100, 97,109,112,105,110,103, 0,105,110,101,114,116,105, 97, 0,102,111, +114,109,102, 97, 99,116,111,114, 0,114,100, 97,109,112,105,110,103, 0,109, 97,114,103,105,110, 0,109, 97,120, 95,118,101,108, + 0,109,105,110, 95,118,101,108, 0,109, 95, 99,111,110,116, 97, 99,116, 80,114,111, 99,101,115,115,105,110,103, 84,104,114,101, +115,104,111,108,100, 0,114,111,116,109,111,100,101, 0,100,116, 0,100,116,120, 0,101,109,112,116,121, 95,100,114, 97,119,116, +121,112,101, 0,112, 97,100, 49, 91, 51, 93, 0,101,109,112,116,121, 95,100,114, 97,119,115,105,122,101, 0,100,117,112,102, 97, + 99,101,115, 99, 97, 0,112,114,111,112, 0,115,101,110,115,111,114,115, 0, 99,111,110,116,114,111,108,108,101,114,115, 0, 97, + 99,116,117, 97,116,111,114,115, 0, 98, 98,115,105,122,101, 91, 51, 93, 0, 97, 99,116,100,101,102, 0,103, 97,109,101,102,108, + 97,103, 0,103, 97,109,101,102,108, 97,103, 50, 0, 42, 98,115,111,102,116, 0,115,111,102,116,102,108, 97,103, 0, 97,110,105, +115,111,116,114,111,112,105, 99, 70,114,105, 99,116,105,111,110, 91, 51, 93, 0, 99,111,110,115,116,114, 97,105,110,116,115, 0, +110,108, 97,115,116,114,105,112,115, 0,104,111,111,107,115, 0,112, 97,114,116,105, 99,108,101,115,121,115,116,101,109, 0, 42, +115,111,102,116, 0, 42,100,117,112, 95,103,114,111,117,112, 0,102,108,117,105,100,115,105,109, 70,108, 97,103, 0,114,101,115, +116,114,105, 99,116,102,108, 97,103, 0,115,104, 97,112,101,110,114, 0,115,104, 97,112,101,102,108, 97,103, 0,114,101, 99, 97, +108, 99,111, 0, 98,111,100,121, 95,116,121,112,101, 0, 42,102,108,117,105,100,115,105,109, 83,101,116,116,105,110,103,115, 0, + 42,100,101,114,105,118,101,100, 68,101,102,111,114,109, 0, 42,100,101,114,105,118,101,100, 70,105,110, 97,108, 0,108, 97,115, +116, 68, 97,116, 97, 77, 97,115,107, 0,115,116, 97,116,101, 0,105,110,105,116, 95,115,116, 97,116,101, 0,103,112,117,108, 97, +109,112, 0,112, 99, 95,105,100,115, 0, 42,100,117,112,108,105,108,105,115,116, 0, 99,117,114,105,110,100,101,120, 0, 97, 99, +116,105,118,101, 0,111,114,105,103,108, 97,121, 0,110,111, 95,100,114, 97,119, 0, 97,110,105,109, 97,116,101,100, 0,111,109, + 97,116, 91, 52, 93, 91, 52, 93, 0,111,114, 99,111, 91, 51, 93, 0,100,101,102,108,101, 99,116, 0,102,111,114, 99,101,102,105, +101,108,100, 0,115,104, 97,112,101, 0,116,101,120, 95,109,111,100,101, 0,107,105,110,107, 0,107,105,110,107, 95, 97,120,105, +115, 0,122,100,105,114, 0,102, 95,115,116,114,101,110,103,116,104, 0,102, 95,100, 97,109,112, 0,102, 95,102,108,111,119, 0, +102, 95,115,105,122,101, 0,102, 95,112,111,119,101,114, 0,109, 97,120,100,105,115,116, 0,109,105,110,100,105,115,116, 0,102, + 95,112,111,119,101,114, 95,114, 0,109, 97,120,114, 97,100, 0,109,105,110,114, 97,100, 0,112,100,101,102, 95,100, 97,109,112, + 0,112,100,101,102, 95,114,100, 97,109,112, 0,112,100,101,102, 95,112,101,114,109, 0,112,100,101,102, 95,102,114,105, 99,116, + 0,112,100,101,102, 95,114,102,114,105, 99,116, 0, 97, 98,115,111,114,112,116,105,111,110, 0,112,100,101,102, 95,115, 98,100, + 97,109,112, 0,112,100,101,102, 95,115, 98,105,102,116, 0,112,100,101,102, 95,115, 98,111,102,116, 0, 99,108,117,109,112, 95, +102, 97, 99, 0, 99,108,117,109,112, 95,112,111,119, 0,107,105,110,107, 95,102,114,101,113, 0,107,105,110,107, 95,115,104, 97, +112,101, 0,107,105,110,107, 95, 97,109,112, 0,102,114,101,101, 95,101,110,100, 0,116,101,120, 95,110, 97, 98,108, 97, 0, 42, +114,110,103, 0,102, 95,110,111,105,115,101, 0,119,101,105,103,104,116, 91, 49, 51, 93, 0,103,108,111, 98, 97,108, 95,103,114, + 97,118,105,116,121, 0,114,116, 91, 51, 93, 0,102,114, 97,109,101, 0,116,111,116,112,111,105,110,116, 0,100, 97,116, 97, 95, +116,121,112,101,115, 0, 42,105,110,100,101,120, 95, 97,114,114, 97,121, 0, 42,100, 97,116, 97, 91, 56, 93, 0, 42, 99,117,114, + 91, 56, 93, 0,115,116,101,112, 0,115,105,109,102,114, 97,109,101, 0,115,116, 97,114,116,102,114, 97,109,101, 0,101,110,100, +102,114, 97,109,101, 0,101,100,105,116,102,114, 97,109,101, 0,108, 97,115,116, 95,101,120, 97, 99,116, 0,110, 97,109,101, 91, + 54, 52, 93, 0,112,114,101,118, 95,110, 97,109,101, 91, 54, 52, 93, 0,105,110,102,111, 91, 54, 52, 93, 0,112, 97,116,104, 91, + 50, 52, 48, 93, 0,109,101,109, 95, 99, 97, 99,104,101, 0, 42,101,100,105,116, 0, 40, 42,102,114,101,101, 95,101,100,105,116, + 41, 40, 41, 0,108,105,110, 83,116,105,102,102, 0, 97,110,103, 83,116,105,102,102, 0,118,111,108,117,109,101, 0,118,105,116, +101,114, 97,116,105,111,110,115, 0,112,105,116,101,114, 97,116,105,111,110,115, 0,100,105,116,101,114, 97,116,105,111,110,115, + 0, 99,105,116,101,114, 97,116,105,111,110,115, 0,107, 83, 82, 72, 82, 95, 67, 76, 0,107, 83, 75, 72, 82, 95, 67, 76, 0,107, + 83, 83, 72, 82, 95, 67, 76, 0,107, 83, 82, 95, 83, 80, 76, 84, 95, 67, 76, 0,107, 83, 75, 95, 83, 80, 76, 84, 95, 67, 76, 0, +107, 83, 83, 95, 83, 80, 76, 84, 95, 67, 76, 0,107, 86, 67, 70, 0,107, 68, 80, 0,107, 68, 71, 0,107, 76, 70, 0,107, 80, 82, + 0,107, 86, 67, 0,107, 68, 70, 0,107, 77, 84, 0,107, 67, 72, 82, 0,107, 75, 72, 82, 0,107, 83, 72, 82, 0,107, 65, 72, 82, + 0, 99,111,108,108,105,115,105,111,110,102,108, 97,103,115, 0,110,117,109, 99,108,117,115,116,101,114,105,116,101,114, 97,116, +105,111,110,115, 0,119,101,108,100,105,110,103, 0,116,111,116,115,112,114,105,110,103, 0, 42, 98,112,111,105,110,116, 0, 42, + 98,115,112,114,105,110,103, 0,109,115,103, 95,108,111, 99,107, 0,109,115,103, 95,118, 97,108,117,101, 0,110,111,100,101,109, + 97,115,115, 0,110, 97,109,101,100, 86, 71, 95, 77, 97,115,115, 91, 51, 50, 93, 0,103,114, 97,118, 0,109,101,100,105, 97,102, +114,105, 99,116, 0,114,107,108,105,109,105,116, 0,112,104,121,115,105, 99,115, 95,115,112,101,101,100, 0,103,111, 97,108,115, +112,114,105,110,103, 0,103,111, 97,108,102,114,105, 99,116, 0,109,105,110,103,111, 97,108, 0,109, 97,120,103,111, 97,108, 0, +100,101,102,103,111, 97,108, 0,118,101,114,116,103,114,111,117,112, 0,110, 97,109,101,100, 86, 71, 95, 83,111,102,116,103,111, + 97,108, 91, 51, 50, 93, 0,102,117,122,122,121,110,101,115,115, 0,105,110,115,112,114,105,110,103, 0,105,110,102,114,105, 99, +116, 0,110, 97,109,101,100, 86, 71, 95, 83,112,114,105,110,103, 95, 75, 91, 51, 50, 93, 0,101,102,114, 97, 0,105,110,116,101, +114,118, 97,108, 0,108,111, 99, 97,108, 0,115,111,108,118,101,114,102,108, 97,103,115, 0, 42, 42,107,101,121,115, 0,116,111, +116,112,111,105,110,116,107,101,121, 0,115,101, 99,111,110,100,115,112,114,105,110,103, 0, 99,111,108, 98, 97,108,108, 0, 98, + 97,108,108,100, 97,109,112, 0, 98, 97,108,108,115,116,105,102,102, 0,115, 98, 99, 95,109,111,100,101, 0, 97,101,114,111,101, +100,103,101, 0,109,105,110,108,111,111,112,115, 0,109, 97,120,108,111,111,112,115, 0, 99,104,111,107,101, 0,115,111,108,118, +101,114, 95, 73, 68, 0,112,108, 97,115,116,105, 99, 0,115,112,114,105,110,103,112,114,101,108,111, 97,100, 0, 42,115, 99,114, + 97,116, 99,104, 0,115,104,101, 97,114,115,116,105,102,102, 0,105,110,112,117,115,104, 0, 42,112,111,105,110,116, 99, 97, 99, +104,101, 0, 42,101,102,102,101, 99,116,111,114, 95,119,101,105,103,104,116,115, 0, 42,102,109,100, 0,115,104,111,119, 95, 97, +100,118, 97,110, 99,101,100,111,112,116,105,111,110,115, 0,114,101,115,111,108,117,116,105,111,110,120,121,122, 0,112,114,101, +118,105,101,119,114,101,115,120,121,122, 0,114,101, 97,108,115,105,122,101, 0,103,117,105, 68,105,115,112,108, 97,121, 77,111, +100,101, 0,114,101,110,100,101,114, 68,105,115,112,108, 97,121, 77,111,100,101, 0,118,105,115, 99,111,115,105,116,121, 86, 97, +108,117,101, 0,118,105,115, 99,111,115,105,116,121, 77,111,100,101, 0,118,105,115, 99,111,115,105,116,121, 69,120,112,111,110, +101,110,116, 0,103,114, 97,118,120, 0,103,114, 97,118,121, 0,103,114, 97,118,122, 0, 97,110,105,109, 83,116, 97,114,116, 0, + 97,110,105,109, 69,110,100, 0,103,115,116, 97,114, 0,109, 97,120, 82,101,102,105,110,101, 0,105,110,105, 86,101,108,120, 0, +105,110,105, 86,101,108,121, 0,105,110,105, 86,101,108,122, 0, 42,111,114,103, 77,101,115,104, 0, 42,109,101,115,104, 83,117, +114,102, 97, 99,101, 0, 42,109,101,115,104, 66, 66, 0,115,117,114,102,100, 97,116, 97, 80, 97,116,104, 91, 50, 52, 48, 93, 0, + 98, 98, 83,116, 97,114,116, 91, 51, 93, 0, 98, 98, 83,105,122,101, 91, 51, 93, 0,116,121,112,101, 70,108, 97,103,115, 0,100, +111,109, 97,105,110, 78,111,118,101, 99,103,101,110, 0,118,111,108,117,109,101, 73,110,105,116, 84,121,112,101, 0,112, 97,114, +116, 83,108,105,112, 86, 97,108,117,101, 0,103,101,110,101,114, 97,116,101, 84,114, 97, 99,101,114,115, 0,103,101,110,101,114, + 97,116,101, 80, 97,114,116,105, 99,108,101,115, 0,115,117,114,102, 97, 99,101, 83,109,111,111,116,104,105,110,103, 0,115,117, +114,102, 97, 99,101, 83,117, 98,100,105,118,115, 0,112, 97,114,116,105, 99,108,101, 73,110,102, 83,105,122,101, 0,112, 97,114, +116,105, 99,108,101, 73,110,102, 65,108,112,104, 97, 0,102, 97,114, 70,105,101,108,100, 83,105,122,101, 0, 42,109,101,115,104, + 83,117,114,102, 78,111,114,109, 97,108,115, 0, 99,112,115, 84,105,109,101, 83,116, 97,114,116, 0, 99,112,115, 84,105,109,101, + 69,110,100, 0, 99,112,115, 81,117, 97,108,105,116,121, 0, 97,116,116,114, 97, 99,116,102,111,114, 99,101, 83,116,114,101,110, +103,116,104, 0, 97,116,116,114, 97, 99,116,102,111,114, 99,101, 82, 97,100,105,117,115, 0,118,101,108,111, 99,105,116,121,102, +111,114, 99,101, 83,116,114,101,110,103,116,104, 0,118,101,108,111, 99,105,116,121,102,111,114, 99,101, 82, 97,100,105,117,115, + 0,108, 97,115,116,103,111,111,100,102,114, 97,109,101, 0,109,105,115,116,121,112,101, 0,104,111,114,114, 0,104,111,114,103, + 0,104,111,114, 98, 0,104,111,114,107, 0,122,101,110,114, 0,122,101,110,103, 0,122,101,110, 98, 0,122,101,110,107, 0, 97, +109, 98,107, 0,102, 97,115,116, 99,111,108, 0,101,120,112,111,115,117,114,101, 0,101,120,112, 0,114, 97,110,103,101, 0,108, +105,110,102, 97, 99, 0,108,111,103,102, 97, 99, 0,103,114, 97,118,105,116,121, 0, 97, 99,116,105,118,105,116,121, 66,111,120, + 82, 97,100,105,117,115, 0,115,107,121,116,121,112,101, 0,111, 99, 99,108,117,115,105,111,110, 82,101,115, 0,112,104,121,115, +105, 99,115, 69,110,103,105,110,101, 0,116,105, 99,114, 97,116,101, 0,109, 97,120,108,111,103,105, 99,115,116,101,112, 0,112, +104,121,115,117, 98,115,116,101,112, 0,109, 97,120,112,104,121,115,116,101,112, 0,109,105,115,105, 0,109,105,115,116,115,116, + 97, 0,109,105,115,116,100,105,115,116, 0,109,105,115,116,104,105, 0,115,116, 97,114,114, 0,115,116, 97,114,103, 0,115,116, + 97,114, 98, 0,115,116, 97,114,107, 0,115,116, 97,114,115,105,122,101, 0,115,116, 97,114,109,105,110,100,105,115,116, 0,115, +116, 97,114,100,105,115,116, 0,115,116, 97,114, 99,111,108,110,111,105,115,101, 0,100,111,102,115,116, 97, 0,100,111,102,101, +110,100, 0,100,111,102,109,105,110, 0,100,111,102,109, 97,120, 0, 97,111,100,105,115,116, 0, 97,111,100,105,115,116,102, 97, + 99, 0, 97,111,101,110,101,114,103,121, 0, 97,111, 98,105, 97,115, 0, 97,111,109,111,100,101, 0, 97,111,115, 97,109,112, 0, + 97,111,109,105,120, 0, 97,111, 99,111,108,111,114, 0, 97,111, 95, 97,100, 97,112,116, 95,116,104,114,101,115,104, 0, 97,111, + 95, 97,100, 97,112,116, 95,115,112,101,101,100, 95,102, 97, 99, 0, 97,111, 95, 97,112,112,114,111,120, 95,101,114,114,111,114, + 0, 97,111, 95, 97,112,112,114,111,120, 95, 99,111,114,114,101, 99,116,105,111,110, 0, 97,111, 95,115, 97,109,112, 95,109,101, +116,104,111,100, 0, 97,111, 95,103, 97,116,104,101,114, 95,109,101,116,104,111,100, 0, 97,111, 95, 97,112,112,114,111,120, 95, +112, 97,115,115,101,115, 0, 42, 97,111,115,112,104,101,114,101, 0, 42, 97,111,116, 97, 98,108,101,115, 0,115,101,108, 99,111, +108, 0,115,120, 0,115,121, 0, 42,108,112, 70,111,114,109, 97,116, 0, 42,108,112, 80, 97,114,109,115, 0, 99, 98, 70,111,114, +109, 97,116, 0, 99, 98, 80, 97,114,109,115, 0,102, 99, 99, 84,121,112,101, 0,102, 99, 99, 72, 97,110,100,108,101,114, 0,100, +119, 75,101,121, 70,114, 97,109,101, 69,118,101,114,121, 0,100,119, 81,117, 97,108,105,116,121, 0,100,119, 66,121,116,101,115, + 80,101,114, 83,101, 99,111,110,100, 0,100,119, 70,108, 97,103,115, 0,100,119, 73,110,116,101,114,108,101, 97,118,101, 69,118, +101,114,121, 0, 97,118,105, 99,111,100,101, 99,110, 97,109,101, 91, 49, 50, 56, 93, 0, 42, 99,100, 80, 97,114,109,115, 0, 42, +112, 97,100, 0, 99,100, 83,105,122,101, 0,113,116, 99,111,100,101, 99,110, 97,109,101, 91, 49, 50, 56, 93, 0, 99,111,100,101, + 99, 0, 97,117,100,105,111, 95, 99,111,100,101, 99, 0,118,105,100,101,111, 95, 98,105,116,114, 97,116,101, 0, 97,117,100,105, +111, 95, 98,105,116,114, 97,116,101, 0, 97,117,100,105,111, 95,109,105,120,114, 97,116,101, 0, 97,117,100,105,111, 95,118,111, +108,117,109,101, 0,103,111,112, 95,115,105,122,101, 0,114, 99, 95,109,105,110, 95,114, 97,116,101, 0,114, 99, 95,109, 97,120, + 95,114, 97,116,101, 0,114, 99, 95, 98,117,102,102,101,114, 95,115,105,122,101, 0,109,117,120, 95,112, 97, 99,107,101,116, 95, +115,105,122,101, 0,109,117,120, 95,114, 97,116,101, 0,109,105,120,114, 97,116,101, 0,109, 97,105,110, 0,115,112,101,101,100, + 95,111,102, 95,115,111,117,110,100, 0,100,111,112,112,108,101,114, 95,102, 97, 99,116,111,114, 0,100,105,115,116, 97,110, 99, +101, 95,109,111,100,101,108, 0, 42,109, 97,116, 95,111,118,101,114,114,105,100,101, 0, 42,108,105,103,104,116, 95,111,118,101, +114,114,105,100,101, 0,108, 97,121, 95,122,109, 97,115,107, 0,108, 97,121,102,108, 97,103, 0,112, 97,115,115,102,108, 97,103, + 0,112, 97,115,115, 95,120,111,114, 0, 42, 97,118,105, 99,111,100,101, 99,100, 97,116, 97, 0, 42,113,116, 99,111,100,101, 99, +100, 97,116, 97, 0,102,102, 99,111,100,101, 99,100, 97,116, 97, 0,112,115,102,114, 97, 0,112,101,102,114, 97, 0,105,109, 97, +103,101,115, 0,102,114, 97,109, 97,112,116,111, 0,116,104,114,101, 97,100,115, 0,102,114, 97,109,101,108,101,110, 0, 98,108, +117,114,102, 97, 99, 0,101,100,103,101, 82, 0,101,100,103,101, 71, 0,101,100,103,101, 66, 0,102,117,108,108,115, 99,114,101, +101,110, 0,120,112,108, 97,121, 0,121,112,108, 97,121, 0,102,114,101,113,112,108, 97,121, 0, 97,116,116,114,105, 98, 0,114, +116, 49, 0,114,116, 50, 0,115,116,101,114,101,111,109,111,100,101, 0,100,105,109,101,110,115,105,111,110,115,112,114,101,115, +101,116, 0,109, 97,120,105,109,115,105,122,101, 0,120,115, 99,104, 0,121,115, 99,104, 0,120,112, 97,114,116,115, 0,121,112, + 97,114,116,115, 0,119,105,110,112,111,115, 0,112,108, 97,110,101,115, 0,105,109,116,121,112,101, 0,115,117, 98,105,109,116, +121,112,101, 0,113,117, 97,108,105,116,121, 0,100,105,115,112,108, 97,121,109,111,100,101, 0,114,112, 97,100, 49, 0,114,112, + 97,100, 50, 0,115, 99,101,109,111,100,101, 0,114,101,110,100,101,114,101,114, 0,111, 99,114,101,115, 0, 97,108,112,104, 97, +109,111,100,101, 0,111,115, 97, 0,102,114,115, 95,115,101, 99, 0,101,100,103,101,105,110,116, 0,115, 97,102,101,116,121, 0, + 98,111,114,100,101,114, 0,100,105,115,112,114,101, 99,116, 0,108, 97,121,101,114,115, 0, 97, 99,116,108, 97,121, 0,120, 97, +115,112, 0,121, 97,115,112, 0,102,114,115, 95,115,101, 99, 95, 98, 97,115,101, 0,103, 97,117,115,115, 0, 99,111,108,111,114, + 95,109,103,116, 95,102,108, 97,103, 0,112,111,115,116,103, 97,109,109, 97, 0,112,111,115,116,104,117,101, 0,112,111,115,116, +115, 97,116, 0,100,105,116,104,101,114, 95,105,110,116,101,110,115,105,116,121, 0, 98, 97,107,101, 95,111,115, 97, 0, 98, 97, +107,101, 95,102,105,108,116,101,114, 0, 98, 97,107,101, 95,109,111,100,101, 0, 98, 97,107,101, 95,102,108, 97,103, 0, 98, 97, +107,101, 95,110,111,114,109, 97,108, 95,115,112, 97, 99,101, 0, 98, 97,107,101, 95,113,117, 97,100, 95,115,112,108,105,116, 0, + 98, 97,107,101, 95,109, 97,120,100,105,115,116, 0, 98, 97,107,101, 95, 98,105, 97,115,100,105,115,116, 0, 98, 97,107,101, 95, +112, 97,100, 0, 71, 73,113,117, 97,108,105,116,121, 0, 71, 73, 99, 97, 99,104,101, 0, 71, 73,109,101,116,104,111,100, 0, 71, + 73,112,104,111,116,111,110,115, 0, 71, 73,100,105,114,101, 99,116, 0, 89, 70, 95, 65, 65, 0, 89, 70,101,120,112,111,114,116, +120,109,108, 0, 89, 70, 95,110,111, 98,117,109,112, 0, 89, 70, 95, 99,108, 97,109,112,114,103, 98, 0,121,102,112, 97,100, 49, + 0, 71, 73,100,101,112,116,104, 0, 71, 73, 99, 97,117,115,100,101,112,116,104, 0, 71, 73,112,105,120,101,108,115,112,101,114, +115, 97,109,112,108,101, 0, 71, 73,112,104,111,116,111,110, 99,111,117,110,116, 0, 71, 73,109,105,120,112,104,111,116,111,110, +115, 0, 71, 73,112,104,111,116,111,110,114, 97,100,105,117,115, 0, 89, 70, 95,114, 97,121,100,101,112,116,104, 0, 89, 70, 95, + 65, 65,112, 97,115,115,101,115, 0, 89, 70, 95, 65, 65,115, 97,109,112,108,101,115, 0,121,102,112, 97,100, 50, 0, 71, 73,115, +104, 97,100,111,119,113,117, 97,108,105,116,121, 0, 71, 73,114,101,102,105,110,101,109,101,110,116, 0, 71, 73,112,111,119,101, +114, 0, 71, 73,105,110,100,105,114,112,111,119,101,114, 0, 89, 70, 95,103, 97,109,109, 97, 0, 89, 70, 95,101,120,112,111,115, +117,114,101, 0, 89, 70, 95,114, 97,121, 98,105, 97,115, 0, 89, 70, 95, 65, 65,112,105,120,101,108,115,105,122,101, 0, 89, 70, + 95, 65, 65,116,104,114,101,115,104,111,108,100, 0, 98, 97, 99,107, 98,117,102, 91, 49, 54, 48, 93, 0,112,105, 99, 91, 49, 54, + 48, 93, 0,115,116, 97,109,112, 0,115,116, 97,109,112, 95,102,111,110,116, 95,105,100, 0,115,116, 97,109,112, 95,117,100, 97, +116, 97, 91, 49, 54, 48, 93, 0,102,103, 95,115,116, 97,109,112, 91, 52, 93, 0, 98,103, 95,115,116, 97,109,112, 91, 52, 93, 0, +115,105,109,112,108,105,102,121, 95,115,117, 98,115,117,114,102, 0,115,105,109,112,108,105,102,121, 95,115,104, 97,100,111,119, +115, 97,109,112,108,101,115, 0,115,105,109,112,108,105,102,121, 95,112, 97,114,116,105, 99,108,101,115, 0,115,105,109,112,108, +105,102,121, 95, 97,111,115,115,115, 0, 99,105,110,101,111,110,119,104,105,116,101, 0, 99,105,110,101,111,110, 98,108, 97, 99, +107, 0, 99,105,110,101,111,110,103, 97,109,109, 97, 0,106,112, 50, 95,112,114,101,115,101,116, 0,106,112, 50, 95,100,101,112, +116,104, 0,114,112, 97,100, 51, 0,100,111,109,101,114,101,115, 0,100,111,109,101,109,111,100,101, 0,100,111,109,101, 97,110, +103,108,101, 0,100,111,109,101,116,105,108,116, 0,100,111,109,101,114,101,115, 98,117,102, 0, 42,100,111,109,101,116,101,120, +116, 0,101,110,103,105,110,101, 91, 51, 50, 93, 0,112, 97,114,116,105, 99,108,101, 95,112,101,114, 99, 0,115,117, 98,115,117, +114,102, 95,109, 97,120, 0,115,104, 97,100, 98,117,102,115, 97,109,112,108,101, 95,109, 97,120, 0, 97,111, 95,101,114,114,111, +114, 0,116,105,108,116, 0,114,101,115, 98,117,102, 0, 42,119, 97,114,112,116,101,120,116, 0, 99,111,108, 91, 51, 93, 0,109, + 97,116,109,111,100,101, 0,102,114, 97,109,105,110,103, 0,100,111,109,101, 0,115,116,101,114,101,111,102,108, 97,103, 0, 42, + 42, 98,114,117,115,104,101,115, 0, 97, 99,116,105,118,101, 95, 98,114,117,115,104, 95,105,110,100,101,120, 0, 98,114,117,115, +104, 95, 99,111,117,110,116, 0, 42,112, 97,105,110,116, 95, 99,117,114,115,111,114, 0,112, 97,105,110,116, 95, 99,117,114,115, +111,114, 95, 99,111,108, 91, 52, 93, 0,112, 97,105,110,116, 0,116,111,111,108, 0,115,101, 97,109, 95, 98,108,101,101,100, 0, +110,111,114,109, 97,108, 95, 97,110,103,108,101, 0, 42,112, 97,105,110,116, 99,117,114,115,111,114, 0,105,110,118,101,114,116, + 0,116,111,116,114,101,107,101,121, 0,116,111,116, 97,100,100,107,101,121, 0, 98,114,117,115,104,116,121,112,101, 0, 98,114, +117,115,104, 91, 55, 93, 0,101,109,105,116,116,101,114,100,105,115,116, 0,115,101,108,101, 99,116,109,111,100,101, 0,101,100, +105,116,116,121,112,101, 0,100,114, 97,119, 95,115,116,101,112, 0,102, 97,100,101, 95,102,114, 97,109,101,115, 0,110, 97,109, +101, 91, 51, 54, 93, 0,109, 97,116, 91, 51, 93, 91, 51, 93, 0,112,105,118,111,116, 91, 51, 93, 0,116, 97, 98,108,101,116, 95, +115,105,122,101, 0,116, 97, 98,108,101,116, 95,115,116,114,101,110,103,116,104, 0,103, 97,109,109, 97, 0,109,117,108, 0, 42, +118,112, 97,105,110,116, 95,112,114,101,118, 0, 42,119,112, 97,105,110,116, 95,112,114,101,118, 0, 42,118,112, 97,105,110,116, + 0, 42,119,112, 97,105,110,116, 0,118,103,114,111,117,112, 95,119,101,105,103,104,116, 0, 99,111,114,110,101,114,116,121,112, +101, 0,101,100,105,116, 98,117,116,102,108, 97,103, 0,106,111,105,110,116,114,105,108,105,109,105,116, 0,100,101,103,114, 0, +116,117,114,110, 0,101,120,116,114, 95,111,102,102,115, 0,100,111,117, 98,108,105,109,105,116, 0,110,111,114,109, 97,108,115, +105,122,101, 0, 97,117,116,111,109,101,114,103,101, 0,115,101,103,109,101,110,116,115, 0,114,105,110,103,115, 0,118,101,114, +116,105, 99,101,115, 0,117,110,119,114, 97,112,112,101,114, 0,117,118, 99, 97,108, 99, 95,114, 97,100,105,117,115, 0,117,118, + 99, 97,108, 99, 95, 99,117, 98,101,115,105,122,101, 0,117,118, 99, 97,108, 99, 95,109, 97,114,103,105,110, 0,117,118, 99, 97, +108, 99, 95,109, 97,112,100,105,114, 0,117,118, 99, 97,108, 99, 95,109, 97,112, 97,108,105,103,110, 0,117,118, 99, 97,108, 99, + 95,102,108, 97,103, 0,117,118, 95,102,108, 97,103, 0,117,118, 95,115,101,108,101, 99,116,109,111,100,101, 0,117,118, 95,112, + 97,100, 91, 50, 93, 0, 97,117,116,111,105,107, 95, 99,104, 97,105,110,108,101,110, 0,105,109, 97,112, 97,105,110,116, 0,112, + 97,114,116,105, 99,108,101, 0,112,114,111,112,111,114,116,105,111,110, 97,108, 95,115,105,122,101, 0,115,101,108,101, 99,116, + 95,116,104,114,101,115,104, 0, 99,108,101, 97,110, 95,116,104,114,101,115,104, 0, 97,117,116,111,107,101,121, 95,109,111,100, +101, 0, 97,117,116,111,107,101,121, 95,102,108, 97,103, 0,114,101,116,111,112,111, 95,109,111,100,101, 0,114,101,116,111,112, +111, 95,112, 97,105,110,116, 95,116,111,111,108, 0,108,105,110,101, 95,100,105,118, 0,101,108,108,105,112,115,101, 95,100,105, +118, 0,114,101,116,111,112,111, 95,104,111,116,115,112,111,116, 0,109,117,108,116,105,114,101,115, 95,115,117, 98,100,105,118, + 95,116,121,112,101, 0,115,107,103,101,110, 95,114,101,115,111,108,117,116,105,111,110, 0,115,107,103,101,110, 95,116,104,114, +101,115,104,111,108,100, 95,105,110,116,101,114,110, 97,108, 0,115,107,103,101,110, 95,116,104,114,101,115,104,111,108,100, 95, +101,120,116,101,114,110, 97,108, 0,115,107,103,101,110, 95,108,101,110,103,116,104, 95,114, 97,116,105,111, 0,115,107,103,101, +110, 95,108,101,110,103,116,104, 95,108,105,109,105,116, 0,115,107,103,101,110, 95, 97,110,103,108,101, 95,108,105,109,105,116, + 0,115,107,103,101,110, 95, 99,111,114,114,101,108, 97,116,105,111,110, 95,108,105,109,105,116, 0,115,107,103,101,110, 95,115, +121,109,109,101,116,114,121, 95,108,105,109,105,116, 0,115,107,103,101,110, 95,114,101,116, 97,114,103,101,116, 95, 97,110,103, +108,101, 95,119,101,105,103,104,116, 0,115,107,103,101,110, 95,114,101,116, 97,114,103,101,116, 95,108,101,110,103,116,104, 95, +119,101,105,103,104,116, 0,115,107,103,101,110, 95,114,101,116, 97,114,103,101,116, 95,100,105,115,116, 97,110, 99,101, 95,119, +101,105,103,104,116, 0,115,107,103,101,110, 95,111,112,116,105,111,110,115, 0,115,107,103,101,110, 95,112,111,115,116,112,114, +111, 0,115,107,103,101,110, 95,112,111,115,116,112,114,111, 95,112, 97,115,115,101,115, 0,115,107,103,101,110, 95,115,117, 98, +100,105,118,105,115,105,111,110,115, 91, 51, 93, 0,115,107,103,101,110, 95,109,117,108,116,105, 95,108,101,118,101,108, 0, 42, +115,107,103,101,110, 95,116,101,109,112,108, 97,116,101, 0, 98,111,110,101, 95,115,107,101,116, 99,104,105,110,103, 0, 98,111, +110,101, 95,115,107,101,116, 99,104,105,110,103, 95, 99,111,110,118,101,114,116, 0,115,107,103,101,110, 95,115,117, 98,100,105, +118,105,115,105,111,110, 95,110,117,109, 98,101,114, 0,115,107,103,101,110, 95,114,101,116, 97,114,103,101,116, 95,111,112,116, +105,111,110,115, 0,115,107,103,101,110, 95,114,101,116, 97,114,103,101,116, 95,114,111,108,108, 0,115,107,103,101,110, 95,115, +105,100,101, 95,115,116,114,105,110,103, 91, 56, 93, 0,115,107,103,101,110, 95,110,117,109, 95,115,116,114,105,110,103, 91, 56, + 93, 0,101,100,103,101, 95,109,111,100,101, 0,115,110, 97,112, 95,109,111,100,101, 0,115,110, 97,112, 95,102,108, 97,103, 0, +115,110, 97,112, 95,116, 97,114,103,101,116, 0,112,114,111,112,111,114,116,105,111,110, 97,108, 0,112,114,111,112, 95,109,111, +100,101, 0,116,111,116,111, 98,106, 0,116,111,116,108, 97,109,112, 0,116,111,116,111, 98,106,115,101,108, 0,116,111,116, 99, +117,114,118,101, 0,116,111,116,109,101,115,104, 0,116,111,116, 97,114,109, 97,116,117,114,101, 0,115, 99, 97,108,101, 95,108, +101,110,103,116,104, 0,115,121,115,116,101,109, 0,103,114, 97,118,105,116,121, 91, 51, 93, 0, 42, 99, 97,109,101,114, 97, 0, + 42,119,111,114,108,100, 0, 42,115,101,116, 0, 98, 97,115,101, 0, 42, 98, 97,115, 97, 99,116, 0, 42,111, 98,101,100,105,116, + 0, 99,117,114,115,111,114, 91, 51, 93, 0,116,119, 99,101,110,116, 91, 51, 93, 0,116,119,109,105,110, 91, 51, 93, 0,116,119, +109, 97,120, 91, 51, 93, 0, 42,101,100, 0, 42,116,111,111,108,115,101,116,116,105,110,103,115, 0, 42,115,116, 97,116,115, 0, + 97,117,100,105,111, 0,116,114, 97,110,115,102,111,114,109, 95,115,112, 97, 99,101,115, 0,115,111,117,110,100, 95,104, 97,110, +100,108,101,115, 0, 42,116,104,101, 68, 97,103, 0,100, 97,103,105,115,118, 97,108,105,100, 0,100, 97,103,102,108, 97,103,115, + 0,106,117,109,112,102,114, 97,109,101, 0,102,114, 97,109,101, 95,115,116,101,112, 0, 97, 99,116,105,118,101, 95,107,101,121, +105,110,103,115,101,116, 0,107,101,121,105,110,103,115,101,116,115, 0,103,109, 0,117,110,105,116, 0,112,104,121,115,105, 99, +115, 95,115,101,116,116,105,110,103,115, 0, 98,108,101,110,100, 0,119,105,110,109, 97,116, 91, 52, 93, 91, 52, 93, 0,118,105, +101,119,109, 97,116, 91, 52, 93, 91, 52, 93, 0,118,105,101,119,105,110,118, 91, 52, 93, 91, 52, 93, 0,112,101,114,115,109, 97, +116, 91, 52, 93, 91, 52, 93, 0,112,101,114,115,105,110,118, 91, 52, 93, 91, 52, 93, 0,118,105,101,119,109, 97,116,111, 98, 91, + 52, 93, 91, 52, 93, 0,112,101,114,115,109, 97,116,111, 98, 91, 52, 93, 91, 52, 93, 0,116,119,109, 97,116, 91, 52, 93, 91, 52, + 93, 0,118,105,101,119,113,117, 97,116, 91, 52, 93, 0,122,102, 97, 99, 0, 99, 97,109,100,120, 0, 99, 97,109,100,121, 0,112, +105,120,115,105,122,101, 0, 99, 97,109,122,111,111,109, 0,118,105,101,119, 98,117,116, 0,114,102,108, 97,103, 0,118,105,101, +119,108,111, 99,107, 0,112,101,114,115,112, 0,118,105,101,119, 0, 99,108,105,112, 91, 54, 93, 91, 52, 93, 0, 42, 99,108,105, +112, 98, 98, 0, 42,108,111, 99, 97,108,118,100, 0, 42,114,105, 0, 42,114,101,116,111,112,111, 95,118,105,101,119, 95,100, 97, +116, 97, 0, 42,100,101,112,116,104,115, 0, 42,115,109,115, 0, 42,115,109,111,111,116,104, 95,116,105,109,101,114, 0,108,118, +105,101,119,113,117, 97,116, 91, 52, 93, 0,108,112,101,114,115,112, 0,108,118,105,101,119, 0,114,101,103,105,111,110, 98, 97, +115,101, 0,115,112, 97, 99,101,116,121,112,101, 0, 98,108,111, 99,107,115, 99, 97,108,101, 0, 98,108,111, 99,107,104, 97,110, +100,108,101,114, 91, 56, 93, 0,108, 97,121, 95,117,115,101,100, 0, 42,111, 98, 95, 99,101,110,116,114,101, 0, 42, 98,103,112, +105, 99, 0,111, 98, 95, 99,101,110,116,114,101, 95, 98,111,110,101, 91, 51, 50, 93, 0,108, 97,121, 97, 99,116, 0,100,114, 97, +119,116,121,112,101, 0,115, 99,101,110,101,108,111, 99,107, 0, 97,114,111,117,110,100, 0,112,105,118,111,116, 95,108, 97,115, 116, 0,103,114,105,100, 0,103,114,105,100,118,105,101,119, 0,112, 97,100,102, 0,110,101, 97,114, 0,102, 97,114, 0,103,114, 105,100,108,105,110,101,115, 0,103,114,105,100,102,108, 97,103, 0,103,114,105,100,115,117, 98,100,105,118, 0,109,111,100,101, 115,101,108,101, 99,116, 0,107,101,121,102,108, 97,103,115, 0,116,119,116,121,112,101, 0,116,119,109,111,100,101, 0,116,119, @@ -1975,374 +2016,379 @@ char datatoc_B_blend[]= { 91, 51, 50, 93, 0,118, 97,108,117,101, 91, 51, 50, 93, 0,109, 97,120,118, 97,108,117,101, 91, 51, 50, 93, 0,100,101,108, 97, 121, 0,100,117,114, 97,116,105,111,110, 0,109, 97,116,101,114,105, 97,108, 78, 97,109,101, 91, 51, 50, 93, 0,100, 97,109,112, 116,105,109,101,114, 0,112,114,111,112,110, 97,109,101, 91, 51, 50, 93, 0,109, 97,116,110, 97,109,101, 91, 51, 50, 93, 0, 97, -120,105,115,102,108, 97,103, 0, 42,102,114,111,109, 79, 98,106,101, 99,116, 0,115,117, 98,106,101, 99,116, 91, 51, 50, 93, 0, - 98,111,100,121, 91, 51, 50, 93, 0,111,116,121,112,101, 0,112,117,108,115,101, 0,102,114,101,113, 0,116,111,116,108,105,110, -107,115, 0, 42, 42,108,105,110,107,115, 0,116, 97,112, 0,106,111,121,105,110,100,101,120, 0, 97,120,105,115, 95,115,105,110, -103,108,101, 0, 97,120,105,115,102, 0, 98,117,116,116,111,110, 0,104, 97,116, 0,104, 97,116,102, 0,112,114,101, 99,105,115, -105,111,110, 0,115,116,114, 91, 49, 50, 56, 93, 0,109,111,100,117,108,101, 91, 54, 52, 93, 0, 42,109,121,110,101,119, 0,105, -110,112,117,116,115, 0,116,111,116,115,108,105,110,107,115, 0, 42, 42,115,108,105,110,107,115, 0,118, 97,108,111, 0,115,116, - 97,116,101, 95,109, 97,115,107, 0, 42, 97, 99,116, 0,102,114, 97,109,101, 80,114,111,112, 91, 51, 50, 93, 0, 98,108,101,110, -100,105,110, 0,112,114,105,111,114,105,116,121, 0,101,110,100, 95,114,101,115,101,116, 0,115,116,114,105,100,101, 97,120,105, -115, 0,115,116,114,105,100,101,108,101,110,103,116,104, 0,115,110,100,110,114, 0,112, 97,100, 49, 91, 50, 93, 0,112,105,116, - 99,104, 0,115,111,117,110,100, 51, 68, 0,109, 97,107,101, 99,111,112,121, 0, 99,111,112,121,109, 97,100,101, 0,112, 97,100, - 50, 91, 49, 93, 0, 42,109,101, 0,108,105,110, 86,101,108,111, 99,105,116,121, 91, 51, 93, 0, 97,110,103, 86,101,108,111, 99, -105,116,121, 91, 51, 93, 0,108,111, 99, 97,108,102,108, 97,103, 0,100,121,110, 95,111,112,101,114, 97,116,105,111,110, 0,102, -111,114, 99,101,108,111, 99, 91, 51, 93, 0,102,111,114, 99,101,114,111,116, 91, 51, 93, 0,108,105,110,101, 97,114,118,101,108, -111, 99,105,116,121, 91, 51, 93, 0, 97,110,103,117,108, 97,114,118,101,108,111, 99,105,116,121, 91, 51, 93, 0, 42,114,101,102, -101,114,101,110, 99,101, 0, 98,117,116,115,116, 97, 0, 98,117,116,101,110,100, 0,109,105,110, 0,109, 97,120, 0,118,105,115, -105,102, 97, 99, 0,114,111,116,100, 97,109,112, 0,109,105,110,108,111, 99, 91, 51, 93, 0,109, 97,120,108,111, 99, 91, 51, 93, - 0,109,105,110,114,111,116, 91, 51, 93, 0,109, 97,120,114,111,116, 91, 51, 93, 0,109, 97,116,112,114,111,112, 91, 51, 50, 93, - 0,100,105,115,116,114,105, 98,117,116,105,111,110, 0,105,110,116, 95, 97,114,103, 95, 49, 0,105,110,116, 95, 97,114,103, 95, - 50, 0,102,108,111, 97,116, 95, 97,114,103, 95, 49, 0,102,108,111, 97,116, 95, 97,114,103, 95, 50, 0,116,111, 80,114,111,112, - 78, 97,109,101, 91, 51, 50, 93, 0, 42,116,111, 79, 98,106,101, 99,116, 0, 98,111,100,121, 84,121,112,101, 0,102,105,108,101, -110, 97,109,101, 91, 54, 52, 93, 0,108,111, 97,100, 97,110,105,110, 97,109,101, 91, 54, 52, 93, 0,105,110,116, 95, 97,114,103, - 0,102,108,111, 97,116, 95, 97,114,103, 0,103,111, 0, 97, 99, 99,101,108,108,101,114, 97,116,105,111,110, 0,109, 97,120,115, -112,101,101,100, 0,109, 97,120,114,111,116,115,112,101,101,100, 0,109, 97,120,116,105,108,116,115,112,101,101,100, 0,116,105, -108,116,100, 97,109,112, 0,115,112,101,101,100,100, 97,109,112, 0, 42,115,111,117,114, 99,101, 0,102,114, 97,109,101,115,107, -105,112, 0,109,117,116,101, 0, 99,104, 97,110,103,101,100, 0,109,105,110, 95,103, 97,105,110, 0,109, 97,120, 95,103, 97,105, -110, 0,114,101,102,101,114,101,110, 99,101, 95,100,105,115,116, 97,110, 99,101, 0,109, 97,120, 95,100,105,115,116, 97,110, 99, -101, 0,114,111,108,108,111,102,102, 95,102, 97, 99,116,111,114, 0, 99,111,110,101, 95,105,110,110,101,114, 95, 97,110,103,108, -101, 0, 99,111,110,101, 95,111,117,116,101,114, 95, 97,110,103,108,101, 0, 99,111,110,101, 95,111,117,116,101,114, 95,103, 97, -105,110, 0, 42,110,101,119,112, 97, 99,107,101,100,102,105,108,101, 0, 97,116,116,101,110,117, 97,116,105,111,110, 0,100,105, -115,116, 97,110, 99,101, 0, 42, 99, 97, 99,104,101, 0, 42, 97,114,101, 97, 0, 42,108, 97,109,112,114,101,110, 0,103,111, 98, -106,101, 99,116, 0,100,117,112,108,105, 95,111,102,115, 91, 51, 93, 0, 99,104,105,108,100, 98, 97,115,101, 0,114,111,108,108, - 0,104,101, 97,100, 91, 51, 93, 0,116, 97,105,108, 91, 51, 93, 0, 98,111,110,101, 95,109, 97,116, 91, 51, 93, 91, 51, 93, 0, - 97,114,109, 95,104,101, 97,100, 91, 51, 93, 0, 97,114,109, 95,116, 97,105,108, 91, 51, 93, 0, 97,114,109, 95,109, 97,116, 91, - 52, 93, 91, 52, 93, 0,120,119,105,100,116,104, 0,122,119,105,100,116,104, 0,101, 97,115,101, 49, 0,101, 97,115,101, 50, 0, -114, 97,100, 95,104,101, 97,100, 0,114, 97,100, 95,116, 97,105,108, 0, 98,111,110,101, 98, 97,115,101, 0, 99,104, 97,105,110, - 98, 97,115,101, 0, 42,101,100, 98,111, 0, 42,115,107,101,116, 99,104, 0,108, 97,121,101,114, 95,112,114,111,116,101, 99,116, -101,100, 0,103,104,111,115,116,101,112, 0,103,104,111,115,116,115,105,122,101, 0,103,104,111,115,116,116,121,112,101, 0,112, - 97,116,104,115,105,122,101, 0,103,104,111,115,116,115,102, 0,103,104,111,115,116,101,102, 0,112, 97,116,104,115,102, 0,112, - 97,116,104,101,102, 0,112, 97,116,104, 98, 99, 0,112, 97,116,104, 97, 99, 0, 42,112,111,105,110,116,115, 0,115,116, 97,114, -116, 95,102,114, 97,109,101, 0,101,110,100, 95,102,114, 97,109,101, 0, 42,112,114,111,112, 0, 99,111,110,115,116,102,108, 97, -103, 0,105,107,102,108, 97,103, 0,115,101,108,101, 99,116,102,108, 97,103, 0, 97,103,114,112, 95,105,110,100,101,120, 0, 42, - 98,111,110,101, 0, 42, 99,104,105,108,100, 0,105,107,116,114,101,101, 0, 42, 98, 95, 98,111,110,101, 95,109, 97,116,115, 0, - 42,100,117, 97,108, 95,113,117, 97,116, 0, 42, 98, 95, 98,111,110,101, 95,100,117, 97,108, 95,113,117, 97,116,115, 0,101,117, -108, 91, 51, 93, 0,114,111,116,109,111,100,101, 0, 99,104, 97,110, 95,109, 97,116, 91, 52, 93, 91, 52, 93, 0,112,111,115,101, - 95,109, 97,116, 91, 52, 93, 91, 52, 93, 0,112,111,115,101, 95,104,101, 97,100, 91, 51, 93, 0,112,111,115,101, 95,116, 97,105, -108, 91, 51, 93, 0,108,105,109,105,116,109,105,110, 91, 51, 93, 0,108,105,109,105,116,109, 97,120, 91, 51, 93, 0,115,116,105, -102,102,110,101,115,115, 91, 51, 93, 0,105,107,115,116,114,101,116, 99,104, 0, 42, 99,117,115,116,111,109, 0, 99,104, 97,110, - 98, 97,115,101, 0,112,114,111,120,121, 95,108, 97,121,101,114, 0,115,116,114,105,100,101, 95,111,102,102,115,101,116, 91, 51, - 93, 0, 99,121, 99,108,105, 99, 95,111,102,102,115,101,116, 91, 51, 93, 0, 97,103,114,111,117,112,115, 0, 97, 99,116,105,118, -101, 95,103,114,111,117,112, 0, 99,104, 97,110,110,101,108,115, 0, 99,117,115,116,111,109, 67,111,108, 0, 99,115, 0, 99,117, -114,118,101,115, 0,103,114,111,117,112,115, 0, 97, 99,116,105,118,101, 95,109, 97,114,107,101,114, 0,102,105,108,116,101,114, -102,108, 97,103, 0, 97,100,115, 0, 97, 99,116,110,114, 0, 97, 99,116,119,105,100,116,104, 0,116,105,109,101,115,108,105,100, -101, 0, 42,103,114,112, 0,116,101,109,112, 0,110, 97,109,101, 91, 51, 48, 93, 0,111,119,110,115,112, 97, 99,101, 0,116, 97, -114,115,112, 97, 99,101, 0,101,110,102,111,114, 99,101, 0,104,101, 97,100,116, 97,105,108, 0, 42,116, 97,114, 0,109, 97,116, -114,105,120, 91, 52, 93, 91, 52, 93, 0,115,112, 97, 99,101, 0,114,111,116, 79,114,100,101,114, 0,116, 97,114,110,117,109, 0, -116, 97,114,103,101,116,115, 0,105,116,101,114, 97,116,105,111,110,115, 0,114,111,111,116, 98,111,110,101, 0,109, 97,120, 95, -114,111,111,116, 98,111,110,101, 0, 42,112,111,108,101,116, 97,114, 0,112,111,108,101,115,117, 98,116, 97,114,103,101,116, 91, - 51, 50, 93, 0,112,111,108,101, 97,110,103,108,101, 0,111,114,105,101,110,116,119,101,105,103,104,116, 0,103,114, 97, 98,116, - 97,114,103,101,116, 91, 51, 93, 0,114,101,115,101,114,118,101,100, 49, 0,114,101,115,101,114,118,101,100, 50, 0,109,105,110, -109, 97,120,102,108, 97,103, 0,115,116,117, 99,107, 0, 99, 97, 99,104,101, 91, 51, 93, 0,108,111, 99,107,102,108, 97,103, 0, -102,111,108,108,111,119,102,108, 97,103, 0,118,111,108,109,111,100,101, 0,112,108, 97,110,101, 0,111,114,103,108,101,110,103, -116,104, 0, 98,117,108,103,101, 0,112,105,118, 88, 0,112,105,118, 89, 0,112,105,118, 90, 0, 97,120, 88, 0, 97,120, 89, 0, - 97,120, 90, 0,109,105,110, 76,105,109,105,116, 91, 54, 93, 0,109, 97,120, 76,105,109,105,116, 91, 54, 93, 0,101,120,116,114, - 97, 70,122, 0,105,110,118,109, 97,116, 91, 52, 93, 91, 52, 93, 0,102,114,111,109, 0,116,111, 0,109, 97,112, 91, 51, 93, 0, -101,120,112,111, 0,102,114,111,109, 95,109,105,110, 91, 51, 93, 0,102,114,111,109, 95,109, 97,120, 91, 51, 93, 0,116,111, 95, -109,105,110, 91, 51, 93, 0,116,111, 95,109, 97,120, 91, 51, 93, 0,122,109,105,110, 0,122,109, 97,120, 0,112, 97,100, 91, 57, - 93, 0, 99,104, 97,110,110,101,108, 91, 51, 50, 93, 0,110,111, 95,114,111,116, 95, 97,120,105,115, 0,115,116,114,105,100,101, - 95, 97,120,105,115, 0, 99,117,114,109,111,100, 0, 97, 99,116,115,116, 97,114,116, 0, 97, 99,116,101,110,100, 0, 97, 99,116, -111,102,102,115, 0,115,116,114,105,100,101,108,101,110, 0,115, 99, 97,108,101, 0, 98,108,101,110,100,111,117,116, 0,115,116, -114,105,100,101, 99,104, 97,110,110,101,108, 91, 51, 50, 93, 0,111,102,102,115, 95, 98,111,110,101, 91, 51, 50, 93, 0,104, 97, -115,105,110,112,117,116, 0,104, 97,115,111,117,116,112,117,116, 0,100, 97,116, 97,116,121,112,101, 0,115,111, 99,107,101,116, -116,121,112,101, 0, 42,110,101,119, 95,115,111, 99,107, 0,110,115, 0,108,105,109,105,116, 0,115,116, 97, 99,107, 95,105,110, -100,101,120, 0,105,110,116,101,114,110, 0,115,116, 97, 99,107, 95,105,110,100,101,120, 95,101,120,116, 0,108,111, 99,120, 0, -108,111, 99,121, 0,111,119,110, 95,105,110,100,101,120, 0,116,111, 95,105,110,100,101,120, 0, 42,116,111,115,111, 99,107, 0, - 42,108,105,110,107, 0, 42,110,101,119, 95,110,111,100,101, 0,117,115,101,114,110, 97,109,101, 91, 51, 50, 93, 0,108, 97,115, -116,121, 0,111,117,116,112,117,116,115, 0, 42,115,116,111,114, 97,103,101, 0,109,105,110,105,119,105,100,116,104, 0, 99,117, -115,116,111,109, 49, 0, 99,117,115,116,111,109, 50, 0, 99,117,115,116,111,109, 51, 0, 99,117,115,116,111,109, 52, 0,110,101, -101,100, 95,101,120,101, 99, 0,101,120,101, 99, 0, 42,116,104,114,101, 97,100,100, 97,116, 97, 0,116,111,116,114, 0, 98,117, -116,114, 0,112,114,118,114, 0, 42,116,121,112,101,105,110,102,111, 0, 42,102,114,111,109,110,111,100,101, 0, 42,116,111,110, -111,100,101, 0, 42,102,114,111,109,115,111, 99,107, 0,110,111,100,101,115, 0,108,105,110,107,115, 0, 42,115,116, 97, 99,107, - 0, 42,116,104,114,101, 97,100,115,116, 97, 99,107, 0,105,110,105,116, 0,115,116, 97, 99,107,115,105,122,101, 0, 99,117,114, - 95,105,110,100,101,120, 0, 97,108,108,116,121,112,101,115, 0, 42,111,119,110,116,121,112,101, 0, 42,115,101,108,105,110, 0, - 42,115,101,108,111,117,116, 0, 40, 42,116,105,109,101, 99,117,114,115,111,114, 41, 40, 41, 0, 40, 42,115,116, 97,116,115, 95, -100,114, 97,119, 41, 40, 41, 0, 40, 42,116,101,115,116, 95, 98,114,101, 97,107, 41, 40, 41, 0, 42,116, 98,104, 0, 42,116, 99, -104, 0, 42,115,100,104, 0, 99,121, 99,108,105, 99, 0,109,111,118,105,101, 0,115, 97,109,112,108,101,115, 0,109,105,110,115, -112,101,101,100, 0,112,101,114, 99,101,110,116,120, 0,112,101,114, 99,101,110,116,121, 0, 98,111,107,101,104, 0, 99,117,114, -118,101,100, 0,105,109, 97,103,101, 95,105,110, 95,119,105,100,116,104, 0,105,109, 97,103,101, 95,105,110, 95,104,101,105,103, -104,116, 0, 99,101,110,116,101,114, 95,120, 0, 99,101,110,116,101,114, 95,121, 0,115,112,105,110, 0,105,116,101,114, 0,119, -114, 97,112, 0,115,105,103,109, 97, 95, 99,111,108,111,114, 0,115,105,103,109, 97, 95,115,112, 97, 99,101, 0,104,117,101, 0, -115, 97,116, 0,116, 49, 0,116, 50, 0,116, 51, 0,102,115,116,114,101,110,103,116,104, 0,102, 97,108,112,104, 97, 0,107,101, -121, 91, 52, 93, 0,120, 49, 0,120, 50, 0,121, 49, 0,121, 50, 0, 99,111,108,110, 97,109,101, 91, 51, 50, 93, 0, 98,107,116, -121,112,101, 0,114,111,116, 97,116,105,111,110, 0,103, 97,109, 99,111, 0,110,111, 95,122, 98,117,102, 0,102,115,116,111,112, - 0,109, 97,120, 98,108,117,114, 0, 98,116,104,114,101,115,104, 0, 42,100,105, 99,116, 0, 42,110,111,100,101, 0, 97,110,103, -108,101, 95,111,102,115, 0, 99,111,108,109,111,100, 0,109,105,120, 0,116,104,114,101,115,104,111,108,100, 0,102, 97,100,101, - 0,109, 0, 99, 0,106,105,116, 0,112,114,111,106, 0,102,105,116, 0,115,104,111,114,116,121, 0,109,105,110,116, 97, 98,108, -101, 0,109, 97,120,116, 97, 98,108,101, 0,101,120,116, 95,105,110, 91, 50, 93, 0,101,120,116, 95,111,117,116, 91, 50, 93, 0, - 42, 99,117,114,118,101, 0, 42,116, 97, 98,108,101, 0, 42,112,114,101,109,117,108,116, 97, 98,108,101, 0, 99,117,114,114, 0, - 99,108,105,112,114, 0, 99,109, 91, 52, 93, 0, 98,108, 97, 99,107, 91, 51, 93, 0,119,104,105,116,101, 91, 51, 93, 0, 98,119, -109,117,108, 91, 51, 93, 0,115, 97,109,112,108,101, 91, 51, 93, 0,111,102,102,115,101,116, 91, 50, 93, 0, 99,108,111,110,101, - 0,105,110,110,101,114,114, 97,100,105,117,115, 0,115,109,111,111,116,104, 95,115,116,114,111,107,101, 95,114, 97,100,105,117, -115, 0,115,109,111,111,116,104, 95,115,116,114,111,107,101, 95,102, 97, 99,116,111,114, 0,114, 97,116,101, 0,114,103, 98, 91, - 51, 93, 0,115, 99,117,108,112,116, 95,116,111,111,108, 0, 97, 99,116,105,118,101, 95,114,110,100, 0, 97, 99,116,105,118,101, - 95, 99,108,111,110,101, 0, 97, 99,116,105,118,101, 95,109, 97,115,107, 0, 42,108, 97,121,101,114,115, 0,116,111,116,108, 97, -121,101,114, 0,109, 97,120,108, 97,121,101,114, 0,116,111,116,115,105,122,101, 0, 42,112,111,111,108, 0,101,100,105,116,102, -108, 97,103, 0,118,101,108, 91, 51, 93, 0,114,111,116, 91, 52, 93, 0, 97,118,101, 91, 51, 93, 0, 42,103,114,111,117,110,100, - 0,103,114, 97,118,105,116,121, 91, 51, 93, 0,119, 97,110,100,101,114, 91, 51, 93, 0,110,117,109, 0,112, 97,114,101,110,116, - 0,112, 97, 91, 52, 93, 0,119, 91, 52, 93, 0,102,117,118, 91, 52, 93, 0,102,111,102,102,115,101,116, 0,114, 97,110,100, 91, - 51, 93, 0,112,114,101,118, 95,115,116, 97,116,101, 0, 42,104, 97,105,114, 0, 42, 98,111,105,100, 0,100,105,101,116,105,109, -101, 0,110,117,109, 95,100,109, 99, 97, 99,104,101, 0, 97,108,105,118,101, 0,108,111,111,112, 0,104, 97,105,114, 95,105,110, -100,101,120, 0, 42, 98,111,105,100,115, 0,100,105,115,116,114, 0,112,104,121,115,116,121,112,101, 0, 97,118,101,109,111,100, -101, 0,114,101, 97, 99,116,101,118,101,110,116, 0,100,114, 97,119, 0,100,114, 97,119, 95, 97,115, 0,100,114, 97,119, 95,115, -105,122,101, 0, 99,104,105,108,100,116,121,112,101, 0,114,101,110, 95, 97,115, 0,114,101,110, 95,115,116,101,112, 0,104, 97, -105,114, 95,115,116,101,112, 0,107,101,121,115, 95,115,116,101,112, 0, 97,100, 97,112,116, 95, 97,110,103,108,101, 0, 97,100, - 97,112,116, 95,112,105,120, 0,114,111,116,102,114,111,109, 0,105,110,116,101,103,114, 97,116,111,114, 0, 98, 98, 95, 97,108, -105,103,110, 0, 98, 98, 95,117,118, 95,115,112,108,105,116, 0, 98, 98, 95, 97,110,105,109, 0, 98, 98, 95,115,112,108,105,116, - 95,111,102,102,115,101,116, 0, 98, 98, 95,116,105,108,116, 0, 98, 98, 95,114, 97,110,100, 95,116,105,108,116, 0, 98, 98, 95, -111,102,102,115,101,116, 91, 50, 93, 0,115,105,109,112,108,105,102,121, 95,102,108, 97,103, 0,115,105,109,112,108,105,102,121, - 95,114,101,102,115,105,122,101, 0,115,105,109,112,108,105,102,121, 95,114, 97,116,101, 0,115,105,109,112,108,105,102,121, 95, -116,114, 97,110,115,105,116,105,111,110, 0,115,105,109,112,108,105,102,121, 95,118,105,101,119,112,111,114,116, 0,116,105,109, -101,116,119,101, 97,107, 0,106,105,116,102, 97, 99, 0,101,102,102, 95,104, 97,105,114, 0,103,114,105,100, 95,114,101,115, 0, -112, 97,114,116,102, 97, 99, 0,116, 97,110,102, 97, 99, 0,116, 97,110,112,104, 97,115,101, 0,114,101, 97, 99,116,102, 97, 99, - 0, 97,118,101,102, 97, 99, 0,112,104, 97,115,101,102, 97, 99, 0,114, 97,110,100,114,111,116,102, 97, 99, 0,114, 97,110,100, -112,104, 97,115,101,102, 97, 99, 0,114, 97,110,100,115,105,122,101, 0,114,101, 97, 99,116,115,104, 97,112,101, 0, 97, 99, 99, - 91, 51, 93, 0,100,114, 97,103,102, 97, 99, 0, 98,114,111,119,110,102, 97, 99, 0,100, 97,109,112,102, 97, 99, 0,114, 97,110, -100,108,101,110,103,116,104, 0, 99,104,105,108,100, 95,110, 98,114, 0,114,101,110, 95, 99,104,105,108,100, 95,110, 98,114, 0, -112, 97,114,101,110,116,115, 0, 99,104,105,108,100,115,105,122,101, 0, 99,104,105,108,100,114, 97,110,100,115,105,122,101, 0, - 99,104,105,108,100,114, 97,100, 0, 99,104,105,108,100,102,108, 97,116, 0, 99,108,117,109,112,102, 97, 99, 0, 99,108,117,109, -112,112,111,119, 0,114,111,117,103,104, 49, 0,114,111,117,103,104, 49, 95,115,105,122,101, 0,114,111,117,103,104, 50, 0,114, -111,117,103,104, 50, 95,115,105,122,101, 0,114,111,117,103,104, 50, 95,116,104,114,101,115, 0,114,111,117,103,104, 95,101,110, -100, 0,114,111,117,103,104, 95,101,110,100, 95,115,104, 97,112,101, 0, 99,108,101,110,103,116,104, 0, 99,108,101,110,103,116, -104, 95,116,104,114,101,115, 0, 98,114, 97,110, 99,104, 95,116,104,114,101,115, 0,100,114, 97,119, 95,108,105,110,101, 91, 50, - 93, 0,112, 97,116,104, 95,115,116, 97,114,116, 0,112, 97,116,104, 95,101,110,100, 0,116,114, 97,105,108, 95, 99,111,117,110, -116, 0,107,101,121,101,100, 95,108,111,111,112,115, 0,101,102,102,101, 99,116,111,114, 95,119,101,105,103,104,116, 91, 49, 48, - 93, 0, 42,101,102,102, 95,103,114,111,117,112, 0, 42,100,117,112, 95,111, 98, 0, 42, 98, 98, 95,111, 98, 0, 42,112,100, 50, - 0, 42,112, 97,114,116, 0, 42,112, 97,114,116,105, 99,108,101,115, 0, 42, 42,112, 97,116,104, 99, 97, 99,104,101, 0, 42, 42, - 99,104,105,108,100, 99, 97, 99,104,101, 0,112, 97,116,104, 99, 97, 99,104,101, 98,117,102,115, 0, 99,104,105,108,100, 99, 97, - 99,104,101, 98,117,102,115, 0, 42, 99,108,109,100, 0, 42,104, 97,105,114, 95,105,110, 95,100,109, 0, 42,104, 97,105,114, 95, -111,117,116, 95,100,109, 0, 42,116, 97,114,103,101,116, 95,111, 98, 0, 42,108, 97,116,116,105, 99,101, 0,101,102,102,101, 99, -116,111,114,115, 0,114,101, 97, 99,116,101,118,101,110,116,115, 0,116,114,101,101, 95,102,114, 97,109,101, 0,116,111,116, 99, -104,105,108,100, 0,116,111,116, 99, 97, 99,104,101,100, 0,116,111,116, 99,104,105,108,100, 99, 97, 99,104,101, 0,116, 97,114, -103,101,116, 95,112,115,121,115, 0,116,111,116,107,101,121,101,100, 0, 98, 97,107,101,115,112, 97, 99,101, 0, 98, 98, 95,117, -118,110, 97,109,101, 91, 51, 93, 91, 51, 50, 93, 0,118,103,114,111,117,112, 91, 49, 50, 93, 0,118,103, 95,110,101,103, 0,114, -116, 51, 0, 42,114,101,110,100,101,114,100, 97,116, 97, 0, 42,116,114,101,101, 0, 67,100,105,115, 0, 67,118,105, 0, 91, 51, - 93, 0,115,116,114,117, 99,116,117,114, 97,108, 0, 98,101,110,100,105,110,103, 0,109, 97,120, 95, 98,101,110,100, 0,109, 97, -120, 95,115,116,114,117, 99,116, 0,109, 97,120, 95,115,104,101, 97,114, 0, 97,118,103, 95,115,112,114,105,110,103, 95,108,101, -110, 0,116,105,109,101,115, 99, 97,108,101, 0,101,102,102, 95,102,111,114, 99,101, 95,115, 99, 97,108,101, 0,101,102,102, 95, -119,105,110,100, 95,115, 99, 97,108,101, 0,115,105,109, 95,116,105,109,101, 95,111,108,100, 0,118,101,108,111, 99,105,116,121, - 95,115,109,111,111,116,104, 0,115,116,101,112,115, 80,101,114, 70,114, 97,109,101, 0,112,114,101,114,111,108,108, 0,109, 97, -120,115,112,114,105,110,103,108,101,110, 0,115,111,108,118,101,114, 95,116,121,112,101, 0,118,103,114,111,117,112, 95, 98,101, -110,100, 0,118,103,114,111,117,112, 95,109, 97,115,115, 0,118,103,114,111,117,112, 95,115,116,114,117, 99,116, 0,112,114,101, -115,101,116,115, 0, 42, 99,111,108,108,105,115,105,111,110, 95,108,105,115,116, 0,101,112,115,105,108,111,110, 0,115,101,108, -102, 95,102,114,105, 99,116,105,111,110, 0,115,101,108,102,101,112,115,105,108,111,110, 0,115,101,108,102, 95,108,111,111,112, - 95, 99,111,117,110,116, 0,108,111,111,112, 95, 99,111,117,110,116, 0,112,114,101,115,115,117,114,101, 0,116,104,105, 99,107, -110,101,115,115, 0,115,116,114,111,107,101,115, 0,102,114, 97,109,101,110,117,109, 0, 42, 97, 99,116,102,114, 97,109,101, 0, -103,115,116,101,112, 0,105,110,102,111, 91, 49, 50, 56, 93, 0,115, 98,117,102,102,101,114, 95,115,105,122,101, 0,115, 98,117, -102,102,101,114, 95,115,102,108, 97,103, 0, 42,115, 98,117,102,102,101,114, 0, 42,116,121,112,101,115,116,114, 0, 42,109,101, -115,115, 97,103,101, 0,108,105,115,116, 0,112,114,105,110,116,108,101,118,101,108, 0,115,116,111,114,101,108,101,118,101,108, - 0, 42,119,105,110,100,114, 97,119, 97, 98,108,101, 0, 42,119,105,110, 97, 99,116,105,118,101, 0,119,105,110,100,111,119,115, - 0,105,110,105,116,105, 97,108,105,122,101,100, 0,102,105,108,101, 95,115, 97,118,101,100, 0,111,112,101,114, 97,116,111,114, -115, 0,113,117,101,117,101, 0,114,101,112,111,114,116,115, 0,106,111, 98,115, 0,112, 97,105,110,116, 99,117,114,115,111,114, -115, 0,107,101,121,109, 97,112,115, 0, 42,103,104,111,115,116,119,105,110, 0, 42,110,101,119,115, 99,114,101,101,110, 0,115, - 99,114,101,101,110,110, 97,109,101, 91, 51, 50, 93, 0,112,111,115,120, 0,112,111,115,121, 0,119,105,110,100,111,119,115,116, - 97,116,101, 0,109,111,110,105,116,111,114, 0,108, 97,115,116, 99,117,114,115,111,114, 0, 97,100,100,109,111,117,115,101,109, -111,118,101, 0, 42,101,118,101,110,116,115,116, 97,116,101, 0, 42, 99,117,114,115,119,105,110, 0, 42,116,119,101, 97,107, 0, -100,114, 97,119,109,101,116,104,111,100, 0,100,114, 97,119,102, 97,105,108, 0, 42,100,114, 97,119,100, 97,116, 97, 0,116,105, -109,101,114,115, 0,115,117, 98,119,105,110,100,111,119,115, 0,103,101,115,116,117,114,101, 0,105,100,110, 97,109,101, 91, 54, - 52, 93, 0, 42,112,116,114, 0,115,104,105,102,116, 0, 99,116,114,108, 0, 97,108,116, 0,111,115,107,101,121, 0,107,101,121, -109,111,100,105,102,105,101,114, 0,112,114,111,112,118, 97,108,117,101, 0,105,110, 97, 99,116,105,118,101, 0,109, 97,112,116, -121,112,101, 0,107,101,121,109, 97,112, 0,110, 97,109,101,105,100, 91, 54, 52, 93, 0,115,112, 97, 99,101,105,100, 0,114,101, -103,105,111,110,105,100, 0,105,115, 95,109,111,100, 97,108, 0, 42,105,116,101,109,115, 0, 42, 99,117,115,116,111,109,100, 97, -116, 97, 0, 42,114,101,112,111,114,116,115, 0,109, 97, 99,114,111, 0, 42,111,112,109, 0,109,118, 97,108, 91, 50, 93, 0,112, -114,101,118,120, 0,112,114,101,118,121, 0,117,110,105, 99,111,100,101, 0, 97,115, 99,105,105, 0, 42,107,101,121,109, 97,112, - 95,105,100,110, 97,109,101, 0, 99,117,115,116,111,109, 0, 99,117,115,116,111,109,100, 97,116, 97,102,114,101,101, 0, 42,101, -100, 97,116, 97, 0,105,110,102,108,117,101,110, 99,101, 0, 42, 99,111,101,102,102,105, 99,105,101,110,116,115, 0, 97,114,114, - 97,121,115,105,122,101, 0,112,111,108,121, 95,111,114,100,101,114, 0, 97,109,112,108,105,116,117,100,101, 0,112,104, 97,115, -101, 95,109,117,108,116,105,112,108,105,101,114, 0,112,104, 97,115,101, 95,111,102,102,115,101,116, 0,118, 97,108,117,101, 95, -111,102,102,115,101,116, 0,109,105,100,118, 97,108, 0, 98,101,102,111,114,101, 95,109,111,100,101, 0, 97,102,116,101,114, 95, -109,111,100,101, 0, 98,101,102,111,114,101, 95, 99,121, 99,108,101,115, 0, 97,102,116,101,114, 95, 99,121, 99,108,101,115, 0, -114,101, 99,116, 0,112,104, 97,115,101, 0,109,111,100,105,102,105, 99, 97,116,105,111,110, 0, 42,114,110, 97, 95,112, 97,116, -104, 0, 97,114,114, 97,121, 95,105,110,100,101,120, 0,101,120,112,114,101,115,115,105,111,110, 91, 50, 53, 54, 93, 0,118,101, - 99, 91, 50, 93, 0, 42,102,112,116, 0, 99,111,108,111,114, 95,109,111,100,101, 0, 99,111,108,111,114, 91, 51, 93, 0,102,114, -111,109, 91, 49, 50, 56, 93, 0,116,111, 91, 49, 50, 56, 93, 0,109, 97,112,112,105,110,103,115, 0,115,116,114,105,112,115, 0, - 42,114,101,109, 97,112, 0,102, 99,117,114,118,101,115, 0,115,116,114,105,112, 95,116,105,109,101, 0, 98,108,101,110,100,109, -111,100,101, 0,101,120,116,101,110,100,109,111,100,101, 0,103,114,111,117,112, 91, 54, 52, 93, 0,105,100,116,121,112,101, 0, -116,101,109,112,108, 97,116,101,115, 0,103,114,111,117,112,109,111,100,101, 0,112, 97,116,104,115, 0,107,101,121,105,110,103, -102,108, 97,103, 0, 42,116,109,112, 97, 99,116, 0,110,108, 97, 95,116,114, 97, 99,107,115, 0, 42, 97, 99,116,115,116,114,105, -112, 0,100,114,105,118,101,114,115, 0,111,118,101,114,114,105,100,101,115, 0, 97, 99,116, 95, 98,108,101,110,100,109,111,100, -101, 0, 97, 99,116, 95,101,120,116,101,110,100,109,111,100,101, 0, 97, 99,116, 95,105,110,102,108,117,101,110, 99,101, 0,114, -117,108,101, 0,111,112,116,105,111,110,115, 0,102,101, 97,114, 95,102, 97, 99,116,111,114, 0,115,105,103,110, 97,108, 95,105, -100, 0,108,111,111,107, 95, 97,104,101, 97,100, 0,111,108,111, 99, 91, 51, 93, 0,113,117,101,117,101, 95,115,105,122,101, 0, -119, 97,110,100,101,114, 0,102,108,101,101, 95,100,105,115,116, 97,110, 99,101, 0,104,101, 97,108,116,104, 0,115,116, 97,116, -101, 95,105,100, 0,114,117,108,101,115, 0, 99,111,110,100,105,116,105,111,110,115, 0, 97, 99,116,105,111,110,115, 0,114,117, -108,101,115,101,116, 95,116,121,112,101, 0,114,117,108,101, 95,102,117,122,122,105,110,101,115,115, 0,108, 97,115,116, 95,115, -116, 97,116,101, 95,105,100, 0,108, 97,110,100,105,110,103, 95,115,109,111,111,116,104,110,101,115,115, 0, 98, 97,110,107,105, -110,103, 0, 97,103,103,114,101,115,115,105,111,110, 0, 97, 99, 99,117,114, 97, 99,121, 0, 97,105,114, 95,109,105,110, 95,115, -112,101,101,100, 0, 97,105,114, 95,109, 97,120, 95,115,112,101,101,100, 0, 97,105,114, 95,109, 97,120, 95, 97, 99, 99, 0, 97, -105,114, 95,109, 97,120, 95, 97,118,101, 0, 97,105,114, 95,112,101,114,115,111,110, 97,108, 95,115,112, 97, 99,101, 0,108, 97, -110,100, 95,106,117,109,112, 95,115,112,101,101,100, 0,108, 97,110,100, 95,109, 97,120, 95,115,112,101,101,100, 0,108, 97,110, -100, 95,109, 97,120, 95, 97, 99, 99, 0,108, 97,110,100, 95,109, 97,120, 95, 97,118,101, 0,108, 97,110,100, 95,112,101,114,115, -111,110, 97,108, 95,115,112, 97, 99,101, 0,108, 97,110,100, 95,115,116,105, 99,107, 95,102,111,114, 99,101, 0,115,116, 97,116, -101,115, 0, 42,115,109,100, 0, 42,102,108,117,105,100, 0, 42,102,108,117,105,100, 95,103,114,111,117,112, 0, 42, 99,111,108, -108, 95,103,114,111,117,112, 0, 42,119,116, 0, 42,116,101,120, 95,119,116, 0, 42,116,101,120, 95,115,104, 97,100,111,119, 0, - 42,115,104, 97,100,111,119, 0,112, 48, 91, 51, 93, 0,112, 49, 91, 51, 93, 0,100,120, 0,111,109,101,103, 97, 0,116,101,109, -112, 65,109, 98, 0, 98,101,116, 97, 0,114,101,115, 91, 51, 93, 0, 97,109,112,108,105,102,121, 0,109, 97,120,114,101,115, 0, -118,105,101,119,115,101,116,116,105,110,103,115, 0,110,111,105,115,101, 0,100,105,115,115, 95,112,101,114, 99,101,110,116, 0, -100,105,115,115, 95,115,112,101,101,100, 0,114,101,115, 95,119,116, 91, 51, 93, 0,100,120, 95,119,116, 0,118, 51,100,110,117, -109, 0, 42,112,111,105,110,116, 95, 99, 97, 99,104,101, 91, 50, 93, 0,112,116, 99, 97, 99,104,101,115, 91, 50, 93, 0,118,101, -108,111, 99,105,116,121, 91, 51, 93, 0,118,103,114,112, 95,104,101, 97,116, 95,115, 99, 97,108,101, 91, 50, 93, 0,118,103,114, -111,117,112, 95,102,108,111,119, 0,118,103,114,111,117,112, 95,100,101,110,115,105,116,121, 0,118,103,114,111,117,112, 95,104, -101, 97,116, 0, 42,112,111,105,110,116,115, 95,111,108,100, 0, 42,118,101,108, 0,109, 97,116, 95,111,108,100, 91, 52, 93, 91, - 52, 93, 0,110,117,109,112,111,105,110,116,115, 0, 0, 0, 0, 84, 89, 80, 69,182, 1, 0, 0, 99,104, 97,114, 0,117, 99,104, - 97,114, 0,115,104,111,114,116, 0,117,115,104,111,114,116, 0,105,110,116, 0,108,111,110,103, 0,117,108,111,110,103, 0,102, -108,111, 97,116, 0,100,111,117, 98,108,101, 0,118,111,105,100, 0, 76,105,110,107, 0, 76,105,110,107, 68, 97,116, 97, 0, 76, -105,115,116, 66, 97,115,101, 0,118,101, 99, 50,115, 0,118,101, 99, 50,105, 0,118,101, 99, 50,102, 0,118,101, 99, 50,100, 0, -118,101, 99, 51,105, 0,118,101, 99, 51,102, 0,118,101, 99, 51,100, 0,118,101, 99, 52,105, 0,118,101, 99, 52,102, 0,118,101, - 99, 52,100, 0,114, 99,116,105, 0,114, 99,116,102, 0, 73, 68, 80,114,111,112,101,114,116,121, 68, 97,116, 97, 0, 73, 68, 80, -114,111,112,101,114,116,121, 0, 73, 68, 0, 76,105, 98,114, 97,114,121, 0, 70,105,108,101, 68, 97,116, 97, 0, 80,114,101,118, -105,101,119, 73,109, 97,103,101, 0, 73,112,111, 68,114,105,118,101,114, 0, 79, 98,106,101, 99,116, 0, 73,112,111, 67,117,114, -118,101, 0, 66, 80,111,105,110,116, 0, 66,101,122, 84,114,105,112,108,101, 0, 73,112,111, 0, 75,101,121, 66,108,111, 99,107, - 0, 75,101,121, 0, 65,110,105,109, 68, 97,116, 97, 0, 84,101,120,116, 76,105,110,101, 0, 84,101,120,116, 77, 97,114,107,101, -114, 0, 84,101,120,116, 0, 80, 97, 99,107,101,100, 70,105,108,101, 0, 67, 97,109,101,114, 97, 0, 73,109, 97,103,101, 85,115, -101,114, 0, 83, 99,101,110,101, 0, 73,109, 97,103,101, 0, 71, 80, 85, 84,101,120,116,117,114,101, 0, 97,110,105,109, 0, 82, -101,110,100,101,114, 82,101,115,117,108,116, 0, 77, 84,101,120, 0, 84,101,120, 0, 80,108,117,103,105,110, 84,101,120, 0, 67, - 66, 68, 97,116, 97, 0, 67,111,108,111,114, 66, 97,110,100, 0, 69,110,118, 77, 97,112, 0, 73,109, 66,117,102, 0, 80,111,105, -110,116, 68,101,110,115,105,116,121, 0, 80, 97,114,116,105, 99,108,101, 83,121,115,116,101,109, 0, 86,111,120,101,108, 68, 97, -116, 97, 0, 98, 78,111,100,101, 84,114,101,101, 0, 84,101,120, 77, 97,112,112,105,110,103, 0, 76, 97,109,112, 0, 67,117,114, -118,101, 77, 97,112,112,105,110,103, 0, 87, 97,118,101, 0, 86,111,108,117,109,101, 83,101,116,116,105,110,103,115, 0, 77, 97, -116,101,114,105, 97,108, 0, 71,114,111,117,112, 0, 86, 70,111,110,116, 0, 86, 70,111,110,116, 68, 97,116, 97, 0, 77,101,116, - 97, 69,108,101,109, 0, 66,111,117,110,100, 66,111,120, 0, 77,101,116, 97, 66, 97,108,108, 0, 78,117,114, 98, 0, 67,104, 97, -114, 73,110,102,111, 0, 84,101,120,116, 66,111,120, 0, 67,117,114,118,101, 0, 80, 97,116,104, 0, 83,101,108, 66,111,120, 0, - 69,100,105,116, 70,111,110,116, 0, 77,101,115,104, 0, 77, 70, 97, 99,101, 0, 77, 84, 70, 97, 99,101, 0, 84, 70, 97, 99,101, - 0, 77, 86,101,114,116, 0, 77, 69,100,103,101, 0, 77, 68,101,102,111,114,109, 86,101,114,116, 0, 77, 67,111,108, 0, 77, 83, -116,105, 99,107,121, 0, 77, 83,101,108,101, 99,116, 0, 69,100,105,116, 77,101,115,104, 0, 67,117,115,116,111,109, 68, 97,116, - 97, 0, 77,117,108,116,105,114,101,115, 0, 80, 97,114,116,105, 97,108, 86,105,115,105, 98,105,108,105,116,121, 0, 77, 68,101, -102,111,114,109, 87,101,105,103,104,116, 0, 77, 84,101,120, 80,111,108,121, 0, 77, 76,111,111,112, 85, 86, 0, 77, 76,111,111, -112, 67,111,108, 0, 77, 70,108,111, 97,116, 80,114,111,112,101,114,116,121, 0, 77, 73,110,116, 80,114,111,112,101,114,116,121, - 0, 77, 83,116,114,105,110,103, 80,114,111,112,101,114,116,121, 0, 79,114,105,103, 83,112, 97, 99,101, 70, 97, 99,101, 0, 77, - 68,105,115,112,115, 0, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 69, 68, 71, 69, 68, 82, 65, 87, 32, 40, 49, 60, 60, 49, - 41, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 83, 69, 65, 77, 32, 40, 49, 60, 60, 50, 41, 32, 35,100,101,102,105,110,101, - 32, 77, 69, 95, 70, 71, 79, 78, 32, 40, 49, 60, 60, 51, 41, 32, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 69, 68, 71, 69, - 82, 69, 78, 68, 69, 82, 32, 40, 49, 60, 60, 53, 41, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 76, 79, 79, 83, 69, 69, 68, - 71, 69, 32, 40, 49, 60, 60, 55, 41, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 83, 69, 65, 77, 95, 76, 65, 83, 84, 32, 40, - 49, 60, 60, 56, 41, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 83, 72, 65, 82, 80, 32, 40, 49, 60, 60, 57, 41, 32, 32, 32, - 35,100,101,102,105,110,101, 32, 77, 69, 95, 70, 76, 73, 80, 86, 49, 32, 49, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 70, - 76, 73, 80, 86, 50, 32, 50, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 70, 76, 73, 80, 86, 51, 32, 52, 32, 35,100,101,102, -105,110,101, 32, 77, 69, 95, 70, 76, 73, 80, 86, 52, 32, 56, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 80, 82, 79, 74, 88, - 89, 32, 49, 54, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 80, 82, 79, 74, 88, 90, 32, 51, 50, 32, 35,100,101,102,105,110, -101, 32, 77, 69, 95, 80, 82, 79, 74, 89, 90, 32, 54, 52, 32, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 86, 49, 86, 50, 32, - 49, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 86, 50, 86, 51, 32, 50, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 86, - 51, 86, 49, 32, 52, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 86, 51, 86, 52, 32, 52, 32, 35,100,101,102,105,110,101, 32, - 77, 69, 95, 86, 52, 86, 49, 32, 56, 32, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 83, 77, 79, 79, 84, 72, 32, 49, 32, 35, -100,101,102,105,110,101, 32, 77, 69, 95, 70, 65, 67, 69, 95, 83, 69, 76, 32, 50, 32, 32, 32, 35,100,101,102,105,110,101, 32, 77, - 69, 95, 86, 83, 69,108, 32, 48, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 69, 83, 69,108, 32, 49, 32, 35,100,101,102,105, -110,101, 32, 77, 69, 95, 70, 83, 69, 76, 32, 50, 32, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 69, 76, 69, 67, 84, 32, - 49, 32, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 65, 67, 84, 73, 86, 69, 32, 50, 32, 32, 35,100,101,102,105,110,101, 32, - 84, 70, 95, 83, 69, 76, 49, 32, 52, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 69, 76, 50, 32, 56, 32, 35,100,101,102, -105,110,101, 32, 84, 70, 95, 83, 69, 76, 51, 32, 49, 54, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 69, 76, 52, 32, 51, - 50, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 72, 73, 68, 69, 32, 54, 52, 32, 32, 32, 35,100,101,102,105,110,101, 32, 84, - 70, 95, 68, 89, 78, 65, 77, 73, 67, 32, 49, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 65, 76, 80, 72, 65, 83, 79, 82, 84, - 32, 50, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 84, 69, 88, 32, 52, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, - 72, 65, 82, 69, 68, 86, 69, 82, 84, 32, 56, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 76, 73, 71, 72, 84, 32, 49, 54, 32, - 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 72, 65, 82, 69, 68, 67, 79, 76, 32, 54, 52, 32, 35,100,101,102,105,110,101, 32, - 84, 70, 95, 84, 73, 76, 69, 83, 32, 49, 50, 56, 32, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 66, 73, 76, 76, 66, 79, 65, - 82, 68, 32, 50, 53, 54, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 84, 87, 79, 83, 73, 68, 69, 32, 53, 49, 50, 32, 35,100, -101,102,105,110,101, 32, 84, 70, 95, 73, 78, 86, 73, 83, 73, 66, 76, 69, 32, 49, 48, 50, 52, 32, 35,100,101,102,105,110,101, 32, - 84, 70, 95, 79, 66, 67, 79, 76, 32, 50, 48, 52, 56, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 66, 73, 76, 76, 66, 79, 65, - 82, 68, 50, 32, 52, 48, 57, 54, 32, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 72, 65, 68, 79, 87, 32, 56, 49, 57, 50, - 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 66, 77, 70, 79, 78, 84, 32, 49, 54, 51, 56, 52, 32, 32, 35,100,101,102,105,110, -101, 32, 84, 70, 95, 83, 79, 76, 73, 68, 32, 48, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 65, 68, 68, 32, 49, 32, 35,100, -101,102,105,110,101, 32, 84, 70, 95, 65, 76, 80, 72, 65, 32, 50, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 67, 76, 73, 80, - 32, 52, 32, 32, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 85, 66, 32, 51, 32, 32, 35,100,101,102,105,110,101, 32, 84, - 70, 95, 68, 69, 80, 82, 69, 67, 65, 84, 69, 68, 49, 32, 49, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 68, 69, 80, 82, 69, - 67, 65, 84, 69, 68, 50, 32, 50, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 68, 69, 80, 82, 69, 67, 65, 84, 69, 68, 51, 32, - 52, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 68, 69, 80, 82, 69, 67, 65, 84, 69, 68, 52, 32, 56, 32, 35,100,101,102,105, -110,101, 32, 84, 70, 95, 80, 73, 78, 49, 32, 49, 54, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 80, 73, 78, 50, 32, 51, 50, - 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 80, 73, 78, 51, 32, 54, 52, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 80, - 73, 78, 52, 32, 49, 50, 56, 32, 35,101,110,100,105,102, 77,117,108,116,105,114,101,115, 76,101,118,101,108, 59, 13, 10, 13, 10, -116,121,112,101,100,101,102, 32,115,116,114,117, 99,116, 32, 77,117,108,116,105,114,101,115, 32,123, 13, 10, 9, 76,105,115,116, - 66, 97,115,101, 32,108,101,118,101,108,115, 59, 13, 10, 9, 77, 86,101,114,116, 32, 42,118,101,114,116,115, 59, 13, 10, 13, 10, - 9,117,110,115,105,103,110,101,100, 32, 99,104, 97,114, 32,108,101,118,101,108, 95, 99,111,117,110,116, 44, 32, 99,117,114,114, -101,110,116, 44, 32,110,101,119,108,118,108, 44, 32,101,100,103,101,108,118,108, 44, 32,112,105,110,108,118,108, 44, 32,114,101, -110,100,101,114,108,118,108, 59, 13, 10, 9,117,110,115,105,103,110,101,100, 32, 99,104, 97,114, 32,117,115,101, 95, 99,111,108, - 44, 32,102,108, 97,103, 59, 13, 10, 13, 10, 9, 47, 42, 32, 83,112,101, 99,105, 97,108, 32,108,101,118,101,108, 32, 49, 32,100, - 97,116, 97, 32,116,104, 97,116, 32, 99, 97,110,110,111,116, 32, 98,101, 32,109,111,100,105,102,105,101,100, 32,102,114,111,109, - 32,111,116,104,101,114, 32,108,101,118,101,108,115, 32, 42, 47, 13, 10, 9, 67,117,115,116,111,109, 68, 97,116, 97, 32,118,100, - 97,116, 97, 59, 13, 10, 9, 67,117,115,116,111,109, 68, 97,116, 97, 32,102,100, 97,116, 97, 59, 13, 10, 9,115,104,111,114,116, - 32, 42,101,100,103,101, 95,102,108, 97,103,115, 59, 13, 10, 9, 99,104, 97,114, 32, 42,101,100,103,101, 95, 99,114,101, 97,115, -101,115, 59, 13, 10,125, 32, 77,117,108,116,105,114,101,115, 59, 13, 10, 13, 10, 47, 42, 42, 32, 69,110,100, 32, 77,117,108,116, -105,114,101,115, 32, 42, 42, 47, 13, 10, 13, 10,116,121,112,101,100,101,102, 32,115,116,114,117, 99,116, 32, 80, 97,114,116,105, - 97,108, 86,105,115,105, 98,105,108,105,116,121, 32,123, 13, 10, 9,117,110,115,105,103,110,101,100, 32,105,110,116, 32, 42,118, -101,114,116, 95,109, 97,112, 59, 32, 47, 42, 32,118,101,114,116, 95,109, 97,112, 91, 79,108,100, 32, 73,110,100,101,120, 93, 61, - 32, 78,101,119, 32, 73,110,100,101,120, 32, 42, 47, 13, 10, 9,105,110,116, 32, 42,101,100,103,101, 95,109, 97,112, 59, 32, 47, - 42, 32,101,100,103,101, 95,109, 97,112, 91, 79,108,100, 32, 73,110,100,101,120, 93, 61, 32, 78,101,119, 32, 73,110,100,101,120, - 44, 32, 45, 49, 61, 32,104,105,100,100,101,110, 32, 42, 47, 13, 10, 9, 77, 70, 97, 99,101, 32, 42,111,108,100, 95,102, 97, 99, -101,115, 59, 13, 10, 9, 77, 69,100,103,101, 32, 42,111,108,100, 95,101,100,103,101,115, 59, 13, 10, 9,117,110,115,105,103,110, -101,100, 32,105,110,116, 32,116,111,116,102, 97, 99,101, 44, 32,116,111,116,101,100,103,101, 44, 32,116,111,116,118,101,114,116, - 44, 32,112, 97,100, 59, 13, 10,125, 32, 80, 97,114,116,105, 97,108, 86,105,115,105, 98,105,108,105,116,121, 59, 13, 10, 13, 10, - 47, 42, 32,109,118,101,114,116, 45, 62,102,108, 97,103, 32, 40, 49, 61, 83, 69, 76, 69, 67, 84, 41, 32, 42, 47, 13, 10, 35,100, -101,102,105,110,101, 32, 77, 69, 95, 83, 80, 72, 69, 82, 69, 84, 69, 83, 84, 9, 50, 13, 10, 35,100,101,102,105,110,101, 32, 77, - 69, 95, 83, 80, 72, 69, 82, 69, 84, 69, 77, 80, 9, 52, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 72, 73, 68, 69, 9, - 9, 9, 49, 54, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 86, 69, 82, 84, 95, 77, 69, 82, 71, 69, 68, 9, 9, 40, 49, - 60, 60, 54, 41, 13, 10, 13, 10, 47, 42, 32,109,101,100,103,101, 45, 62,102,108, 97,103, 32, 40, 49, 61, 83, 69, 76, 69, 67, 84, - 41, 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 69, 68, 71, 69, 68, 82, 65, 87, 9, 9, 9, 40, 49, 60, 60, 49, - 41, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 83, 69, 65, 77, 9, 9, 9, 9, 40, 49, 60, 60, 50, 41, 13, 10, 35,100, -101,102,105,110,101, 32, 77, 69, 95, 70, 71, 79, 78, 9, 9, 9, 9, 40, 49, 60, 60, 51, 41, 13, 10, 9, 9, 9, 9, 9, 9, 47, - 42, 32,114,101,115,101,114,118,101, 32, 49, 54, 32,102,111,114, 32, 77, 69, 95, 72, 73, 68, 69, 32, 42, 47, 13, 10, 35,100,101, -102,105,110,101, 32, 77, 69, 95, 69, 68, 71, 69, 82, 69, 78, 68, 69, 82, 9, 9, 40, 49, 60, 60, 53, 41, 13, 10, 35,100,101,102, -105,110,101, 32, 77, 69, 95, 76, 79, 79, 83, 69, 69, 68, 71, 69, 9, 9, 40, 49, 60, 60, 55, 41, 13, 10, 35,100,101,102,105,110, -101, 32, 77, 69, 95, 83, 69, 65, 77, 95, 76, 65, 83, 84, 9, 9, 40, 49, 60, 60, 56, 41, 13, 10, 35,100,101,102,105,110,101, 32, - 77, 69, 95, 83, 72, 65, 82, 80, 9, 9, 9, 40, 49, 60, 60, 57, 41, 13, 10, 13, 10, 47, 42, 32,112,117,110,111, 32, 61, 32,118, -101,114,116,101,120,110,111,114,109, 97,108, 32, 40,109,102, 97, 99,101, 41, 32, 42, 47, 13, 10, 47, 42, 32,114,101,110,100,101, -114, 32, 97,115,115,117,109,101,115, 32,102,108,105,112,115, 32,116,111, 32, 98,101, 32,111,114,100,101,114,101,100, 32,108,105, -107,101, 32,116,104,105,115, 32, 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 70, 76, 73, 80, 86, 49, 9, 9, 49, - 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 70, 76, 73, 80, 86, 50, 9, 9, 50, 13, 10, 35,100,101,102,105,110,101, 32, - 77, 69, 95, 70, 76, 73, 80, 86, 51, 9, 9, 52, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 70, 76, 73, 80, 86, 52, 9, - 9, 56, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 80, 82, 79, 74, 88, 89, 9, 9, 49, 54, 13, 10, 35,100,101,102,105, -110,101, 32, 77, 69, 95, 80, 82, 79, 74, 88, 90, 9, 9, 51, 50, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 80, 82, 79, - 74, 89, 90, 9, 9, 54, 52, 13, 10, 13, 10, 47, 42, 32,101,100, 99,111,100,101, 32, 40,109,102, 97, 99,101, 41, 32, 42, 47, 13, - 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 86, 49, 86, 50, 9, 9, 9, 49, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, - 95, 86, 50, 86, 51, 9, 9, 9, 50, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 86, 51, 86, 49, 9, 9, 9, 52, 13, 10, - 35,100,101,102,105,110,101, 32, 77, 69, 95, 86, 51, 86, 52, 9, 9, 9, 52, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, - 86, 52, 86, 49, 9, 9, 9, 56, 13, 10, 13, 10, 47, 42, 32,102,108, 97,103, 32, 40,109,102, 97, 99,101, 41, 32, 42, 47, 13, 10, - 35,100,101,102,105,110,101, 32, 77, 69, 95, 83, 77, 79, 79, 84, 72, 9, 9, 9, 49, 13, 10, 35,100,101,102,105,110,101, 32, 77, - 69, 95, 70, 65, 67, 69, 95, 83, 69, 76, 9, 9, 9, 50, 13, 10, 9, 9, 9, 9, 9, 9, 47, 42, 32,102,108, 97,103, 32, 77, 69, - 95, 72, 73, 68, 69, 61, 61, 49, 54, 32,105,115, 32,117,115,101,100, 32,104,101,114,101, 32,116,111,111, 32, 42, 47, 32, 13, 10, - 47, 42, 32,109,115,101,108,101, 99,116, 45, 62,116,121,112,101, 32, 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, - 86, 83, 69,108, 9, 48, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 69, 83, 69,108, 32, 49, 13, 10, 35,100,101,102,105, -110,101, 32, 77, 69, 95, 70, 83, 69, 76, 32, 50, 13, 10, 13, 10, 47, 42, 32,109,116,102, 97, 99,101, 45, 62,102,108, 97,103, 32, - 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 69, 76, 69, 67, 84, 9, 49, 32, 47, 42, 32,117,115,101, 32, 77, - 70, 97, 99,101, 32,104,105,100,101, 32,102,108, 97,103, 32, 40, 97,102,116,101,114, 32, 50, 46, 52, 51, 41, 44, 32,115,104,111, -117,108,100, 32, 98,101, 32, 97, 98,108,101, 32,116,111, 32,114,101,117,115,101, 32, 97,102,116,101,114, 32, 50, 46, 52, 52, 32, - 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 65, 67, 84, 73, 86, 69, 9, 50, 32, 47, 42, 32,100,101,112,114,101, - 99, 97,116,101,100, 33, 32, 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 69, 76, 49, 9, 9, 52, 13, 10, 35, -100,101,102,105,110,101, 32, 84, 70, 95, 83, 69, 76, 50, 9, 9, 56, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 69, - 76, 51, 9, 9, 49, 54, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 69, 76, 52, 9, 9, 51, 50, 13, 10, 35,100,101, -102,105,110,101, 32, 84, 70, 95, 72, 73, 68, 69, 9, 9, 54, 52, 32, 47, 42, 32,117,110,117,115,101,100, 44, 32,115, 97,109,101, - 32, 97,115, 32, 84, 70, 95, 83, 69, 76, 69, 67, 84, 32, 42, 47, 13, 10, 13, 10, 47, 42, 32,109,116,102, 97, 99,101, 45, 62,109, -111,100,101, 32, 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 68, 89, 78, 65, 77, 73, 67, 9, 9, 49, 13, 10, 35, -100,101,102,105,110,101, 32, 84, 70, 95, 65, 76, 80, 72, 65, 83, 79, 82, 84, 9, 50, 13, 10, 35,100,101,102,105,110,101, 32, 84, - 70, 95, 84, 69, 88, 9, 9, 9, 52, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 72, 65, 82, 69, 68, 86, 69, 82, 84, - 9, 56, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 76, 73, 71, 72, 84, 9, 9, 49, 54, 13, 10, 13, 10, 35,100,101,102, -105,110,101, 32, 84, 70, 95, 83, 72, 65, 82, 69, 68, 67, 79, 76, 9, 54, 52, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, - 84, 73, 76, 69, 83, 9, 9, 49, 50, 56, 9, 9, 47, 42, 32,100,101,112,114,101, 99, 97,116,101,100, 32, 42, 47, 13, 10, 35,100, -101,102,105,110,101, 32, 84, 70, 95, 66, 73, 76, 76, 66, 79, 65, 82, 68, 9, 50, 53, 54, 13, 10, 35,100,101,102,105,110,101, 32, - 84, 70, 95, 84, 87, 79, 83, 73, 68, 69, 9, 9, 53, 49, 50, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 73, 78, 86, 73, - 83, 73, 66, 76, 69, 9, 49, 48, 50, 52, 13, 10, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 79, 66, 67, 79, 76, 9, 9, - 50, 48, 52, 56, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 66, 73, 76, 76, 66, 79, 65, 82, 68, 50, 9, 52, 48, 57, 54, - 9, 47, 42, 32,119,105,116,104, 32, 90, 32, 97,120,105,115, 32, 99,111,110,115,116,114, 97,105,110,116, 32, 42, 47, 13, 10, 35, -100,101,102,105,110,101, 32, 84, 70, 95, 83, 72, 65, 68, 79, 87, 9, 9, 56, 49, 57, 50, 13, 10, 35,100,101,102,105,110,101, 32, - 84, 70, 95, 66, 77, 70, 79, 78, 84, 9, 9, 49, 54, 51, 56, 52, 13, 10, 13, 10, 47, 42, 32,109,116,102, 97, 99,101, 45, 62,116, -114, 97,110,115,112, 44, 32,118, 97,108,117,101,115, 32, 49, 45, 52, 32, 97,114,101, 32,117,115,101,100, 32, 97,115, 32,102,108, - 97,103,115, 32,105,110, 32,116,104,101, 32, 71, 76, 44, 32, 87, 65, 82, 78, 73, 78, 71, 44, 32, 84, 70, 95, 83, 85, 66, 32, 99, - 97,110,116, 32,119,111,114,107, 32,119,105,116,104, 32,116,104,105,115, 32, 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 84, - 70, 95, 83, 79, 76, 73, 68, 9, 48, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 65, 68, 68, 9, 9, 49, 13, 10, 35,100, -101,102,105,110,101, 32, 84, 70, 95, 65, 76, 80, 72, 65, 9, 50, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 67, 76, 73, - 80, 9, 9, 52, 32, 47, 42, 32, 99,108,105,112,109, 97,112, 32, 97,108,112,104, 97, 47, 98,105,110, 97,114,121, 32, 97,108,112, -104, 97, 32, 97,108,108, 32,111,114, 32,110,111,116,104,105,110,103, 33, 32, 42, 47, 13, 10, 13, 10, 47, 42, 32,115,117, 98, 32, -105,115, 32,110,111,116, 32, 97,118, 97,105,108, 97, 98,108,101, 32,105,110, 32,116,104,101, 32,117,115,101,114, 32,105,110,116, -101,114,102, 97, 99,101, 32, 97,110,121,109,111,114,101, 32, 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 85, - 66, 9, 9, 51, 13, 10, 13, 10, 13, 10, 47, 42, 32,109,116,102, 97, 99,101, 45, 62,117,110,119,114, 97,112, 32, 42, 47, 13, 10, - 35,100,101,102,105,110,101, 32, 84, 70, 95, 68, 69, 80, 82, 69, 67, 65, 84, 69, 68, 49, 9, 49, 13, 10, 35,100,101,102,105,110, -101, 32, 84, 70, 95, 68, 69, 80, 82, 69, 67, 65, 84, 69, 68, 50, 9, 50, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 68, - 69, 80, 82, 69, 67, 65, 84, 69, 68, 51, 9, 52, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 68, 69, 80, 82, 69, 67, 65, - 84, 69, 68, 52, 9, 56, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 80, 73, 78, 49, 9, 9, 32, 32, 32, 32, 49, 54, 13, - 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 80, 73, 78, 50, 9, 9, 32, 32, 32, 32, 51, 50, 13, 10, 35,100,101,102,105,110, -101, 32, 84, 70, 95, 80, 73, 78, 51, 9, 32, 32, 32, 9, 9, 54, 52, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 80, 73, - 78, 52, 9, 32, 32, 32, 32, 9, 49, 50, 56, 13, 10, 13, 10, 35,101,110,100,105,102, 13, 10,104, 79, 67, 75, 33,109, 98,101,114, - 97, 2, 67, 3,191, 16, 8, 1,232, 80,100, 0, 77,117,108,116,105,114,101,115, 67,111,108, 0, 77,117,108,116,105,114,101,115, +120,105,115,102,108, 97,103, 0,112,111,115,101, 99,104, 97,110,110,101,108, 91, 51, 50, 93, 0, 99,111,110,115,116,114, 97,105, +110,116, 91, 51, 50, 93, 0, 42,102,114,111,109, 79, 98,106,101, 99,116, 0,115,117, 98,106,101, 99,116, 91, 51, 50, 93, 0, 98, +111,100,121, 91, 51, 50, 93, 0,111,116,121,112,101, 0,112,117,108,115,101, 0,102,114,101,113, 0,116,111,116,108,105,110,107, +115, 0, 42, 42,108,105,110,107,115, 0,116, 97,112, 0,106,111,121,105,110,100,101,120, 0, 97,120,105,115, 95,115,105,110,103, +108,101, 0, 97,120,105,115,102, 0, 98,117,116,116,111,110, 0,104, 97,116, 0,104, 97,116,102, 0,112,114,101, 99,105,115,105, +111,110, 0,115,116,114, 91, 49, 50, 56, 93, 0,109,111,100,117,108,101, 91, 54, 52, 93, 0, 42,109,121,110,101,119, 0,105,110, +112,117,116,115, 0,116,111,116,115,108,105,110,107,115, 0, 42, 42,115,108,105,110,107,115, 0,118, 97,108,111, 0,115,116, 97, +116,101, 95,109, 97,115,107, 0, 42, 97, 99,116, 0,102,114, 97,109,101, 80,114,111,112, 91, 51, 50, 93, 0, 98,108,101,110,100, +105,110, 0,112,114,105,111,114,105,116,121, 0,101,110,100, 95,114,101,115,101,116, 0,115,116,114,105,100,101, 97,120,105,115, + 0,115,116,114,105,100,101,108,101,110,103,116,104, 0,115,110,100,110,114, 0,112, 97,100, 49, 91, 50, 93, 0,112,105,116, 99, +104, 0,115,111,117,110,100, 51, 68, 0,109, 97,107,101, 99,111,112,121, 0, 99,111,112,121,109, 97,100,101, 0,112, 97,100, 50, + 91, 49, 93, 0, 42,109,101, 0,108,105,110, 86,101,108,111, 99,105,116,121, 91, 51, 93, 0, 97,110,103, 86,101,108,111, 99,105, +116,121, 91, 51, 93, 0,108,111, 99, 97,108,102,108, 97,103, 0,100,121,110, 95,111,112,101,114, 97,116,105,111,110, 0,102,111, +114, 99,101,108,111, 99, 91, 51, 93, 0,102,111,114, 99,101,114,111,116, 91, 51, 93, 0,108,105,110,101, 97,114,118,101,108,111, + 99,105,116,121, 91, 51, 93, 0, 97,110,103,117,108, 97,114,118,101,108,111, 99,105,116,121, 91, 51, 93, 0, 42,114,101,102,101, +114,101,110, 99,101, 0, 98,117,116,115,116, 97, 0, 98,117,116,101,110,100, 0,109,105,110, 0,109, 97,120, 0,118,105,115,105, +102, 97, 99, 0,114,111,116,100, 97,109,112, 0,109,105,110,108,111, 99, 91, 51, 93, 0,109, 97,120,108,111, 99, 91, 51, 93, 0, +109,105,110,114,111,116, 91, 51, 93, 0,109, 97,120,114,111,116, 91, 51, 93, 0,109, 97,116,112,114,111,112, 91, 51, 50, 93, 0, +100,105,115,116,114,105, 98,117,116,105,111,110, 0,105,110,116, 95, 97,114,103, 95, 49, 0,105,110,116, 95, 97,114,103, 95, 50, + 0,102,108,111, 97,116, 95, 97,114,103, 95, 49, 0,102,108,111, 97,116, 95, 97,114,103, 95, 50, 0,116,111, 80,114,111,112, 78, + 97,109,101, 91, 51, 50, 93, 0, 42,116,111, 79, 98,106,101, 99,116, 0, 98,111,100,121, 84,121,112,101, 0,102,105,108,101,110, + 97,109,101, 91, 54, 52, 93, 0,108,111, 97,100, 97,110,105,110, 97,109,101, 91, 54, 52, 93, 0,105,110,116, 95, 97,114,103, 0, +102,108,111, 97,116, 95, 97,114,103, 0, 42,115,117, 98,116, 97,114,103,101,116, 0,103,111, 0, 97, 99, 99,101,108,108,101,114, + 97,116,105,111,110, 0,109, 97,120,115,112,101,101,100, 0,109, 97,120,114,111,116,115,112,101,101,100, 0,109, 97,120,116,105, +108,116,115,112,101,101,100, 0,116,105,108,116,100, 97,109,112, 0,115,112,101,101,100,100, 97,109,112, 0, 42,115,111,117,114, + 99,101, 0,102,114, 97,109,101,115,107,105,112, 0,109,117,116,101, 0, 99,104, 97,110,103,101,100, 0,109,105,110, 95,103, 97, +105,110, 0,109, 97,120, 95,103, 97,105,110, 0,114,101,102,101,114,101,110, 99,101, 95,100,105,115,116, 97,110, 99,101, 0,109, + 97,120, 95,100,105,115,116, 97,110, 99,101, 0,114,111,108,108,111,102,102, 95,102, 97, 99,116,111,114, 0, 99,111,110,101, 95, +105,110,110,101,114, 95, 97,110,103,108,101, 0, 99,111,110,101, 95,111,117,116,101,114, 95, 97,110,103,108,101, 0, 99,111,110, +101, 95,111,117,116,101,114, 95,103, 97,105,110, 0, 42,110,101,119,112, 97, 99,107,101,100,102,105,108,101, 0, 97,116,116,101, +110,117, 97,116,105,111,110, 0,100,105,115,116, 97,110, 99,101, 0, 42, 99, 97, 99,104,101, 0, 42, 97,114,101, 97, 0, 42,108, + 97,109,112,114,101,110, 0,103,111, 98,106,101, 99,116, 0,100,117,112,108,105, 95,111,102,115, 91, 51, 93, 0, 99,104,105,108, +100, 98, 97,115,101, 0,114,111,108,108, 0,104,101, 97,100, 91, 51, 93, 0,116, 97,105,108, 91, 51, 93, 0, 98,111,110,101, 95, +109, 97,116, 91, 51, 93, 91, 51, 93, 0, 97,114,109, 95,104,101, 97,100, 91, 51, 93, 0, 97,114,109, 95,116, 97,105,108, 91, 51, + 93, 0, 97,114,109, 95,109, 97,116, 91, 52, 93, 91, 52, 93, 0,120,119,105,100,116,104, 0,122,119,105,100,116,104, 0,101, 97, +115,101, 49, 0,101, 97,115,101, 50, 0,114, 97,100, 95,104,101, 97,100, 0,114, 97,100, 95,116, 97,105,108, 0, 98,111,110,101, + 98, 97,115,101, 0, 99,104, 97,105,110, 98, 97,115,101, 0, 42,101,100, 98,111, 0, 42,115,107,101,116, 99,104, 0,108, 97,121, +101,114, 95,112,114,111,116,101, 99,116,101,100, 0,103,104,111,115,116,101,112, 0,103,104,111,115,116,115,105,122,101, 0,103, +104,111,115,116,116,121,112,101, 0,112, 97,116,104,115,105,122,101, 0,103,104,111,115,116,115,102, 0,103,104,111,115,116,101, +102, 0,112, 97,116,104,115,102, 0,112, 97,116,104,101,102, 0,112, 97,116,104, 98, 99, 0,112, 97,116,104, 97, 99, 0, 42,112, +111,105,110,116,115, 0,115,116, 97,114,116, 95,102,114, 97,109,101, 0,101,110,100, 95,102,114, 97,109,101, 0, 42,112,114,111, +112, 0, 99,111,110,115,116,102,108, 97,103, 0,105,107,102,108, 97,103, 0,115,101,108,101, 99,116,102,108, 97,103, 0, 97,103, +114,112, 95,105,110,100,101,120, 0, 42, 98,111,110,101, 0, 42, 99,104,105,108,100, 0,105,107,116,114,101,101, 0, 42, 98, 95, + 98,111,110,101, 95,109, 97,116,115, 0, 42,100,117, 97,108, 95,113,117, 97,116, 0, 42, 98, 95, 98,111,110,101, 95,100,117, 97, +108, 95,113,117, 97,116,115, 0,101,117,108, 91, 51, 93, 0, 99,104, 97,110, 95,109, 97,116, 91, 52, 93, 91, 52, 93, 0,112,111, +115,101, 95,109, 97,116, 91, 52, 93, 91, 52, 93, 0,112,111,115,101, 95,104,101, 97,100, 91, 51, 93, 0,112,111,115,101, 95,116, + 97,105,108, 91, 51, 93, 0,108,105,109,105,116,109,105,110, 91, 51, 93, 0,108,105,109,105,116,109, 97,120, 91, 51, 93, 0,115, +116,105,102,102,110,101,115,115, 91, 51, 93, 0,105,107,115,116,114,101,116, 99,104, 0,105,107,114,111,116,119,101,105,103,104, +116, 0,105,107,108,105,110,119,101,105,103,104,116, 0, 42, 99,117,115,116,111,109, 0, 99,104, 97,110, 98, 97,115,101, 0,112, +114,111,120,121, 95,108, 97,121,101,114, 0,115,116,114,105,100,101, 95,111,102,102,115,101,116, 91, 51, 93, 0, 99,121, 99,108, +105, 99, 95,111,102,102,115,101,116, 91, 51, 93, 0, 97,103,114,111,117,112,115, 0, 97, 99,116,105,118,101, 95,103,114,111,117, +112, 0,105,107,115,111,108,118,101,114, 0, 42,105,107,100, 97,116, 97, 0, 42,105,107,112, 97,114, 97,109, 0,110,117,109,105, +116,101,114, 0,110,117,109,115,116,101,112, 0,109,105,110,115,116,101,112, 0,109, 97,120,115,116,101,112, 0,115,111,108,118, +101,114, 0,102,101,101,100, 98, 97, 99,107, 0,109, 97,120,118,101,108, 0,100, 97,109,112,109, 97,120, 0,100, 97,109,112,101, +112,115, 0, 99,104, 97,110,110,101,108,115, 0, 99,117,115,116,111,109, 67,111,108, 0, 99,115, 0, 99,117,114,118,101,115, 0, +103,114,111,117,112,115, 0, 97, 99,116,105,118,101, 95,109, 97,114,107,101,114, 0,102,105,108,116,101,114,102,108, 97,103, 0, + 97,100,115, 0, 97, 99,116,110,114, 0, 97, 99,116,119,105,100,116,104, 0,116,105,109,101,115,108,105,100,101, 0, 42,103,114, +112, 0,116,101,109,112, 0,110, 97,109,101, 91, 51, 48, 93, 0,111,119,110,115,112, 97, 99,101, 0,116, 97,114,115,112, 97, 99, +101, 0,101,110,102,111,114, 99,101, 0,104,101, 97,100,116, 97,105,108, 0,108,105,110, 95,101,114,114,111,114, 0,114,111,116, + 95,101,114,114,111,114, 0, 42,116, 97,114, 0,109, 97,116,114,105,120, 91, 52, 93, 91, 52, 93, 0,115,112, 97, 99,101, 0,114, +111,116, 79,114,100,101,114, 0,116, 97,114,110,117,109, 0,116, 97,114,103,101,116,115, 0,105,116,101,114, 97,116,105,111,110, +115, 0,114,111,111,116, 98,111,110,101, 0,109, 97,120, 95,114,111,111,116, 98,111,110,101, 0, 42,112,111,108,101,116, 97,114, + 0,112,111,108,101,115,117, 98,116, 97,114,103,101,116, 91, 51, 50, 93, 0,112,111,108,101, 97,110,103,108,101, 0,111,114,105, +101,110,116,119,101,105,103,104,116, 0,103,114, 97, 98,116, 97,114,103,101,116, 91, 51, 93, 0,114,101,115,101,114,118,101,100, + 49, 0,114,101,115,101,114,118,101,100, 50, 0,109,105,110,109, 97,120,102,108, 97,103, 0,115,116,117, 99,107, 0, 99, 97, 99, +104,101, 91, 51, 93, 0,108,111, 99,107,102,108, 97,103, 0,102,111,108,108,111,119,102,108, 97,103, 0,118,111,108,109,111,100, +101, 0,112,108, 97,110,101, 0,111,114,103,108,101,110,103,116,104, 0, 98,117,108,103,101, 0,112,105,118, 88, 0,112,105,118, + 89, 0,112,105,118, 90, 0, 97,120, 88, 0, 97,120, 89, 0, 97,120, 90, 0,109,105,110, 76,105,109,105,116, 91, 54, 93, 0,109, + 97,120, 76,105,109,105,116, 91, 54, 93, 0,101,120,116,114, 97, 70,122, 0,105,110,118,109, 97,116, 91, 52, 93, 91, 52, 93, 0, +102,114,111,109, 0,116,111, 0,109, 97,112, 91, 51, 93, 0,101,120,112,111, 0,102,114,111,109, 95,109,105,110, 91, 51, 93, 0, +102,114,111,109, 95,109, 97,120, 91, 51, 93, 0,116,111, 95,109,105,110, 91, 51, 93, 0,116,111, 95,109, 97,120, 91, 51, 93, 0, +122,109,105,110, 0,122,109, 97,120, 0,112, 97,100, 91, 57, 93, 0, 99,104, 97,110,110,101,108, 91, 51, 50, 93, 0,110,111, 95, +114,111,116, 95, 97,120,105,115, 0,115,116,114,105,100,101, 95, 97,120,105,115, 0, 99,117,114,109,111,100, 0, 97, 99,116,115, +116, 97,114,116, 0, 97, 99,116,101,110,100, 0, 97, 99,116,111,102,102,115, 0,115,116,114,105,100,101,108,101,110, 0,115, 99, + 97,108,101, 0, 98,108,101,110,100,111,117,116, 0,115,116,114,105,100,101, 99,104, 97,110,110,101,108, 91, 51, 50, 93, 0,111, +102,102,115, 95, 98,111,110,101, 91, 51, 50, 93, 0,104, 97,115,105,110,112,117,116, 0,104, 97,115,111,117,116,112,117,116, 0, +100, 97,116, 97,116,121,112,101, 0,115,111, 99,107,101,116,116,121,112,101, 0, 42,110,101,119, 95,115,111, 99,107, 0,110,115, + 0,108,105,109,105,116, 0,115,116, 97, 99,107, 95,105,110,100,101,120, 0,105,110,116,101,114,110, 0,115,116, 97, 99,107, 95, +105,110,100,101,120, 95,101,120,116, 0,108,111, 99,120, 0,108,111, 99,121, 0,111,119,110, 95,105,110,100,101,120, 0,116,111, + 95,105,110,100,101,120, 0, 42,116,111,115,111, 99,107, 0, 42,108,105,110,107, 0, 42,110,101,119, 95,110,111,100,101, 0,117, +115,101,114,110, 97,109,101, 91, 51, 50, 93, 0,108, 97,115,116,121, 0,111,117,116,112,117,116,115, 0, 42,115,116,111,114, 97, +103,101, 0,109,105,110,105,119,105,100,116,104, 0, 99,117,115,116,111,109, 49, 0, 99,117,115,116,111,109, 50, 0, 99,117,115, +116,111,109, 51, 0, 99,117,115,116,111,109, 52, 0,110,101,101,100, 95,101,120,101, 99, 0,101,120,101, 99, 0, 42,116,104,114, +101, 97,100,100, 97,116, 97, 0,116,111,116,114, 0, 98,117,116,114, 0,112,114,118,114, 0, 42, 98,108,111, 99,107, 0, 42,116, +121,112,101,105,110,102,111, 0, 42,102,114,111,109,110,111,100,101, 0, 42,116,111,110,111,100,101, 0, 42,102,114,111,109,115, +111, 99,107, 0,110,111,100,101,115, 0,108,105,110,107,115, 0, 42,115,116, 97, 99,107, 0, 42,116,104,114,101, 97,100,115,116, + 97, 99,107, 0,105,110,105,116, 0,115,116, 97, 99,107,115,105,122,101, 0, 99,117,114, 95,105,110,100,101,120, 0, 97,108,108, +116,121,112,101,115, 0, 42,111,119,110,116,121,112,101, 0, 42,115,101,108,105,110, 0, 42,115,101,108,111,117,116, 0, 40, 42, +116,105,109,101, 99,117,114,115,111,114, 41, 40, 41, 0, 40, 42,115,116, 97,116,115, 95,100,114, 97,119, 41, 40, 41, 0, 40, 42, +116,101,115,116, 95, 98,114,101, 97,107, 41, 40, 41, 0, 42,116, 98,104, 0, 42,116, 99,104, 0, 42,115,100,104, 0, 99,121, 99, +108,105, 99, 0,109,111,118,105,101, 0,115, 97,109,112,108,101,115, 0,109,105,110,115,112,101,101,100, 0,112,101,114, 99,101, +110,116,120, 0,112,101,114, 99,101,110,116,121, 0, 98,111,107,101,104, 0, 99,117,114,118,101,100, 0,105,109, 97,103,101, 95, +105,110, 95,119,105,100,116,104, 0,105,109, 97,103,101, 95,105,110, 95,104,101,105,103,104,116, 0, 99,101,110,116,101,114, 95, +120, 0, 99,101,110,116,101,114, 95,121, 0,115,112,105,110, 0,105,116,101,114, 0,119,114, 97,112, 0,115,105,103,109, 97, 95, + 99,111,108,111,114, 0,115,105,103,109, 97, 95,115,112, 97, 99,101, 0,104,117,101, 0,115, 97,116, 0,116, 49, 0,116, 50, 0, +116, 51, 0,102,115,116,114,101,110,103,116,104, 0,102, 97,108,112,104, 97, 0,107,101,121, 91, 52, 93, 0,120, 49, 0,120, 50, + 0,121, 49, 0,121, 50, 0, 99,111,108,110, 97,109,101, 91, 51, 50, 93, 0, 98,107,116,121,112,101, 0,114,111,116, 97,116,105, +111,110, 0,103, 97,109, 99,111, 0,110,111, 95,122, 98,117,102, 0,102,115,116,111,112, 0,109, 97,120, 98,108,117,114, 0, 98, +116,104,114,101,115,104, 0, 42,100,105, 99,116, 0, 42,110,111,100,101, 0, 97,110,103,108,101, 95,111,102,115, 0, 99,111,108, +109,111,100, 0,109,105,120, 0,116,104,114,101,115,104,111,108,100, 0,102, 97,100,101, 0,109, 0, 99, 0,106,105,116, 0,112, +114,111,106, 0,102,105,116, 0,115,104,111,114,116,121, 0,109,105,110,116, 97, 98,108,101, 0,109, 97,120,116, 97, 98,108,101, + 0,101,120,116, 95,105,110, 91, 50, 93, 0,101,120,116, 95,111,117,116, 91, 50, 93, 0, 42, 99,117,114,118,101, 0, 42,116, 97, + 98,108,101, 0, 42,112,114,101,109,117,108,116, 97, 98,108,101, 0, 99,117,114,114, 0, 99,108,105,112,114, 0, 99,109, 91, 52, + 93, 0, 98,108, 97, 99,107, 91, 51, 93, 0,119,104,105,116,101, 91, 51, 93, 0, 98,119,109,117,108, 91, 51, 93, 0,115, 97,109, +112,108,101, 91, 51, 93, 0,111,102,102,115,101,116, 91, 50, 93, 0, 99,108,111,110,101, 0,106,105,116,116,101,114, 0,115,109, +111,111,116,104, 95,115,116,114,111,107,101, 95,114, 97,100,105,117,115, 0,115,109,111,111,116,104, 95,115,116,114,111,107,101, + 95,102, 97, 99,116,111,114, 0,114, 97,116,101, 0,114,103, 98, 91, 51, 93, 0,115, 99,117,108,112,116, 95,116,111,111,108, 0, + 97, 99,116,105,118,101, 95,114,110,100, 0, 97, 99,116,105,118,101, 95, 99,108,111,110,101, 0, 97, 99,116,105,118,101, 95,109, + 97,115,107, 0, 42,108, 97,121,101,114,115, 0,116,111,116,108, 97,121,101,114, 0,109, 97,120,108, 97,121,101,114, 0,116,111, +116,115,105,122,101, 0, 42,112,111,111,108, 0,101,100,105,116,102,108, 97,103, 0,118,101,108, 91, 51, 93, 0,114,111,116, 91, + 52, 93, 0, 97,118,101, 91, 51, 93, 0, 42,103,114,111,117,110,100, 0,119, 97,110,100,101,114, 91, 51, 93, 0,110,117,109, 0, +112, 97,114,101,110,116, 0,112, 97, 91, 52, 93, 0,119, 91, 52, 93, 0,102,117,118, 91, 52, 93, 0,102,111,102,102,115,101,116, + 0,112,114,101,118, 95,115,116, 97,116,101, 0, 42,104, 97,105,114, 0, 42, 98,111,105,100, 0,100,105,101,116,105,109,101, 0, +110,117,109, 95,100,109, 99, 97, 99,104,101, 0, 97,108,105,118,101, 0,108,111,111,112, 0,104, 97,105,114, 95,105,110,100,101, +120, 0, 42, 98,111,105,100,115, 0,100,105,115,116,114, 0,112,104,121,115,116,121,112,101, 0, 97,118,101,109,111,100,101, 0, +114,101, 97, 99,116,101,118,101,110,116, 0,100,114, 97,119, 0,100,114, 97,119, 95, 97,115, 0,100,114, 97,119, 95,115,105,122, +101, 0, 99,104,105,108,100,116,121,112,101, 0,114,101,110, 95, 97,115, 0,114,101,110, 95,115,116,101,112, 0,104, 97,105,114, + 95,115,116,101,112, 0,107,101,121,115, 95,115,116,101,112, 0, 97,100, 97,112,116, 95, 97,110,103,108,101, 0, 97,100, 97,112, +116, 95,112,105,120, 0,114,111,116,102,114,111,109, 0,105,110,116,101,103,114, 97,116,111,114, 0, 98, 98, 95, 97,108,105,103, +110, 0, 98, 98, 95,117,118, 95,115,112,108,105,116, 0, 98, 98, 95, 97,110,105,109, 0, 98, 98, 95,115,112,108,105,116, 95,111, +102,102,115,101,116, 0, 98, 98, 95,116,105,108,116, 0, 98, 98, 95,114, 97,110,100, 95,116,105,108,116, 0, 98, 98, 95,111,102, +102,115,101,116, 91, 50, 93, 0,115,105,109,112,108,105,102,121, 95,102,108, 97,103, 0,115,105,109,112,108,105,102,121, 95,114, +101,102,115,105,122,101, 0,115,105,109,112,108,105,102,121, 95,114, 97,116,101, 0,115,105,109,112,108,105,102,121, 95,116,114, + 97,110,115,105,116,105,111,110, 0,115,105,109,112,108,105,102,121, 95,118,105,101,119,112,111,114,116, 0,116,105,109,101,116, +119,101, 97,107, 0,106,105,116,102, 97, 99, 0,101,102,102, 95,104, 97,105,114, 0,103,114,105,100, 95,114,101,115, 0,112, 97, +114,116,102, 97, 99, 0,116, 97,110,102, 97, 99, 0,116, 97,110,112,104, 97,115,101, 0,114,101, 97, 99,116,102, 97, 99, 0, 97, +118,101,102, 97, 99, 0,112,104, 97,115,101,102, 97, 99, 0,114, 97,110,100,114,111,116,102, 97, 99, 0,114, 97,110,100,112,104, + 97,115,101,102, 97, 99, 0,114, 97,110,100,115,105,122,101, 0,114,101, 97, 99,116,115,104, 97,112,101, 0, 97, 99, 99, 91, 51, + 93, 0,100,114, 97,103,102, 97, 99, 0, 98,114,111,119,110,102, 97, 99, 0,100, 97,109,112,102, 97, 99, 0,114, 97,110,100,108, +101,110,103,116,104, 0, 99,104,105,108,100, 95,110, 98,114, 0,114,101,110, 95, 99,104,105,108,100, 95,110, 98,114, 0,112, 97, +114,101,110,116,115, 0, 99,104,105,108,100,115,105,122,101, 0, 99,104,105,108,100,114, 97,110,100,115,105,122,101, 0, 99,104, +105,108,100,114, 97,100, 0, 99,104,105,108,100,102,108, 97,116, 0, 99,108,117,109,112,112,111,119, 0,114,111,117,103,104, 49, + 0,114,111,117,103,104, 49, 95,115,105,122,101, 0,114,111,117,103,104, 50, 0,114,111,117,103,104, 50, 95,115,105,122,101, 0, +114,111,117,103,104, 50, 95,116,104,114,101,115, 0,114,111,117,103,104, 95,101,110,100, 0,114,111,117,103,104, 95,101,110,100, + 95,115,104, 97,112,101, 0, 99,108,101,110,103,116,104, 0, 99,108,101,110,103,116,104, 95,116,104,114,101,115, 0, 98,114, 97, +110, 99,104, 95,116,104,114,101,115, 0,100,114, 97,119, 95,108,105,110,101, 91, 50, 93, 0,112, 97,116,104, 95,115,116, 97,114, +116, 0,112, 97,116,104, 95,101,110,100, 0,116,114, 97,105,108, 95, 99,111,117,110,116, 0,107,101,121,101,100, 95,108,111,111, +112,115, 0, 42,101,102,102, 95,103,114,111,117,112, 0, 42,100,117,112, 95,111, 98, 0, 42, 98, 98, 95,111, 98, 0, 42,112,100, + 50, 0, 42,112, 97,114,116, 0, 42,112, 97,114,116,105, 99,108,101,115, 0, 42, 42,112, 97,116,104, 99, 97, 99,104,101, 0, 42, + 42, 99,104,105,108,100, 99, 97, 99,104,101, 0,112, 97,116,104, 99, 97, 99,104,101, 98,117,102,115, 0, 99,104,105,108,100, 99, + 97, 99,104,101, 98,117,102,115, 0, 42, 99,108,109,100, 0, 42,104, 97,105,114, 95,105,110, 95,100,109, 0, 42,104, 97,105,114, + 95,111,117,116, 95,100,109, 0, 42,116, 97,114,103,101,116, 95,111, 98, 0, 42,108, 97,116,116,105, 99,101, 0,116,114,101,101, + 95,102,114, 97,109,101, 0,116,111,116, 99,104,105,108,100, 0,116,111,116, 99, 97, 99,104,101,100, 0,116,111,116, 99,104,105, +108,100, 99, 97, 99,104,101, 0,116, 97,114,103,101,116, 95,112,115,121,115, 0,116,111,116,107,101,121,101,100, 0, 98, 97,107, +101,115,112, 97, 99,101, 0, 98, 98, 95,117,118,110, 97,109,101, 91, 51, 93, 91, 51, 50, 93, 0,118,103,114,111,117,112, 91, 49, + 50, 93, 0,118,103, 95,110,101,103, 0,114,116, 51, 0, 42,114,101,110,100,101,114,100, 97,116, 97, 0, 42,101,102,102,101, 99, +116,111,114,115, 0, 42,116,114,101,101, 0, 42,112,100,100, 0, 42,102,114, 97,110,100, 0, 67,100,105,115, 0, 67,118,105, 0, + 91, 51, 93, 0,115,116,114,117, 99,116,117,114, 97,108, 0, 98,101,110,100,105,110,103, 0,109, 97,120, 95, 98,101,110,100, 0, +109, 97,120, 95,115,116,114,117, 99,116, 0,109, 97,120, 95,115,104,101, 97,114, 0, 97,118,103, 95,115,112,114,105,110,103, 95, +108,101,110, 0,116,105,109,101,115, 99, 97,108,101, 0,101,102,102, 95,102,111,114, 99,101, 95,115, 99, 97,108,101, 0,101,102, +102, 95,119,105,110,100, 95,115, 99, 97,108,101, 0,115,105,109, 95,116,105,109,101, 95,111,108,100, 0,118,101,108,111, 99,105, +116,121, 95,115,109,111,111,116,104, 0,115,116,101,112,115, 80,101,114, 70,114, 97,109,101, 0,112,114,101,114,111,108,108, 0, +109, 97,120,115,112,114,105,110,103,108,101,110, 0,115,111,108,118,101,114, 95,116,121,112,101, 0,118,103,114,111,117,112, 95, + 98,101,110,100, 0,118,103,114,111,117,112, 95,109, 97,115,115, 0,118,103,114,111,117,112, 95,115,116,114,117, 99,116, 0,112, +114,101,115,101,116,115, 0, 42, 99,111,108,108,105,115,105,111,110, 95,108,105,115,116, 0,101,112,115,105,108,111,110, 0,115, +101,108,102, 95,102,114,105, 99,116,105,111,110, 0,115,101,108,102,101,112,115,105,108,111,110, 0,115,101,108,102, 95,108,111, +111,112, 95, 99,111,117,110,116, 0,108,111,111,112, 95, 99,111,117,110,116, 0,112,114,101,115,115,117,114,101, 0,116,104,105, + 99,107,110,101,115,115, 0,115,116,114,111,107,101,115, 0,102,114, 97,109,101,110,117,109, 0, 42, 97, 99,116,102,114, 97,109, +101, 0,103,115,116,101,112, 0,105,110,102,111, 91, 49, 50, 56, 93, 0,115, 98,117,102,102,101,114, 95,115,105,122,101, 0,115, + 98,117,102,102,101,114, 95,115,102,108, 97,103, 0, 42,115, 98,117,102,102,101,114, 0, 42,116,121,112,101,115,116,114, 0, 42, +109,101,115,115, 97,103,101, 0,108,105,115,116, 0,112,114,105,110,116,108,101,118,101,108, 0,115,116,111,114,101,108,101,118, +101,108, 0, 42,119,105,110,100,114, 97,119, 97, 98,108,101, 0, 42,119,105,110, 97, 99,116,105,118,101, 0,119,105,110,100,111, +119,115, 0,105,110,105,116,105, 97,108,105,122,101,100, 0,102,105,108,101, 95,115, 97,118,101,100, 0,111,112,101,114, 97,116, +111,114,115, 0,113,117,101,117,101, 0,114,101,112,111,114,116,115, 0,106,111, 98,115, 0,112, 97,105,110,116, 99,117,114,115, +111,114,115, 0,107,101,121,109, 97,112,115, 0, 42,103,104,111,115,116,119,105,110, 0, 42,110,101,119,115, 99,114,101,101,110, + 0,115, 99,114,101,101,110,110, 97,109,101, 91, 51, 50, 93, 0,112,111,115,120, 0,112,111,115,121, 0,119,105,110,100,111,119, +115,116, 97,116,101, 0,109,111,110,105,116,111,114, 0,108, 97,115,116, 99,117,114,115,111,114, 0, 97,100,100,109,111,117,115, +101,109,111,118,101, 0, 42,101,118,101,110,116,115,116, 97,116,101, 0, 42, 99,117,114,115,119,105,110, 0, 42,116,119,101, 97, +107, 0,100,114, 97,119,109,101,116,104,111,100, 0,100,114, 97,119,102, 97,105,108, 0, 42,100,114, 97,119,100, 97,116, 97, 0, +116,105,109,101,114,115, 0,109,111,100, 97,108,104, 97,110,100,108,101,114,115, 0,115,117, 98,119,105,110,100,111,119,115, 0, +103,101,115,116,117,114,101, 0,105,100,110, 97,109,101, 91, 54, 52, 93, 0, 42,112,116,114, 0,115,104,105,102,116, 0, 99,116, +114,108, 0, 97,108,116, 0,111,115,107,101,121, 0,107,101,121,109,111,100,105,102,105,101,114, 0,112,114,111,112,118, 97,108, +117,101, 0,105,110, 97, 99,116,105,118,101, 0,109, 97,112,116,121,112,101, 0,107,101,121,109, 97,112, 0,110, 97,109,101,105, +100, 91, 54, 52, 93, 0,115,112, 97, 99,101,105,100, 0,114,101,103,105,111,110,105,100, 0,105,115, 95,109,111,100, 97,108, 0, + 42,105,116,101,109,115, 0, 40, 42,112,111,108,108, 41, 40, 41, 0, 42, 99,117,115,116,111,109,100, 97,116, 97, 0, 42,114,101, +112,111,114,116,115, 0,109, 97, 99,114,111, 0, 42,111,112,109, 0,109,118, 97,108, 91, 50, 93, 0,112,114,101,118,120, 0,112, +114,101,118,121, 0,117,110,105, 99,111,100,101, 0, 97,115, 99,105,105, 0, 42,107,101,121,109, 97,112, 95,105,100,110, 97,109, +101, 0, 99,117,115,116,111,109, 0, 99,117,115,116,111,109,100, 97,116, 97,102,114,101,101, 0, 42,101,100, 97,116, 97, 0,105, +110,102,108,117,101,110, 99,101, 0, 42, 99,111,101,102,102,105, 99,105,101,110,116,115, 0, 97,114,114, 97,121,115,105,122,101, + 0,112,111,108,121, 95,111,114,100,101,114, 0, 97,109,112,108,105,116,117,100,101, 0,112,104, 97,115,101, 95,109,117,108,116, +105,112,108,105,101,114, 0,112,104, 97,115,101, 95,111,102,102,115,101,116, 0,118, 97,108,117,101, 95,111,102,102,115,101,116, + 0,109,105,100,118, 97,108, 0, 98,101,102,111,114,101, 95,109,111,100,101, 0, 97,102,116,101,114, 95,109,111,100,101, 0, 98, +101,102,111,114,101, 95, 99,121, 99,108,101,115, 0, 97,102,116,101,114, 95, 99,121, 99,108,101,115, 0,114,101, 99,116, 0,112, +104, 97,115,101, 0,109,111,100,105,102,105, 99, 97,116,105,111,110, 0, 42,114,110, 97, 95,112, 97,116,104, 0, 97,114,114, 97, +121, 95,105,110,100,101,120, 0,101,120,112,114,101,115,115,105,111,110, 91, 50, 53, 54, 93, 0,118,101, 99, 91, 50, 93, 0, 42, +102,112,116, 0, 99,111,108,111,114, 95,109,111,100,101, 0, 99,111,108,111,114, 91, 51, 93, 0,102,114,111,109, 91, 49, 50, 56, + 93, 0,116,111, 91, 49, 50, 56, 93, 0,109, 97,112,112,105,110,103,115, 0,115,116,114,105,112,115, 0, 42,114,101,109, 97,112, + 0,102, 99,117,114,118,101,115, 0,115,116,114,105,112, 95,116,105,109,101, 0, 98,108,101,110,100,109,111,100,101, 0,101,120, +116,101,110,100,109,111,100,101, 0,103,114,111,117,112, 91, 54, 52, 93, 0,105,100,116,121,112,101, 0,116,101,109,112,108, 97, +116,101,115, 0,103,114,111,117,112,109,111,100,101, 0,112, 97,116,104,115, 0,107,101,121,105,110,103,102,108, 97,103, 0, 97, + 99,116,105,118,101, 95,112, 97,116,104, 0, 42,116,109,112, 97, 99,116, 0,110,108, 97, 95,116,114, 97, 99,107,115, 0, 42, 97, + 99,116,115,116,114,105,112, 0,100,114,105,118,101,114,115, 0,111,118,101,114,114,105,100,101,115, 0, 97, 99,116, 95, 98,108, +101,110,100,109,111,100,101, 0, 97, 99,116, 95,101,120,116,101,110,100,109,111,100,101, 0, 97, 99,116, 95,105,110,102,108,117, +101,110, 99,101, 0,114,117,108,101, 0,111,112,116,105,111,110,115, 0,102,101, 97,114, 95,102, 97, 99,116,111,114, 0,115,105, +103,110, 97,108, 95,105,100, 0,108,111,111,107, 95, 97,104,101, 97,100, 0,111,108,111, 99, 91, 51, 93, 0,113,117,101,117,101, + 95,115,105,122,101, 0,119, 97,110,100,101,114, 0,102,108,101,101, 95,100,105,115,116, 97,110, 99,101, 0,104,101, 97,108,116, +104, 0,115,116, 97,116,101, 95,105,100, 0,114,117,108,101,115, 0, 99,111,110,100,105,116,105,111,110,115, 0, 97, 99,116,105, +111,110,115, 0,114,117,108,101,115,101,116, 95,116,121,112,101, 0,114,117,108,101, 95,102,117,122,122,105,110,101,115,115, 0, +108, 97,115,116, 95,115,116, 97,116,101, 95,105,100, 0,108, 97,110,100,105,110,103, 95,115,109,111,111,116,104,110,101,115,115, + 0, 98, 97,110,107,105,110,103, 0, 97,103,103,114,101,115,115,105,111,110, 0, 97, 99, 99,117,114, 97, 99,121, 0, 97,105,114, + 95,109,105,110, 95,115,112,101,101,100, 0, 97,105,114, 95,109, 97,120, 95,115,112,101,101,100, 0, 97,105,114, 95,109, 97,120, + 95, 97, 99, 99, 0, 97,105,114, 95,109, 97,120, 95, 97,118,101, 0, 97,105,114, 95,112,101,114,115,111,110, 97,108, 95,115,112, + 97, 99,101, 0,108, 97,110,100, 95,106,117,109,112, 95,115,112,101,101,100, 0,108, 97,110,100, 95,109, 97,120, 95,115,112,101, +101,100, 0,108, 97,110,100, 95,109, 97,120, 95, 97, 99, 99, 0,108, 97,110,100, 95,109, 97,120, 95, 97,118,101, 0,108, 97,110, +100, 95,112,101,114,115,111,110, 97,108, 95,115,112, 97, 99,101, 0,108, 97,110,100, 95,115,116,105, 99,107, 95,102,111,114, 99, +101, 0,115,116, 97,116,101,115, 0, 42,115,109,100, 0, 42,102,108,117,105,100, 0, 42,102,108,117,105,100, 95,103,114,111,117, +112, 0, 42, 99,111,108,108, 95,103,114,111,117,112, 0, 42,119,116, 0, 42,116,101,120, 95,119,116, 0, 42,116,101,120, 95,115, +104, 97,100,111,119, 0, 42,115,104, 97,100,111,119, 0,112, 48, 91, 51, 93, 0,112, 49, 91, 51, 93, 0,100,120, 0,111,109,101, +103, 97, 0,116,101,109,112, 65,109, 98, 0, 98,101,116, 97, 0,114,101,115, 91, 51, 93, 0, 97,109,112,108,105,102,121, 0,109, + 97,120,114,101,115, 0,118,105,101,119,115,101,116,116,105,110,103,115, 0,110,111,105,115,101, 0,100,105,115,115, 95,112,101, +114, 99,101,110,116, 0,100,105,115,115, 95,115,112,101,101,100, 0,114,101,115, 95,119,116, 91, 51, 93, 0,100,120, 95,119,116, + 0,118, 51,100,110,117,109, 0, 42,112,111,105,110,116, 95, 99, 97, 99,104,101, 91, 50, 93, 0,112,116, 99, 97, 99,104,101,115, + 91, 50, 93, 0,118,101,108,111, 99,105,116,121, 91, 51, 93, 0,118,103,114,112, 95,104,101, 97,116, 95,115, 99, 97,108,101, 91, + 50, 93, 0,118,103,114,111,117,112, 95,102,108,111,119, 0,118,103,114,111,117,112, 95,100,101,110,115,105,116,121, 0,118,103, +114,111,117,112, 95,104,101, 97,116, 0, 42,112,111,105,110,116,115, 95,111,108,100, 0, 42,118,101,108, 0,109, 97,116, 95,111, +108,100, 91, 52, 93, 91, 52, 93, 0,110,117,109,112,111,105,110,116,115, 0, 0, 84, 89, 80, 69,191, 1, 0, 0, 99,104, 97,114, + 0,117, 99,104, 97,114, 0,115,104,111,114,116, 0,117,115,104,111,114,116, 0,105,110,116, 0,108,111,110,103, 0,117,108,111, +110,103, 0,102,108,111, 97,116, 0,100,111,117, 98,108,101, 0,118,111,105,100, 0, 76,105,110,107, 0, 76,105,110,107, 68, 97, +116, 97, 0, 76,105,115,116, 66, 97,115,101, 0,118,101, 99, 50,115, 0,118,101, 99, 50,105, 0,118,101, 99, 50,102, 0,118,101, + 99, 50,100, 0,118,101, 99, 51,105, 0,118,101, 99, 51,102, 0,118,101, 99, 51,100, 0,118,101, 99, 52,105, 0,118,101, 99, 52, +102, 0,118,101, 99, 52,100, 0,114, 99,116,105, 0,114, 99,116,102, 0, 73, 68, 80,114,111,112,101,114,116,121, 68, 97,116, 97, + 0, 73, 68, 80,114,111,112,101,114,116,121, 0, 73, 68, 0, 76,105, 98,114, 97,114,121, 0, 70,105,108,101, 68, 97,116, 97, 0, + 80,114,101,118,105,101,119, 73,109, 97,103,101, 0, 73,112,111, 68,114,105,118,101,114, 0, 79, 98,106,101, 99,116, 0, 73,112, +111, 67,117,114,118,101, 0, 66, 80,111,105,110,116, 0, 66,101,122, 84,114,105,112,108,101, 0, 73,112,111, 0, 75,101,121, 66, +108,111, 99,107, 0, 75,101,121, 0, 65,110,105,109, 68, 97,116, 97, 0, 84,101,120,116, 76,105,110,101, 0, 84,101,120,116, 77, + 97,114,107,101,114, 0, 84,101,120,116, 0, 80, 97, 99,107,101,100, 70,105,108,101, 0, 67, 97,109,101,114, 97, 0, 73,109, 97, +103,101, 85,115,101,114, 0, 83, 99,101,110,101, 0, 73,109, 97,103,101, 0, 71, 80, 85, 84,101,120,116,117,114,101, 0, 97,110, +105,109, 0, 82,101,110,100,101,114, 82,101,115,117,108,116, 0, 77, 84,101,120, 0, 84,101,120, 0, 80,108,117,103,105,110, 84, +101,120, 0, 67, 66, 68, 97,116, 97, 0, 67,111,108,111,114, 66, 97,110,100, 0, 69,110,118, 77, 97,112, 0, 73,109, 66,117,102, + 0, 80,111,105,110,116, 68,101,110,115,105,116,121, 0, 80, 97,114,116,105, 99,108,101, 83,121,115,116,101,109, 0, 86,111,120, +101,108, 68, 97,116, 97, 0, 98, 78,111,100,101, 84,114,101,101, 0, 84,101,120, 77, 97,112,112,105,110,103, 0, 76, 97,109,112, + 0, 67,117,114,118,101, 77, 97,112,112,105,110,103, 0, 87, 97,118,101, 0, 86,111,108,117,109,101, 83,101,116,116,105,110,103, +115, 0, 77, 97,116,101,114,105, 97,108, 0, 71,114,111,117,112, 0, 86, 70,111,110,116, 0, 86, 70,111,110,116, 68, 97,116, 97, + 0, 77,101,116, 97, 69,108,101,109, 0, 66,111,117,110,100, 66,111,120, 0, 77,101,116, 97, 66, 97,108,108, 0, 78,117,114, 98, + 0, 67,104, 97,114, 73,110,102,111, 0, 84,101,120,116, 66,111,120, 0, 67,117,114,118,101, 0, 80, 97,116,104, 0, 83,101,108, + 66,111,120, 0, 69,100,105,116, 70,111,110,116, 0, 77,101,115,104, 0, 77, 70, 97, 99,101, 0, 77, 84, 70, 97, 99,101, 0, 84, + 70, 97, 99,101, 0, 77, 86,101,114,116, 0, 77, 69,100,103,101, 0, 77, 68,101,102,111,114,109, 86,101,114,116, 0, 77, 67,111, +108, 0, 77, 83,116,105, 99,107,121, 0, 77, 83,101,108,101, 99,116, 0, 69,100,105,116, 77,101,115,104, 0, 67,117,115,116,111, +109, 68, 97,116, 97, 0, 77,117,108,116,105,114,101,115, 0, 80, 97,114,116,105, 97,108, 86,105,115,105, 98,105,108,105,116,121, + 0, 77, 68,101,102,111,114,109, 87,101,105,103,104,116, 0, 77, 84,101,120, 80,111,108,121, 0, 77, 76,111,111,112, 85, 86, 0, + 77, 76,111,111,112, 67,111,108, 0, 77, 70,108,111, 97,116, 80,114,111,112,101,114,116,121, 0, 77, 73,110,116, 80,114,111,112, +101,114,116,121, 0, 77, 83,116,114,105,110,103, 80,114,111,112,101,114,116,121, 0, 79,114,105,103, 83,112, 97, 99,101, 70, 97, + 99,101, 0, 77, 68,105,115,112,115, 0, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 69, 68, 71, 69, 68, 82, 65, 87, 32, 40, + 49, 60, 60, 49, 41, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 83, 69, 65, 77, 32, 40, 49, 60, 60, 50, 41, 32, 35,100,101, +102,105,110,101, 32, 77, 69, 95, 70, 71, 79, 78, 32, 40, 49, 60, 60, 51, 41, 32, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, + 69, 68, 71, 69, 82, 69, 78, 68, 69, 82, 32, 40, 49, 60, 60, 53, 41, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 76, 79, 79, + 83, 69, 69, 68, 71, 69, 32, 40, 49, 60, 60, 55, 41, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 83, 69, 65, 77, 95, 76, 65, + 83, 84, 32, 40, 49, 60, 60, 56, 41, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 83, 72, 65, 82, 80, 32, 40, 49, 60, 60, 57, + 41, 32, 32, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 70, 76, 73, 80, 86, 49, 32, 49, 32, 35,100,101,102,105,110,101, 32, + 77, 69, 95, 70, 76, 73, 80, 86, 50, 32, 50, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 70, 76, 73, 80, 86, 51, 32, 52, 32, + 35,100,101,102,105,110,101, 32, 77, 69, 95, 70, 76, 73, 80, 86, 52, 32, 56, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 80, + 82, 79, 74, 88, 89, 32, 49, 54, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 80, 82, 79, 74, 88, 90, 32, 51, 50, 32, 35,100, +101,102,105,110,101, 32, 77, 69, 95, 80, 82, 79, 74, 89, 90, 32, 54, 52, 32, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 86, + 49, 86, 50, 32, 49, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 86, 50, 86, 51, 32, 50, 32, 35,100,101,102,105,110,101, 32, + 77, 69, 95, 86, 51, 86, 49, 32, 52, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 86, 51, 86, 52, 32, 52, 32, 35,100,101,102, +105,110,101, 32, 77, 69, 95, 86, 52, 86, 49, 32, 56, 32, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 83, 77, 79, 79, 84, 72, + 32, 49, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 70, 65, 67, 69, 95, 83, 69, 76, 32, 50, 32, 32, 32, 35,100,101,102,105, +110,101, 32, 77, 69, 95, 86, 83, 69,108, 32, 48, 32, 35,100,101,102,105,110,101, 32, 77, 69, 95, 69, 83, 69,108, 32, 49, 32, 35, +100,101,102,105,110,101, 32, 77, 69, 95, 70, 83, 69, 76, 32, 50, 32, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 69, 76, + 69, 67, 84, 32, 49, 32, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 65, 67, 84, 73, 86, 69, 32, 50, 32, 32, 35,100,101,102, +105,110,101, 32, 84, 70, 95, 83, 69, 76, 49, 32, 52, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 69, 76, 50, 32, 56, 32, + 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 69, 76, 51, 32, 49, 54, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 69, + 76, 52, 32, 51, 50, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 72, 73, 68, 69, 32, 54, 52, 32, 32, 32, 35,100,101,102,105, +110,101, 32, 84, 70, 95, 68, 89, 78, 65, 77, 73, 67, 32, 49, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 65, 76, 80, 72, 65, + 83, 79, 82, 84, 32, 50, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 84, 69, 88, 32, 52, 32, 35,100,101,102,105,110,101, 32, + 84, 70, 95, 83, 72, 65, 82, 69, 68, 86, 69, 82, 84, 32, 56, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 76, 73, 71, 72, 84, + 32, 49, 54, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 72, 65, 82, 69, 68, 67, 79, 76, 32, 54, 52, 32, 35,100,101,102, +105,110,101, 32, 84, 70, 95, 84, 73, 76, 69, 83, 32, 49, 50, 56, 32, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 66, 73, 76, + 76, 66, 79, 65, 82, 68, 32, 50, 53, 54, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 84, 87, 79, 83, 73, 68, 69, 32, 53, 49, + 50, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 73, 78, 86, 73, 83, 73, 66, 76, 69, 32, 49, 48, 50, 52, 32, 35,100,101,102, +105,110,101, 32, 84, 70, 95, 79, 66, 67, 79, 76, 32, 50, 48, 52, 56, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 66, 73, 76, + 76, 66, 79, 65, 82, 68, 50, 32, 52, 48, 57, 54, 32, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 72, 65, 68, 79, 87, 32, + 56, 49, 57, 50, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 66, 77, 70, 79, 78, 84, 32, 49, 54, 51, 56, 52, 32, 32, 35,100, +101,102,105,110,101, 32, 84, 70, 95, 83, 79, 76, 73, 68, 32, 48, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 65, 68, 68, 32, + 49, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 65, 76, 80, 72, 65, 32, 50, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, + 67, 76, 73, 80, 32, 52, 32, 32, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 85, 66, 32, 51, 32, 32, 35,100,101,102,105, +110,101, 32, 84, 70, 95, 68, 69, 80, 82, 69, 67, 65, 84, 69, 68, 49, 32, 49, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 68, + 69, 80, 82, 69, 67, 65, 84, 69, 68, 50, 32, 50, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 68, 69, 80, 82, 69, 67, 65, 84, + 69, 68, 51, 32, 52, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 68, 69, 80, 82, 69, 67, 65, 84, 69, 68, 52, 32, 56, 32, 35, +100,101,102,105,110,101, 32, 84, 70, 95, 80, 73, 78, 49, 32, 49, 54, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 80, 73, 78, + 50, 32, 51, 50, 32, 35,100,101,102,105,110,101, 32, 84, 70, 95, 80, 73, 78, 51, 32, 54, 52, 32, 35,100,101,102,105,110,101, 32, + 84, 70, 95, 80, 73, 78, 52, 32, 49, 50, 56, 32, 35,101,110,100,105,102, 32,117,108,116,105,114,101,115, 76,101,118,101,108, 59, + 13, 10, 13, 10,116,121,112,101,100,101,102, 32,115,116,114,117, 99,116, 32, 77,117,108,116,105,114,101,115, 32,123, 13, 10, 9, + 76,105,115,116, 66, 97,115,101, 32,108,101,118,101,108,115, 59, 13, 10, 9, 77, 86,101,114,116, 32, 42,118,101,114,116,115, 59, + 13, 10, 13, 10, 9,117,110,115,105,103,110,101,100, 32, 99,104, 97,114, 32,108,101,118,101,108, 95, 99,111,117,110,116, 44, 32, + 99,117,114,114,101,110,116, 44, 32,110,101,119,108,118,108, 44, 32,101,100,103,101,108,118,108, 44, 32,112,105,110,108,118,108, + 44, 32,114,101,110,100,101,114,108,118,108, 59, 13, 10, 9,117,110,115,105,103,110,101,100, 32, 99,104, 97,114, 32,117,115,101, + 95, 99,111,108, 44, 32,102,108, 97,103, 59, 13, 10, 13, 10, 9, 47, 42, 32, 83,112,101, 99,105, 97,108, 32,108,101,118,101,108, + 32, 49, 32,100, 97,116, 97, 32,116,104, 97,116, 32, 99, 97,110,110,111,116, 32, 98,101, 32,109,111,100,105,102,105,101,100, 32, +102,114,111,109, 32,111,116,104,101,114, 32,108,101,118,101,108,115, 32, 42, 47, 13, 10, 9, 67,117,115,116,111,109, 68, 97,116, + 97, 32,118,100, 97,116, 97, 59, 13, 10, 9, 67,117,115,116,111,109, 68, 97,116, 97, 32,102,100, 97,116, 97, 59, 13, 10, 9,115, +104,111,114,116, 32, 42,101,100,103,101, 95,102,108, 97,103,115, 59, 13, 10, 9, 99,104, 97,114, 32, 42,101,100,103,101, 95, 99, +114,101, 97,115,101,115, 59, 13, 10,125, 32, 77,117,108,116,105,114,101,115, 59, 13, 10, 13, 10, 47, 42, 42, 32, 69,110,100, 32, + 77,117,108,116,105,114,101,115, 32, 42, 42, 47, 13, 10, 13, 10,116,121,112,101,100,101,102, 32,115,116,114,117, 99,116, 32, 80, + 97,114,116,105, 97,108, 86,105,115,105, 98,105,108,105,116,121, 32,123, 13, 10, 9,117,110,115,105,103,110,101,100, 32,105,110, +116, 32, 42,118,101,114,116, 95,109, 97,112, 59, 32, 47, 42, 32,118,101,114,116, 95,109, 97,112, 91, 79,108,100, 32, 73,110,100, +101,120, 93, 61, 32, 78,101,119, 32, 73,110,100,101,120, 32, 42, 47, 13, 10, 9,105,110,116, 32, 42,101,100,103,101, 95,109, 97, +112, 59, 32, 47, 42, 32,101,100,103,101, 95,109, 97,112, 91, 79,108,100, 32, 73,110,100,101,120, 93, 61, 32, 78,101,119, 32, 73, +110,100,101,120, 44, 32, 45, 49, 61, 32,104,105,100,100,101,110, 32, 42, 47, 13, 10, 9, 77, 70, 97, 99,101, 32, 42,111,108,100, + 95,102, 97, 99,101,115, 59, 13, 10, 9, 77, 69,100,103,101, 32, 42,111,108,100, 95,101,100,103,101,115, 59, 13, 10, 9,117,110, +115,105,103,110,101,100, 32,105,110,116, 32,116,111,116,102, 97, 99,101, 44, 32,116,111,116,101,100,103,101, 44, 32,116,111,116, +118,101,114,116, 44, 32,112, 97,100, 59, 13, 10,125, 32, 80, 97,114,116,105, 97,108, 86,105,115,105, 98,105,108,105,116,121, 59, + 13, 10, 13, 10, 47, 42, 32,109,118,101,114,116, 45, 62,102,108, 97,103, 32, 40, 49, 61, 83, 69, 76, 69, 67, 84, 41, 32, 42, 47, + 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 83, 80, 72, 69, 82, 69, 84, 69, 83, 84, 9, 50, 13, 10, 35,100,101,102,105, +110,101, 32, 77, 69, 95, 83, 80, 72, 69, 82, 69, 84, 69, 77, 80, 9, 52, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 72, + 73, 68, 69, 9, 9, 9, 49, 54, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 86, 69, 82, 84, 95, 77, 69, 82, 71, 69, 68, + 9, 9, 40, 49, 60, 60, 54, 41, 13, 10, 13, 10, 47, 42, 32,109,101,100,103,101, 45, 62,102,108, 97,103, 32, 40, 49, 61, 83, 69, + 76, 69, 67, 84, 41, 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 69, 68, 71, 69, 68, 82, 65, 87, 9, 9, 9, 40, + 49, 60, 60, 49, 41, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 83, 69, 65, 77, 9, 9, 9, 9, 40, 49, 60, 60, 50, 41, + 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 70, 71, 79, 78, 9, 9, 9, 9, 40, 49, 60, 60, 51, 41, 13, 10, 9, 9, 9, + 9, 9, 9, 47, 42, 32,114,101,115,101,114,118,101, 32, 49, 54, 32,102,111,114, 32, 77, 69, 95, 72, 73, 68, 69, 32, 42, 47, 13, + 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 69, 68, 71, 69, 82, 69, 78, 68, 69, 82, 9, 9, 40, 49, 60, 60, 53, 41, 13, 10, + 35,100,101,102,105,110,101, 32, 77, 69, 95, 76, 79, 79, 83, 69, 69, 68, 71, 69, 9, 9, 40, 49, 60, 60, 55, 41, 13, 10, 35,100, +101,102,105,110,101, 32, 77, 69, 95, 83, 69, 65, 77, 95, 76, 65, 83, 84, 9, 9, 40, 49, 60, 60, 56, 41, 13, 10, 35,100,101,102, +105,110,101, 32, 77, 69, 95, 83, 72, 65, 82, 80, 9, 9, 9, 40, 49, 60, 60, 57, 41, 13, 10, 13, 10, 47, 42, 32,112,117,110,111, + 32, 61, 32,118,101,114,116,101,120,110,111,114,109, 97,108, 32, 40,109,102, 97, 99,101, 41, 32, 42, 47, 13, 10, 47, 42, 32,114, +101,110,100,101,114, 32, 97,115,115,117,109,101,115, 32,102,108,105,112,115, 32,116,111, 32, 98,101, 32,111,114,100,101,114,101, +100, 32,108,105,107,101, 32,116,104,105,115, 32, 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 70, 76, 73, 80, 86, + 49, 9, 9, 49, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 70, 76, 73, 80, 86, 50, 9, 9, 50, 13, 10, 35,100,101,102, +105,110,101, 32, 77, 69, 95, 70, 76, 73, 80, 86, 51, 9, 9, 52, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 70, 76, 73, + 80, 86, 52, 9, 9, 56, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 80, 82, 79, 74, 88, 89, 9, 9, 49, 54, 13, 10, 35, +100,101,102,105,110,101, 32, 77, 69, 95, 80, 82, 79, 74, 88, 90, 9, 9, 51, 50, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, + 95, 80, 82, 79, 74, 89, 90, 9, 9, 54, 52, 13, 10, 13, 10, 47, 42, 32,101,100, 99,111,100,101, 32, 40,109,102, 97, 99,101, 41, + 32, 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 86, 49, 86, 50, 9, 9, 9, 49, 13, 10, 35,100,101,102,105,110, +101, 32, 77, 69, 95, 86, 50, 86, 51, 9, 9, 9, 50, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 86, 51, 86, 49, 9, 9, + 9, 52, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 86, 51, 86, 52, 9, 9, 9, 52, 13, 10, 35,100,101,102,105,110,101, + 32, 77, 69, 95, 86, 52, 86, 49, 9, 9, 9, 56, 13, 10, 13, 10, 47, 42, 32,102,108, 97,103, 32, 40,109,102, 97, 99,101, 41, 32, + 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 83, 77, 79, 79, 84, 72, 9, 9, 9, 49, 13, 10, 35,100,101,102,105, +110,101, 32, 77, 69, 95, 70, 65, 67, 69, 95, 83, 69, 76, 9, 9, 9, 50, 13, 10, 9, 9, 9, 9, 9, 9, 47, 42, 32,102,108, 97, +103, 32, 77, 69, 95, 72, 73, 68, 69, 61, 61, 49, 54, 32,105,115, 32,117,115,101,100, 32,104,101,114,101, 32,116,111,111, 32, 42, + 47, 32, 13, 10, 47, 42, 32,109,115,101,108,101, 99,116, 45, 62,116,121,112,101, 32, 42, 47, 13, 10, 35,100,101,102,105,110,101, + 32, 77, 69, 95, 86, 83, 69,108, 9, 48, 13, 10, 35,100,101,102,105,110,101, 32, 77, 69, 95, 69, 83, 69,108, 32, 49, 13, 10, 35, +100,101,102,105,110,101, 32, 77, 69, 95, 70, 83, 69, 76, 32, 50, 13, 10, 13, 10, 47, 42, 32,109,116,102, 97, 99,101, 45, 62,102, +108, 97,103, 32, 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 69, 76, 69, 67, 84, 9, 49, 32, 47, 42, 32,117, +115,101, 32, 77, 70, 97, 99,101, 32,104,105,100,101, 32,102,108, 97,103, 32, 40, 97,102,116,101,114, 32, 50, 46, 52, 51, 41, 44, + 32,115,104,111,117,108,100, 32, 98,101, 32, 97, 98,108,101, 32,116,111, 32,114,101,117,115,101, 32, 97,102,116,101,114, 32, 50, + 46, 52, 52, 32, 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 65, 67, 84, 73, 86, 69, 9, 50, 32, 47, 42, 32,100, +101,112,114,101, 99, 97,116,101,100, 33, 32, 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 69, 76, 49, 9, 9, + 52, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 69, 76, 50, 9, 9, 56, 13, 10, 35,100,101,102,105,110,101, 32, 84, + 70, 95, 83, 69, 76, 51, 9, 9, 49, 54, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 69, 76, 52, 9, 9, 51, 50, 13, + 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 72, 73, 68, 69, 9, 9, 54, 52, 32, 47, 42, 32,117,110,117,115,101,100, 44, 32, +115, 97,109,101, 32, 97,115, 32, 84, 70, 95, 83, 69, 76, 69, 67, 84, 32, 42, 47, 13, 10, 13, 10, 47, 42, 32,109,116,102, 97, 99, +101, 45, 62,109,111,100,101, 32, 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 68, 89, 78, 65, 77, 73, 67, 9, 9, + 49, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 65, 76, 80, 72, 65, 83, 79, 82, 84, 9, 50, 13, 10, 35,100,101,102,105, +110,101, 32, 84, 70, 95, 84, 69, 88, 9, 9, 9, 52, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 72, 65, 82, 69, 68, + 86, 69, 82, 84, 9, 56, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 76, 73, 71, 72, 84, 9, 9, 49, 54, 13, 10, 13, 10, + 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 72, 65, 82, 69, 68, 67, 79, 76, 9, 54, 52, 13, 10, 35,100,101,102,105,110,101, + 32, 84, 70, 95, 84, 73, 76, 69, 83, 9, 9, 49, 50, 56, 9, 9, 47, 42, 32,100,101,112,114,101, 99, 97,116,101,100, 32, 42, 47, + 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 66, 73, 76, 76, 66, 79, 65, 82, 68, 9, 50, 53, 54, 13, 10, 35,100,101,102, +105,110,101, 32, 84, 70, 95, 84, 87, 79, 83, 73, 68, 69, 9, 9, 53, 49, 50, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, + 73, 78, 86, 73, 83, 73, 66, 76, 69, 9, 49, 48, 50, 52, 13, 10, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 79, 66, 67, + 79, 76, 9, 9, 50, 48, 52, 56, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 66, 73, 76, 76, 66, 79, 65, 82, 68, 50, 9, + 52, 48, 57, 54, 9, 47, 42, 32,119,105,116,104, 32, 90, 32, 97,120,105,115, 32, 99,111,110,115,116,114, 97,105,110,116, 32, 42, + 47, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 83, 72, 65, 68, 79, 87, 9, 9, 56, 49, 57, 50, 13, 10, 35,100,101,102, +105,110,101, 32, 84, 70, 95, 66, 77, 70, 79, 78, 84, 9, 9, 49, 54, 51, 56, 52, 13, 10, 13, 10, 47, 42, 32,109,116,102, 97, 99, +101, 45, 62,116,114, 97,110,115,112, 44, 32,118, 97,108,117,101,115, 32, 49, 45, 52, 32, 97,114,101, 32,117,115,101,100, 32, 97, +115, 32,102,108, 97,103,115, 32,105,110, 32,116,104,101, 32, 71, 76, 44, 32, 87, 65, 82, 78, 73, 78, 71, 44, 32, 84, 70, 95, 83, + 85, 66, 32, 99, 97,110,116, 32,119,111,114,107, 32,119,105,116,104, 32,116,104,105,115, 32, 42, 47, 13, 10, 35,100,101,102,105, +110,101, 32, 84, 70, 95, 83, 79, 76, 73, 68, 9, 48, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 65, 68, 68, 9, 9, 49, + 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 65, 76, 80, 72, 65, 9, 50, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, + 95, 67, 76, 73, 80, 9, 9, 52, 32, 47, 42, 32, 99,108,105,112,109, 97,112, 32, 97,108,112,104, 97, 47, 98,105,110, 97,114,121, + 32, 97,108,112,104, 97, 32, 97,108,108, 32,111,114, 32,110,111,116,104,105,110,103, 33, 32, 42, 47, 13, 10, 13, 10, 47, 42, 32, +115,117, 98, 32,105,115, 32,110,111,116, 32, 97,118, 97,105,108, 97, 98,108,101, 32,105,110, 32,116,104,101, 32,117,115,101,114, + 32,105,110,116,101,114,102, 97, 99,101, 32, 97,110,121,109,111,114,101, 32, 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 84, + 70, 95, 83, 85, 66, 9, 9, 51, 13, 10, 13, 10, 13, 10, 47, 42, 32,109,116,102, 97, 99,101, 45, 62,117,110,119,114, 97,112, 32, + 42, 47, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 68, 69, 80, 82, 69, 67, 65, 84, 69, 68, 49, 9, 49, 13, 10, 35,100, +101,102,105,110,101, 32, 84, 70, 95, 68, 69, 80, 82, 69, 67, 65, 84, 69, 68, 50, 9, 50, 13, 10, 35,100,101,102,105,110,101, 32, + 84, 70, 95, 68, 69, 80, 82, 69, 67, 65, 84, 69, 68, 51, 9, 52, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 68, 69, 80, + 82, 69, 67, 65, 84, 69, 68, 52, 9, 56, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 80, 73, 78, 49, 9, 9, 32, 32, 32, + 32, 49, 54, 13, 10, 35,100,101,102,105,110,101, 32, 84, 70, 95, 80, 73, 78, 50, 9, 9, 32, 32, 32, 32, 51, 50, 13, 10, 35,100, +101,102,105,110,101, 32, 84, 70, 95, 80, 73, 78, 51, 9, 32, 32, 32, 9, 9, 54, 52, 13, 10, 35,100,101,102,105,110,101, 32, 84, + 70, 95, 80, 73, 78, 52, 9, 32, 32, 32, 32, 9, 49, 50, 56, 13, 10, 13, 10, 35,101,110,100,105,102, 13, 10,104, 79, 67, 75, 33, +109, 98,101,114, 82,163, 81,172,147,203, 19, 0, 77,117,108,116,105,114,101,115, 67,111,108, 0, 77,117,108,116,105,114,101,115, 67,111,108, 70, 97, 99,101, 0, 77,117,108,116,105,114,101,115, 70, 97, 99,101, 0, 77,117,108,116,105,114,101,115, 69,100,103, 101, 0, 77,117,108,116,105,114,101,115, 76,101,118,101,108, 0, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 83,117, 98, 115,117,114,102, 77,111,100,105,102,105,101,114, 68, 97,116, 97, 0, 76, 97,116,116,105, 99,101, 77,111,100,105,102,105,101,114, @@ -2374,770 +2420,787 @@ char datatoc_B_blend[]= { 76, 97,116,116,105, 99,101, 0, 98, 68,101,102,111,114,109, 71,114,111,117,112, 0, 83, 99,117,108,112,116, 83,101,115,115,105, 111,110, 0, 98, 65, 99,116,105,111,110, 0, 98, 80,111,115,101, 0, 98, 71, 80,100, 97,116, 97, 0, 66,117,108,108,101,116, 83, 111,102,116, 66,111,100,121, 0, 80, 97,114,116, 68,101,102,108,101, 99,116, 0, 83,111,102,116, 66,111,100,121, 0, 79, 98, 72, -111,111,107, 0, 82, 78, 71, 0, 80, 84, 67, 97, 99,104,101, 77,101,109, 0, 80, 84, 67, 97, 99,104,101, 69,100,105,116, 0, 83, - 66, 86,101,114,116,101,120, 0, 66,111,100,121, 80,111,105,110,116, 0, 66,111,100,121, 83,112,114,105,110,103, 0, 83, 66, 83, - 99,114, 97,116, 99,104, 0, 87,111,114,108,100, 0, 66, 97,115,101, 0, 65,118,105, 67,111,100,101, 99, 68, 97,116, 97, 0, 81, -117,105, 99,107,116,105,109,101, 67,111,100,101, 99, 68, 97,116, 97, 0, 70, 70, 77,112,101,103, 67,111,100,101, 99, 68, 97,116, - 97, 0, 65,117,100,105,111, 68, 97,116, 97, 0, 83, 99,101,110,101, 82,101,110,100,101,114, 76, 97,121,101,114, 0, 82,101,110, -100,101,114, 68, 97,116, 97, 0, 82,101,110,100,101,114, 80,114,111,102,105,108,101, 0, 71, 97,109,101, 68,111,109,101, 0, 71, - 97,109,101, 70,114, 97,109,105,110,103, 0, 71, 97,109,101, 68, 97,116, 97, 0, 84,105,109,101, 77, 97,114,107,101,114, 0, 80, - 97,105,110,116, 0, 66,114,117,115,104, 0, 73,109, 97,103,101, 80, 97,105,110,116, 83,101,116,116,105,110,103,115, 0, 80, 97, -114,116,105, 99,108,101, 66,114,117,115,104, 68, 97,116, 97, 0, 80, 97,114,116,105, 99,108,101, 69,100,105,116, 83,101,116,116, -105,110,103,115, 0, 84,114, 97,110,115,102,111,114,109, 79,114,105,101,110,116, 97,116,105,111,110, 0, 83, 99,117,108,112,116, - 0, 86, 80, 97,105,110,116, 0, 84,111,111,108, 83,101,116,116,105,110,103,115, 0, 98, 83,116, 97,116,115, 0, 85,110,105,116, - 83,101,116,116,105,110,103,115, 0, 69,100,105,116,105,110,103, 0, 83, 99,101,110,101, 83,116, 97,116,115, 0, 68, 97,103, 70, -111,114,101,115,116, 0, 66, 71,112,105, 99, 0, 82,101,103,105,111,110, 86,105,101,119, 51, 68, 0, 82,101,110,100,101,114, 73, -110,102,111, 0, 82,101,116,111,112,111, 86,105,101,119, 68, 97,116, 97, 0, 86,105,101,119, 68,101,112,116,104,115, 0, 83,109, -111,111,116,104, 86,105,101,119, 83,116,111,114,101, 0,119,109, 84,105,109,101,114, 0, 86,105,101,119, 51, 68, 0, 83,112, 97, - 99,101, 76,105,110,107, 0, 86,105,101,119, 50, 68, 0, 83,112, 97, 99,101, 73,110,102,111, 0, 98, 83, 99,114,101,101,110, 0, - 83,112, 97, 99,101, 73,112,111, 0, 98, 68,111,112,101, 83,104,101,101,116, 0, 83,112, 97, 99,101, 66,117,116,115, 0, 83,112, - 97, 99,101, 83,101,113, 0, 70,105,108,101, 83,101,108,101, 99,116, 80, 97,114, 97,109,115, 0, 83,112, 97, 99,101, 70,105,108, -101, 0, 70,105,108,101, 76,105,115,116, 0,119,109, 79,112,101,114, 97,116,111,114, 0, 70,105,108,101, 76, 97,121,111,117,116, - 0, 83,112, 97, 99,101, 79,111,112,115, 0, 84,114,101,101, 83,116,111,114,101, 0, 84,114,101,101, 83,116,111,114,101, 69,108, -101,109, 0, 83,112, 97, 99,101, 73,109, 97,103,101, 0, 83,112, 97, 99,101, 78,108, 97, 0, 83,112, 97, 99,101, 84,101,120,116, - 0, 83, 99,114,105,112,116, 0, 83,112, 97, 99,101, 83, 99,114,105,112,116, 0, 83,112, 97, 99,101, 84,105,109,101, 0, 83,112, - 97, 99,101, 78,111,100,101, 0, 83,112, 97, 99,101, 76,111,103,105, 99, 0, 83,112, 97, 99,101, 73,109, 97, 83,101,108, 0, 67, -111,110,115,111,108,101, 76,105,110,101, 0, 83,112, 97, 99,101, 67,111,110,115,111,108,101, 0, 83,112, 97, 99,101, 85,115,101, -114, 80,114,101,102, 0,117,105, 70,111,110,116, 0,117,105, 70,111,110,116, 83,116,121,108,101, 0,117,105, 83,116,121,108,101, - 0,117,105, 87,105,100,103,101,116, 67,111,108,111,114,115, 0,117,105, 87,105,100,103,101,116, 83,116, 97,116,101, 67,111,108, -111,114,115, 0, 84,104,101,109,101, 85, 73, 0, 84,104,101,109,101, 83,112, 97, 99,101, 0, 84,104,101,109,101, 87,105,114,101, - 67,111,108,111,114, 0, 98, 84,104,101,109,101, 0, 83,111,108,105,100, 76,105,103,104,116, 0, 85,115,101,114, 68,101,102, 0, - 83, 99,114, 86,101,114,116, 0, 83, 99,114, 69,100,103,101, 0, 80, 97,110,101,108, 0, 80, 97,110,101,108, 84,121,112,101, 0, -117,105, 76, 97,121,111,117,116, 0, 83, 99,114, 65,114,101, 97, 0, 83,112, 97, 99,101, 84,121,112,101, 0, 65, 82,101,103,105, -111,110, 0, 65, 82,101,103,105,111,110, 84,121,112,101, 0, 70,105,108,101, 71,108,111, 98, 97,108, 0, 83,116,114,105,112, 69, -108,101,109, 0, 84, 83,116,114,105,112, 69,108,101,109, 0, 83,116,114,105,112, 67,114,111,112, 0, 83,116,114,105,112, 84,114, - 97,110,115,102,111,114,109, 0, 83,116,114,105,112, 67,111,108,111,114, 66, 97,108, 97,110, 99,101, 0, 83,116,114,105,112, 80, -114,111,120,121, 0, 83,116,114,105,112, 0, 80,108,117,103,105,110, 83,101,113, 0, 83,101,113,117,101,110, 99,101, 0, 98, 83, -111,117,110,100, 0, 83,111,117,110,100, 72, 97,110,100,108,101, 0, 77,101,116, 97, 83,116, 97, 99,107, 0, 87,105,112,101, 86, - 97,114,115, 0, 71,108,111,119, 86, 97,114,115, 0, 84,114, 97,110,115,102,111,114,109, 86, 97,114,115, 0, 83,111,108,105,100, - 67,111,108,111,114, 86, 97,114,115, 0, 83,112,101,101,100, 67,111,110,116,114,111,108, 86, 97,114,115, 0, 69,102,102,101, 99, -116, 0, 66,117,105,108,100, 69,102,102, 0, 80, 97,114,116, 69,102,102, 0, 80, 97,114,116,105, 99,108,101, 0, 87, 97,118,101, - 69,102,102, 0, 98, 80,114,111,112,101,114,116,121, 0, 98, 78,101, 97,114, 83,101,110,115,111,114, 0, 98, 77,111,117,115,101, - 83,101,110,115,111,114, 0, 98, 84,111,117, 99,104, 83,101,110,115,111,114, 0, 98, 75,101,121, 98,111, 97,114,100, 83,101,110, -115,111,114, 0, 98, 80,114,111,112,101,114,116,121, 83,101,110,115,111,114, 0, 98, 65, 99,116,117, 97,116,111,114, 83,101,110, -115,111,114, 0, 98, 68,101,108, 97,121, 83,101,110,115,111,114, 0, 98, 67,111,108,108,105,115,105,111,110, 83,101,110,115,111, -114, 0, 98, 82, 97,100, 97,114, 83,101,110,115,111,114, 0, 98, 82, 97,110,100,111,109, 83,101,110,115,111,114, 0, 98, 82, 97, -121, 83,101,110,115,111,114, 0, 98, 77,101,115,115, 97,103,101, 83,101,110,115,111,114, 0, 98, 83,101,110,115,111,114, 0, 98, - 67,111,110,116,114,111,108,108,101,114, 0, 98, 74,111,121,115,116,105, 99,107, 83,101,110,115,111,114, 0, 98, 69,120,112,114, -101,115,115,105,111,110, 67,111,110,116, 0, 98, 80,121,116,104,111,110, 67,111,110,116, 0, 98, 65, 99,116,117, 97,116,111,114, - 0, 98, 65,100,100, 79, 98,106,101, 99,116, 65, 99,116,117, 97,116,111,114, 0, 98, 65, 99,116,105,111,110, 65, 99,116,117, 97, -116,111,114, 0, 98, 83,111,117,110,100, 65, 99,116,117, 97,116,111,114, 0, 83,111,117,110,100, 51, 68, 0, 98, 69,100,105,116, - 79, 98,106,101, 99,116, 65, 99,116,117, 97,116,111,114, 0, 98, 83, 99,101,110,101, 65, 99,116,117, 97,116,111,114, 0, 98, 80, -114,111,112,101,114,116,121, 65, 99,116,117, 97,116,111,114, 0, 98, 79, 98,106,101, 99,116, 65, 99,116,117, 97,116,111,114, 0, - 98, 73,112,111, 65, 99,116,117, 97,116,111,114, 0, 98, 67, 97,109,101,114, 97, 65, 99,116,117, 97,116,111,114, 0, 98, 67,111, -110,115,116,114, 97,105,110,116, 65, 99,116,117, 97,116,111,114, 0, 98, 71,114,111,117,112, 65, 99,116,117, 97,116,111,114, 0, - 98, 82, 97,110,100,111,109, 65, 99,116,117, 97,116,111,114, 0, 98, 77,101,115,115, 97,103,101, 65, 99,116,117, 97,116,111,114, - 0, 98, 71, 97,109,101, 65, 99,116,117, 97,116,111,114, 0, 98, 86,105,115,105, 98,105,108,105,116,121, 65, 99,116,117, 97,116, -111,114, 0, 98, 84,119,111, 68, 70,105,108,116,101,114, 65, 99,116,117, 97,116,111,114, 0, 98, 80, 97,114,101,110,116, 65, 99, -116,117, 97,116,111,114, 0, 98, 83,116, 97,116,101, 65, 99,116,117, 97,116,111,114, 0, 70,114,101,101, 67, 97,109,101,114, 97, - 0, 83,112, 97, 99,101, 83,111,117,110,100, 0, 71,114,111,117,112, 79, 98,106,101, 99,116, 0, 66,111,110,101, 0, 98, 65,114, -109, 97,116,117,114,101, 0, 98, 77,111,116,105,111,110, 80, 97,116,104, 86,101,114,116, 0, 98, 77,111,116,105,111,110, 80, 97, -116,104, 0, 98, 65,110,105,109, 86,105,122, 83,101,116,116,105,110,103,115, 0, 98, 80,111,115,101, 67,104, 97,110,110,101,108, - 0, 98, 65, 99,116,105,111,110, 71,114,111,117,112, 0, 83,112, 97, 99,101, 65, 99,116,105,111,110, 0, 98, 65, 99,116,105,111, -110, 67,104, 97,110,110,101,108, 0, 98, 67,111,110,115,116,114, 97,105,110,116, 67,104, 97,110,110,101,108, 0, 98, 67,111,110, -115,116,114, 97,105,110,116, 0, 98, 67,111,110,115,116,114, 97,105,110,116, 84, 97,114,103,101,116, 0, 98, 80,121,116,104,111, -110, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 75,105,110,101,109, 97,116,105, 99, 67,111,110,115,116,114, 97,105,110,116, - 0, 98, 84,114, 97, 99,107, 84,111, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 82,111,116, 97,116,101, 76,105,107,101, 67, -111,110,115,116,114, 97,105,110,116, 0, 98, 76,111, 99, 97,116,101, 76,105,107,101, 67,111,110,115,116,114, 97,105,110,116, 0, - 98, 77,105,110, 77, 97,120, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 83,105,122,101, 76,105,107,101, 67,111,110,115,116, -114, 97,105,110,116, 0, 98, 65, 99,116,105,111,110, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 76,111, 99,107, 84,114, 97, - 99,107, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 70,111,108,108,111,119, 80, 97,116,104, 67,111,110,115,116,114, 97,105, -110,116, 0, 98, 83,116,114,101,116, 99,104, 84,111, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 82,105,103,105,100, 66,111, -100,121, 74,111,105,110,116, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 67,108, 97,109,112, 84,111, 67,111,110,115,116,114, - 97,105,110,116, 0, 98, 67,104,105,108,100, 79,102, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 84,114, 97,110,115,102,111, -114,109, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 76,111, 99, 76,105,109,105,116, 67,111,110,115,116,114, 97,105,110,116, - 0, 98, 82,111,116, 76,105,109,105,116, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 83,105,122,101, 76,105,109,105,116, 67, -111,110,115,116,114, 97,105,110,116, 0, 98, 68,105,115,116, 76,105,109,105,116, 67,111,110,115,116,114, 97,105,110,116, 0, 98, - 83,104,114,105,110,107,119,114, 97,112, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 65, 99,116,105,111,110, 77,111,100,105, -102,105,101,114, 0, 98, 65, 99,116,105,111,110, 83,116,114,105,112, 0, 98, 78,111,100,101, 83,116, 97, 99,107, 0, 98, 78,111, -100,101, 83,111, 99,107,101,116, 0, 98, 78,111,100,101, 76,105,110,107, 0, 98, 78,111,100,101, 0, 98, 78,111,100,101, 80,114, -101,118,105,101,119, 0, 98, 78,111,100,101, 84,121,112,101, 0, 78,111,100,101, 73,109, 97,103,101, 65,110,105,109, 0, 78,111, -100,101, 66,108,117,114, 68, 97,116, 97, 0, 78,111,100,101, 68, 66,108,117,114, 68, 97,116, 97, 0, 78,111,100,101, 66,105,108, - 97,116,101,114, 97,108, 66,108,117,114, 68, 97,116, 97, 0, 78,111,100,101, 72,117,101, 83, 97,116, 0, 78,111,100,101, 73,109, - 97,103,101, 70,105,108,101, 0, 78,111,100,101, 67,104,114,111,109, 97, 0, 78,111,100,101, 84,119,111, 88, 89,115, 0, 78,111, -100,101, 84,119,111, 70,108,111, 97,116,115, 0, 78,111,100,101, 71,101,111,109,101,116,114,121, 0, 78,111,100,101, 86,101,114, -116,101,120, 67,111,108, 0, 78,111,100,101, 68,101,102,111, 99,117,115, 0, 78,111,100,101, 83, 99,114,105,112,116, 68,105, 99, -116, 0, 78,111,100,101, 71,108, 97,114,101, 0, 78,111,100,101, 84,111,110,101,109, 97,112, 0, 78,111,100,101, 76,101,110,115, - 68,105,115,116, 0, 84,101,120, 78,111,100,101, 79,117,116,112,117,116, 0, 67,117,114,118,101, 77, 97,112, 80,111,105,110,116, - 0, 67,117,114,118,101, 77, 97,112, 0, 66,114,117,115,104, 67,108,111,110,101, 0, 67,117,115,116,111,109, 68, 97,116, 97, 76, - 97,121,101,114, 0, 72, 97,105,114, 75,101,121, 0, 80, 97,114,116,105, 99,108,101, 75,101,121, 0, 66,111,105,100, 80, 97,114, -116,105, 99,108,101, 0, 66,111,105,100, 68, 97,116, 97, 0, 67,104,105,108,100, 80, 97,114,116,105, 99,108,101, 0, 80, 97,114, -116,105, 99,108,101, 84, 97,114,103,101,116, 0, 80, 97,114,116,105, 99,108,101, 68, 97,116, 97, 0, 80, 97,114,116,105, 99,108, -101, 83,101,116,116,105,110,103,115, 0, 66,111,105,100, 83,101,116,116,105,110,103,115, 0, 80, 97,114,116,105, 99,108,101, 67, - 97, 99,104,101, 75,101,121, 0, 75, 68, 84,114,101,101, 0, 76,105,110,107, 78,111,100,101, 0, 98, 71, 80, 68,115,112,111,105, -110,116, 0, 98, 71, 80, 68,115,116,114,111,107,101, 0, 98, 71, 80, 68,102,114, 97,109,101, 0, 98, 71, 80, 68,108, 97,121,101, -114, 0, 82,101,112,111,114,116, 0, 82,101,112,111,114,116, 76,105,115,116, 0,119,109, 87,105,110,100,111,119, 77, 97,110, 97, -103,101,114, 0,119,109, 87,105,110,100,111,119, 0,119,109, 69,118,101,110,116, 0,119,109, 83,117, 98, 87,105,110,100,111,119, - 0,119,109, 71,101,115,116,117,114,101, 0,119,109, 75,101,121,109, 97,112, 73,116,101,109, 0, 80,111,105,110,116,101,114, 82, - 78, 65, 0,119,109, 75,101,121, 77, 97,112, 0,119,109, 79,112,101,114, 97,116,111,114, 84,121,112,101, 0, 70, 77,111,100,105, -102,105,101,114, 0, 70, 77,111,100, 95, 71,101,110,101,114, 97,116,111,114, 0, 70, 77,111,100, 95, 70,117,110, 99,116,105,111, -110, 71,101,110,101,114, 97,116,111,114, 0, 70, 67, 77, 95, 69,110,118,101,108,111,112,101, 68, 97,116, 97, 0, 70, 77,111,100, - 95, 69,110,118,101,108,111,112,101, 0, 70, 77,111,100, 95, 67,121, 99,108,101,115, 0, 70, 77,111,100, 95, 80,121,116,104,111, -110, 0, 70, 77,111,100, 95, 76,105,109,105,116,115, 0, 70, 77,111,100, 95, 78,111,105,115,101, 0, 68,114,105,118,101,114, 84, - 97,114,103,101,116, 0, 67,104, 97,110,110,101,108, 68,114,105,118,101,114, 0, 70, 80,111,105,110,116, 0, 70, 67,117,114,118, -101, 0, 65,110,105,109, 77, 97,112, 80, 97,105,114, 0, 65,110,105,109, 77, 97,112,112,101,114, 0, 78,108, 97, 83,116,114,105, -112, 0, 78,108, 97, 84,114, 97, 99,107, 0, 75, 83, 95, 80, 97,116,104, 0, 75,101,121,105,110,103, 83,101,116, 0, 65,110,105, -109, 79,118,101,114,114,105,100,101, 0, 73,100, 65,100,116, 84,101,109,112,108, 97,116,101, 0, 66,111,105,100, 82,117,108,101, - 0, 66,111,105,100, 82,117,108,101, 71,111, 97,108, 65,118,111,105,100, 0, 66,111,105,100, 82,117,108,101, 65,118,111,105,100, - 67,111,108,108,105,115,105,111,110, 0, 66,111,105,100, 82,117,108,101, 70,111,108,108,111,119, 76,101, 97,100,101,114, 0, 66, -111,105,100, 82,117,108,101, 65,118,101,114, 97,103,101, 83,112,101,101,100, 0, 66,111,105,100, 82,117,108,101, 70,105,103,104, -116, 0, 66,111,105,100, 83,116, 97,116,101, 0, 70, 76, 85, 73, 68, 95, 51, 68, 0, 87, 84, 85, 82, 66, 85, 76, 69, 78, 67, 69, - 0, 0, 0, 0, 84, 76, 69, 78, 1, 0, 1, 0, 2, 0, 2, 0, 4, 0, 4, 0, 4, 0, 4, 0, 8, 0, 0, 0, 8, 0, 12, 0, - 8, 0, 4, 0, 8, 0, 8, 0, 16, 0, 12, 0, 12, 0, 24, 0, 16, 0, 16, 0, 32, 0, 16, 0, 16, 0, 20, 0, 76, 0, 52, 0, - 40, 2, 0, 0, 32, 0,140, 0,100, 3, 92, 0, 36, 0, 56, 0, 84, 0,112, 0,124, 0, 56, 0, 24, 0, 40, 0,120, 0, 12, 0, -120, 0, 36, 0, 92, 5,128, 1, 0, 0, 0, 0, 0, 0,144, 0, 40, 1, 84, 1, 24, 0, 8, 3,168, 0, 0, 0, 76, 0,128, 1, - 24, 1,140, 0,132, 0,124, 1, 8, 1, 56, 0, 88, 0,184, 2, 76, 0, 60, 1, 0, 0,108, 0,104, 0,148, 0, 56, 0, 8, 0, - 16, 0, 92, 1, 0, 0, 0, 0, 0, 0, 24, 1, 20, 0, 44, 0, 60, 0, 24, 0, 12, 0, 12, 0, 4, 0, 8, 0, 8, 0, 0, 0, - 24, 0, 76, 0, 32, 0, 8, 0, 12, 0, 8, 0, 8, 0, 4, 0, 4, 0, 0, 1, 32, 0, 12, 0, 0, 0, 16, 0, 64, 0, 24, 0, - 12, 0, 40, 0, 56, 0, 72, 0, 92, 0,100, 0, 72, 0,100, 0,120, 0, 68, 0, 64, 0,112, 0, 64, 0, 76, 0,176, 0, 48, 0, -168, 0,152, 0,156, 0, 64, 0, 96, 0,108, 0,188, 0,104, 0,216, 0, 56, 0, 84, 0, 0, 0,132, 0, 28, 0,240, 1,104, 0, - 0, 0, 80, 0, 0, 0, 0, 0, 68, 0, 8, 0, 8, 0,220, 0, 80, 0, 76, 0, 68, 0, 68, 0, 64, 0,164, 1,112, 0,108, 0, -188, 0, 40, 0, 0, 0, 92, 0, 56, 0, 72, 0,120, 0,128, 0,252, 0,208, 0, 0, 0, 92, 0, 0, 0, 16, 0, 0, 0, 0, 0, - 0, 0,104, 1, 28, 0,176, 0,144, 0, 52, 0, 16, 0, 72, 0, 0, 4, 56, 0, 20, 0, 16, 0, 92, 0, 80, 0, 24, 0,196, 0, - 36, 0, 8, 0,100, 0, 80, 0, 48, 0, 52, 0, 72, 1, 32, 0, 8, 0, 24, 2, 0, 0, 0, 0, 56, 0,216, 2, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,240, 0, 40, 0,148, 0, 48, 0,140, 0,208, 0, 20, 0,224, 0,216, 0,204, 1, 60, 0, 0, 0,112, 0, - 0, 0, 4, 1, 12, 0, 12, 0,136, 0,200, 0,124, 2, 80, 2, 40, 0,180, 0,244, 0, 52, 0,148, 2, 28, 0, 80, 0, 24, 0, - 16, 1, 32, 0,224, 0, 32, 0, 32, 0, 80, 2, 16, 1, 16, 0,200, 21, 56, 0, 56, 11, 20, 0, 24, 0, 56, 1, 0, 0, 0, 0, - 96, 0, 0, 0,248, 0, 0, 0, 32, 0, 80, 0, 28, 0, 16, 0, 8, 0, 52, 0,252, 0,240, 0,168, 1,196, 0, 8, 1, 48, 0, - 16, 0, 12, 0, 24, 0, 48, 0, 16, 0, 20, 0, 16, 0, 24, 0, 56, 1, 0, 0, 56, 0, 52, 0, 48, 0, 8, 0, 44, 0, 72, 0, -104, 0, 40, 0, 8, 0, 72, 0, 44, 0, 40, 0,108, 0, 68, 0, 76, 0, 80, 0, 60, 0,128, 0, 76, 0, 60, 0, 12, 0, 92, 0, - 68, 0, 32, 0, 80, 0, 16, 0, 76, 0,108, 0, 84, 0, 28, 0, 96, 0, 60, 0, 56, 0,108, 0,140, 0, 4, 0, 20, 0, 12, 0, - 8, 0, 40, 0,196, 0, 24, 0, 4, 1,124, 0, 16, 0, 20, 0, 24, 0,172, 1,104, 0,228, 0, 64, 0, 44, 0, 64, 0,116, 0, - 60, 0,104, 0, 52, 0, 44, 0, 44, 0, 68, 0, 44, 0, 64, 0, 44, 0, 20, 0, 52, 0, 96, 0, 12, 0,108, 0, 92, 0, 28, 0, - 28, 0, 28, 0, 52, 0, 20, 0, 60, 0,140, 0, 36, 0,120, 0, 32, 0,208, 0, 0, 0, 0, 0, 16, 0, 40, 0, 28, 0, 12, 0, - 12, 0, 16, 1, 40, 0, 8, 0, 8, 0, 64, 0, 32, 0, 24, 0, 8, 0, 24, 0, 32, 0, 8, 0, 32, 0, 12, 0, 44, 0, 20, 0, - 68, 0, 24, 0, 56, 0, 52, 0, 20, 0, 72, 0, 28, 0,180, 0,208, 1, 96, 0, 0, 0, 0, 0, 0, 0, 16, 0, 20, 0, 24, 0, -172, 0, 24, 0, 24, 0,140, 0,148, 0, 56, 0, 0, 0, 0, 0,100, 0, 0, 0, 92, 0, 0, 0, 88, 0, 20, 0, 24, 0, 16, 0, - 20, 0, 8, 0, 8, 0, 24, 0, 20, 0, 88, 0, 24, 1, 16, 0, 68, 0, 0, 1, 20, 0,160, 0, 88, 0, 96, 0, 88, 0, 20, 0, - 56, 0, 48, 0, 68, 0, 56, 0, 92, 0, 64, 0, 56, 0, 96, 0, 0, 0, 0, 0, 83, 84, 82, 67,126, 1, 0, 0, 10, 0, 2, 0, - 10, 0, 0, 0, 10, 0, 1, 0, 11, 0, 3, 0, 11, 0, 0, 0, 11, 0, 1, 0, 9, 0, 2, 0, 12, 0, 2, 0, 9, 0, 3, 0, - 9, 0, 4, 0, 13, 0, 2, 0, 2, 0, 5, 0, 2, 0, 6, 0, 14, 0, 2, 0, 4, 0, 5, 0, 4, 0, 6, 0, 15, 0, 2, 0, - 7, 0, 5, 0, 7, 0, 6, 0, 16, 0, 2, 0, 8, 0, 5, 0, 8, 0, 6, 0, 17, 0, 3, 0, 4, 0, 5, 0, 4, 0, 6, 0, - 4, 0, 7, 0, 18, 0, 3, 0, 7, 0, 5, 0, 7, 0, 6, 0, 7, 0, 7, 0, 19, 0, 3, 0, 8, 0, 5, 0, 8, 0, 6, 0, - 8, 0, 7, 0, 20, 0, 4, 0, 4, 0, 5, 0, 4, 0, 6, 0, 4, 0, 7, 0, 4, 0, 8, 0, 21, 0, 4, 0, 7, 0, 5, 0, - 7, 0, 6, 0, 7, 0, 7, 0, 7, 0, 8, 0, 22, 0, 4, 0, 8, 0, 5, 0, 8, 0, 6, 0, 8, 0, 7, 0, 8, 0, 8, 0, - 23, 0, 4, 0, 4, 0, 9, 0, 4, 0, 10, 0, 4, 0, 11, 0, 4, 0, 12, 0, 24, 0, 4, 0, 7, 0, 9, 0, 7, 0, 10, 0, - 7, 0, 11, 0, 7, 0, 12, 0, 25, 0, 4, 0, 9, 0, 13, 0, 12, 0, 14, 0, 4, 0, 15, 0, 4, 0, 16, 0, 26, 0, 10, 0, - 26, 0, 0, 0, 26, 0, 1, 0, 0, 0, 17, 0, 0, 0, 18, 0, 2, 0, 19, 0, 0, 0, 20, 0, 4, 0, 21, 0, 25, 0, 22, 0, - 4, 0, 23, 0, 4, 0, 24, 0, 27, 0, 9, 0, 9, 0, 0, 0, 9, 0, 1, 0, 27, 0, 25, 0, 28, 0, 26, 0, 0, 0, 27, 0, - 2, 0, 28, 0, 2, 0, 19, 0, 4, 0, 29, 0, 26, 0, 30, 0, 28, 0, 8, 0, 27, 0, 31, 0, 27, 0, 32, 0, 29, 0, 33, 0, - 0, 0, 34, 0, 0, 0, 35, 0, 4, 0, 36, 0, 4, 0, 37, 0, 28, 0, 38, 0, 30, 0, 6, 0, 4, 0, 39, 0, 4, 0, 40, 0, - 2, 0, 41, 0, 2, 0, 42, 0, 2, 0, 43, 0, 4, 0, 44, 0, 31, 0, 6, 0, 32, 0, 45, 0, 2, 0, 46, 0, 2, 0, 47, 0, - 2, 0, 17, 0, 2, 0, 19, 0, 0, 0, 48, 0, 33, 0, 21, 0, 33, 0, 0, 0, 33, 0, 1, 0, 34, 0, 49, 0, 35, 0, 50, 0, - 24, 0, 51, 0, 24, 0, 52, 0, 2, 0, 46, 0, 2, 0, 47, 0, 2, 0, 53, 0, 2, 0, 54, 0, 2, 0, 55, 0, 2, 0, 56, 0, - 2, 0, 19, 0, 2, 0, 57, 0, 7, 0, 11, 0, 7, 0, 12, 0, 4, 0, 58, 0, 7, 0, 59, 0, 7, 0, 60, 0, 7, 0, 61, 0, - 31, 0, 62, 0, 36, 0, 7, 0, 27, 0, 31, 0, 12, 0, 63, 0, 24, 0, 64, 0, 2, 0, 46, 0, 2, 0, 65, 0, 2, 0, 66, 0, - 2, 0, 37, 0, 37, 0, 16, 0, 37, 0, 0, 0, 37, 0, 1, 0, 7, 0, 67, 0, 7, 0, 61, 0, 2, 0, 17, 0, 2, 0, 47, 0, - 2, 0, 68, 0, 2, 0, 19, 0, 4, 0, 69, 0, 4, 0, 70, 0, 9, 0, 2, 0, 7, 0, 71, 0, 0, 0, 20, 0, 0, 0, 72, 0, - 7, 0, 73, 0, 7, 0, 74, 0, 38, 0, 13, 0, 27, 0, 31, 0, 39, 0, 75, 0, 37, 0, 76, 0, 0, 0, 77, 0, 4, 0, 78, 0, - 7, 0, 61, 0, 12, 0, 79, 0, 36, 0, 80, 0, 27, 0, 81, 0, 2, 0, 17, 0, 2, 0, 82, 0, 2, 0, 83, 0, 2, 0, 19, 0, - 40, 0, 6, 0, 40, 0, 0, 0, 40, 0, 1, 0, 0, 0, 84, 0, 0, 0, 85, 0, 4, 0, 23, 0, 4, 0, 86, 0, 41, 0, 10, 0, - 41, 0, 0, 0, 41, 0, 1, 0, 4, 0, 87, 0, 4, 0, 88, 0, 4, 0, 89, 0, 4, 0, 43, 0, 4, 0, 14, 0, 4, 0, 90, 0, - 0, 0, 91, 0, 0, 0, 92, 0, 42, 0, 15, 0, 27, 0, 31, 0, 0, 0, 93, 0, 4, 0, 90, 0, 4, 0, 94, 0, 12, 0, 95, 0, - 40, 0, 96, 0, 40, 0, 97, 0, 4, 0, 98, 0, 4, 0, 99, 0, 12, 0,100, 0, 0, 0,101, 0, 4, 0,102, 0, 4, 0,103, 0, - 9, 0,104, 0, 8, 0,105, 0, 43, 0, 3, 0, 4, 0,106, 0, 4, 0,107, 0, 9, 0, 2, 0, 44, 0, 20, 0, 27, 0, 31, 0, - 39, 0, 75, 0, 2, 0, 17, 0, 2, 0, 19, 0, 7, 0,108, 0, 7, 0,109, 0, 7, 0,110, 0, 7, 0,111, 0, 7, 0,112, 0, - 7, 0,113, 0, 7, 0,114, 0, 7, 0,115, 0, 7, 0,116, 0, 7, 0,117, 0, 7, 0,118, 0, 2, 0,119, 0, 2, 0,120, 0, - 7, 0,121, 0, 36, 0, 80, 0, 32, 0,122, 0, 45, 0, 13, 0, 4, 0,123, 0, 4, 0,124, 0, 4, 0,125, 0, 4, 0,126, 0, - 2, 0,127, 0, 2, 0,128, 0, 2, 0, 19, 0, 2, 0,129, 0, 2, 0,130, 0, 2, 0,131, 0, 2, 0,132, 0, 2, 0,133, 0, - 46, 0,134, 0, 47, 0, 32, 0, 27, 0, 31, 0, 0, 0, 34, 0, 12, 0,135, 0, 48, 0,136, 0, 49, 0,137, 0, 50, 0,138, 0, - 2, 0,129, 0, 2, 0, 19, 0, 2, 0,139, 0, 2, 0, 17, 0, 2, 0, 37, 0, 2, 0, 43, 0, 4, 0,140, 0, 2, 0,141, 0, - 2, 0,142, 0, 2, 0,143, 0, 2, 0,144, 0, 2, 0,145, 0, 2, 0,146, 0, 4, 0,147, 0, 4, 0,148, 0, 43, 0,149, 0, - 30, 0,150, 0, 0, 0,151, 0, 7, 0,152, 0, 4, 0,153, 0, 2, 0,154, 0, 2, 0,155, 0, 2, 0,156, 0, 2, 0,157, 0, - 7, 0,158, 0, 7, 0,159, 0, 51, 0, 33, 0, 2, 0,160, 0, 2, 0,161, 0, 2, 0,162, 0, 2, 0,163, 0, 32, 0,164, 0, - 52, 0,165, 0, 0, 0,166, 0, 0, 0,167, 0, 0, 0,168, 0, 0, 0,169, 0, 0, 0,170, 0, 7, 0,171, 0, 7, 0,172, 0, - 7, 0,173, 0, 2, 0,174, 0, 2, 0,175, 0, 2, 0,176, 0, 2, 0,177, 0, 2, 0,178, 0, 2, 0,179, 0, 0, 0,180, 0, - 0, 0,181, 0, 7, 0,182, 0, 7, 0,183, 0, 7, 0,184, 0, 7, 0,185, 0, 7, 0,186, 0, 7, 0, 57, 0, 7, 0,187, 0, - 7, 0,188, 0, 7, 0,189, 0, 7, 0,190, 0, 7, 0,191, 0, 53, 0, 15, 0, 0, 0,192, 0, 9, 0,193, 0, 0, 0,194, 0, - 0, 0,195, 0, 4, 0,196, 0, 4, 0,197, 0, 9, 0,198, 0, 7, 0,199, 0, 7, 0,200, 0, 7, 0,201, 0, 4, 0,202, 0, - 9, 0,203, 0, 9, 0,204, 0, 4, 0,205, 0, 4, 0, 37, 0, 54, 0, 6, 0, 7, 0,182, 0, 7, 0,183, 0, 7, 0,184, 0, - 7, 0,206, 0, 7, 0, 67, 0, 4, 0, 64, 0, 55, 0, 5, 0, 2, 0, 19, 0, 2, 0, 36, 0, 2, 0, 64, 0, 2, 0,207, 0, - 54, 0,201, 0, 56, 0, 17, 0, 32, 0,164, 0, 47, 0,208, 0, 57, 0,209, 0, 7, 0,210, 0, 7, 0,211, 0, 2, 0, 17, 0, - 2, 0,212, 0, 7, 0,110, 0, 7, 0,111, 0, 7, 0,213, 0, 4, 0,214, 0, 2, 0,215, 0, 2, 0,216, 0, 4, 0,129, 0, - 4, 0,140, 0, 2, 0,217, 0, 2, 0,218, 0, 58, 0, 23, 0, 2, 0, 19, 0, 2, 0,219, 0, 7, 0,220, 0, 7, 0,221, 0, - 2, 0,139, 0, 2, 0,222, 0, 4, 0,223, 0, 4, 0,224, 0, 32, 0,164, 0, 59, 0,225, 0, 2, 0,226, 0, 2, 0,227, 0, - 2, 0,228, 0, 9, 0,229, 0, 7, 0,230, 0, 7, 0,231, 0, 2, 0,232, 0, 2, 0,233, 0, 2, 0,234, 0, 2, 0,235, 0, - 7, 0,236, 0, 7, 0,237, 0, 55, 0,238, 0, 60, 0, 10, 0, 4, 0,239, 0, 4, 0,240, 0, 2, 0,241, 0, 2, 0, 19, 0, - 4, 0, 37, 0, 32, 0,164, 0, 7, 0,242, 0, 4, 0,243, 0, 0, 0,244, 0, 7, 0,245, 0, 52, 0, 61, 0, 27, 0, 31, 0, - 39, 0, 75, 0, 7, 0,246, 0, 7, 0,247, 0, 7, 0,248, 0, 7, 0,249, 0, 7, 0,250, 0, 7, 0,251, 0, 7, 0,252, 0, - 7, 0,253, 0, 7, 0,254, 0, 7, 0,255, 0, 7, 0, 0, 1, 7, 0, 1, 1, 7, 0, 2, 1, 7, 0, 3, 1, 7, 0, 4, 1, - 7, 0, 5, 1, 7, 0, 6, 1, 7, 0, 7, 1, 7, 0, 8, 1, 7, 0, 9, 1, 2, 0, 10, 1, 2, 0, 11, 1, 2, 0, 12, 1, - 2, 0, 13, 1, 2, 0, 14, 1, 2, 0, 15, 1, 2, 0, 16, 1, 2, 0, 19, 0, 2, 0, 17, 0, 2, 0,212, 0, 7, 0, 17, 1, - 7, 0, 18, 1, 7, 0, 19, 1, 7, 0, 20, 1, 4, 0, 21, 1, 4, 0, 22, 1, 2, 0, 23, 1, 2, 0, 24, 1, 2, 0, 25, 1, - 2, 0,127, 0, 4, 0, 23, 0, 4, 0,124, 0, 4, 0,125, 0, 4, 0,126, 0, 7, 0, 26, 1, 7, 0, 27, 1, 7, 0,188, 0, - 45, 0, 28, 1, 61, 0, 29, 1, 36, 0, 80, 0, 47, 0,208, 0, 53, 0, 30, 1, 55, 0,238, 0, 56, 0, 31, 1, 30, 0,150, 0, - 58, 0, 32, 1, 60, 0, 33, 1, 0, 0, 34, 1, 0, 0,181, 0, 62, 0, 8, 0, 7, 0, 35, 1, 7, 0, 36, 1, 7, 0,172, 0, - 4, 0, 19, 0, 7, 0, 37, 1, 7, 0, 38, 1, 7, 0, 39, 1, 32, 0, 45, 0, 63, 0, 82, 0, 27, 0, 31, 0, 39, 0, 75, 0, - 2, 0, 17, 0, 2, 0, 19, 0, 4, 0, 40, 1, 2, 0,175, 0, 2, 0, 41, 1, 7, 0,182, 0, 7, 0,183, 0, 7, 0,184, 0, - 7, 0,185, 0, 7, 0, 42, 1, 7, 0, 43, 1, 7, 0, 44, 1, 7, 0, 45, 1, 7, 0, 46, 1, 7, 0, 47, 1, 7, 0, 48, 1, - 7, 0, 49, 1, 7, 0, 50, 1, 7, 0, 51, 1, 7, 0, 52, 1, 64, 0, 53, 1, 2, 0,219, 0, 2, 0, 70, 0, 7, 0,110, 0, - 7, 0,111, 0, 7, 0, 54, 1, 7, 0, 55, 1, 7, 0, 56, 1, 2, 0, 57, 1, 2, 0, 58, 1, 2, 0, 59, 1, 2, 0, 60, 1, - 0, 0, 61, 1, 0, 0, 62, 1, 2, 0, 63, 1, 2, 0, 64, 1, 2, 0, 65, 1, 2, 0, 66, 1, 2, 0, 67, 1, 7, 0, 68, 1, - 7, 0, 69, 1, 7, 0, 70, 1, 7, 0, 71, 1, 2, 0, 72, 1, 2, 0, 43, 0, 2, 0, 73, 1, 2, 0, 74, 1, 2, 0, 75, 1, - 2, 0, 76, 1, 7, 0, 77, 1, 7, 0, 78, 1, 7, 0, 79, 1, 7, 0, 80, 1, 7, 0, 81, 1, 7, 0, 82, 1, 7, 0, 83, 1, - 7, 0, 84, 1, 7, 0, 85, 1, 7, 0, 86, 1, 7, 0, 87, 1, 7, 0, 88, 1, 2, 0, 89, 1, 2, 0, 90, 1, 4, 0, 91, 1, - 4, 0, 92, 1, 2, 0, 93, 1, 2, 0, 94, 1, 2, 0, 95, 1, 2, 0, 96, 1, 7, 0, 97, 1, 7, 0, 98, 1, 7, 0, 99, 1, - 7, 0,100, 1, 2, 0,101, 1, 2, 0,102, 1, 36, 0, 80, 0, 51, 0,103, 1, 2, 0,104, 1, 2, 0,105, 1, 30, 0,150, 0, - 65, 0, 2, 0, 27, 0, 31, 0, 36, 0, 80, 0, 66, 0, 20, 0, 7, 0,106, 1, 7, 0,107, 1, 7, 0,108, 1, 7, 0,109, 1, - 7, 0,110, 1, 7, 0,111, 1, 7, 0,112, 1, 7, 0,113, 1, 2, 0,114, 1, 2, 0,115, 1, 7, 0,116, 1, 7, 0,117, 1, - 7, 0,118, 1, 2, 0,119, 1, 2, 0,120, 1, 2, 0,121, 1, 2, 0,122, 1, 7, 0,123, 1, 7, 0,124, 1, 4, 0,125, 1, - 67, 0,130, 0, 27, 0, 31, 0, 39, 0, 75, 0, 2, 0,126, 1, 2, 0, 19, 0, 7, 0,182, 0, 7, 0,183, 0, 7, 0,184, 0, - 7, 0,127, 1, 7, 0,128, 1, 7, 0,129, 1, 7, 0,130, 1, 7, 0,131, 1, 7, 0,132, 1, 7, 0,133, 1, 7, 0,134, 1, - 7, 0,135, 1, 7, 0,136, 1, 7, 0,137, 1, 7, 0,138, 1, 7, 0,139, 1, 7, 0,140, 1, 7, 0,141, 1, 7, 0,142, 1, - 7, 0,143, 1, 7, 0,144, 1, 7, 0,145, 1, 7, 0,146, 1, 66, 0,147, 1, 7, 0,148, 1, 7, 0,149, 1, 7, 0,150, 1, - 7, 0,151, 1, 7, 0,152, 1, 7, 0,153, 1, 7, 0,154, 1, 2, 0,155, 1, 2, 0,156, 1, 2, 0,157, 1, 0, 0,158, 1, - 0, 0,159, 1, 7, 0,160, 1, 7, 0,161, 1, 2, 0,162, 1, 2, 0,163, 1, 7, 0,164, 1, 7, 0,165, 1, 7, 0,166, 1, - 7, 0,167, 1, 2, 0,168, 1, 2, 0,169, 1, 4, 0, 40, 1, 4, 0,170, 1, 2, 0,171, 1, 2, 0,172, 1, 2, 0,173, 1, - 2, 0,174, 1, 7, 0,175, 1, 7, 0,176, 1, 7, 0,177, 1, 7, 0,178, 1, 7, 0,179, 1, 7, 0,180, 1, 7, 0,181, 1, - 7, 0,182, 1, 7, 0,183, 1, 7, 0,184, 1, 0, 0,185, 1, 7, 0,186, 1, 7, 0,187, 1, 7, 0,188, 1, 4, 0,189, 1, - 0, 0,190, 1, 0, 0, 73, 1, 0, 0,191, 1, 0, 0, 34, 1, 2, 0,192, 1, 2, 0,193, 1, 2, 0,104, 1, 2, 0,194, 1, - 2, 0,195, 1, 2, 0,196, 1, 7, 0,197, 1, 7, 0,198, 1, 7, 0,199, 1, 7, 0,200, 1, 7, 0,201, 1, 2, 0,160, 0, - 2, 0,161, 0, 55, 0,202, 1, 55, 0,203, 1, 0, 0,204, 1, 0, 0,205, 1, 0, 0,206, 1, 0, 0,207, 1, 2, 0,208, 1, - 2, 0,209, 1, 7, 0,210, 1, 7, 0,211, 1, 51, 0,103, 1, 61, 0, 29, 1, 36, 0, 80, 0, 68, 0,212, 1, 30, 0,150, 0, - 7, 0,213, 1, 7, 0,214, 1, 7, 0,215, 1, 7, 0,216, 1, 7, 0,217, 1, 2, 0,218, 1, 2, 0, 70, 0, 7, 0,219, 1, - 7, 0,220, 1, 7, 0,221, 1, 7, 0,222, 1, 7, 0,223, 1, 7, 0,224, 1, 7, 0,225, 1, 7, 0,226, 1, 7, 0,227, 1, - 2, 0,228, 1, 2, 0,229, 1, 7, 0,230, 1, 7, 0,231, 1, 7, 0,232, 1, 7, 0,233, 1, 7, 0,234, 1, 4, 0,235, 1, - 4, 0,236, 1, 4, 0,237, 1, 12, 0,238, 1, 69, 0, 4, 0, 27, 0, 31, 0, 0, 0,239, 1, 70, 0, 2, 0, 43, 0,149, 0, - 71, 0, 26, 0, 71, 0, 0, 0, 71, 0, 1, 0, 72, 0,240, 1, 4, 0,241, 1, 4, 0,242, 1, 4, 0,243, 1, 4, 0,244, 1, - 4, 0,245, 1, 4, 0,246, 1, 2, 0, 17, 0, 2, 0, 19, 0, 2, 0,247, 1, 2, 0,248, 1, 7, 0, 5, 0, 7, 0, 6, 0, - 7, 0, 7, 0, 7, 0,249, 1, 7, 0,250, 1, 7, 0,251, 1, 7, 0,252, 1, 7, 0,253, 1, 7, 0,254, 1, 7, 0,255, 1, - 7, 0, 23, 0, 7, 0, 0, 2, 7, 0, 1, 2, 73, 0, 19, 0, 27, 0, 31, 0, 39, 0, 75, 0, 72, 0,240, 1, 12, 0, 2, 2, - 12, 0, 3, 2, 12, 0, 4, 2, 36, 0, 80, 0, 67, 0, 5, 2, 0, 0, 19, 0, 0, 0, 6, 2, 2, 0, 7, 2, 4, 0,174, 0, - 7, 0, 35, 1, 7, 0,172, 0, 7, 0, 36, 1, 7, 0, 8, 2, 7, 0, 9, 2, 7, 0, 10, 2, 71, 0, 11, 2, 35, 0, 11, 0, - 7, 0, 12, 2, 7, 0, 13, 2, 7, 0, 14, 2, 7, 0,221, 0, 2, 0, 55, 0, 0, 0, 15, 2, 0, 0, 16, 2, 0, 0, 17, 2, - 0, 0, 18, 2, 0, 0, 19, 2, 0, 0, 20, 2, 34, 0, 7, 0, 7, 0, 21, 2, 7, 0, 13, 2, 7, 0, 14, 2, 2, 0, 17, 2, - 2, 0, 20, 2, 7, 0,221, 0, 7, 0, 37, 0, 74, 0, 21, 0, 74, 0, 0, 0, 74, 0, 1, 0, 2, 0, 17, 0, 2, 0, 22, 2, - 2, 0, 20, 2, 2, 0, 19, 0, 2, 0, 23, 2, 2, 0, 24, 2, 2, 0, 25, 2, 2, 0, 26, 2, 2, 0, 27, 2, 2, 0, 28, 2, - 2, 0, 29, 2, 2, 0, 30, 2, 7, 0, 31, 2, 7, 0, 32, 2, 34, 0, 49, 0, 35, 0, 50, 0, 2, 0, 33, 2, 2, 0, 34, 2, - 4, 0, 35, 2, 75, 0, 5, 0, 2, 0, 36, 2, 2, 0, 22, 2, 0, 0, 19, 0, 0, 0, 37, 0, 2, 0, 70, 0, 76, 0, 4, 0, - 7, 0, 5, 0, 7, 0, 6, 0, 7, 0, 8, 0, 7, 0, 37, 2, 77, 0, 67, 0, 27, 0, 31, 0, 39, 0, 75, 0, 72, 0,240, 1, - 12, 0, 38, 2, 12, 0, 3, 2, 12, 0, 39, 2, 32, 0, 40, 2, 32, 0, 41, 2, 32, 0, 42, 2, 36, 0, 80, 0, 78, 0, 43, 2, - 38, 0, 44, 2, 67, 0, 5, 2, 12, 0, 45, 2, 7, 0, 35, 1, 7, 0,172, 0, 7, 0, 36, 1, 4, 0,174, 0, 2, 0, 46, 2, - 2, 0, 47, 2, 2, 0, 48, 2, 7, 0, 49, 2, 7, 0, 70, 0, 2, 0, 50, 2, 2, 0, 7, 2, 2, 0, 19, 0, 2, 0, 51, 2, - 7, 0, 52, 2, 7, 0, 53, 2, 7, 0, 54, 2, 2, 0, 25, 2, 2, 0, 26, 2, 2, 0, 55, 2, 2, 0, 56, 2, 4, 0, 57, 2, - 34, 0, 58, 2, 2, 0, 23, 0, 2, 0, 95, 0, 2, 0, 67, 0, 2, 0, 59, 2, 7, 0, 60, 2, 7, 0, 61, 2, 7, 0, 62, 2, - 7, 0, 63, 2, 7, 0, 64, 2, 7, 0, 65, 2, 7, 0, 66, 2, 7, 0, 67, 2, 7, 0, 68, 2, 7, 0, 69, 2, 0, 0, 70, 2, - 79, 0, 71, 2, 80, 0, 72, 2, 0, 0, 73, 2, 69, 0, 74, 2, 69, 0, 75, 2, 69, 0, 76, 2, 69, 0, 77, 2, 4, 0, 78, 2, - 7, 0, 79, 2, 4, 0, 80, 2, 4, 0, 81, 2, 76, 0, 82, 2, 4, 0, 83, 2, 4, 0, 84, 2, 75, 0, 85, 2, 75, 0, 86, 2, - 81, 0, 39, 0, 27, 0, 31, 0, 72, 0,240, 1, 12, 0, 87, 2, 36, 0, 80, 0, 38, 0, 44, 2, 67, 0, 5, 2, 82, 0, 88, 2, - 83, 0, 89, 2, 84, 0, 90, 2, 85, 0, 91, 2, 86, 0, 92, 2, 87, 0, 93, 2, 88, 0, 94, 2, 89, 0, 95, 2, 81, 0, 96, 2, - 90, 0, 97, 2, 91, 0, 98, 2, 92, 0, 99, 2, 92, 0,100, 2, 92, 0,101, 2, 4, 0, 54, 0, 4, 0,102, 2, 4, 0,103, 2, - 4, 0,104, 2, 4, 0,105, 2, 4, 0,174, 0, 7, 0, 35, 1, 7, 0,172, 0, 7, 0, 36, 1, 7, 0,106, 2, 4, 0, 46, 2, - 2, 0,107, 2, 2, 0, 19, 0, 2, 0,108, 2, 2, 0,109, 2, 2, 0, 7, 2, 2, 0,110, 2, 93, 0,111, 2, 94, 0,112, 2, - 84, 0, 8, 0, 9, 0,113, 2, 7, 0,114, 2, 4, 0,115, 2, 0, 0, 19, 0, 0, 0,116, 2, 2, 0, 40, 1, 2, 0,117, 2, - 2, 0,118, 2, 82, 0, 7, 0, 4, 0,119, 2, 4, 0,120, 2, 4, 0,121, 2, 4, 0,122, 2, 2, 0, 22, 2, 0, 0,123, 2, - 0, 0, 19, 0, 86, 0, 5, 0, 4, 0,119, 2, 4, 0,120, 2, 0, 0,124, 2, 0, 0,125, 2, 2, 0, 19, 0, 95, 0, 2, 0, - 4, 0,126, 2, 7, 0, 14, 2, 87, 0, 3, 0, 95, 0,127, 2, 4, 0,128, 2, 4, 0, 19, 0, 85, 0, 6, 0, 7, 0,129, 2, - 2, 0,130, 2, 2, 0, 22, 2, 0, 0, 19, 0, 0, 0,125, 2, 0, 0, 48, 2, 88, 0, 4, 0, 0, 0,206, 0, 0, 0,182, 0, - 0, 0,183, 0, 0, 0,184, 0, 96, 0, 6, 0, 47, 0,113, 2, 0, 0, 19, 0, 0, 0,116, 2, 2, 0, 40, 1, 2, 0,117, 2, - 2, 0,118, 2, 97, 0, 1, 0, 7, 0,131, 2, 98, 0, 5, 0, 0, 0,206, 0, 0, 0,182, 0, 0, 0,183, 0, 0, 0,184, 0, - 4, 0, 37, 0, 89, 0, 1, 0, 7, 0,132, 2, 90, 0, 2, 0, 4, 0,133, 2, 4, 0, 17, 0, 83, 0, 7, 0, 7, 0,114, 2, - 47, 0,113, 2, 0, 0, 19, 0, 0, 0,116, 2, 2, 0, 40, 1, 2, 0,117, 2, 2, 0,118, 2, 99, 0, 1, 0, 7, 0,134, 2, -100, 0, 1, 0, 4, 0,135, 2,101, 0, 1, 0, 0, 0,136, 2,102, 0, 1, 0, 7, 0,114, 2,103, 0, 3, 0, 4, 0,137, 2, - 0, 0, 92, 0, 7, 0,138, 2,105, 0, 4, 0, 7, 0,206, 0, 7, 0,182, 0, 7, 0,183, 0, 7, 0,184, 0,106, 0, 1, 0, -105, 0,115, 2,107, 0, 5, 0, 4, 0,139, 2, 4, 0,140, 2, 0, 0, 19, 0, 0, 0, 22, 2, 0, 0, 48, 2,108, 0, 2, 0, - 4, 0,141, 2, 4, 0,140, 2,109, 0, 10, 0,109, 0, 0, 0,109, 0, 1, 0,107, 0,142, 2,106, 0,143, 2,108, 0,144, 2, - 4, 0, 54, 0, 4, 0,103, 2, 4, 0,102, 2, 4, 0, 37, 0, 85, 0,145, 2, 93, 0, 14, 0, 12, 0,146, 2, 85, 0,145, 2, - 0, 0,147, 2, 0, 0,148, 2, 0, 0,149, 2, 0, 0,150, 2, 0, 0,151, 2, 0, 0,152, 2, 0, 0,153, 2, 0, 0, 19, 0, - 92, 0, 99, 2, 92, 0,101, 2, 2, 0,154, 2, 0, 0,155, 2, 94, 0, 8, 0, 4, 0,156, 2, 4, 0,157, 2, 82, 0,158, 2, - 86, 0,159, 2, 4, 0,103, 2, 4, 0,102, 2, 4, 0, 54, 0, 4, 0, 37, 0,110, 0, 7, 0,110, 0, 0, 0,110, 0, 1, 0, - 4, 0, 17, 0, 4, 0, 40, 1, 0, 0, 20, 0, 46, 0,134, 0, 0, 0,160, 2,111, 0, 7, 0,110, 0,161, 2, 2, 0,162, 2, - 2, 0,146, 2, 2, 0,163, 2, 2, 0, 90, 0, 9, 0,164, 2, 9, 0,165, 2,112, 0, 3, 0,110, 0,161, 2, 32, 0,164, 0, - 0, 0, 20, 0,113, 0, 5, 0,110, 0,161, 2, 32, 0,164, 0, 0, 0, 20, 0, 2, 0,166, 2, 0, 0,167, 2,114, 0, 5, 0, -110, 0,161, 2, 7, 0, 88, 0, 7, 0,168, 2, 4, 0,169, 2, 4, 0,170, 2,115, 0, 5, 0,110, 0,161, 2, 32, 0,171, 2, - 0, 0, 72, 0, 4, 0, 40, 1, 4, 0, 19, 0,116, 0, 13, 0,110, 0,161, 2, 32, 0,172, 2, 32, 0,173, 2, 32, 0,174, 2, - 32, 0,175, 2, 7, 0,176, 2, 7, 0,177, 2, 7, 0,168, 2, 7, 0,178, 2, 4, 0,179, 2, 4, 0,180, 2, 4, 0, 90, 0, - 4, 0,181, 2,117, 0, 5, 0,110, 0,161, 2, 2, 0,182, 2, 2, 0, 19, 0, 7, 0,183, 2, 32, 0,184, 2,118, 0, 3, 0, -110, 0,161, 2, 7, 0,185, 2, 4, 0, 90, 0,119, 0, 10, 0,110, 0,161, 2, 7, 0,186, 2, 4, 0,187, 2, 4, 0, 37, 0, - 2, 0, 90, 0, 2, 0,188, 2, 2, 0,189, 2, 2, 0,190, 2, 7, 0,191, 2, 0, 0,192, 2,120, 0, 3, 0,110, 0,161, 2, - 7, 0, 37, 0, 4, 0, 17, 0,121, 0, 6, 0,110, 0,161, 2,122, 0,193, 2,123, 0,194, 2,124, 0,195, 2, 7, 0,196, 2, - 4, 0, 17, 0,125, 0, 11, 0,110, 0,161, 2, 52, 0,197, 2, 7, 0,198, 2, 4, 0,199, 2, 0, 0,192, 2, 7, 0,200, 2, - 4, 0,201, 2, 32, 0,202, 2, 0, 0,203, 2, 4, 0,204, 2, 4, 0, 37, 0,126, 0, 10, 0,110, 0,161, 2, 32, 0,205, 2, - 47, 0,206, 2, 4, 0, 90, 0, 4, 0,207, 2, 7, 0,208, 2, 7, 0,209, 2, 0, 0,203, 2, 4, 0,204, 2, 4, 0, 37, 0, -127, 0, 3, 0,110, 0,161, 2, 7, 0,210, 2, 4, 0,211, 2,128, 0, 5, 0,110, 0,161, 2, 7, 0,212, 2, 0, 0,192, 2, - 2, 0, 19, 0, 2, 0,213, 2,129, 0, 8, 0,110, 0,161, 2, 32, 0,164, 0, 7, 0,212, 2, 7, 0,221, 0, 7, 0,106, 0, - 0, 0,192, 2, 2, 0, 19, 0, 2, 0, 17, 0,130, 0, 21, 0,110, 0,161, 2, 32, 0,214, 2, 0, 0,192, 2, 52, 0,197, 2, - 32, 0,202, 2, 2, 0, 19, 0, 2, 0, 37, 0, 7, 0,215, 2, 7, 0,216, 2, 7, 0,217, 2, 7, 0, 52, 2, 7, 0,218, 2, - 7, 0,219, 2, 7, 0,220, 2, 7, 0,221, 2, 4, 0,201, 2, 4, 0,204, 2, 0, 0,203, 2, 7, 0,222, 2, 7, 0,223, 2, - 7, 0, 43, 0,131, 0, 7, 0,110, 0,161, 2, 2, 0,224, 2, 2, 0,225, 2, 4, 0, 70, 0, 32, 0,164, 0, 7, 0,226, 2, - 0, 0,192, 2,132, 0, 10, 0,110, 0,161, 2, 32, 0,164, 0, 0, 0,227, 2, 7, 0,228, 2, 7, 0,229, 2, 7, 0,221, 2, - 4, 0,230, 2, 4, 0,231, 2, 7, 0,232, 2, 0, 0, 20, 0,133, 0, 1, 0,110, 0,161, 2,134, 0, 7, 0,110, 0,161, 2, - 46, 0,134, 0,135, 0,233, 2,136, 0,234, 2,137, 0,235, 2,138, 0,236, 2, 12, 0,237, 2,139, 0, 14, 0,110, 0,161, 2, - 85, 0,238, 2, 85, 0,239, 2, 85, 0,240, 2, 85, 0,241, 2, 85, 0,242, 2, 85, 0,243, 2, 82, 0,244, 2, 4, 0,245, 2, - 4, 0,246, 2, 2, 0,108, 1, 2, 0, 37, 0, 7, 0,196, 2,140, 0,247, 2,141, 0, 7, 0,110, 0,161, 2, 85, 0,238, 2, - 85, 0,248, 2,142, 0,249, 2,143, 0,247, 2, 4, 0,250, 2, 4, 0,245, 2,144, 0, 4, 0,110, 0,161, 2, 32, 0,164, 0, - 4, 0,251, 2, 4, 0, 37, 0,145, 0, 2, 0, 4, 0,252, 2, 7, 0, 14, 2,146, 0, 2, 0, 4, 0,125, 0, 4, 0,253, 2, -147, 0, 20, 0,110, 0,161, 2, 32, 0,164, 0, 0, 0,192, 2, 2, 0,254, 2, 2, 0,255, 2, 2, 0, 19, 0, 2, 0, 37, 0, - 7, 0, 0, 3, 7, 0, 1, 3, 4, 0, 54, 0, 4, 0, 2, 3,146, 0, 3, 3,145, 0, 4, 3, 4, 0, 5, 3, 4, 0, 6, 3, - 4, 0, 7, 3, 4, 0,253, 2, 7, 0, 8, 3, 7, 0, 9, 3, 7, 0, 10, 3,148, 0, 8, 0,110, 0,161, 2, 59, 0,225, 0, -142, 0,249, 2, 4, 0, 11, 3, 4, 0, 12, 3, 4, 0, 13, 3, 2, 0, 19, 0, 2, 0, 57, 0,149, 0, 8, 0,110, 0,161, 2, - 32, 0, 45, 0, 2, 0, 14, 3, 2, 0, 19, 0, 2, 0,182, 2, 2, 0, 57, 0, 7, 0, 15, 3, 7, 0, 16, 3,150, 0, 5, 0, -110, 0,161, 2, 4, 0, 17, 3, 2, 0, 19, 0, 2, 0, 18, 3, 7, 0, 19, 3,151, 0, 7, 0,110, 0,161, 2, 85, 0, 20, 3, - 4, 0, 21, 3, 0, 0, 22, 3, 0, 0, 23, 3, 0, 0, 24, 3, 0, 0, 25, 3,152, 0, 3, 0,110, 0,161, 2,153, 0, 26, 3, -138, 0,236, 2,154, 0, 10, 0,110, 0,161, 2, 32, 0, 27, 3, 32, 0, 28, 3, 0, 0, 29, 3, 7, 0, 30, 3, 2, 0, 31, 3, - 2, 0, 32, 3, 0, 0, 33, 3, 0, 0, 34, 3, 0, 0,167, 2,155, 0, 9, 0,110, 0,161, 2, 32, 0, 35, 3, 0, 0, 29, 3, - 7, 0, 36, 3, 7, 0, 37, 3, 0, 0, 40, 1, 0, 0,182, 2, 0, 0, 38, 3, 0, 0, 37, 0,156, 0, 27, 0, 27, 0, 31, 0, - 2, 0, 23, 2, 2, 0, 24, 2, 2, 0, 39, 3, 2, 0, 19, 0, 2, 0, 40, 3, 2, 0, 41, 3, 2, 0, 42, 3, 2, 0, 70, 0, - 0, 0, 43, 3, 0, 0, 44, 3, 0, 0, 45, 3, 0, 0, 17, 0, 4, 0, 37, 0, 7, 0, 46, 3, 7, 0, 47, 3, 7, 0, 48, 3, - 7, 0, 49, 3, 7, 0, 50, 3, 7, 0, 51, 3, 34, 0, 52, 3, 36, 0, 80, 0, 38, 0, 44, 2, 87, 0, 93, 2, 7, 0, 53, 3, - 7, 0, 54, 3,156, 0, 55, 3,157, 0, 3, 0,157, 0, 0, 0,157, 0, 1, 0, 0, 0, 20, 0, 72, 0, 3, 0, 7, 0, 56, 3, - 4, 0, 19, 0, 4, 0, 37, 0, 32, 0,116, 0, 27, 0, 31, 0, 39, 0, 75, 0,158, 0, 57, 3, 2, 0, 17, 0, 2, 0, 58, 3, - 4, 0, 59, 3, 4, 0, 60, 3, 4, 0, 61, 3, 0, 0, 62, 3, 32, 0, 38, 0, 32, 0, 63, 3, 32, 0, 64, 3, 32, 0, 65, 3, - 32, 0, 66, 3, 36, 0, 80, 0, 78, 0, 43, 2, 72, 0,240, 1,159, 0, 67, 3,159, 0, 68, 3,160, 0, 69, 3, 9, 0, 2, 0, -161, 0, 70, 3, 12, 0, 71, 3, 12, 0, 87, 2, 12, 0, 3, 2, 12, 0, 72, 3, 12, 0, 73, 3, 4, 0, 40, 1, 4, 0, 74, 3, - 67, 0, 5, 2, 0, 0, 75, 3, 4, 0, 7, 2, 4, 0, 76, 3, 7, 0, 35, 1, 7, 0, 77, 3, 7, 0, 78, 3, 7, 0,172, 0, - 7, 0, 79, 3, 7, 0, 36, 1, 7, 0, 80, 3, 7, 0, 81, 3, 7, 0,228, 2, 7, 0, 82, 3, 7, 0,210, 0, 4, 0, 83, 3, - 2, 0, 19, 0, 2, 0, 84, 3, 2, 0, 85, 3, 2, 0, 86, 3, 2, 0, 87, 3, 2, 0, 88, 3, 2, 0, 89, 3, 2, 0, 90, 3, - 2, 0, 91, 3, 2, 0, 92, 3, 2, 0, 93, 3, 2, 0, 94, 3, 4, 0, 95, 3, 4, 0, 96, 3, 4, 0, 97, 3, 4, 0, 98, 3, - 7, 0, 99, 3, 7, 0, 79, 2, 7, 0,100, 3, 7, 0,101, 3, 7, 0,102, 3, 7, 0,103, 3, 7, 0,104, 3, 7, 0,105, 3, - 7, 0,106, 3, 7, 0,107, 3, 7, 0,108, 3, 7, 0,109, 3, 0, 0,110, 3, 0, 0,111, 3, 0, 0,112, 3, 0, 0,113, 3, - 7, 0,114, 3, 7, 0,115, 3, 12, 0,116, 3, 12, 0,117, 3, 12, 0,118, 3, 12, 0,119, 3, 7, 0,120, 3, 2, 0,133, 2, - 2, 0,121, 3, 7, 0,115, 2, 4, 0,122, 3, 4, 0,123, 3,162, 0,124, 3, 2, 0,125, 3, 2, 0,217, 0, 7, 0,126, 3, - 12, 0,127, 3, 12, 0,128, 3, 12, 0,129, 3, 12, 0,130, 3,163, 0, 32, 1,164, 0,131, 3, 68, 0,132, 3, 2, 0,133, 3, - 2, 0,134, 3, 2, 0,135, 3, 2, 0,136, 3, 7, 0,107, 2, 2, 0,137, 3, 2, 0,138, 3,153, 0,139, 3,142, 0,140, 3, -142, 0,141, 3, 4, 0,142, 3, 4, 0,143, 3, 4, 0,144, 3, 4, 0, 70, 0, 12, 0,145, 3, 12, 0,146, 3,165, 0, 14, 0, -165, 0, 0, 0,165, 0, 1, 0, 32, 0, 38, 0, 7, 0,228, 2, 7, 0, 37, 1, 7, 0,229, 2, 7, 0,221, 2, 0, 0, 20, 0, - 4, 0,230, 2, 4, 0,231, 2, 4, 0,147, 3, 2, 0, 17, 0, 2, 0,148, 3, 7, 0,232, 2,163, 0, 36, 0, 2, 0,149, 3, - 2, 0,150, 3, 2, 0, 19, 0, 2, 0,221, 2, 7, 0,151, 3, 7, 0,152, 3, 7, 0,153, 3, 7, 0,154, 3, 7, 0,155, 3, - 7, 0,156, 3, 7, 0,157, 3, 7, 0,158, 3, 7, 0,159, 3, 7, 0,160, 3, 7, 0,161, 3, 7, 0,162, 3, 7, 0,163, 3, - 7, 0,164, 3, 7, 0,165, 3, 7, 0,166, 3, 7, 0,167, 3, 7, 0,168, 3, 7, 0,169, 3, 7, 0,170, 3, 7, 0,171, 3, - 7, 0,172, 3, 7, 0,173, 3, 7, 0,174, 3, 2, 0,175, 3, 2, 0,176, 3, 2, 0,177, 3, 2, 0,178, 3, 52, 0,165, 0, -166, 0,179, 3, 7, 0,180, 3, 4, 0,170, 2,167, 0, 9, 0,167, 0, 0, 0,167, 0, 1, 0, 4, 0,181, 3, 4, 0,182, 3, - 4, 0,183, 3, 4, 0, 19, 0, 4, 0,184, 3, 9, 0,185, 3, 9, 0,186, 3,138, 0, 19, 0,138, 0, 0, 0,138, 0, 1, 0, - 4, 0, 19, 0, 4, 0,187, 3, 4, 0,188, 3, 4, 0,189, 3, 4, 0,190, 3, 4, 0,191, 3, 4, 0,192, 3, 4, 0,182, 3, - 4, 0,133, 2, 4, 0, 57, 0, 0, 0,193, 3, 0, 0,194, 3, 0, 0,195, 3, 0, 0,196, 3, 12, 0,197, 3,168, 0,198, 3, - 9, 0,199, 3,169, 0, 1, 0, 7, 0, 21, 2,162, 0, 30, 0, 4, 0, 19, 0, 7, 0,200, 3, 7, 0,201, 3, 7, 0,202, 3, - 4, 0,203, 3, 4, 0,204, 3, 4, 0,205, 3, 4, 0,206, 3, 7, 0,207, 3, 7, 0,208, 3, 7, 0,209, 3, 7, 0,210, 3, - 7, 0,211, 3, 7, 0,212, 3, 7, 0,213, 3, 7, 0,214, 3, 7, 0,215, 3, 7, 0,216, 3, 7, 0,217, 3, 7, 0,218, 3, - 7, 0,219, 3, 7, 0,220, 3, 7, 0,221, 3, 7, 0,222, 3, 7, 0,223, 3, 7, 0,224, 3, 4, 0,225, 3, 4, 0,226, 3, - 7, 0,227, 3, 7, 0,106, 3,164, 0, 49, 0, 4, 0,182, 3, 4, 0,228, 3,170, 0,229, 3,171, 0,230, 3, 0, 0, 37, 0, - 0, 0,231, 3, 2, 0,232, 3, 7, 0,233, 3, 0, 0,234, 3, 7, 0,235, 3, 7, 0,236, 3, 7, 0,237, 3, 7, 0,238, 3, - 7, 0,239, 3, 7, 0,240, 3, 7, 0,241, 3, 7, 0,242, 3, 7, 0,243, 3, 2, 0,244, 3, 0, 0,245, 3, 2, 0,246, 3, - 7, 0,247, 3, 7, 0,248, 3, 0, 0,249, 3, 4, 0,126, 0, 4, 0,250, 3, 4, 0,251, 3, 2, 0,252, 3, 2, 0,253, 3, -169, 0,254, 3, 4, 0,255, 3, 4, 0, 82, 0, 7, 0, 0, 4, 7, 0, 1, 4, 7, 0, 2, 4, 7, 0, 3, 4, 2, 0, 4, 4, - 2, 0, 5, 4, 2, 0, 6, 4, 2, 0, 7, 4, 2, 0, 8, 4, 2, 0, 9, 4, 2, 0, 10, 4, 2, 0, 11, 4,172, 0, 12, 4, - 7, 0, 13, 4, 7, 0, 14, 4,138, 0, 15, 4, 12, 0,237, 2,153, 0, 48, 0, 2, 0, 17, 0, 2, 0, 16, 4, 2, 0, 17, 4, - 2, 0, 18, 4, 7, 0, 19, 4, 2, 0, 20, 4, 2, 0, 21, 4, 7, 0, 22, 4, 2, 0, 23, 4, 2, 0, 24, 4, 7, 0, 25, 4, - 7, 0, 26, 4, 7, 0, 27, 4, 7, 0, 28, 4, 7, 0, 29, 4, 7, 0, 30, 4, 4, 0, 31, 4, 7, 0, 32, 4, 7, 0, 33, 4, - 7, 0, 34, 4, 81, 0, 35, 4, 81, 0, 36, 4, 81, 0, 37, 4, 0, 0, 38, 4, 7, 0, 39, 4, 7, 0, 40, 4, 36, 0, 80, 0, - 2, 0, 41, 4, 0, 0, 42, 4, 0, 0, 43, 4, 7, 0, 44, 4, 4, 0, 45, 4, 7, 0, 46, 4, 7, 0, 47, 4, 4, 0, 48, 4, - 4, 0, 19, 0, 7, 0, 49, 4, 7, 0, 50, 4, 7, 0, 51, 4, 85, 0, 52, 4, 7, 0, 53, 4, 7, 0, 54, 4, 7, 0, 55, 4, - 7, 0, 56, 4, 7, 0, 57, 4, 7, 0, 58, 4, 7, 0, 59, 4, 4, 0, 60, 4,173, 0, 73, 0, 27, 0, 31, 0, 39, 0, 75, 0, - 2, 0,175, 0, 2, 0, 41, 1, 2, 0, 73, 1, 2, 0, 61, 4, 7, 0, 62, 4, 7, 0, 63, 4, 7, 0, 64, 4, 7, 0, 65, 4, - 7, 0, 66, 4, 7, 0, 67, 4, 7, 0, 68, 4, 7, 0, 69, 4, 7, 0,133, 1, 7, 0,135, 1, 7, 0,134, 1, 7, 0, 70, 4, - 4, 0, 71, 4, 7, 0, 72, 4, 7, 0, 73, 4, 7, 0, 74, 4, 7, 0, 75, 4, 7, 0, 76, 4, 7, 0, 77, 4, 7, 0, 78, 4, - 2, 0, 79, 4, 2, 0, 40, 1, 2, 0, 80, 4, 2, 0, 81, 4, 2, 0, 82, 4, 2, 0, 83, 4, 2, 0, 84, 4, 2, 0, 85, 4, - 7, 0, 86, 4, 7, 0, 87, 4, 7, 0, 88, 4, 7, 0, 89, 4, 7, 0, 90, 4, 7, 0, 91, 4, 7, 0, 92, 4, 7, 0, 93, 4, - 7, 0, 94, 4, 7, 0, 95, 4, 7, 0, 96, 4, 7, 0, 97, 4, 2, 0, 98, 4, 2, 0, 99, 4, 2, 0,100, 4, 2, 0,101, 4, - 7, 0,102, 4, 7, 0,103, 4, 7, 0,104, 4, 7, 0,105, 4, 2, 0,106, 4, 2, 0,107, 4, 2, 0,108, 4, 2, 0,109, 4, - 7, 0,110, 4, 7, 0,111, 4, 7, 0,112, 4, 7, 0,113, 4, 2, 0,114, 4, 2, 0,115, 4, 2, 0,116, 4, 2, 0, 19, 0, - 7, 0,117, 4, 7, 0,118, 4, 36, 0, 80, 0, 51, 0,103, 1, 2, 0,104, 1, 2, 0,105, 1, 30, 0,150, 0,174, 0, 8, 0, -174, 0, 0, 0,174, 0, 1, 0, 4, 0, 83, 3, 4, 0,119, 4, 4, 0, 19, 0, 2, 0,120, 4, 2, 0,121, 4, 32, 0,164, 0, -175, 0, 13, 0, 9, 0,122, 4, 9, 0,123, 4, 4, 0,124, 4, 4, 0,125, 4, 4, 0,126, 4, 4, 0,127, 4, 4, 0,128, 4, - 4, 0,129, 4, 4, 0,130, 4, 4, 0,131, 4, 4, 0,132, 4, 4, 0, 37, 0, 0, 0,133, 4,176, 0, 5, 0, 9, 0,134, 4, - 9, 0,135, 4, 4, 0,136, 4, 4, 0, 70, 0, 0, 0,137, 4,177, 0, 13, 0, 4, 0, 17, 0, 4, 0,138, 4, 4, 0,139, 4, - 4, 0,140, 4, 4, 0,141, 4, 4, 0,142, 4, 4, 0, 90, 0, 4, 0,143, 4, 4, 0,144, 4, 4, 0,145, 4, 4, 0,146, 4, - 4, 0,147, 4, 26, 0, 30, 0,178, 0, 4, 0, 4, 0,148, 4, 7, 0,149, 4, 2, 0, 19, 0, 2, 0,105, 1,179, 0, 11, 0, -179, 0, 0, 0,179, 0, 1, 0, 0, 0, 20, 0, 67, 0,150, 4, 68, 0,151, 4, 4, 0, 83, 3, 4, 0,152, 4, 4, 0,153, 4, - 4, 0, 37, 0, 4, 0,154, 4, 4, 0,155, 4,180, 0,132, 0,175, 0,156, 4,176, 0,157, 4,177, 0,158, 4,178, 0,159, 4, - 4, 0,250, 2, 4, 0,126, 0, 4, 0,250, 3, 4, 0,160, 4, 4, 0,161, 4, 4, 0,162, 4, 4, 0,163, 4, 2, 0, 19, 0, - 2, 0,164, 4, 7, 0, 79, 2, 7, 0,165, 4, 7, 0,166, 4, 7, 0,167, 4, 7, 0,168, 4, 7, 0,169, 4, 2, 0,170, 4, - 2, 0,171, 4, 2, 0,172, 4, 2, 0,173, 4, 2, 0,216, 0, 2, 0,174, 4, 2, 0,175, 4, 2, 0,178, 3, 2, 0,176, 4, - 2, 0,177, 4, 2, 0, 60, 1, 2, 0,106, 0, 2, 0,178, 4, 2, 0,179, 4, 2, 0,180, 4, 2, 0,181, 4, 2, 0,182, 4, - 2, 0,183, 4, 2, 0,184, 4, 2, 0,185, 4, 2, 0,186, 4, 2, 0, 61, 1, 2, 0,187, 4, 2, 0,188, 4, 2, 0,189, 4, - 2, 0,190, 4, 4, 0,191, 4, 4, 0, 40, 1, 2, 0,192, 4, 2, 0,193, 4, 2, 0,194, 4, 2, 0,195, 4, 2, 0,196, 4, - 2, 0,197, 4, 24, 0,198, 4, 24, 0,199, 4, 23, 0,200, 4, 12, 0,201, 4, 2, 0,202, 4, 2, 0, 37, 0, 7, 0,203, 4, - 7, 0,204, 4, 7, 0,205, 4, 7, 0,206, 4, 4, 0,207, 4, 7, 0,208, 4, 7, 0,209, 4, 7, 0,210, 4, 7, 0,211, 4, - 2, 0,212, 4, 2, 0,213, 4, 2, 0,214, 4, 2, 0,215, 4, 2, 0,216, 4, 2, 0,217, 4, 7, 0,218, 4, 7, 0,219, 4, - 7, 0,220, 4, 2, 0,221, 4, 2, 0,222, 4, 2, 0,223, 4, 2, 0,224, 4, 2, 0,225, 4, 2, 0,226, 4, 2, 0,227, 4, - 2, 0,228, 4, 2, 0,229, 4, 2, 0,230, 4, 4, 0,231, 4, 4, 0,232, 4, 4, 0,233, 4, 4, 0,234, 4, 4, 0,235, 4, - 7, 0,236, 4, 4, 0,237, 4, 4, 0,238, 4, 4, 0,239, 4, 4, 0,240, 4, 7, 0,241, 4, 7, 0,242, 4, 7, 0,243, 4, - 7, 0,244, 4, 7, 0,245, 4, 7, 0,246, 4, 7, 0,247, 4, 7, 0,248, 4, 7, 0,249, 4, 0, 0,250, 4, 0, 0,251, 4, - 4, 0,252, 4, 2, 0,253, 4, 2, 0,209, 1, 0, 0,254, 4, 7, 0,255, 4, 7, 0, 0, 5, 4, 0, 1, 5, 4, 0, 2, 5, - 7, 0, 3, 5, 7, 0, 4, 5, 2, 0, 5, 5, 2, 0, 6, 5, 7, 0, 7, 5, 2, 0, 8, 5, 2, 0, 9, 5, 4, 0, 10, 5, - 2, 0, 11, 5, 2, 0, 12, 5, 2, 0, 13, 5, 2, 0, 14, 5, 7, 0, 15, 5, 7, 0, 70, 0, 42, 0, 16, 5, 0, 0, 17, 5, -181, 0, 9, 0,181, 0, 0, 0,181, 0, 1, 0, 0, 0, 20, 0, 2, 0, 18, 5, 2, 0, 19, 5, 2, 0, 20, 5, 2, 0, 43, 0, - 7, 0, 21, 5, 7, 0, 70, 0,182, 0, 7, 0, 2, 0,187, 2, 2, 0, 40, 1, 2, 0,109, 0, 2, 0, 22, 5, 7, 0, 23, 5, - 7, 0, 70, 0, 42, 0, 24, 5,183, 0, 5, 0, 7, 0, 25, 5, 0, 0, 17, 0, 0, 0, 43, 0, 0, 0, 70, 0, 0, 0,209, 1, -184, 0, 26, 0, 7, 0, 77, 4, 7, 0, 78, 4, 2, 0, 40, 1, 2, 0, 19, 0, 2, 0, 26, 5, 2, 0,105, 1, 2, 0, 80, 4, - 2, 0, 81, 4, 2, 0, 82, 4, 2, 0, 83, 4, 2, 0, 84, 4, 2, 0, 85, 4,183, 0, 27, 5, 2, 0,170, 4, 2, 0,171, 4, - 2, 0,172, 4, 2, 0,173, 4, 2, 0,216, 0, 2, 0,174, 4, 2, 0,175, 4, 2, 0,178, 3,182, 0, 28, 5, 2, 0, 29, 5, - 2, 0,176, 4, 2, 0,179, 4, 2, 0,180, 4,185, 0, 5, 0,185, 0, 0, 0,185, 0, 1, 0, 4, 0,181, 3, 0, 0,193, 3, - 4, 0, 19, 0,186, 0, 6, 0,187, 0, 30, 5, 4, 0, 31, 5, 4, 0, 32, 5, 9, 0, 33, 5, 0, 0, 34, 5, 4, 0, 37, 0, -188, 0, 6, 0,186, 0, 35, 5, 2, 0, 19, 0, 2, 0, 36, 5, 2, 0, 37, 5, 2, 0, 38, 5, 9, 0, 39, 5,189, 0, 4, 0, - 2, 0,106, 0, 2, 0,198, 2, 2, 0,187, 3, 2, 0, 40, 5,190, 0, 14, 0, 2, 0, 19, 0, 2, 0, 41, 5, 2, 0, 42, 5, - 2, 0, 43, 5,189, 0, 44, 5, 9, 0, 39, 5, 7, 0, 45, 5, 7, 0, 57, 0, 4, 0, 46, 5, 4, 0, 47, 5, 4, 0, 48, 5, - 4, 0, 49, 5, 46, 0,134, 0, 32, 0,164, 0,191, 0, 4, 0,191, 0, 0, 0,191, 0, 1, 0, 0, 0, 50, 5, 7, 0, 51, 5, -192, 0, 6, 0,186, 0, 35, 5, 7, 0, 52, 5, 4, 0, 90, 0, 0, 0, 53, 5, 0, 0, 54, 5, 0, 0,167, 2,193, 0, 9, 0, -186, 0, 35, 5, 7, 0, 55, 5, 7, 0, 56, 5, 2, 0, 40, 1, 2, 0, 19, 0, 4, 0, 36, 0, 4, 0, 57, 5, 87, 0, 58, 5, - 9, 0, 39, 5,194, 0, 72, 0,193, 0, 59, 5,193, 0, 60, 5,192, 0, 57, 3, 7, 0, 61, 5, 2, 0, 62, 5, 2, 0, 63, 5, - 7, 0, 64, 5, 7, 0, 65, 5, 2, 0,187, 3, 2, 0, 66, 5, 7, 0, 67, 5, 7, 0, 68, 5, 7, 0, 69, 5, 2, 0, 70, 5, - 2, 0, 46, 5, 2, 0, 71, 5, 2, 0, 72, 5, 2, 0, 73, 5, 2, 0, 74, 5, 7, 0, 75, 5, 7, 0, 76, 5, 7, 0, 77, 5, - 2, 0, 78, 5, 2, 0, 79, 5, 2, 0, 80, 5, 2, 0, 81, 5, 2, 0, 82, 5, 2, 0, 83, 5, 2, 0, 84, 5,188, 0, 85, 5, -190, 0, 86, 5, 7, 0, 87, 5, 7, 0, 88, 5, 7, 0, 89, 5, 2, 0, 90, 5, 2, 0, 91, 5, 0, 0, 92, 5, 0, 0, 93, 5, - 0, 0, 94, 5, 0, 0, 95, 5, 0, 0, 96, 5, 0, 0, 97, 5, 2, 0, 98, 5, 7, 0, 99, 5, 7, 0,100, 5, 7, 0,101, 5, - 7, 0,102, 5, 7, 0,103, 5, 7, 0,104, 5, 7, 0,105, 5, 7, 0,106, 5, 7, 0,107, 5, 7, 0,108, 5, 2, 0,109, 5, - 0, 0,110, 5, 0, 0,111, 5, 0, 0,112, 5, 0, 0,113, 5, 32, 0,114, 5, 0, 0,115, 5, 0, 0,116, 5, 0, 0,117, 5, - 0, 0,118, 5, 0, 0,119, 5, 0, 0,120, 5, 0, 0,121, 5, 0, 0,122, 5, 2, 0,123, 5, 2, 0,124, 5, 2, 0,125, 5, - 2, 0,126, 5, 2, 0,127, 5,195, 0, 8, 0, 4, 0,128, 5, 4, 0,129, 5, 4, 0,130, 5, 4, 0,131, 5, 4, 0,132, 5, - 4, 0,133, 5, 4, 0, 54, 0, 4, 0,103, 2,196, 0, 3, 0, 7, 0,134, 5, 2, 0,135, 5, 2, 0, 19, 0, 46, 0, 37, 0, - 27, 0, 31, 0, 39, 0, 75, 0, 32, 0,136, 5,173, 0,137, 5, 46, 0,138, 5, 47, 0,208, 0, 12, 0,139, 5,174, 0,140, 5, - 32, 0,141, 5, 7, 0,142, 5, 7, 0,143, 5, 7, 0,144, 5, 7, 0,145, 5, 4, 0, 83, 3, 2, 0, 19, 0, 2, 0, 34, 1, - 61, 0, 29, 1,197, 0,146, 5,194, 0,147, 5,198, 0,148, 5,180, 0,182, 0,178, 0,159, 4, 12, 0,100, 0, 12, 0,149, 5, - 12, 0,150, 5,199, 0,151, 5, 2, 0,152, 5, 2, 0,153, 5, 2, 0,217, 0, 2, 0,154, 5, 4, 0,155, 5, 4, 0,156, 5, - 12, 0,157, 5,183, 0, 27, 5,184, 0,158, 5,196, 0,159, 5,161, 0, 70, 3,200, 0, 6, 0, 47, 0,208, 0, 45, 0, 28, 1, - 7, 0, 67, 2, 7, 0, 68, 2, 7, 0,106, 0, 7, 0,160, 5,201, 0, 35, 0, 7, 0,161, 5, 7, 0,162, 5, 7, 0,163, 5, - 7, 0,164, 5, 7, 0,165, 5, 7, 0,166, 5, 7, 0,167, 5, 7, 0,168, 5, 7, 0,169, 5, 7, 0, 47, 1, 7, 0,170, 5, - 7, 0,171, 5, 7, 0,172, 5, 7, 0,173, 5, 7, 0,171, 0, 2, 0,174, 5, 2, 0,175, 5, 4, 0,176, 5, 2, 0,177, 5, - 2, 0,178, 5, 2, 0,179, 5, 2, 0,180, 5, 7, 0,181, 5, 72, 0,182, 5,161, 0, 70, 3,201, 0,183, 5,202, 0,184, 5, -203, 0,185, 5,204, 0,186, 5,205, 0,187, 5,206, 0,188, 5, 7, 0,189, 5, 2, 0,190, 5, 2, 0,191, 5, 4, 0,209, 1, -207, 0, 54, 0,208, 0, 0, 0,208, 0, 1, 0, 12, 0,192, 5, 4, 0,193, 5, 7, 0,194, 5, 2, 0,195, 5, 7, 0,169, 5, - 7, 0, 47, 1, 7, 0, 43, 0, 4, 0,196, 5, 2, 0,179, 5, 2, 0,180, 5, 32, 0,136, 5, 32, 0,197, 5,200, 0,198, 5, -207, 0,183, 5, 0, 0,199, 5, 4, 0, 83, 3, 4, 0,200, 5, 2, 0,201, 5, 2, 0,202, 5, 2, 0,203, 5, 2, 0,204, 5, - 2, 0,209, 1, 2, 0, 19, 0, 2, 0, 6, 2, 2, 0,205, 5, 7, 0,112, 0, 7, 0,206, 5, 7, 0,207, 5, 7, 0,208, 5, - 7, 0,209, 5, 7, 0,210, 5, 7, 0,171, 0, 7, 0,142, 5, 2, 0,211, 5, 2, 0, 90, 1, 2, 0,212, 5, 2, 0,213, 5, - 2, 0,214, 5, 2, 0,215, 5, 2, 0,216, 5, 2, 0,217, 5, 2, 0,218, 5, 2, 0,219, 5, 4, 0,220, 5, 12, 0,221, 5, - 2, 0,222, 5, 2, 0,116, 2, 2, 0,223, 5, 0, 0,224, 5, 0, 0,225, 5, 9, 0,226, 5,161, 0, 70, 3,209, 0, 25, 0, - 24, 0, 36, 0, 24, 0, 64, 0, 23, 0,227, 5, 23, 0,228, 5, 23, 0,229, 5, 7, 0,230, 5, 7, 0,231, 5, 7, 0,232, 5, - 7, 0,233, 5, 2, 0,234, 5, 2, 0,235, 5, 2, 0,236, 5, 2, 0,237, 5, 2, 0,238, 5, 2, 0, 19, 0, 2, 0,239, 5, - 2, 0,240, 5, 2, 0,241, 5, 2, 0,242, 5, 2, 0,243, 5, 2, 0,204, 5, 7, 0,244, 5, 7, 0,245, 5, 4, 0,246, 5, - 4, 0,247, 5,208, 0, 6, 0,208, 0, 0, 0,208, 0, 1, 0, 12, 0,192, 5, 4, 0,193, 5, 7, 0,194, 5, 2, 0,195, 5, -210, 0, 8, 0,208, 0, 0, 0,208, 0, 1, 0, 12, 0,192, 5, 4, 0,193, 5, 7, 0,194, 5, 2, 0,195, 5,211, 0,248, 5, - 46, 0,134, 0,212, 0, 14, 0,208, 0, 0, 0,208, 0, 1, 0, 12, 0,192, 5, 4, 0,193, 5, 7, 0,194, 5, 2, 0,195, 5, -209, 0,249, 5,213, 0,250, 5, 12, 0,251, 5, 2, 0, 40, 1, 2, 0, 19, 0, 2, 0,252, 5, 0, 0,253, 5, 0, 0,254, 5, -214, 0, 20, 0,208, 0, 0, 0,208, 0, 1, 0, 12, 0,192, 5, 4, 0,193, 5, 7, 0,194, 5, 2, 0,195, 5,202, 0,184, 5, -209, 0,249, 5, 2, 0,255, 5, 2, 0, 0, 6, 2, 0, 1, 6, 2, 0, 2, 6, 2, 0,239, 5, 2, 0, 3, 6, 0, 0, 19, 0, - 0, 0,105, 1, 9, 0, 43, 2, 4, 0, 4, 6, 4, 0, 5, 6, 27, 0, 6, 6,215, 0, 16, 0,208, 0, 0, 0,208, 0, 1, 0, - 12, 0,192, 5, 4, 0,193, 5, 7, 0,194, 5, 2, 0,195, 5,209, 0,249, 5, 7, 0, 67, 2, 7, 0, 68, 2, 2, 0,255, 5, - 2, 0, 7, 6, 2, 0, 8, 6, 2, 0, 9, 6, 4, 0, 19, 0, 7, 0, 10, 6,161, 0, 70, 3,216, 0, 16, 0, 0, 0, 11, 6, - 0, 0, 12, 6, 0, 0, 13, 6, 0, 0, 14, 6, 2, 0, 17, 0, 2, 0, 19, 0, 2, 0, 15, 6, 2, 0, 16, 6, 2, 0,152, 1, - 2, 0, 17, 6, 4, 0, 18, 6, 4, 0, 19, 6, 2, 0, 20, 6, 2, 0, 21, 6, 0, 0, 22, 6, 0, 0, 23, 6,217, 0, 16, 0, -208, 0, 0, 0,208, 0, 1, 0, 12, 0,192, 5, 4, 0,193, 5, 4, 0, 37, 0,216, 0, 24, 6,218, 0, 25, 6, 12, 0, 26, 6, - 12, 0, 27, 6,219, 0, 28, 6,206, 0, 29, 6,220, 0, 30, 6, 2, 0, 31, 6, 2, 0, 32, 6, 2, 0, 33, 6, 2, 0, 70, 0, -221, 0, 17, 0,208, 0, 0, 0,208, 0, 1, 0, 12, 0,192, 5, 4, 0,193, 5, 7, 0,194, 5, 2, 0,195, 5,209, 0,249, 5, - 12, 0, 34, 6,222, 0, 35, 6, 0, 0, 36, 6,223, 0, 37, 6, 4, 0, 38, 6, 4, 0, 39, 6, 2, 0, 19, 0, 2, 0, 40, 6, - 2, 0, 41, 6, 2, 0, 37, 0,224, 0, 29, 0,208, 0, 0, 0,208, 0, 1, 0, 12, 0,192, 5, 4, 0,193, 5, 7, 0,194, 5, - 2, 0,195, 5, 47, 0,206, 2, 45, 0, 28, 1, 64, 0, 42, 6, 2, 0,133, 0, 2, 0, 43, 6, 2, 0, 70, 0, 2, 0, 44, 6, - 4, 0, 19, 0, 2, 0, 45, 6, 2, 0,254, 5, 2, 0,253, 5, 2, 0,209, 1, 0, 0, 46, 6, 0, 0, 47, 6, 0, 0, 48, 6, - 0, 0,204, 5, 7, 0, 67, 2, 7, 0, 68, 2, 7, 0, 10, 6, 7, 0, 90, 1, 7, 0, 49, 6, 7, 0, 50, 6,161, 0, 70, 3, -225, 0, 11, 0,208, 0, 0, 0,208, 0, 1, 0, 12, 0,192, 5, 4, 0,193, 5, 7, 0,194, 5, 2, 0,195, 5, 2, 0,252, 5, - 2, 0, 19, 0, 4, 0, 37, 0,213, 0,250, 5,209, 0,249, 5,226, 0, 27, 0,208, 0, 0, 0,208, 0, 1, 0, 12, 0,192, 5, - 4, 0,193, 5, 7, 0,194, 5, 2, 0,195, 5, 42, 0, 51, 6, 4, 0, 52, 6, 4, 0, 53, 6, 2, 0, 90, 0, 2, 0,133, 0, - 2, 0, 54, 6, 0, 0, 55, 6, 0, 0, 56, 6, 4, 0, 57, 6, 4, 0, 58, 6, 4, 0, 59, 6, 4, 0, 60, 6, 2, 0, 61, 6, - 2, 0, 62, 6, 7, 0, 63, 6, 23, 0, 64, 6, 23, 0, 65, 6, 4, 0, 66, 6, 4, 0, 67, 6, 0, 0, 68, 6, 0, 0, 69, 6, -227, 0, 10, 0, 27, 0, 31, 0, 9, 0, 70, 6, 9, 0, 71, 6, 9, 0, 72, 6, 9, 0, 73, 6, 9, 0, 74, 6, 4, 0, 90, 0, - 4, 0, 75, 6, 0, 0, 76, 6, 0, 0, 77, 6,228, 0, 10, 0,208, 0, 0, 0,208, 0, 1, 0, 12, 0,192, 5, 4, 0,193, 5, - 7, 0,194, 5,227, 0, 78, 6, 2, 0, 90, 0, 2, 0,133, 0, 4, 0, 43, 0, 9, 0, 79, 6,229, 0, 8, 0,208, 0, 0, 0, -208, 0, 1, 0, 12, 0,192, 5, 4, 0,193, 5, 7, 0,194, 5,209, 0,249, 5, 4, 0, 19, 0, 4, 0, 80, 6,230, 0, 23, 0, -208, 0, 0, 0,208, 0, 1, 0, 12, 0,192, 5, 4, 0,193, 5, 7, 0,194, 5, 2, 0,195, 5,209, 0,249, 5, 27, 0, 81, 6, - 27, 0, 81, 0, 2, 0, 19, 0, 2, 0,133, 0, 7, 0, 82, 6, 9, 0, 83, 6, 7, 0, 67, 2, 7, 0, 68, 2, 7, 0, 84, 6, - 7, 0, 85, 6, 61, 0, 29, 1, 61, 0, 86, 6, 4, 0, 87, 6, 2, 0, 88, 6, 2, 0, 37, 0,161, 0, 70, 3,231, 0, 10, 0, -208, 0, 0, 0,208, 0, 1, 0, 12, 0,192, 5, 4, 0,193, 5, 7, 0,194, 5, 2, 0,195, 5, 2, 0, 19, 0, 2, 0, 92, 3, - 4, 0, 37, 0,161, 0, 70, 3,232, 0, 42, 0,208, 0, 0, 0,208, 0, 1, 0, 12, 0,192, 5, 4, 0,193, 5, 7, 0,194, 5, - 2, 0,195, 5,209, 0,249, 5,218, 0, 25, 6, 0, 0, 11, 6, 0, 0, 12, 6, 0, 0, 13, 6, 2, 0, 17, 0, 2, 0, 21, 6, - 2, 0, 19, 0, 2, 0, 15, 6, 9, 0, 83, 6, 4, 0, 18, 6, 4, 0, 89, 6, 4, 0, 90, 6, 4, 0, 19, 6, 23, 0, 91, 6, - 23, 0, 92, 6, 7, 0, 93, 6, 7, 0, 94, 6, 7, 0, 95, 6, 7, 0, 82, 6, 2, 0, 96, 6, 2, 0,207, 0, 2, 0,152, 1, - 2, 0, 17, 6, 2, 0, 37, 0, 2, 0, 43, 0, 2, 0, 97, 6, 2, 0, 98, 6, 9, 0, 99, 6, 9, 0,100, 6, 9, 0,101, 6, - 9, 0,102, 6, 9, 0,103, 6, 2, 0,104, 6, 0, 0, 23, 6, 57, 0,105, 6,233, 0, 7, 0,233, 0, 0, 0,233, 0, 1, 0, - 4, 0,106, 6, 4, 0, 23, 0, 0, 0, 84, 0, 4, 0,107, 6, 4, 0, 17, 0,234, 0, 13, 0,208, 0, 0, 0,208, 0, 1, 0, - 12, 0,192, 5, 4, 0,193, 5, 7, 0,194, 5, 2, 0,195, 5, 4, 0, 17, 0, 4, 0,108, 6, 4, 0, 19, 0, 4, 0, 54, 6, - 12, 0,109, 6, 12, 0,110, 6, 0, 0,111, 6,235, 0, 5, 0,208, 0, 0, 0,208, 0, 1, 0, 12, 0,192, 5, 4, 0,193, 5, - 4, 0, 37, 0,236, 0, 7, 0,236, 0, 0, 0,236, 0, 1, 0, 0, 0,112, 6, 2, 0,113, 6, 2, 0,114, 6, 2, 0,115, 6, - 2, 0, 37, 0,237, 0, 12, 0, 2, 0,114, 6, 2, 0,116, 6, 2, 0,117, 6, 0, 0,167, 2, 2, 0,118, 6, 2, 0,119, 6, - 2, 0,120, 6, 2, 0,121, 6, 2, 0,122, 6, 2, 0,239, 5, 7, 0,123, 6, 7, 0,124, 6,238, 0, 18, 0,238, 0, 0, 0, -238, 0, 1, 0, 0, 0,193, 3,237, 0,125, 6,237, 0,126, 6,237, 0,127, 6,237, 0,128, 6, 7, 0,129, 6, 2, 0,130, 6, - 2, 0,131, 6, 2, 0,132, 6, 2, 0,133, 6, 2, 0,134, 6, 2, 0,135, 6, 2, 0,136, 6, 2, 0,137, 6, 2, 0,138, 6, - 2, 0,139, 6,239, 0, 10, 0, 0, 0,140, 6, 0, 0,141, 6, 0, 0,142, 6, 0, 0,143, 6, 0, 0,144, 6, 0, 0,145, 6, - 2, 0,146, 6, 2, 0,147, 6, 2, 0,148, 6, 2, 0, 37, 0,240, 0, 8, 0, 0, 0,149, 6, 0, 0,150, 6, 0, 0,151, 6, - 0, 0,152, 6, 0, 0,153, 6, 0, 0,154, 6, 7, 0,160, 5, 7, 0, 37, 0,241, 0, 17, 0,239, 0,155, 6,239, 0,156, 6, -239, 0,157, 6,239, 0,158, 6,239, 0,159, 6,239, 0,160, 6,239, 0,161, 6,239, 0,162, 6,239, 0,163, 6,239, 0,164, 6, -239, 0,165, 6,239, 0,166, 6,239, 0,167, 6,239, 0,168, 6,239, 0,169, 6,240, 0,170, 6, 0, 0,171, 6,242, 0, 71, 0, - 0, 0,172, 6, 0, 0,173, 6, 0, 0,144, 6, 0, 0,174, 6, 0, 0,175, 6, 0, 0,176, 6, 0, 0,177, 6, 0, 0,178, 6, - 0, 0,179, 6, 0, 0,180, 6, 0, 0,181, 6, 0, 0,182, 6, 0, 0,183, 6, 0, 0,184, 6, 0, 0,185, 6, 0, 0,186, 6, - 0, 0,187, 6, 0, 0,188, 6, 0, 0,189, 6, 0, 0,190, 6, 0, 0,191, 6, 0, 0,192, 6, 0, 0,193, 6, 0, 0,194, 6, - 0, 0,195, 6, 0, 0,196, 6, 0, 0,197, 6, 0, 0,198, 6, 0, 0,199, 6, 0, 0,200, 6, 0, 0,201, 6, 0, 0,202, 6, - 0, 0,203, 6, 0, 0,204, 6, 0, 0,205, 6, 0, 0,206, 6, 0, 0,207, 6, 0, 0,208, 6, 0, 0,209, 6, 0, 0,210, 6, - 0, 0,211, 6, 0, 0,212, 6, 0, 0,213, 6, 0, 0,214, 6, 0, 0,215, 6, 0, 0,216, 6, 0, 0,217, 6, 0, 0,218, 6, - 0, 0,219, 6, 0, 0,220, 6, 0, 0,221, 6, 0, 0,222, 6, 0, 0,223, 6, 0, 0,224, 6, 0, 0,225, 6, 0, 0,226, 6, - 0, 0,227, 6, 0, 0,228, 6, 0, 0,229, 6, 0, 0,230, 6, 0, 0,231, 6, 0, 0,232, 6, 0, 0,233, 6, 0, 0,234, 6, - 0, 0,235, 6, 0, 0,236, 6, 0, 0,237, 6, 0, 0,238, 6, 0, 0,239, 6, 0, 0,240, 6, 0, 0, 92, 0,243, 0, 5, 0, - 0, 0,241, 6, 0, 0,196, 6, 0, 0,198, 6, 2, 0, 19, 0, 2, 0, 37, 0,244, 0, 22, 0,244, 0, 0, 0,244, 0, 1, 0, - 0, 0, 20, 0,241, 0,242, 6,242, 0,243, 6,242, 0,244, 6,242, 0,245, 6,242, 0,246, 6,242, 0,247, 6,242, 0,248, 6, -242, 0,249, 6,242, 0,250, 6,242, 0,251, 6,242, 0,252, 6,242, 0,253, 6,242, 0,254, 6,242, 0,255, 6,242, 0, 0, 7, -242, 0, 1, 7,242, 0, 2, 7,242, 0, 3, 7,243, 0, 4, 7,245, 0, 5, 0, 4, 0, 19, 0, 4, 0, 37, 0, 7, 0,115, 2, - 7, 0, 5, 7, 7, 0, 21, 2,246, 0, 71, 0, 4, 0, 19, 0, 4, 0, 6, 7, 4, 0, 7, 7, 0, 0, 8, 7, 0, 0, 9, 7, - 0, 0, 10, 7, 0, 0, 11, 7, 0, 0, 12, 7, 0, 0, 13, 7, 0, 0, 14, 7, 0, 0, 15, 7, 0, 0, 16, 7, 2, 0, 17, 7, - 2, 0, 37, 0, 4, 0, 18, 7, 4, 0, 19, 7, 4, 0, 20, 7, 4, 0, 21, 7, 2, 0, 22, 7, 2, 0, 23, 7, 4, 0, 24, 7, - 4, 0, 25, 7, 4, 0, 26, 7, 4, 0, 27, 7, 4, 0, 28, 7, 4, 0,109, 6, 4, 0, 29, 7, 2, 0, 30, 7, 2, 0, 31, 7, - 2, 0, 32, 7, 2, 0, 33, 7, 12, 0, 34, 7, 12, 0, 35, 7, 12, 0, 36, 7, 2, 0, 37, 7, 2, 0, 38, 7, 2, 0, 39, 7, - 2, 0, 40, 7, 2, 0, 41, 7, 2, 0, 42, 7, 2, 0, 43, 7, 2, 0, 44, 7,245, 0, 45, 7, 2, 0, 46, 7, 2, 0, 47, 7, - 2, 0, 48, 7, 2, 0, 49, 7, 2, 0, 50, 7, 2, 0, 51, 7, 2, 0, 52, 7, 2, 0, 53, 7, 4, 0, 54, 7, 4, 0, 55, 7, - 2, 0, 56, 7, 2, 0, 57, 7, 2, 0, 58, 7, 2, 0, 59, 7, 2, 0, 60, 7, 2, 0, 61, 7, 2, 0, 62, 7, 2, 0, 63, 7, - 2, 0, 64, 7, 2, 0, 65, 7, 2, 0, 66, 7, 2, 0, 67, 7, 0, 0, 68, 7, 0, 0, 69, 7, 7, 0, 70, 7, 2, 0, 90, 5, - 2, 0, 91, 5, 55, 0, 71, 7,211, 0, 21, 0, 27, 0, 31, 0, 12, 0, 72, 7, 12, 0, 73, 7, 12, 0, 74, 7, 12, 0,192, 5, - 46, 0,134, 0, 46, 0, 75, 7, 2, 0, 76, 7, 2, 0, 77, 7, 2, 0, 78, 7, 2, 0, 79, 7, 2, 0, 80, 7, 2, 0, 81, 7, - 2, 0, 82, 7, 2, 0, 37, 0, 2, 0, 83, 7, 2, 0, 84, 7, 4, 0, 70, 0,206, 0, 85, 7, 9, 0, 86, 7, 2, 0, 87, 7, -247, 0, 5, 0,247, 0, 0, 0,247, 0, 1, 0,247, 0, 88, 7, 13, 0, 89, 7, 4, 0, 19, 0,248, 0, 7, 0,248, 0, 0, 0, -248, 0, 1, 0,247, 0, 90, 7,247, 0, 91, 7, 2, 0,199, 4, 2, 0, 19, 0, 4, 0, 37, 0,249, 0, 23, 0,249, 0, 0, 0, -249, 0, 1, 0,250, 0, 92, 7,251, 0, 30, 6, 0, 0, 93, 7, 0, 0, 94, 7, 0, 0, 95, 7, 2, 0, 96, 7, 2, 0, 97, 7, - 2, 0, 98, 7, 2, 0, 99, 7, 2, 0,100, 7, 2, 0, 37, 0, 2, 0, 19, 0, 2, 0,101, 7, 2, 0,102, 7, 2, 0,103, 7, - 4, 0,104, 7,249, 0,105, 7, 9, 0,106, 7, 4, 0,107, 7, 4, 0,108, 7, 0, 0,109, 7,252, 0, 22, 0,252, 0, 0, 0, -252, 0, 1, 0,247, 0, 90, 7,247, 0, 91, 7,247, 0,110, 7,247, 0,111, 7,211, 0,112, 7, 23, 0, 52, 0, 0, 0,193, 5, - 0, 0,113, 7, 2, 0,240, 5, 2, 0,241, 5, 2, 0,114, 7, 2, 0, 37, 0, 2, 0, 79, 7, 2, 0,107, 6, 2, 0, 19, 0, -253, 0, 92, 7, 12, 0,115, 7, 12, 0,192, 5, 12, 0,116, 7, 12, 0,117, 7,254, 0, 21, 0,254, 0, 0, 0,254, 0, 1, 0, -209, 0,249, 5, 23, 0,118, 7, 23, 0,119, 7, 2, 0,240, 5, 2, 0,241, 5, 2, 0,120, 7, 2, 0,121, 7, 2, 0,122, 7, - 2, 0, 19, 0, 7, 0, 63, 2, 2, 0, 78, 7, 2, 0, 82, 7, 4, 0, 43, 0,255, 0, 92, 7, 12, 0,123, 7, 12, 0,124, 7, - 12, 0,116, 7, 0, 0,125, 7, 9, 0,126, 7, 0, 1, 11, 0, 0, 0,127, 7, 2, 0,128, 7, 2, 0,129, 7, 2, 0,130, 7, - 2, 0,131, 7, 2, 0,188, 4, 2, 0,183, 4,211, 0,132, 7, 46, 0,133, 7, 4, 0,134, 7, 4, 0,135, 7, 1, 1, 1, 0, - 0, 0,136, 7, 2, 1, 8, 0, 57, 0,137, 7, 57, 0,138, 7, 2, 1,139, 7, 2, 1,140, 7, 2, 1,141, 7, 2, 0,129, 0, - 2, 0, 19, 0, 4, 0,142, 7, 3, 1, 4, 0, 4, 0, 52, 6, 4, 0,143, 7, 4, 0, 57, 6, 4, 0,144, 7, 4, 1, 2, 0, - 4, 0,145, 7, 4, 0,146, 7, 5, 1, 7, 0, 7, 0,147, 7, 7, 0,148, 7, 7, 0,149, 7, 4, 0, 19, 0, 4, 0, 37, 0, - 7, 0, 72, 4, 7, 0,150, 7, 6, 1, 6, 0, 0, 0,151, 7, 0, 0, 13, 6, 49, 0,137, 0, 2, 0,106, 0, 2, 0,187, 4, - 4, 0, 37, 0, 7, 1, 21, 0, 7, 1, 0, 0, 7, 1, 1, 0, 4, 0, 57, 0, 4, 0, 23, 0, 4, 0, 28, 0, 4, 0,152, 7, - 4, 0,153, 7, 4, 0,154, 7, 1, 1,155, 7, 0, 0,151, 7, 4, 0,156, 7, 4, 0,157, 7, 6, 1, 64, 3, 3, 1,158, 7, - 4, 1,159, 7, 5, 1,160, 7, 2, 1,161, 7, 2, 1,162, 7, 2, 1,163, 7, 57, 0,164, 7, 57, 0,165, 7, 8, 1, 12, 0, - 0, 0,239, 1, 9, 0,193, 0, 0, 0,194, 0, 4, 0,197, 0, 4, 0,205, 0, 9, 0,198, 0, 7, 0,200, 0, 7, 0,201, 0, - 9, 0,166, 7, 9, 0,167, 7, 9, 0,202, 0, 9, 0,204, 0, 9, 1, 43, 0, 9, 1, 0, 0, 9, 1, 1, 0, 9, 0,168, 7, - 9, 0, 26, 0, 0, 0, 27, 0, 4, 0, 19, 0, 4, 0, 17, 0, 4, 0, 23, 0, 4, 0, 88, 0, 4, 0,169, 7, 4, 0,170, 7, - 4, 0,153, 7, 4, 0,154, 7, 4, 0,171, 7, 4, 0,216, 0, 4, 0,172, 7, 4, 0,173, 7, 7, 0, 56, 5, 7, 0,174, 7, - 4, 0,126, 0, 4, 0,175, 7, 7, 1,176, 7, 36, 0, 80, 0, 46, 0,134, 0, 49, 0,137, 0, 7, 0,177, 7, 7, 0,178, 7, - 8, 1, 30, 1, 9, 1,179, 7, 9, 1,180, 7, 9, 1,181, 7, 12, 0,182, 7, 10, 1,183, 7, 11, 1,184, 7, 7, 0,185, 7, - 7, 0,186, 7, 4, 0,187, 7, 7, 0,188, 7, 9, 0,189, 7, 4, 0,190, 7, 4, 0,191, 7, 4, 0,192, 7, 7, 0,193, 7, - 12, 1, 4, 0, 12, 1, 0, 0, 12, 1, 1, 0, 12, 0,194, 7, 9, 1,195, 7,197, 0, 6, 0, 12, 0,196, 7, 12, 0,182, 7, - 12, 0,197, 7, 9, 1,198, 7, 0, 0,199, 7, 0, 0,200, 7, 13, 1, 4, 0, 7, 0,201, 7, 7, 0,109, 0, 2, 0,202, 7, - 2, 0,203, 7, 14, 1, 6, 0, 7, 0,204, 7, 7, 0,205, 7, 7, 0,206, 7, 7, 0,207, 7, 4, 0,208, 7, 4, 0,209, 7, - 15, 1, 12, 0, 7, 0,210, 7, 7, 0,211, 7, 7, 0,212, 7, 7, 0,213, 7, 7, 0,214, 7, 7, 0,215, 7, 7, 0,216, 7, - 7, 0,217, 7, 7, 0,218, 7, 7, 0,219, 7, 4, 0,210, 2, 4, 0,220, 7, 16, 1, 2, 0, 7, 0, 25, 5, 7, 0, 37, 0, - 17, 1, 5, 0, 7, 0,221, 7, 7, 0,222, 7, 4, 0, 90, 0, 4, 0,168, 2, 4, 0,223, 7, 18, 1, 6, 0, 18, 1, 0, 0, - 18, 1, 1, 0, 2, 0, 17, 0, 2, 0, 19, 0, 2, 0,224, 7, 2, 0, 57, 0, 19, 1, 8, 0, 19, 1, 0, 0, 19, 1, 1, 0, - 2, 0, 17, 0, 2, 0, 19, 0, 2, 0,224, 7, 2, 0, 57, 0, 7, 0, 23, 0, 7, 0,126, 0, 20, 1, 45, 0, 20, 1, 0, 0, - 20, 1, 1, 0, 2, 0, 17, 0, 2, 0, 19, 0, 2, 0,224, 7, 2, 0,212, 0, 2, 0,244, 3, 2, 0,225, 7, 7, 0,226, 7, - 7, 0, 89, 0, 7, 0,223, 2, 4, 0,227, 7, 4, 0, 82, 0, 4, 0,170, 2, 7, 0,228, 7, 7, 0,229, 7, 7, 0,230, 7, - 7, 0,231, 7, 7, 0,232, 7, 7, 0,233, 7, 7, 0,220, 2, 7, 0, 27, 1, 7, 0,234, 7, 7, 0,235, 7, 7, 0, 37, 0, - 7, 0,236, 7, 7, 0,237, 7, 7, 0,238, 7, 2, 0,239, 7, 2, 0,240, 7, 2, 0,241, 7, 2, 0,242, 7, 2, 0,243, 7, - 2, 0,244, 7, 2, 0,245, 7, 2, 0,246, 7, 2, 0, 6, 2, 2, 0,247, 7, 2, 0, 3, 2, 2, 0,248, 7, 0, 0,249, 7, - 0, 0,250, 7, 7, 0,210, 0, 21, 1,251, 7, 68, 0,212, 1, 22, 1, 16, 0, 22, 1, 0, 0, 22, 1, 1, 0, 2, 0, 17, 0, - 2, 0, 19, 0, 2, 0,224, 7, 2, 0,212, 0, 7, 0,215, 2, 7, 0,216, 2, 7, 0,217, 2, 7, 0, 52, 2, 7, 0,218, 2, - 7, 0,219, 2, 7, 0,252, 7, 7, 0,220, 2, 7, 0,222, 2, 7, 0,223, 2,223, 0, 5, 0, 2, 0, 17, 0, 2, 0,142, 7, - 2, 0, 19, 0, 2, 0,253, 7, 27, 0, 81, 6,222, 0, 3, 0, 4, 0, 69, 0, 4, 0,254, 7,223, 0, 2, 0, 23, 1, 7, 0, - 23, 1, 0, 0, 23, 1, 1, 0, 0, 0, 20, 0, 2, 0, 17, 0, 2, 0, 19, 0, 4, 0, 22, 0, 9, 0,255, 7, 24, 1, 5, 0, - 0, 0, 20, 0, 7, 0, 47, 1, 7, 0, 0, 8, 4, 0, 1, 8, 4, 0, 37, 0, 25, 1, 4, 0, 2, 0, 17, 0, 2, 0, 19, 0, - 2, 0, 43, 0, 2, 0, 70, 0, 26, 1, 4, 0, 0, 0, 20, 0, 67, 0, 2, 8, 7, 0, 47, 1, 7, 0, 37, 0, 27, 1, 6, 0, - 2, 0, 3, 8, 2, 0, 4, 8, 2, 0, 17, 0, 2, 0, 5, 8, 0, 0, 6, 8, 0, 0, 7, 8, 28, 1, 5, 0, 4, 0, 17, 0, - 4, 0, 37, 0, 0, 0, 20, 0, 0, 0, 8, 8, 0, 0, 9, 8, 29, 1, 3, 0, 4, 0, 17, 0, 4, 0, 37, 0, 0, 0, 20, 0, - 30, 1, 4, 0, 2, 0, 10, 8, 2, 0, 11, 8, 2, 0, 19, 0, 2, 0, 37, 0, 31, 1, 6, 0, 0, 0, 20, 0, 0, 0, 12, 8, - 2, 0, 13, 8, 2, 0,220, 2, 2, 0, 40, 1, 2, 0, 70, 0, 32, 1, 5, 0, 0, 0, 20, 0, 7, 0,109, 0, 7, 0, 74, 4, - 2, 0, 19, 0, 2, 0,182, 2, 33, 1, 3, 0, 0, 0, 20, 0, 4, 0,170, 2, 4, 0, 10, 8, 34, 1, 7, 0, 0, 0, 20, 0, - 7, 0, 74, 4, 0, 0, 14, 8, 0, 0, 15, 8, 2, 0, 40, 1, 2, 0, 43, 0, 4, 0, 16, 8, 35, 1, 3, 0, 32, 0, 17, 8, - 0, 0, 18, 8, 0, 0, 19, 8, 36, 1, 18, 0, 36, 1, 0, 0, 36, 1, 1, 0, 2, 0, 17, 0, 2, 0, 20, 8, 2, 0, 19, 0, - 2, 0, 21, 8, 2, 0, 22, 8, 2, 0, 23, 8, 2, 0, 43, 0, 2, 0, 70, 0, 0, 0, 20, 0, 9, 0, 2, 0, 37, 1, 24, 8, - 32, 0, 45, 0, 2, 0, 40, 5, 2, 0,185, 7, 2, 0, 25, 8, 2, 0, 37, 0, 38, 1, 11, 0, 0, 0, 20, 0, 0, 0, 17, 0, - 0, 0, 26, 8, 2, 0, 19, 0, 2, 0,182, 2, 2, 0, 27, 8, 4, 0, 28, 8, 4, 0, 29, 8, 4, 0, 30, 8, 4, 0, 31, 8, - 4, 0, 32, 8, 39, 1, 1, 0, 0, 0, 33, 8, 40, 1, 4, 0, 42, 0, 51, 6, 0, 0, 34, 8, 4, 0, 40, 1, 4, 0, 19, 0, - 37, 1, 18, 0, 37, 1, 0, 0, 37, 1, 1, 0, 37, 1, 35, 8, 2, 0, 17, 0, 2, 0, 19, 0, 2, 0, 36, 8, 2, 0, 23, 8, - 2, 0, 20, 8, 2, 0, 37, 8, 2, 0, 70, 0, 2, 0,209, 1, 0, 0, 20, 0, 9, 0, 2, 0, 41, 1, 24, 8, 36, 1, 38, 8, - 2, 0, 15, 0, 2, 0, 39, 8, 4, 0, 40, 8, 42, 1, 3, 0, 4, 0,196, 2, 4, 0, 37, 0, 32, 0, 45, 0, 43, 1, 12, 0, -159, 0, 41, 8, 2, 0, 17, 0, 2, 0, 19, 0, 4, 0,226, 7, 4, 0, 89, 0, 0, 0, 20, 0, 0, 0, 42, 8, 2, 0, 43, 8, - 2, 0, 44, 8, 2, 0, 45, 8, 2, 0, 46, 8, 7, 0, 47, 8, 44, 1, 13, 0, 2, 0, 19, 0, 2, 0, 48, 8, 4, 0,226, 7, - 4, 0, 89, 0, 2, 0, 49, 8, 7, 0,202, 3, 7, 0, 50, 8, 10, 1,183, 7, 45, 1, 51, 8, 2, 0, 17, 0, 2, 0, 52, 8, - 2, 0, 53, 8, 2, 0, 54, 8, 46, 1, 11, 0, 4, 0,196, 2, 2, 0, 17, 0, 2, 0, 19, 0, 32, 0, 45, 0, 81, 0, 55, 8, - 0, 0, 20, 0, 7, 0, 56, 8, 7, 0, 57, 8, 7, 0,100, 3, 2, 0, 58, 8, 2, 0, 59, 8, 47, 1, 5, 0, 2, 0, 17, 0, - 2, 0, 19, 0, 4, 0, 37, 0, 46, 0,134, 0, 32, 0,136, 5, 48, 1, 5, 0, 4, 0, 19, 0, 4, 0, 17, 0, 0, 0, 20, 0, - 0, 0, 8, 8, 32, 0, 45, 0, 49, 1, 13, 0, 2, 0, 19, 0, 2, 0, 17, 0, 2, 0, 20, 8, 2, 0,101, 3, 7, 0, 60, 8, - 7, 0, 61, 8, 7, 0, 35, 1, 7, 0, 36, 1, 7, 0, 77, 3, 7, 0, 80, 3, 7, 0, 62, 8, 7, 0, 63, 8, 32, 0, 64, 8, - 50, 1, 10, 0, 2, 0, 19, 0, 2, 0, 17, 0, 4, 0,226, 7, 4, 0, 89, 0, 0, 0, 20, 0, 0, 0, 42, 8, 2, 0, 43, 0, - 2, 0, 64, 0, 2, 0, 65, 8, 2, 0, 66, 8, 51, 1, 8, 0, 32, 0, 45, 0, 7, 0,217, 2, 7, 0, 67, 8, 7, 0, 68, 8, - 7, 0,212, 2, 2, 0, 19, 0, 2, 0,182, 2, 7, 0, 69, 8, 52, 1, 12, 0, 2, 0, 17, 0, 2, 0, 40, 1, 2, 0, 19, 0, - 2, 0,220, 2, 2, 0,196, 2, 2, 0, 70, 8, 4, 0, 37, 0, 7, 0, 71, 8, 7, 0, 72, 8, 7, 0, 73, 8, 7, 0, 74, 8, - 0, 0, 75, 8, 53, 1, 10, 0, 2, 0, 19, 0, 2, 0, 17, 0, 4, 0,226, 7, 4, 0, 89, 0, 0, 0, 20, 0, 2, 0,105, 1, - 2, 0, 64, 0, 2, 0, 65, 8, 2, 0, 66, 8, 68, 0,212, 1, 54, 1, 7, 0, 4, 0,170, 2, 4, 0, 76, 8, 4, 0, 77, 8, - 4, 0, 78, 8, 7, 0, 79, 8, 7, 0, 80, 8, 0, 0, 14, 8, 55, 1, 7, 0, 0, 0, 81, 8, 32, 0, 82, 8, 0, 0, 18, 8, - 2, 0, 83, 8, 2, 0, 43, 0, 4, 0, 70, 0, 0, 0, 19, 8, 56, 1, 6, 0, 2, 0, 19, 0, 2, 0, 17, 0, 4, 0,226, 7, - 4, 0, 89, 0, 0, 0, 84, 8, 0, 0, 85, 8, 57, 1, 1, 0, 4, 0, 19, 0, 58, 1, 6, 0, 0, 0, 92, 0, 2, 0, 17, 0, - 2, 0, 19, 0, 4, 0, 86, 8, 7, 0, 87, 8, 42, 0, 51, 6, 59, 1, 4, 0, 0, 0, 48, 2, 2, 0, 19, 0, 4, 0, 17, 0, - 32, 0, 45, 0, 60, 1, 2, 0, 4, 0, 17, 0, 4, 0,229, 5, 41, 1, 10, 0, 41, 1, 0, 0, 41, 1, 1, 0, 41, 1, 35, 8, - 2, 0, 17, 0, 2, 0, 19, 0, 2, 0, 20, 8, 2, 0, 88, 8, 0, 0, 20, 0, 9, 0, 2, 0, 32, 0, 45, 0, 61, 1, 10, 0, - 7, 0,100, 3, 7, 0, 89, 8, 7, 0, 90, 8, 7, 0, 91, 8, 7, 0, 92, 8, 4, 0, 19, 0, 7, 0, 70, 8, 7, 0, 93, 8, - 7, 0, 94, 8, 7, 0, 37, 0, 11, 1, 12, 0, 11, 1, 0, 0, 11, 1, 1, 0, 10, 1, 95, 8, 9, 0,193, 0, 4, 0,143, 3, - 4, 0,189, 3, 4, 0,190, 3, 4, 0, 96, 8, 4, 0, 97, 8, 4, 0, 98, 8, 7, 0,202, 3, 7, 0, 37, 0, 45, 1, 8, 0, - 7, 0, 99, 8, 7, 0,100, 8, 7, 0,101, 8, 7, 0,102, 8, 7, 0,103, 8, 7, 0,104, 8, 7, 0,105, 8, 7, 0,106, 8, - 10, 1, 15, 0, 27, 0, 31, 0, 0, 0,192, 0, 43, 0,149, 0, 9, 0,193, 0, 43, 0,107, 8, 36, 0, 80, 0, 7, 0,202, 3, - 7, 0,108, 8, 7, 0, 50, 8, 7, 0, 99, 8, 7, 0,100, 8, 7, 0,109, 8, 4, 0, 90, 0, 4, 0, 98, 8, 9, 0,110, 8, - 62, 1, 15, 0,208, 0, 0, 0,208, 0, 1, 0, 12, 0,192, 5, 4, 0,193, 5, 7, 0,194, 5,252, 0,111, 8,209, 0,249, 5, - 10, 1,183, 7, 2, 0, 40, 1, 2, 0, 48, 8, 2, 0, 67, 2, 2, 0, 68, 2, 2, 0, 19, 0, 2, 0,254, 5, 4, 0, 70, 0, - 63, 1, 6, 0, 63, 1, 0, 0, 63, 1, 1, 0, 32, 0, 45, 0, 9, 0,112, 8, 4, 0,217, 0, 4, 0, 37, 0, 68, 0, 4, 0, - 27, 0, 31, 0, 12, 0,113, 8, 4, 0,131, 0, 7, 0,114, 8, 64, 1, 25, 0, 64, 1, 0, 0, 64, 1, 1, 0, 64, 1, 38, 0, - 12, 0,115, 8, 0, 0, 20, 0, 7, 0,116, 8, 7, 0,117, 8, 7, 0,118, 8, 7, 0,119, 8, 4, 0, 19, 0, 7, 0,120, 8, - 7, 0,121, 8, 7, 0,122, 8, 7, 0, 47, 1, 7, 0, 14, 2, 7, 0,123, 8, 7, 0,168, 2, 7, 0,124, 8, 7, 0,125, 8, - 7, 0,126, 8, 7, 0,127, 8, 7, 0,128, 8, 7, 0,172, 0, 2, 0,131, 0, 2, 0, 71, 5, 65, 1, 21, 0, 27, 0, 31, 0, - 12, 0,129, 8, 12, 0,130, 8, 12, 0,131, 8, 9, 0,132, 8, 4, 0, 19, 0, 4, 0,201, 5, 2, 0,224, 2, 2, 0, 4, 6, - 2, 0,131, 0, 2, 0,133, 8, 2, 0,134, 8, 2, 0,135, 8, 2, 0,136, 8, 2, 0,137, 8, 4, 0,138, 8, 4, 0,139, 8, - 4, 0,140, 8, 4, 0,141, 8, 4, 0,142, 8, 4, 0,143, 8, 66, 1, 2, 0, 7, 0,129, 2, 4, 0, 19, 0, 67, 1, 5, 0, - 66, 1,144, 8, 4, 0,168, 2, 4, 0,145, 8, 4, 0,146, 8, 4, 0, 19, 0, 68, 1, 6, 0, 4, 0, 37, 0, 4, 0, 4, 6, - 4, 0,140, 8, 4, 0,141, 8, 4, 0,142, 8, 4, 0,143, 8, 69, 1, 38, 0, 69, 1, 0, 0, 69, 1, 1, 0, 26, 0,147, 8, - 12, 0,127, 3, 0, 0, 20, 0, 2, 0, 19, 0, 2, 0,148, 8, 2, 0,149, 8, 2, 0,150, 8, 2, 0, 86, 3, 2, 0,151, 8, - 4, 0, 50, 2, 4, 0,140, 8, 4, 0,141, 8, 64, 1,152, 8, 69, 1, 38, 0, 69, 1,153, 8, 12, 0,154, 8, 9, 0,155, 8, - 9, 0,156, 8, 9, 0,157, 8, 7, 0, 35, 1, 7, 0,172, 0, 7, 0,158, 8, 7, 0,249, 1, 2, 0,159, 8, 2, 0, 37, 0, - 7, 0,160, 8, 7, 0,161, 8, 7, 0, 82, 3, 7, 0,162, 8, 7, 0,163, 8, 7, 0,164, 8, 7, 0,165, 8, 7, 0,166, 8, - 7, 0,167, 8, 7, 0, 43, 2, 32, 0,168, 8,160, 0, 9, 0, 12, 0,169, 8, 2, 0, 19, 0, 2, 0,170, 8, 7, 0, 79, 2, - 7, 0,171, 8, 7, 0,172, 8, 12, 0,173, 8, 4, 0,174, 8, 4, 0, 37, 0, 70, 1, 7, 0, 70, 1, 0, 0, 70, 1, 1, 0, - 12, 0,175, 8, 4, 0, 19, 0, 4, 0,176, 8, 0, 0,193, 3,243, 0,177, 8,159, 0, 7, 0, 27, 0, 31, 0, 12, 0,178, 8, - 12, 0,169, 8, 12, 0,179, 8, 12, 0,100, 0, 4, 0, 19, 0, 4, 0,180, 8,213, 0, 4, 0, 27, 0, 95, 8, 12, 0,169, 8, - 4, 0,181, 8, 4, 0, 19, 0, 71, 1, 17, 0,208, 0, 0, 0,208, 0, 1, 0, 12, 0,192, 5, 4, 0,193, 5, 7, 0,194, 5, - 2, 0,195, 5,209, 0,249, 5,159, 0, 67, 3,213, 0,182, 8, 0, 0, 40, 1, 0, 0,252, 5, 2, 0, 19, 0, 2, 0,183, 8, - 2, 0,253, 5, 2, 0,254, 5, 2, 0,184, 8, 7, 0,185, 8, 72, 1, 8, 0, 72, 1, 0, 0, 72, 1, 1, 0, 70, 1,186, 8, - 36, 0, 80, 0, 12, 0, 71, 3, 4, 0, 19, 0, 0, 0, 20, 0, 4, 0,187, 8, 73, 1, 5, 0, 73, 1, 0, 0, 73, 1, 1, 0, - 36, 0, 80, 0, 2, 0, 19, 0, 0, 0,188, 8, 74, 1, 12, 0, 74, 1, 0, 0, 74, 1, 1, 0, 9, 0, 2, 0, 2, 0, 17, 0, - 2, 0, 19, 0, 0, 0,189, 8, 0, 0,190, 8, 0, 0,188, 8, 7, 0,191, 8, 7, 0,192, 8, 4, 0, 37, 0, 36, 0, 80, 0, - 75, 1, 9, 0, 75, 1, 0, 0, 75, 1, 1, 0, 32, 0,193, 8, 0, 0,227, 2, 7, 0,194, 8, 2, 0,195, 8, 2, 0, 19, 0, - 2, 0, 17, 0, 2, 0,196, 8, 76, 1, 7, 0, 42, 0, 51, 6, 26, 0,147, 8, 4, 0, 19, 0, 4, 0,197, 8, 12, 0,198, 8, - 32, 0,193, 8, 0, 0,227, 2, 77, 1, 12, 0, 32, 0,193, 8, 2, 0,199, 8, 2, 0, 19, 0, 2, 0,200, 8, 2, 0,201, 8, - 0, 0,227, 2, 32, 0,202, 8, 0, 0,203, 8, 7, 0,204, 8, 7, 0, 14, 2, 7, 0,205, 8, 7, 0,206, 8, 78, 1, 6, 0, - 32, 0,193, 8, 4, 0,207, 8, 4, 0,208, 8, 4, 0, 90, 0, 4, 0, 37, 0, 0, 0,227, 2, 79, 1, 4, 0, 32, 0,193, 8, - 4, 0, 19, 0, 4, 0,207, 8, 0, 0,227, 2, 80, 1, 4, 0, 32, 0,193, 8, 4, 0, 19, 0, 4, 0,207, 8, 0, 0,227, 2, - 81, 1, 10, 0, 32, 0,193, 8, 4, 0,209, 8, 7, 0,125, 0, 4, 0, 19, 0, 2, 0, 47, 6, 2, 0,210, 8, 2, 0, 43, 0, - 2, 0, 70, 0, 7, 0,211, 8, 0, 0,227, 2, 82, 1, 4, 0, 32, 0,193, 8, 4, 0, 19, 0, 4, 0,207, 8, 0, 0,227, 2, - 83, 1, 10, 0, 32, 0,193, 8, 2, 0, 17, 0, 2, 0,252, 3, 4, 0, 88, 0, 4, 0, 89, 0, 7, 0, 67, 8, 7, 0, 68, 8, - 4, 0, 37, 0,159, 0, 41, 8, 0, 0,227, 2, 84, 1, 4, 0, 32, 0,193, 8, 4, 0, 87, 3, 4, 0,212, 8, 0, 0,227, 2, - 85, 1, 5, 0, 32, 0,193, 8, 7, 0,125, 0, 4, 0,213, 8, 4, 0, 87, 3, 4, 0, 88, 3, 86, 1, 6, 0, 32, 0,193, 8, - 4, 0,214, 8, 4, 0,215, 8, 7, 0,216, 8, 7, 0,217, 8, 0, 0,227, 2, 87, 1, 16, 0, 32, 0,193, 8, 32, 0,153, 8, - 4, 0, 17, 0, 7, 0,218, 8, 7, 0,219, 8, 7, 0,220, 8, 7, 0,221, 8, 7, 0,222, 8, 7, 0,223, 8, 7, 0,224, 8, - 7, 0,225, 8, 7, 0,226, 8, 2, 0, 19, 0, 2, 0, 37, 0, 2, 0, 43, 0, 2, 0, 70, 0, 88, 1, 3, 0, 32, 0,193, 8, - 4, 0, 19, 0, 4, 0, 6, 2, 89, 1, 5, 0, 32, 0,193, 8, 4, 0, 19, 0, 4, 0, 37, 0, 7, 0,227, 8, 0, 0,227, 2, - 90, 1, 10, 0, 32, 0,193, 8, 0, 0,227, 2, 2, 0,228, 8, 2, 0,229, 8, 0, 0,230, 8, 0, 0,231, 8, 7, 0,232, 8, - 7, 0,233, 8, 7, 0,234, 8, 7, 0,235, 8, 91, 1, 8, 0, 7, 0, 9, 0, 7, 0, 10, 0, 7, 0, 11, 0, 7, 0, 12, 0, - 7, 0,236, 8, 7, 0,237, 8, 2, 0, 19, 0, 2, 0, 6, 2, 92, 1, 8, 0, 7, 0, 9, 0, 7, 0, 10, 0, 7, 0, 11, 0, - 7, 0, 12, 0, 7, 0,236, 8, 7, 0,237, 8, 2, 0, 19, 0, 2, 0, 6, 2, 93, 1, 8, 0, 7, 0, 9, 0, 7, 0, 10, 0, - 7, 0, 11, 0, 7, 0, 12, 0, 7, 0,236, 8, 7, 0,237, 8, 2, 0, 19, 0, 2, 0, 6, 2, 94, 1, 7, 0, 32, 0,193, 8, - 0, 0,227, 2, 7, 0, 47, 1, 7, 0, 56, 1, 2, 0, 19, 0, 2, 0, 40, 1, 4, 0, 37, 0, 95, 1, 5, 0, 32, 0, 27, 3, - 7, 0, 47, 1, 2, 0, 31, 3, 0, 0, 33, 3, 0, 0,238, 8, 96, 1, 10, 0, 96, 1, 0, 0, 96, 1, 1, 0, 2, 0, 17, 0, - 2, 0, 19, 0, 0, 0,239, 8, 7, 0,246, 0, 7, 0,247, 0, 2, 0,175, 8, 2, 0,240, 8, 32, 0, 45, 0, 97, 1, 22, 0, - 97, 1, 0, 0, 97, 1, 1, 0, 2, 0, 19, 0, 2, 0, 40, 1, 2, 0,241, 8, 2, 0,242, 8, 36, 0, 80, 0,159, 0, 41, 8, - 32, 0,164, 0, 7, 0, 88, 0, 7, 0, 89, 0, 7, 0,243, 8, 7, 0,244, 8, 7, 0,245, 8, 7, 0,246, 8, 7, 0,213, 2, - 7, 0,247, 8, 7, 0, 43, 8, 7, 0,248, 8, 0, 0,249, 8, 0, 0,250, 8, 12, 0, 73, 3, 98, 1, 8, 0, 7, 0, 21, 2, - 7, 0, 67, 8, 7, 0, 68, 8, 9, 0, 2, 0, 2, 0,251, 8, 2, 0,252, 8, 2, 0,253, 8, 2, 0,254, 8, 99, 1, 18, 0, - 99, 1, 0, 0, 99, 1, 1, 0, 99, 1,255, 8, 0, 0, 20, 0, 98, 1, 0, 9, 2, 0, 17, 0, 2, 0, 19, 0, 2, 0, 1, 9, - 2, 0, 2, 9, 2, 0, 3, 9, 2, 0, 4, 9, 4, 0, 43, 0, 7, 0, 5, 9, 7, 0, 6, 9, 4, 0, 7, 9, 4, 0, 8, 9, - 99, 1, 9, 9,100, 1, 10, 9,101, 1, 33, 0,101, 1, 0, 0,101, 1, 1, 0,101, 1, 11, 9, 0, 0, 20, 0, 0, 0, 12, 9, - 2, 0, 17, 0, 2, 0, 19, 0, 2, 0,152, 7, 2, 0,185, 7, 2, 0, 13, 9, 2, 0,133, 0, 2, 0, 2, 9, 2, 0,142, 7, - 12, 0, 36, 8, 12, 0, 14, 9, 27, 0, 81, 6, 9, 0, 15, 9, 7, 0, 5, 9, 7, 0, 6, 9, 7, 0, 52, 2, 7, 0, 16, 9, - 2, 0, 17, 9, 2, 0, 18, 9, 7, 0, 19, 9, 7, 0, 20, 9, 2, 0, 21, 9, 2, 0, 22, 9, 9, 0, 23, 9, 24, 0, 24, 9, - 24, 0, 25, 9, 24, 0, 26, 9,102, 1,150, 0,103, 1, 27, 9,100, 1, 8, 0,100, 1, 0, 0,100, 1, 1, 0,101, 1, 28, 9, -101, 1, 29, 9, 99, 1, 30, 9, 99, 1, 9, 9, 4, 0, 19, 0, 4, 0, 37, 0, 61, 0, 20, 0, 27, 0, 31, 0, 39, 0, 75, 0, - 12, 0, 31, 9, 12, 0, 32, 9, 98, 1, 33, 9, 12, 0, 34, 9, 4, 0, 17, 0, 4, 0, 35, 9, 4, 0, 36, 9, 4, 0, 37, 9, - 12, 0, 38, 9,103, 1, 39, 9, 99, 1, 40, 9, 99, 1, 41, 9, 9, 0, 42, 9, 9, 0, 43, 9, 4, 0, 44, 9, 9, 0, 45, 9, - 9, 0, 46, 9, 9, 0, 47, 9,104, 1, 6, 0, 4, 0,124, 0, 4, 0,126, 0, 4, 0,142, 7, 0, 0, 48, 9, 0, 0, 49, 9, - 2, 0, 37, 0,105, 1, 16, 0, 2, 0, 98, 7, 2, 0, 99, 7, 2, 0, 50, 9, 2, 0, 90, 8, 2, 0, 51, 9, 2, 0, 68, 0, - 7, 0,212, 2, 7, 0, 52, 9, 7, 0, 53, 9, 2, 0, 60, 1, 0, 0, 54, 9, 0, 0, 55, 5, 2, 0, 55, 9, 2, 0, 37, 0, - 4, 0, 56, 9, 4, 0, 57, 9,106, 1, 9, 0, 7, 0, 58, 9, 7, 0, 59, 9, 7, 0,109, 8, 7, 0,109, 0, 7, 0, 60, 9, - 7, 0, 10, 6, 2, 0, 61, 9, 0, 0, 62, 9, 0, 0, 37, 0,107, 1, 4, 0, 7, 0, 63, 9, 7, 0, 64, 9, 2, 0, 61, 9, - 2, 0, 37, 0,108, 1, 3, 0, 7, 0, 65, 9, 7, 0, 66, 9, 7, 0, 15, 0,109, 1, 7, 0, 0, 0,239, 1, 2, 0,185, 4, - 2, 0,186, 4, 2, 0,187, 4, 2, 0,138, 4, 4, 0,126, 0, 4, 0,250, 3,110, 1, 7, 0, 7, 0, 67, 9, 7, 0, 68, 9, - 7, 0, 69, 9, 7, 0, 63, 2, 7, 0, 70, 9, 7, 0, 71, 9, 7, 0, 72, 9,111, 1, 4, 0, 2, 0, 73, 9, 2, 0, 74, 9, - 2, 0, 75, 9, 2, 0, 76, 9,112, 1, 2, 0, 7, 0, 5, 0, 7, 0, 6, 0,113, 1, 2, 0, 0, 0,166, 0, 0, 0, 77, 9, -114, 1, 1, 0, 0, 0, 20, 0,115, 1, 10, 0, 0, 0, 78, 9, 0, 0, 79, 9, 0, 0, 3, 6, 0, 0, 80, 9, 2, 0, 50, 9, - 2, 0, 81, 9, 7, 0, 82, 9, 7, 0, 83, 9, 7, 0, 84, 9, 7, 0,247, 8,116, 1, 2, 0, 9, 0, 85, 9, 9, 0, 86, 9, -117, 1, 11, 0, 0, 0,187, 4, 0, 0, 17, 0, 0, 0, 61, 9, 0, 0,109, 0, 0, 0, 87, 9, 0, 0,106, 0, 0, 0, 48, 2, - 7, 0, 88, 9, 7, 0, 89, 9, 7, 0, 90, 9, 7, 0, 91, 9,118, 1, 8, 0, 7, 0, 3, 8, 7, 0,125, 0, 7, 0, 55, 5, - 7, 0,134, 2, 7, 0, 92, 9, 7, 0,206, 0, 7, 0, 93, 9, 4, 0, 17, 0,119, 1, 4, 0, 2, 0, 94, 9, 2, 0, 95, 9, - 2, 0, 96, 9, 2, 0, 37, 0,120, 1, 1, 0, 0, 0, 20, 0,121, 1, 4, 0, 7, 0, 5, 0, 7, 0, 6, 0, 2, 0, 19, 0, - 2, 0, 97, 9,122, 1, 10, 0, 2, 0,182, 3, 2, 0, 19, 0, 7, 0, 74, 4, 7, 0, 98, 9, 7, 0, 99, 9, 7, 0,100, 9, - 7, 0,101, 9,121, 1,102, 9,121, 1,103, 9,121, 1,104, 9, 64, 0, 9, 0, 4, 0, 19, 0, 4, 0, 64, 0, 24, 0,105, 9, - 24, 0,106, 9,122, 1,107, 9, 7, 0,108, 9, 7, 0,109, 9, 7, 0,110, 9, 7, 0,111, 9,123, 1, 4, 0, 47, 0,206, 2, - 7, 0,112, 9, 7, 0,141, 1, 7, 0, 37, 0,187, 0, 17, 0, 27, 0, 31, 0,123, 1,113, 9, 64, 0,102, 9, 51, 0,103, 1, - 2, 0, 19, 0, 2, 0,160, 5, 4, 0,106, 0, 7, 0,114, 9, 7, 0, 60, 2, 4, 0,115, 9, 7, 0,116, 9, 7, 0,117, 9, - 7, 0,118, 9, 7, 0,141, 1, 2, 0, 73, 1, 0, 0,119, 9, 0, 0,139, 6,124, 1, 10, 0, 4, 0, 17, 0, 4, 0,125, 0, - 4, 0, 19, 0, 4, 0,148, 3, 4, 0,120, 9, 4, 0,121, 9, 4, 0,122, 9, 0, 0, 92, 0, 0, 0, 20, 0, 9, 0, 2, 0, - 92, 0, 6, 0,124, 1,123, 9, 4, 0,124, 9, 4, 0,125, 9, 4, 0,126, 9, 4, 0, 37, 0, 9, 0,127, 9,125, 1, 5, 0, - 7, 0,129, 2, 7, 0,196, 2, 7, 0, 14, 2, 2, 0,128, 9, 2, 0, 37, 0,126, 1, 5, 0, 7, 0,129, 2, 7, 0,129, 9, - 7, 0,130, 9, 7, 0,131, 9, 7, 0,196, 2,127, 1, 5, 0, 32, 0,132, 9,128, 1, 22, 0, 7, 0,133, 9, 7, 0,134, 9, - 7, 0, 57, 0,129, 1, 7, 0, 4, 0,135, 9, 4, 0,136, 9, 4, 0,137, 9, 7, 0,138, 9, 7, 0,139, 9, 7, 0,140, 9, - 7, 0,141, 9,130, 1, 8, 0,130, 1, 0, 0,130, 1, 1, 0, 32, 0, 45, 0, 4, 0, 14, 3, 2, 0, 19, 0, 2, 0, 40, 1, - 7, 0,196, 2, 7, 0, 11, 8,131, 1, 18, 0,126, 1,143, 3,126, 1,142, 9,125, 1,143, 9,126, 1,251, 7,127, 1,144, 9, - 4, 0, 82, 0, 7, 0,196, 2, 7, 0,223, 2, 7, 0,145, 9, 4, 0,135, 9, 4, 0,146, 9, 7, 0,139, 9, 7, 0,140, 9, - 7, 0,106, 0, 2, 0, 19, 0, 2, 0,147, 9, 2, 0,148, 9, 2, 0,149, 9,132, 1,107, 0, 27, 0, 31, 0, 39, 0, 75, 0, -133, 1,150, 9, 4, 0, 19, 0, 2, 0, 17, 0, 2, 0,228, 8, 2, 0,151, 9, 2, 0,152, 9, 2, 0,159, 8, 2, 0,153, 9, - 2, 0,154, 9, 2, 0,155, 9, 2, 0,156, 9, 2, 0,157, 9, 2, 0,158, 9, 2, 0,159, 9, 2, 0,178, 3, 2, 0, 48, 5, - 2, 0,160, 9, 2, 0,161, 9, 2, 0,162, 9, 2, 0,163, 9, 2, 0,164, 9, 2, 0, 3, 2, 2, 0,244, 7, 2, 0,220, 7, - 2, 0,165, 9, 2, 0,166, 9, 2, 0,176, 3, 2, 0,177, 3, 2, 0,167, 9, 2, 0,168, 9, 2, 0,169, 9, 2, 0,170, 9, - 7, 0,171, 9, 7, 0,172, 9, 7, 0,173, 9, 2, 0,174, 9, 2, 0,175, 9, 7, 0,176, 9, 7, 0,177, 9, 7, 0,178, 9, - 7, 0,226, 7, 7, 0, 89, 0, 7, 0,223, 2, 7, 0,232, 7, 7, 0,179, 9, 7, 0,180, 9, 7, 0,181, 9, 4, 0,227, 7, - 4, 0,225, 7, 4, 0,182, 9, 7, 0,228, 7, 7, 0,229, 7, 7, 0,230, 7, 7, 0,183, 9, 7, 0,184, 9, 7, 0,185, 9, - 7, 0,186, 9, 7, 0,187, 9, 7, 0,188, 9, 7, 0,189, 9, 7, 0,190, 9, 7, 0,100, 3, 7, 0,106, 0, 7, 0,191, 9, - 7, 0,192, 9, 7, 0,193, 9, 7, 0,194, 9, 7, 0,195, 9, 7, 0,196, 9, 7, 0,197, 9, 4, 0,198, 9, 4, 0,199, 9, - 7, 0,200, 9, 7, 0,201, 9, 7, 0,202, 9, 7, 0,203, 9, 7, 0,204, 9, 7, 0,205, 9, 7, 0,206, 9, 7, 0,172, 3, - 7, 0,170, 3, 7, 0,171, 3, 7, 0,207, 9, 7, 0,208, 9, 7, 0,209, 9, 7, 0,210, 9, 7, 0,211, 9, 7, 0,212, 9, - 7, 0,213, 9, 7, 0,214, 9, 7, 0,215, 9, 7, 0,216, 9, 7, 0,217, 9, 7, 0,218, 9, 7, 0,219, 9, 4, 0,220, 9, - 4, 0,221, 9, 7, 0,222, 9, 68, 0,132, 3, 68, 0,223, 9, 32, 0,224, 9, 32, 0,225, 9, 36, 0, 80, 0,163, 0, 32, 1, -163, 0,226, 9, 59, 0, 43, 0, 59, 0, 0, 0, 59, 0, 1, 0,132, 1,227, 9,131, 1,228, 9,129, 1,153, 8,168, 0,198, 3, - 9, 0,199, 3,134, 1,229, 9,134, 1,230, 9, 12, 0,231, 9, 12, 0,232, 9,134, 0,233, 9,142, 0,234, 9,142, 0,235, 9, - 32, 0,236, 9, 32, 0,237, 9, 32, 0, 38, 0, 12, 0,238, 9, 12, 0,239, 9, 12, 0,198, 8, 0, 0, 20, 0, 7, 0,210, 0, - 7, 0,250, 2, 7, 0,240, 9, 4, 0,170, 2, 4, 0, 57, 0, 4, 0, 19, 0, 4, 0,227, 7, 4, 0,241, 9, 4, 0,242, 9, - 4, 0,243, 9, 2, 0,217, 0, 2, 0,244, 9, 2, 0,245, 9, 2, 0,246, 9, 0, 0,247, 9, 2, 0,248, 9, 2, 0,249, 9, - 2, 0,250, 9, 9, 0,251, 9,138, 0, 15, 4, 12, 0,237, 2,135, 1,252, 9,136, 0, 34, 0,136, 1,110, 8, 7, 0,241, 3, - 7, 0,253, 9, 7, 0,254, 9, 7, 0, 77, 4, 7, 0,255, 9, 7, 0,110, 3, 7, 0,100, 3, 7, 0, 0, 10, 7, 0, 62, 2, - 7, 0, 1, 10, 7, 0, 2, 10, 7, 0, 3, 10, 7, 0, 4, 10, 7, 0, 5, 10, 7, 0, 6, 10, 7, 0,242, 3, 7, 0, 7, 10, - 7, 0, 8, 10, 7, 0, 9, 10, 7, 0,243, 3, 7, 0,239, 3, 7, 0,240, 3, 7, 0, 10, 10, 4, 0, 11, 10, 4, 0, 90, 0, - 4, 0, 12, 10, 4, 0, 13, 10, 2, 0, 14, 10, 2, 0, 15, 10, 2, 0, 16, 10, 2, 0, 17, 10, 2, 0, 18, 10, 2, 0, 37, 0, -137, 0, 8, 0,136, 1, 19, 10, 7, 0, 20, 10, 7, 0, 21, 10, 7, 0,213, 1, 7, 0, 22, 10, 4, 0, 90, 0, 2, 0, 23, 10, - 2, 0, 24, 10,137, 1, 4, 0, 7, 0, 5, 0, 7, 0, 6, 0, 7, 0, 7, 0, 7, 0, 25, 10,138, 1, 6, 0,138, 1, 0, 0, -138, 1, 1, 0,137, 1,144, 8, 4, 0,223, 0, 2, 0, 26, 10, 2, 0, 19, 0,139, 1, 5, 0,139, 1, 0, 0,139, 1, 1, 0, - 12, 0, 27, 10, 4, 0, 28, 10, 4, 0, 19, 0,140, 1, 9, 0,140, 1, 0, 0,140, 1, 1, 0, 12, 0,124, 0,139, 1, 29, 10, - 4, 0, 19, 0, 2, 0, 26, 10, 2, 0, 30, 10, 7, 0, 91, 0, 0, 0, 31, 10,161, 0, 6, 0, 27, 0, 31, 0, 12, 0,201, 4, - 4, 0, 19, 0, 2, 0, 32, 10, 2, 0, 33, 10, 9, 0, 34, 10,141, 1, 7, 0,141, 1, 0, 0,141, 1, 1, 0, 2, 0, 17, 0, - 2, 0, 19, 0, 4, 0, 23, 0, 0, 0, 35, 10, 0, 0, 36, 10,142, 1, 5, 0, 12, 0, 37, 10, 4, 0, 38, 10, 4, 0, 39, 10, - 4, 0, 19, 0, 4, 0, 37, 0,143, 1, 13, 0, 27, 0, 31, 0,144, 1, 40, 10,144, 1, 41, 10, 12, 0, 42, 10, 4, 0, 43, 10, - 2, 0, 44, 10, 2, 0, 37, 0, 12, 0, 45, 10, 12, 0, 46, 10,142, 1, 47, 10, 12, 0, 48, 10, 12, 0, 49, 10, 12, 0, 50, 10, -144, 1, 30, 0,144, 1, 0, 0,144, 1, 1, 0, 9, 0, 51, 10, 4, 0, 77, 7, 4, 0, 37, 0,211, 0,248, 5,211, 0, 52, 10, - 0, 0, 53, 10, 2, 0, 54, 10, 2, 0, 55, 10, 2, 0, 98, 7, 2, 0, 99, 7, 2, 0, 56, 10, 2, 0, 57, 10, 2, 0,148, 3, - 2, 0,107, 6, 2, 0, 58, 10, 2, 0, 59, 10, 4, 0,209, 1,145, 1, 60, 10,146, 1, 61, 10,147, 1, 62, 10, 4, 0, 63, 10, - 4, 0, 64, 10, 9, 0, 65, 10, 12, 0, 66, 10, 12, 0, 46, 10, 12, 0,116, 7, 12, 0, 67, 10, 12, 0, 68, 10,148, 1, 16, 0, -148, 1, 0, 0,148, 1, 1, 0, 0, 0, 69, 10,149, 1, 70, 10, 2, 0, 17, 0, 2, 0, 15, 0, 2, 0, 71, 10, 2, 0, 72, 10, - 2, 0, 73, 10, 2, 0, 74, 10, 2, 0, 75, 10, 2, 0, 76, 10, 2, 0, 77, 10, 2, 0, 78, 10, 2, 0, 70, 0, 2, 0,209, 1, -150, 1, 9, 0,150, 1, 0, 0,150, 1, 1, 0, 12, 0, 79, 10, 0, 0, 80, 10, 2, 0, 81, 10, 2, 0, 82, 10, 2, 0, 83, 10, - 2, 0, 37, 0, 9, 0, 84, 10,219, 0, 12, 0,219, 0, 0, 0,219, 0, 1, 0, 0, 0, 69, 10, 26, 0, 30, 0,151, 1, 92, 7, - 9, 0, 85, 10,149, 1, 70, 10,142, 1, 86, 10, 12, 0, 87, 10,219, 0, 88, 10, 2, 0, 19, 0, 2, 0,105, 1,145, 1, 23, 0, -145, 1, 0, 0,145, 1, 1, 0, 2, 0, 17, 0, 2, 0, 15, 0, 2, 0, 5, 0, 2, 0, 6, 0, 2, 0, 89, 10, 2, 0, 90, 10, - 2, 0, 91, 10, 2, 0, 92, 10, 0, 0, 93, 10, 0, 0, 37, 0, 2, 0, 71, 10, 2, 0, 72, 10, 2, 0, 73, 10, 2, 0, 74, 10, - 2, 0, 75, 10, 2, 0, 43, 0, 0, 0, 94, 10, 2, 0, 95, 10, 2, 0, 96, 10, 4, 0, 70, 0, 9, 0, 85, 10,152, 1, 8, 0, -152, 1, 0, 0,152, 1, 1, 0, 9, 0, 2, 0, 9, 0, 97, 10, 0, 0,193, 3, 2, 0, 17, 0, 2, 0, 19, 0, 7, 0, 98, 10, -153, 1, 5, 0, 7, 0, 99, 10, 4, 0,100, 10, 4, 0,101, 10, 4, 0, 40, 1, 4, 0, 19, 0,154, 1, 6, 0, 7, 0,102, 10, - 7, 0,103, 10, 7, 0,104, 10, 7, 0,105, 10, 4, 0, 17, 0, 4, 0, 19, 0,155, 1, 5, 0, 7, 0, 67, 8, 7, 0, 68, 8, - 7, 0,196, 2, 2, 0, 17, 2, 2, 0, 18, 2,156, 1, 5, 0,155, 1, 2, 0, 4, 0, 54, 0, 7, 0,106, 10, 7, 0, 67, 8, - 7, 0, 68, 8,157, 1, 4, 0, 2, 0,107, 10, 2, 0,108, 10, 2, 0,109, 10, 2, 0,110, 10,158, 1, 2, 0, 42, 0, 78, 6, - 26, 0,147, 8,159, 1, 3, 0, 24, 0,111, 10, 4, 0, 19, 0, 4, 0, 37, 0,160, 1, 6, 0, 7, 0,106, 0, 7, 0,198, 2, - 7, 0,112, 10, 7, 0, 37, 0, 2, 0,216, 0, 2, 0,113, 10,161, 1, 7, 0,161, 1, 0, 0,161, 1, 1, 0, 27, 0, 81, 6, - 0, 0,114, 10, 4, 0,115, 10, 4, 0, 90, 0, 0, 0,193, 3,162, 1, 6, 0, 12, 0,198, 8, 0, 0,116, 10, 7, 0, 61, 0, - 7, 0, 98, 10, 4, 0, 17, 0, 4, 0, 19, 0,163, 1, 3, 0, 7, 0,117, 10, 4, 0, 19, 0, 4, 0, 37, 0,164, 1, 15, 0, -164, 1, 0, 0,164, 1, 1, 0, 70, 1,186, 8,162, 1, 62, 0, 12, 0, 73, 3, 35, 0, 50, 0,163, 1,118, 10, 4, 0, 54, 0, - 7, 0, 61, 0, 2, 0, 19, 0, 2, 0, 25, 1, 4, 0,115, 10, 0, 0,114, 10, 4, 0,119, 10, 7, 0,120, 10,165, 1, 2, 0, - 0, 0,121, 10, 0, 0,122, 10,166, 1, 4, 0,166, 1, 0, 0,166, 1, 1, 0,159, 0, 27, 3, 12, 0,123, 10,167, 1, 24, 0, -167, 1, 0, 0,167, 1, 1, 0, 12, 0,124, 10,159, 0, 41, 8,166, 1,125, 10, 12, 0,126, 10, 12, 0, 73, 3, 0, 0,193, 3, - 7, 0, 98, 10, 7, 0,127, 10, 7, 0, 88, 0, 7, 0, 89, 0, 7, 0,243, 8, 7, 0,244, 8, 7, 0,213, 2, 7, 0,247, 8, - 7, 0, 43, 8, 7, 0,248, 8, 2, 0,128, 10, 2, 0,129, 10, 2, 0, 43, 0, 2, 0, 17, 0, 4, 0, 19, 0, 4, 0, 70, 0, -168, 1, 6, 0,168, 1, 0, 0,168, 1, 1, 0, 12, 0,124, 10, 4, 0, 19, 0, 4, 0,133, 2, 0, 0,193, 3,169, 1, 10, 0, -169, 1, 0, 0,169, 1, 1, 0, 27, 0, 81, 6, 0, 0,130, 10, 4, 0,131, 10, 4, 0,132, 10, 0, 0,114, 10, 4, 0,115, 10, - 2, 0, 19, 0, 2, 0,133, 10,170, 1, 6, 0,170, 1, 0, 0,170, 1, 1, 0, 12, 0,134, 10, 0, 0,193, 3, 4, 0, 19, 0, - 4, 0,135, 10,171, 1, 5, 0,171, 1, 0, 0,171, 1, 1, 0, 0, 0,114, 10, 4, 0,115, 10, 7, 0,186, 2, 39, 0, 12, 0, -159, 0, 67, 3,159, 0,136, 10,166, 1,125, 10, 12, 0,137, 10,167, 1,138, 10, 12, 0,139, 10, 12, 0,140, 10, 4, 0, 19, 0, - 4, 0,217, 0, 2, 0,141, 10, 2, 0,142, 10, 7, 0,143, 10,172, 1, 2, 0, 27, 0, 31, 0, 39, 0, 75, 0,173, 1, 5, 0, -173, 1, 0, 0,173, 1, 1, 0, 4, 0, 17, 0, 4, 0, 19, 0, 0, 0, 20, 0,174, 1, 6, 0,173, 1,144, 10, 32, 0, 45, 0, - 4, 0,145, 10, 7, 0,146, 10, 4, 0,147, 10, 4, 0,175, 8,175, 1, 3, 0,173, 1,144, 10, 4, 0,145, 10, 7, 0,148, 10, -176, 1, 8, 0,173, 1,144, 10, 32, 0, 45, 0, 7, 0, 35, 1, 7, 0,149, 10, 7, 0,250, 2, 7, 0,109, 8, 4, 0,145, 10, - 4, 0,150, 10,177, 1, 5, 0,173, 1,144, 10, 7, 0,151, 10, 7, 0,185, 7, 7, 0,219, 2, 7, 0, 57, 0,178, 1, 3, 0, -173, 1,144, 10, 7, 0,109, 8, 7, 0,152, 10,128, 1, 4, 0, 7, 0,153, 10, 7, 0,193, 9, 2, 0,154, 10, 2, 0, 40, 1, -179, 1, 14, 0,179, 1, 0, 0,179, 1, 1, 0, 12, 0,155, 10, 12, 0,156, 10, 12, 0,157, 10, 0, 0, 20, 0, 4, 0, 31, 0, - 4, 0, 19, 0, 4, 0,158, 10, 7, 0,159, 10, 4, 0,147, 10, 4, 0,175, 8, 7, 0,202, 3, 7, 0,221, 2,133, 1, 23, 0, - 4, 0,145, 10, 4, 0,160, 10, 7, 0,161, 10, 7, 0, 57, 0, 7, 0,162, 10, 7, 0,217, 2, 7, 0,153, 10, 7, 0,163, 10, - 7, 0,198, 2, 7, 0,164, 10, 7, 0, 74, 4, 7, 0,165, 10, 7, 0,166, 10, 7, 0,167, 10, 7, 0,168, 10, 7, 0,169, 10, - 7, 0,170, 10, 7, 0,171, 10, 7, 0,172, 10, 7, 0,173, 10, 7, 0,174, 10, 7, 0,175, 10, 12, 0,176, 10,122, 0, 33, 0, -121, 0,177, 10,180, 1,178, 10, 68, 0,179, 10, 68, 0,223, 9, 68, 0,180, 10,181, 1,181, 10, 48, 0,165, 0, 48, 0,182, 10, - 48, 0,183, 10, 7, 0,184, 10, 7, 0,185, 10, 7, 0,186, 10, 7, 0,187, 10, 7, 0,188, 10, 7, 0,187, 8, 7, 0,189, 10, - 7, 0,141, 1, 7, 0,190, 10, 4, 0,191, 10, 4, 0,192, 10, 4, 0,193, 10, 4, 0, 90, 0, 4, 0, 37, 0, 4, 0,194, 10, - 2, 0,195, 10, 2, 0,196, 10, 4, 0,197, 10, 7, 0,198, 2, 4, 0,198, 10, 7, 0,199, 10, 4, 0,200, 10,138, 0,201, 10, - 12, 0,202, 10,123, 0, 11, 0,121, 0,177, 10, 59, 0,225, 0, 7, 0,106, 1, 7, 0,187, 8, 7, 0,203, 10, 7, 0,204, 10, - 2, 0,205, 10, 2, 0,206, 10, 2, 0,207, 10, 2, 0, 17, 0, 4, 0, 37, 0,124, 0, 13, 0,121, 0,177, 10,140, 0,247, 2, -142, 0,249, 2, 7, 0,144, 8, 7, 0,208, 10, 7, 0,209, 10, 7, 0, 37, 1, 7, 0,210, 10, 4, 0,211, 10, 4, 0,245, 2, +111,111,107, 0, 68,117,112,108,105, 79, 98,106,101, 99,116, 0, 82, 78, 71, 0, 69,102,102,101, 99,116,111,114, 87,101,105,103, +104,116,115, 0, 80, 84, 67, 97, 99,104,101, 77,101,109, 0, 80, 84, 67, 97, 99,104,101, 69,100,105,116, 0, 83, 66, 86,101,114, +116,101,120, 0, 66,111,100,121, 80,111,105,110,116, 0, 66,111,100,121, 83,112,114,105,110,103, 0, 83, 66, 83, 99,114, 97,116, + 99,104, 0, 87,111,114,108,100, 0, 66, 97,115,101, 0, 65,118,105, 67,111,100,101, 99, 68, 97,116, 97, 0, 81,117,105, 99,107, +116,105,109,101, 67,111,100,101, 99, 68, 97,116, 97, 0, 70, 70, 77,112,101,103, 67,111,100,101, 99, 68, 97,116, 97, 0, 65,117, +100,105,111, 68, 97,116, 97, 0, 83, 99,101,110,101, 82,101,110,100,101,114, 76, 97,121,101,114, 0, 82,101,110,100,101,114, 68, + 97,116, 97, 0, 82,101,110,100,101,114, 80,114,111,102,105,108,101, 0, 71, 97,109,101, 68,111,109,101, 0, 71, 97,109,101, 70, +114, 97,109,105,110,103, 0, 71, 97,109,101, 68, 97,116, 97, 0, 84,105,109,101, 77, 97,114,107,101,114, 0, 80, 97,105,110,116, + 0, 66,114,117,115,104, 0, 73,109, 97,103,101, 80, 97,105,110,116, 83,101,116,116,105,110,103,115, 0, 80, 97,114,116,105, 99, +108,101, 66,114,117,115,104, 68, 97,116, 97, 0, 80, 97,114,116,105, 99,108,101, 69,100,105,116, 83,101,116,116,105,110,103,115, + 0, 84,114, 97,110,115,102,111,114,109, 79,114,105,101,110,116, 97,116,105,111,110, 0, 83, 99,117,108,112,116, 0, 86, 80, 97, +105,110,116, 0, 84,111,111,108, 83,101,116,116,105,110,103,115, 0, 98, 83,116, 97,116,115, 0, 85,110,105,116, 83,101,116,116, +105,110,103,115, 0, 80,104,121,115,105, 99,115, 83,101,116,116,105,110,103,115, 0, 69,100,105,116,105,110,103, 0, 83, 99,101, +110,101, 83,116, 97,116,115, 0, 68, 97,103, 70,111,114,101,115,116, 0, 66, 71,112,105, 99, 0, 82,101,103,105,111,110, 86,105, +101,119, 51, 68, 0, 82,101,110,100,101,114, 73,110,102,111, 0, 82,101,116,111,112,111, 86,105,101,119, 68, 97,116, 97, 0, 86, +105,101,119, 68,101,112,116,104,115, 0, 83,109,111,111,116,104, 86,105,101,119, 83,116,111,114,101, 0,119,109, 84,105,109,101, +114, 0, 86,105,101,119, 51, 68, 0, 83,112, 97, 99,101, 76,105,110,107, 0, 86,105,101,119, 50, 68, 0, 83,112, 97, 99,101, 73, +110,102,111, 0, 98, 83, 99,114,101,101,110, 0, 83,112, 97, 99,101, 73,112,111, 0, 98, 68,111,112,101, 83,104,101,101,116, 0, + 83,112, 97, 99,101, 66,117,116,115, 0, 83,112, 97, 99,101, 83,101,113, 0, 70,105,108,101, 83,101,108,101, 99,116, 80, 97,114, + 97,109,115, 0, 83,112, 97, 99,101, 70,105,108,101, 0, 70,105,108,101, 76,105,115,116, 0,119,109, 79,112,101,114, 97,116,111, +114, 0, 70,105,108,101, 76, 97,121,111,117,116, 0, 83,112, 97, 99,101, 79,111,112,115, 0, 84,114,101,101, 83,116,111,114,101, + 0, 84,114,101,101, 83,116,111,114,101, 69,108,101,109, 0, 83,112, 97, 99,101, 73,109, 97,103,101, 0, 83,112, 97, 99,101, 78, +108, 97, 0, 83,112, 97, 99,101, 84,101,120,116, 0, 83, 99,114,105,112,116, 0, 83,112, 97, 99,101, 83, 99,114,105,112,116, 0, + 83,112, 97, 99,101, 84,105,109,101, 0, 83,112, 97, 99,101, 78,111,100,101, 0, 83,112, 97, 99,101, 76,111,103,105, 99, 0, 83, +112, 97, 99,101, 73,109, 97, 83,101,108, 0, 67,111,110,115,111,108,101, 76,105,110,101, 0, 83,112, 97, 99,101, 67,111,110,115, +111,108,101, 0, 83,112, 97, 99,101, 85,115,101,114, 80,114,101,102, 0,117,105, 70,111,110,116, 0,117,105, 70,111,110,116, 83, +116,121,108,101, 0,117,105, 83,116,121,108,101, 0,117,105, 87,105,100,103,101,116, 67,111,108,111,114,115, 0,117,105, 87,105, +100,103,101,116, 83,116, 97,116,101, 67,111,108,111,114,115, 0, 84,104,101,109,101, 85, 73, 0, 84,104,101,109,101, 83,112, 97, + 99,101, 0, 84,104,101,109,101, 87,105,114,101, 67,111,108,111,114, 0, 98, 84,104,101,109,101, 0, 83,111,108,105,100, 76,105, +103,104,116, 0, 85,115,101,114, 68,101,102, 0, 83, 99,114, 86,101,114,116, 0, 83, 99,114, 69,100,103,101, 0, 80, 97,110,101, +108, 0, 80, 97,110,101,108, 84,121,112,101, 0,117,105, 76, 97,121,111,117,116, 0, 83, 99,114, 65,114,101, 97, 0, 83,112, 97, + 99,101, 84,121,112,101, 0, 65, 82,101,103,105,111,110, 0, 65, 82,101,103,105,111,110, 84,121,112,101, 0, 70,105,108,101, 71, +108,111, 98, 97,108, 0, 83,116,114,105,112, 69,108,101,109, 0, 84, 83,116,114,105,112, 69,108,101,109, 0, 83,116,114,105,112, + 67,114,111,112, 0, 83,116,114,105,112, 84,114, 97,110,115,102,111,114,109, 0, 83,116,114,105,112, 67,111,108,111,114, 66, 97, +108, 97,110, 99,101, 0, 83,116,114,105,112, 80,114,111,120,121, 0, 83,116,114,105,112, 0, 80,108,117,103,105,110, 83,101,113, + 0, 83,101,113,117,101,110, 99,101, 0, 98, 83,111,117,110,100, 0, 83,111,117,110,100, 72, 97,110,100,108,101, 0, 77,101,116, + 97, 83,116, 97, 99,107, 0, 87,105,112,101, 86, 97,114,115, 0, 71,108,111,119, 86, 97,114,115, 0, 84,114, 97,110,115,102,111, +114,109, 86, 97,114,115, 0, 83,111,108,105,100, 67,111,108,111,114, 86, 97,114,115, 0, 83,112,101,101,100, 67,111,110,116,114, +111,108, 86, 97,114,115, 0, 69,102,102,101, 99,116, 0, 66,117,105,108,100, 69,102,102, 0, 80, 97,114,116, 69,102,102, 0, 80, + 97,114,116,105, 99,108,101, 0, 87, 97,118,101, 69,102,102, 0, 98, 80,114,111,112,101,114,116,121, 0, 98, 78,101, 97,114, 83, +101,110,115,111,114, 0, 98, 77,111,117,115,101, 83,101,110,115,111,114, 0, 98, 84,111,117, 99,104, 83,101,110,115,111,114, 0, + 98, 75,101,121, 98,111, 97,114,100, 83,101,110,115,111,114, 0, 98, 80,114,111,112,101,114,116,121, 83,101,110,115,111,114, 0, + 98, 65, 99,116,117, 97,116,111,114, 83,101,110,115,111,114, 0, 98, 68,101,108, 97,121, 83,101,110,115,111,114, 0, 98, 67,111, +108,108,105,115,105,111,110, 83,101,110,115,111,114, 0, 98, 82, 97,100, 97,114, 83,101,110,115,111,114, 0, 98, 82, 97,110,100, +111,109, 83,101,110,115,111,114, 0, 98, 82, 97,121, 83,101,110,115,111,114, 0, 98, 65,114,109, 97,116,117,114,101, 83,101,110, +115,111,114, 0, 98, 77,101,115,115, 97,103,101, 83,101,110,115,111,114, 0, 98, 83,101,110,115,111,114, 0, 98, 67,111,110,116, +114,111,108,108,101,114, 0, 98, 74,111,121,115,116,105, 99,107, 83,101,110,115,111,114, 0, 98, 69,120,112,114,101,115,115,105, +111,110, 67,111,110,116, 0, 98, 80,121,116,104,111,110, 67,111,110,116, 0, 98, 65, 99,116,117, 97,116,111,114, 0, 98, 65,100, +100, 79, 98,106,101, 99,116, 65, 99,116,117, 97,116,111,114, 0, 98, 65, 99,116,105,111,110, 65, 99,116,117, 97,116,111,114, 0, + 98, 83,111,117,110,100, 65, 99,116,117, 97,116,111,114, 0, 83,111,117,110,100, 51, 68, 0, 98, 69,100,105,116, 79, 98,106,101, + 99,116, 65, 99,116,117, 97,116,111,114, 0, 98, 83, 99,101,110,101, 65, 99,116,117, 97,116,111,114, 0, 98, 80,114,111,112,101, +114,116,121, 65, 99,116,117, 97,116,111,114, 0, 98, 79, 98,106,101, 99,116, 65, 99,116,117, 97,116,111,114, 0, 98, 73,112,111, + 65, 99,116,117, 97,116,111,114, 0, 98, 67, 97,109,101,114, 97, 65, 99,116,117, 97,116,111,114, 0, 98, 67,111,110,115,116,114, + 97,105,110,116, 65, 99,116,117, 97,116,111,114, 0, 98, 71,114,111,117,112, 65, 99,116,117, 97,116,111,114, 0, 98, 82, 97,110, +100,111,109, 65, 99,116,117, 97,116,111,114, 0, 98, 77,101,115,115, 97,103,101, 65, 99,116,117, 97,116,111,114, 0, 98, 71, 97, +109,101, 65, 99,116,117, 97,116,111,114, 0, 98, 86,105,115,105, 98,105,108,105,116,121, 65, 99,116,117, 97,116,111,114, 0, 98, + 84,119,111, 68, 70,105,108,116,101,114, 65, 99,116,117, 97,116,111,114, 0, 98, 80, 97,114,101,110,116, 65, 99,116,117, 97,116, +111,114, 0, 98, 83,116, 97,116,101, 65, 99,116,117, 97,116,111,114, 0, 98, 65,114,109, 97,116,117,114,101, 65, 99,116,117, 97, +116,111,114, 0, 70,114,101,101, 67, 97,109,101,114, 97, 0, 83,112, 97, 99,101, 83,111,117,110,100, 0, 71,114,111,117,112, 79, + 98,106,101, 99,116, 0, 66,111,110,101, 0, 98, 65,114,109, 97,116,117,114,101, 0, 98, 77,111,116,105,111,110, 80, 97,116,104, + 86,101,114,116, 0, 98, 77,111,116,105,111,110, 80, 97,116,104, 0, 98, 65,110,105,109, 86,105,122, 83,101,116,116,105,110,103, +115, 0, 98, 80,111,115,101, 67,104, 97,110,110,101,108, 0, 98, 73, 75, 80, 97,114, 97,109, 0, 98, 73,116, 97,115, 99, 0, 98, + 65, 99,116,105,111,110, 71,114,111,117,112, 0, 83,112, 97, 99,101, 65, 99,116,105,111,110, 0, 98, 65, 99,116,105,111,110, 67, +104, 97,110,110,101,108, 0, 98, 67,111,110,115,116,114, 97,105,110,116, 67,104, 97,110,110,101,108, 0, 98, 67,111,110,115,116, +114, 97,105,110,116, 0, 98, 67,111,110,115,116,114, 97,105,110,116, 84, 97,114,103,101,116, 0, 98, 80,121,116,104,111,110, 67, +111,110,115,116,114, 97,105,110,116, 0, 98, 75,105,110,101,109, 97,116,105, 99, 67,111,110,115,116,114, 97,105,110,116, 0, 98, + 84,114, 97, 99,107, 84,111, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 82,111,116, 97,116,101, 76,105,107,101, 67,111,110, +115,116,114, 97,105,110,116, 0, 98, 76,111, 99, 97,116,101, 76,105,107,101, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 77, +105,110, 77, 97,120, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 83,105,122,101, 76,105,107,101, 67,111,110,115,116,114, 97, +105,110,116, 0, 98, 65, 99,116,105,111,110, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 76,111, 99,107, 84,114, 97, 99,107, + 67,111,110,115,116,114, 97,105,110,116, 0, 98, 70,111,108,108,111,119, 80, 97,116,104, 67,111,110,115,116,114, 97,105,110,116, + 0, 98, 83,116,114,101,116, 99,104, 84,111, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 82,105,103,105,100, 66,111,100,121, + 74,111,105,110,116, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 67,108, 97,109,112, 84,111, 67,111,110,115,116,114, 97,105, +110,116, 0, 98, 67,104,105,108,100, 79,102, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 84,114, 97,110,115,102,111,114,109, + 67,111,110,115,116,114, 97,105,110,116, 0, 98, 76,111, 99, 76,105,109,105,116, 67,111,110,115,116,114, 97,105,110,116, 0, 98, + 82,111,116, 76,105,109,105,116, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 83,105,122,101, 76,105,109,105,116, 67,111,110, +115,116,114, 97,105,110,116, 0, 98, 68,105,115,116, 76,105,109,105,116, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 83,104, +114,105,110,107,119,114, 97,112, 67,111,110,115,116,114, 97,105,110,116, 0, 98, 65, 99,116,105,111,110, 77,111,100,105,102,105, +101,114, 0, 98, 65, 99,116,105,111,110, 83,116,114,105,112, 0, 98, 78,111,100,101, 83,116, 97, 99,107, 0, 98, 78,111,100,101, + 83,111, 99,107,101,116, 0, 98, 78,111,100,101, 76,105,110,107, 0, 98, 78,111,100,101, 0, 98, 78,111,100,101, 80,114,101,118, +105,101,119, 0,117,105, 66,108,111, 99,107, 0, 98, 78,111,100,101, 84,121,112,101, 0, 78,111,100,101, 73,109, 97,103,101, 65, +110,105,109, 0, 78,111,100,101, 66,108,117,114, 68, 97,116, 97, 0, 78,111,100,101, 68, 66,108,117,114, 68, 97,116, 97, 0, 78, +111,100,101, 66,105,108, 97,116,101,114, 97,108, 66,108,117,114, 68, 97,116, 97, 0, 78,111,100,101, 72,117,101, 83, 97,116, 0, + 78,111,100,101, 73,109, 97,103,101, 70,105,108,101, 0, 78,111,100,101, 67,104,114,111,109, 97, 0, 78,111,100,101, 84,119,111, + 88, 89,115, 0, 78,111,100,101, 84,119,111, 70,108,111, 97,116,115, 0, 78,111,100,101, 71,101,111,109,101,116,114,121, 0, 78, +111,100,101, 86,101,114,116,101,120, 67,111,108, 0, 78,111,100,101, 68,101,102,111, 99,117,115, 0, 78,111,100,101, 83, 99,114, +105,112,116, 68,105, 99,116, 0, 78,111,100,101, 71,108, 97,114,101, 0, 78,111,100,101, 84,111,110,101,109, 97,112, 0, 78,111, +100,101, 76,101,110,115, 68,105,115,116, 0, 84,101,120, 78,111,100,101, 79,117,116,112,117,116, 0, 67,117,114,118,101, 77, 97, +112, 80,111,105,110,116, 0, 67,117,114,118,101, 77, 97,112, 0, 66,114,117,115,104, 67,108,111,110,101, 0, 67,117,115,116,111, +109, 68, 97,116, 97, 76, 97,121,101,114, 0, 72, 97,105,114, 75,101,121, 0, 80, 97,114,116,105, 99,108,101, 75,101,121, 0, 66, +111,105,100, 80, 97,114,116,105, 99,108,101, 0, 66,111,105,100, 68, 97,116, 97, 0, 67,104,105,108,100, 80, 97,114,116,105, 99, +108,101, 0, 80, 97,114,116,105, 99,108,101, 84, 97,114,103,101,116, 0, 80, 97,114,116,105, 99,108,101, 68, 97,116, 97, 0, 80, + 97,114,116,105, 99,108,101, 83,101,116,116,105,110,103,115, 0, 66,111,105,100, 83,101,116,116,105,110,103,115, 0, 80, 97,114, +116,105, 99,108,101, 67, 97, 99,104,101, 75,101,121, 0, 75, 68, 84,114,101,101, 0, 80, 97,114,116,105, 99,108,101, 68,114, 97, +119, 68, 97,116, 97, 0, 76,105,110,107, 78,111,100,101, 0, 98, 71, 80, 68,115,112,111,105,110,116, 0, 98, 71, 80, 68,115,116, +114,111,107,101, 0, 98, 71, 80, 68,102,114, 97,109,101, 0, 98, 71, 80, 68,108, 97,121,101,114, 0, 82,101,112,111,114,116, 0, + 82,101,112,111,114,116, 76,105,115,116, 0,119,109, 87,105,110,100,111,119, 77, 97,110, 97,103,101,114, 0,119,109, 87,105,110, +100,111,119, 0,119,109, 69,118,101,110,116, 0,119,109, 83,117, 98, 87,105,110,100,111,119, 0,119,109, 71,101,115,116,117,114, +101, 0,119,109, 75,101,121,109, 97,112, 73,116,101,109, 0, 80,111,105,110,116,101,114, 82, 78, 65, 0,119,109, 75,101,121, 77, + 97,112, 0,119,109, 79,112,101,114, 97,116,111,114, 84,121,112,101, 0, 70, 77,111,100,105,102,105,101,114, 0, 70, 77,111,100, + 95, 71,101,110,101,114, 97,116,111,114, 0, 70, 77,111,100, 95, 70,117,110, 99,116,105,111,110, 71,101,110,101,114, 97,116,111, +114, 0, 70, 67, 77, 95, 69,110,118,101,108,111,112,101, 68, 97,116, 97, 0, 70, 77,111,100, 95, 69,110,118,101,108,111,112,101, + 0, 70, 77,111,100, 95, 67,121, 99,108,101,115, 0, 70, 77,111,100, 95, 80,121,116,104,111,110, 0, 70, 77,111,100, 95, 76,105, +109,105,116,115, 0, 70, 77,111,100, 95, 78,111,105,115,101, 0, 68,114,105,118,101,114, 84, 97,114,103,101,116, 0, 67,104, 97, +110,110,101,108, 68,114,105,118,101,114, 0, 70, 80,111,105,110,116, 0, 70, 67,117,114,118,101, 0, 65,110,105,109, 77, 97,112, + 80, 97,105,114, 0, 65,110,105,109, 77, 97,112,112,101,114, 0, 78,108, 97, 83,116,114,105,112, 0, 78,108, 97, 84,114, 97, 99, +107, 0, 75, 83, 95, 80, 97,116,104, 0, 75,101,121,105,110,103, 83,101,116, 0, 65,110,105,109, 79,118,101,114,114,105,100,101, + 0, 73,100, 65,100,116, 84,101,109,112,108, 97,116,101, 0, 66,111,105,100, 82,117,108,101, 0, 66,111,105,100, 82,117,108,101, + 71,111, 97,108, 65,118,111,105,100, 0, 66,111,105,100, 82,117,108,101, 65,118,111,105,100, 67,111,108,108,105,115,105,111,110, + 0, 66,111,105,100, 82,117,108,101, 70,111,108,108,111,119, 76,101, 97,100,101,114, 0, 66,111,105,100, 82,117,108,101, 65,118, +101,114, 97,103,101, 83,112,101,101,100, 0, 66,111,105,100, 82,117,108,101, 70,105,103,104,116, 0, 66,111,105,100, 83,116, 97, +116,101, 0, 70, 76, 85, 73, 68, 95, 51, 68, 0, 87, 84, 85, 82, 66, 85, 76, 69, 78, 67, 69, 0, 84, 76, 69, 78, 1, 0, 1, 0, + 2, 0, 2, 0, 4, 0, 4, 0, 4, 0, 4, 0, 8, 0, 0, 0, 8, 0, 12, 0, 8, 0, 4, 0, 8, 0, 8, 0, 16, 0, 12, 0, + 12, 0, 24, 0, 16, 0, 16, 0, 32, 0, 16, 0, 16, 0, 20, 0, 76, 0, 52, 0, 40, 2, 0, 0, 32, 0,140, 0,136, 3, 92, 0, + 36, 0, 56, 0, 84, 0,112, 0,124, 0, 56, 0, 24, 0, 40, 0,120, 0, 12, 0,120, 0, 36, 0,108, 5,128, 1, 0, 0, 0, 0, + 0, 0, 8, 1, 40, 1, 84, 1, 24, 0, 8, 3,168, 0, 0, 0, 76, 0,124, 1, 24, 1,140, 0,132, 0,124, 1, 8, 1, 56, 0, + 88, 0,160, 2, 76, 0, 60, 1, 0, 0,108, 0,104, 0,148, 0, 56, 0, 8, 0, 16, 0, 92, 1, 0, 0, 0, 0, 0, 0, 24, 1, + 20, 0, 44, 0, 60, 0, 24, 0, 12, 0, 12, 0, 4, 0, 8, 0, 8, 0, 0, 0, 24, 0, 76, 0, 32, 0, 8, 0, 12, 0, 8, 0, + 8, 0, 4, 0, 4, 0, 0, 1, 32, 0, 12, 0, 0, 0, 16, 0, 64, 0, 24, 0, 12, 0, 40, 0, 56, 0, 72, 0, 92, 0,100, 0, + 72, 0,100, 0,120, 0, 68, 0, 64, 0,112, 0, 64, 0, 76, 0,176, 0, 48, 0,168, 0,152, 0,156, 0, 64, 0, 96, 0,108, 0, +188, 0,104, 0,216, 0, 56, 0, 84, 0, 0, 0,136, 0, 28, 0,240, 1,104, 0, 0, 0, 80, 0, 0, 0, 0, 0, 68, 0, 8, 0, + 8, 0,220, 0, 80, 0, 76, 0, 68, 0, 68, 0, 64, 0,168, 1,112, 0,108, 0,188, 0, 40, 0, 0, 0, 92, 0, 64, 0, 72, 0, +120, 0,144, 0, 0, 1,208, 0,180, 0, 0, 0, 68, 0, 92, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0,104, 1, 28, 0,176, 0, +144, 0, 60, 0, 24, 0, 72, 0,248, 3, 56, 0, 20, 0, 16, 0, 92, 0, 80, 0, 24, 0,196, 0, 36, 0, 8, 0,100, 0, 80, 0, + 48, 0, 52, 0, 72, 1, 32, 0, 8, 0, 16, 0, 24, 2, 0, 0, 0, 0, 56, 0,216, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +240, 0, 40, 0,148, 0, 48, 0,140, 0,208, 0, 20, 0,224, 0,216, 0,204, 1, 60, 0, 0, 0,112, 0, 0, 0, 4, 1, 12, 0, + 12, 0,136, 0,200, 0,124, 2, 80, 2, 40, 0,180, 0,244, 0, 52, 0,148, 2, 28, 0, 80, 0, 24, 0, 16, 1, 32, 0,224, 0, + 32, 0, 32, 0, 80, 2, 16, 1, 16, 0,200, 21, 56, 0, 56, 11, 20, 0, 24, 0, 56, 1, 0, 0, 0, 0, 96, 0, 0, 0,248, 0, + 0, 0, 32, 0, 80, 0, 28, 0, 16, 0, 8, 0, 52, 0,252, 0,240, 0,168, 1,196, 0, 8, 1, 48, 0, 16, 0, 12, 0, 24, 0, + 48, 0, 16, 0, 20, 0, 16, 0, 24, 0, 56, 1, 0, 0, 56, 0, 52, 0, 48, 0, 8, 0, 44, 0, 72, 0,104, 0, 40, 0, 8, 0, + 72, 0, 44, 0, 40, 0,108, 0, 72, 0, 68, 0, 76, 0, 80, 0, 60, 0,128, 0, 76, 0, 60, 0, 12, 0, 92, 0, 68, 0, 32, 0, + 80, 0, 16, 0, 76, 0,108, 0, 84, 0, 28, 0, 96, 0, 56, 0, 56, 0,108, 0,140, 0, 4, 0, 20, 0, 12, 0, 8, 0, 80, 0, + 40, 0,196, 0, 24, 0, 4, 1,128, 0, 16, 0, 20, 0, 24, 0,180, 1, 4, 0, 40, 0,104, 0,228, 0, 64, 0, 44, 0, 72, 0, +116, 0, 60, 0,112, 0, 52, 0, 44, 0, 44, 0, 68, 0, 44, 0, 64, 0, 44, 0, 20, 0, 52, 0, 96, 0, 12, 0,108, 0, 92, 0, + 28, 0, 28, 0, 28, 0, 52, 0, 20, 0, 60, 0,140, 0, 36, 0,120, 0, 32, 0,212, 0, 0, 0, 0, 0, 0, 0, 16, 0, 40, 0, + 28, 0, 12, 0, 12, 0, 16, 1, 40, 0, 8, 0, 8, 0, 64, 0, 32, 0, 24, 0, 8, 0, 24, 0, 32, 0, 8, 0, 32, 0, 12, 0, + 44, 0, 20, 0, 68, 0, 24, 0, 56, 0, 52, 0, 20, 0, 64, 0, 28, 0,180, 0,172, 1, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 20, 0, 24, 0,172, 0, 24, 0, 24, 0,140, 0,156, 0, 56, 0, 0, 0, 0, 0,100, 0, 0, 0, 96, 0, 0, 0, 88, 0, + 20, 0, 24, 0, 16, 0, 20, 0, 8, 0, 8, 0, 24, 0, 20, 0, 88, 0, 24, 1, 16, 0, 68, 0, 0, 1, 20, 0,160, 0, 88, 0, + 96, 0, 88, 0, 20, 0, 56, 0, 48, 0, 68, 0, 56, 0, 92, 0, 64, 0, 56, 0, 96, 0, 0, 0, 0, 0, 0, 0, 83, 84, 82, 67, +133, 1, 0, 0, 10, 0, 2, 0, 10, 0, 0, 0, 10, 0, 1, 0, 11, 0, 3, 0, 11, 0, 0, 0, 11, 0, 1, 0, 9, 0, 2, 0, + 12, 0, 2, 0, 9, 0, 3, 0, 9, 0, 4, 0, 13, 0, 2, 0, 2, 0, 5, 0, 2, 0, 6, 0, 14, 0, 2, 0, 4, 0, 5, 0, + 4, 0, 6, 0, 15, 0, 2, 0, 7, 0, 5, 0, 7, 0, 6, 0, 16, 0, 2, 0, 8, 0, 5, 0, 8, 0, 6, 0, 17, 0, 3, 0, + 4, 0, 5, 0, 4, 0, 6, 0, 4, 0, 7, 0, 18, 0, 3, 0, 7, 0, 5, 0, 7, 0, 6, 0, 7, 0, 7, 0, 19, 0, 3, 0, + 8, 0, 5, 0, 8, 0, 6, 0, 8, 0, 7, 0, 20, 0, 4, 0, 4, 0, 5, 0, 4, 0, 6, 0, 4, 0, 7, 0, 4, 0, 8, 0, + 21, 0, 4, 0, 7, 0, 5, 0, 7, 0, 6, 0, 7, 0, 7, 0, 7, 0, 8, 0, 22, 0, 4, 0, 8, 0, 5, 0, 8, 0, 6, 0, + 8, 0, 7, 0, 8, 0, 8, 0, 23, 0, 4, 0, 4, 0, 9, 0, 4, 0, 10, 0, 4, 0, 11, 0, 4, 0, 12, 0, 24, 0, 4, 0, + 7, 0, 9, 0, 7, 0, 10, 0, 7, 0, 11, 0, 7, 0, 12, 0, 25, 0, 4, 0, 9, 0, 13, 0, 12, 0, 14, 0, 4, 0, 15, 0, + 4, 0, 16, 0, 26, 0, 10, 0, 26, 0, 0, 0, 26, 0, 1, 0, 0, 0, 17, 0, 0, 0, 18, 0, 2, 0, 19, 0, 0, 0, 20, 0, + 4, 0, 21, 0, 25, 0, 22, 0, 4, 0, 23, 0, 4, 0, 24, 0, 27, 0, 9, 0, 9, 0, 0, 0, 9, 0, 1, 0, 27, 0, 25, 0, + 28, 0, 26, 0, 0, 0, 27, 0, 2, 0, 28, 0, 2, 0, 19, 0, 4, 0, 29, 0, 26, 0, 30, 0, 28, 0, 8, 0, 27, 0, 31, 0, + 27, 0, 32, 0, 29, 0, 33, 0, 0, 0, 34, 0, 0, 0, 35, 0, 4, 0, 36, 0, 4, 0, 37, 0, 28, 0, 38, 0, 30, 0, 6, 0, + 4, 0, 39, 0, 4, 0, 40, 0, 2, 0, 41, 0, 2, 0, 42, 0, 2, 0, 43, 0, 4, 0, 44, 0, 31, 0, 6, 0, 32, 0, 45, 0, + 2, 0, 46, 0, 2, 0, 47, 0, 2, 0, 17, 0, 2, 0, 19, 0, 0, 0, 48, 0, 33, 0, 21, 0, 33, 0, 0, 0, 33, 0, 1, 0, + 34, 0, 49, 0, 35, 0, 50, 0, 24, 0, 51, 0, 24, 0, 52, 0, 2, 0, 46, 0, 2, 0, 47, 0, 2, 0, 53, 0, 2, 0, 54, 0, + 2, 0, 55, 0, 2, 0, 56, 0, 2, 0, 19, 0, 2, 0, 57, 0, 7, 0, 11, 0, 7, 0, 12, 0, 4, 0, 58, 0, 7, 0, 59, 0, + 7, 0, 60, 0, 7, 0, 61, 0, 31, 0, 62, 0, 36, 0, 7, 0, 27, 0, 31, 0, 12, 0, 63, 0, 24, 0, 64, 0, 2, 0, 46, 0, + 2, 0, 65, 0, 2, 0, 66, 0, 2, 0, 37, 0, 37, 0, 16, 0, 37, 0, 0, 0, 37, 0, 1, 0, 7, 0, 67, 0, 7, 0, 61, 0, + 2, 0, 17, 0, 2, 0, 47, 0, 2, 0, 68, 0, 2, 0, 19, 0, 4, 0, 69, 0, 4, 0, 70, 0, 9, 0, 2, 0, 7, 0, 71, 0, + 0, 0, 20, 0, 0, 0, 72, 0, 7, 0, 73, 0, 7, 0, 74, 0, 38, 0, 13, 0, 27, 0, 31, 0, 39, 0, 75, 0, 37, 0, 76, 0, + 0, 0, 77, 0, 4, 0, 78, 0, 7, 0, 61, 0, 12, 0, 79, 0, 36, 0, 80, 0, 27, 0, 81, 0, 2, 0, 17, 0, 2, 0, 82, 0, + 2, 0, 83, 0, 2, 0, 19, 0, 40, 0, 6, 0, 40, 0, 0, 0, 40, 0, 1, 0, 0, 0, 84, 0, 0, 0, 85, 0, 4, 0, 23, 0, + 4, 0, 86, 0, 41, 0, 10, 0, 41, 0, 0, 0, 41, 0, 1, 0, 4, 0, 87, 0, 4, 0, 88, 0, 4, 0, 89, 0, 4, 0, 43, 0, + 4, 0, 14, 0, 4, 0, 90, 0, 0, 0, 91, 0, 0, 0, 92, 0, 42, 0, 15, 0, 27, 0, 31, 0, 0, 0, 93, 0, 4, 0, 90, 0, + 4, 0, 94, 0, 12, 0, 95, 0, 40, 0, 96, 0, 40, 0, 97, 0, 4, 0, 98, 0, 4, 0, 99, 0, 12, 0,100, 0, 0, 0,101, 0, + 4, 0,102, 0, 4, 0,103, 0, 9, 0,104, 0, 8, 0,105, 0, 43, 0, 3, 0, 4, 0,106, 0, 4, 0,107, 0, 9, 0, 2, 0, + 44, 0, 20, 0, 27, 0, 31, 0, 39, 0, 75, 0, 2, 0, 17, 0, 2, 0, 19, 0, 7, 0,108, 0, 7, 0,109, 0, 7, 0,110, 0, + 7, 0,111, 0, 7, 0,112, 0, 7, 0,113, 0, 7, 0,114, 0, 7, 0,115, 0, 7, 0,116, 0, 7, 0,117, 0, 7, 0,118, 0, + 2, 0,119, 0, 2, 0,120, 0, 7, 0,121, 0, 36, 0, 80, 0, 32, 0,122, 0, 45, 0, 13, 0, 4, 0,123, 0, 4, 0,124, 0, + 4, 0,125, 0, 4, 0,126, 0, 2, 0,127, 0, 2, 0,128, 0, 2, 0, 19, 0, 2, 0,129, 0, 2, 0,130, 0, 2, 0,131, 0, + 2, 0,132, 0, 2, 0,133, 0, 46, 0,134, 0, 47, 0, 32, 0, 27, 0, 31, 0, 0, 0, 34, 0, 12, 0,135, 0, 48, 0,136, 0, + 49, 0,137, 0, 50, 0,138, 0, 2, 0,129, 0, 2, 0, 19, 0, 2, 0,139, 0, 2, 0, 17, 0, 2, 0, 37, 0, 2, 0, 43, 0, + 4, 0,140, 0, 2, 0,141, 0, 2, 0,142, 0, 2, 0,143, 0, 2, 0,144, 0, 2, 0,145, 0, 2, 0,146, 0, 4, 0,147, 0, + 4, 0,148, 0, 43, 0,149, 0, 30, 0,150, 0, 0, 0,151, 0, 7, 0,152, 0, 4, 0,153, 0, 2, 0,154, 0, 2, 0,155, 0, + 2, 0,156, 0, 2, 0,157, 0, 7, 0,158, 0, 7, 0,159, 0, 51, 0, 63, 0, 2, 0,160, 0, 2, 0,161, 0, 2, 0,162, 0, + 2, 0,163, 0, 32, 0,164, 0, 52, 0,165, 0, 0, 0,166, 0, 0, 0,167, 0, 0, 0,168, 0, 0, 0,169, 0, 0, 0,170, 0, + 7, 0,171, 0, 7, 0,172, 0, 7, 0,173, 0, 2, 0,174, 0, 2, 0,175, 0, 2, 0,176, 0, 2, 0,177, 0, 2, 0,178, 0, + 2, 0,179, 0, 0, 0,180, 0, 0, 0,181, 0, 7, 0,182, 0, 7, 0,183, 0, 7, 0,184, 0, 7, 0,185, 0, 7, 0,186, 0, + 7, 0, 57, 0, 7, 0,187, 0, 7, 0,188, 0, 7, 0,189, 0, 7, 0,190, 0, 7, 0,191, 0, 7, 0,192, 0, 7, 0,193, 0, + 7, 0,194, 0, 7, 0,195, 0, 7, 0,196, 0, 7, 0,197, 0, 7, 0,198, 0, 7, 0,199, 0, 7, 0,200, 0, 7, 0,201, 0, + 7, 0,202, 0, 7, 0,203, 0, 7, 0,204, 0, 7, 0,205, 0, 7, 0,206, 0, 7, 0,207, 0, 7, 0,208, 0, 7, 0,209, 0, + 7, 0,210, 0, 7, 0,211, 0, 7, 0,212, 0, 7, 0,213, 0, 7, 0,214, 0, 7, 0,215, 0, 7, 0,216, 0, 7, 0,217, 0, + 7, 0,218, 0, 7, 0,219, 0, 7, 0,220, 0, 7, 0,221, 0, 53, 0, 15, 0, 0, 0,222, 0, 9, 0,223, 0, 0, 0,224, 0, + 0, 0,225, 0, 4, 0,226, 0, 4, 0,227, 0, 9, 0,228, 0, 7, 0,229, 0, 7, 0,230, 0, 7, 0,231, 0, 4, 0,232, 0, + 9, 0,233, 0, 9, 0,234, 0, 4, 0,235, 0, 4, 0, 37, 0, 54, 0, 6, 0, 7, 0,182, 0, 7, 0,183, 0, 7, 0,184, 0, + 7, 0,236, 0, 7, 0, 67, 0, 4, 0, 64, 0, 55, 0, 5, 0, 2, 0, 19, 0, 2, 0, 36, 0, 2, 0, 64, 0, 2, 0,237, 0, + 54, 0,231, 0, 56, 0, 17, 0, 32, 0,164, 0, 47, 0,238, 0, 57, 0,239, 0, 7, 0,240, 0, 7, 0,241, 0, 2, 0, 17, 0, + 2, 0,242, 0, 7, 0,110, 0, 7, 0,111, 0, 7, 0,243, 0, 4, 0,244, 0, 2, 0,245, 0, 2, 0,246, 0, 4, 0,129, 0, + 4, 0,140, 0, 2, 0,247, 0, 2, 0,248, 0, 58, 0, 23, 0, 2, 0, 19, 0, 2, 0,249, 0, 7, 0,250, 0, 7, 0,251, 0, + 2, 0,139, 0, 2, 0,252, 0, 4, 0,253, 0, 4, 0,254, 0, 32, 0,164, 0, 59, 0,255, 0, 2, 0, 0, 1, 2, 0, 1, 1, + 2, 0, 2, 1, 9, 0, 3, 1, 7, 0, 4, 1, 7, 0, 5, 1, 2, 0, 6, 1, 2, 0, 7, 1, 2, 0, 8, 1, 2, 0, 9, 1, + 7, 0, 10, 1, 7, 0, 11, 1, 55, 0, 12, 1, 60, 0, 11, 0, 4, 0, 13, 1, 4, 0, 14, 1, 2, 0, 15, 1, 2, 0, 19, 0, + 2, 0, 16, 1, 2, 0, 37, 0, 32, 0,164, 0, 7, 0, 17, 1, 4, 0, 18, 1, 0, 0, 19, 1, 7, 0, 20, 1, 52, 0, 61, 0, + 27, 0, 31, 0, 39, 0, 75, 0, 7, 0, 21, 1, 7, 0, 22, 1, 7, 0, 23, 1, 7, 0, 24, 1, 7, 0, 25, 1, 7, 0, 26, 1, + 7, 0, 27, 1, 7, 0, 28, 1, 7, 0, 29, 1, 7, 0, 30, 1, 7, 0, 31, 1, 7, 0, 32, 1, 7, 0, 33, 1, 7, 0, 34, 1, + 7, 0, 35, 1, 7, 0, 36, 1, 7, 0, 37, 1, 7, 0, 38, 1, 7, 0, 39, 1, 7, 0, 40, 1, 2, 0, 41, 1, 2, 0, 42, 1, + 2, 0, 43, 1, 2, 0, 44, 1, 2, 0, 45, 1, 2, 0, 46, 1, 2, 0, 47, 1, 2, 0, 19, 0, 2, 0, 17, 0, 2, 0,242, 0, + 7, 0, 48, 1, 7, 0, 49, 1, 7, 0, 50, 1, 7, 0, 51, 1, 4, 0, 52, 1, 4, 0, 53, 1, 2, 0, 54, 1, 2, 0, 55, 1, + 2, 0, 16, 1, 2, 0,127, 0, 4, 0, 23, 0, 4, 0,124, 0, 4, 0,125, 0, 4, 0,126, 0, 7, 0, 56, 1, 7, 0, 57, 1, + 7, 0,189, 0, 45, 0, 58, 1, 61, 0, 59, 1, 36, 0, 80, 0, 47, 0,238, 0, 53, 0, 60, 1, 55, 0, 12, 1, 56, 0, 61, 1, + 30, 0,150, 0, 58, 0, 62, 1, 60, 0, 63, 1, 0, 0, 64, 1, 0, 0,181, 0, 62, 0, 8, 0, 7, 0, 65, 1, 7, 0, 66, 1, + 7, 0,172, 0, 4, 0, 19, 0, 7, 0, 67, 1, 7, 0, 68, 1, 7, 0, 69, 1, 32, 0, 45, 0, 63, 0, 82, 0, 27, 0, 31, 0, + 39, 0, 75, 0, 2, 0, 17, 0, 2, 0, 19, 0, 4, 0, 70, 1, 2, 0,175, 0, 2, 0, 71, 1, 7, 0,182, 0, 7, 0,183, 0, + 7, 0,184, 0, 7, 0,185, 0, 7, 0, 72, 1, 7, 0, 73, 1, 7, 0, 74, 1, 7, 0, 75, 1, 7, 0, 76, 1, 7, 0, 77, 1, + 7, 0, 78, 1, 7, 0, 79, 1, 7, 0, 80, 1, 7, 0, 81, 1, 7, 0, 82, 1, 64, 0, 83, 1, 2, 0,249, 0, 2, 0, 70, 0, + 7, 0,110, 0, 7, 0,111, 0, 7, 0, 84, 1, 7, 0, 85, 1, 7, 0, 86, 1, 2, 0, 87, 1, 2, 0, 88, 1, 2, 0, 89, 1, + 2, 0, 90, 1, 0, 0, 91, 1, 0, 0, 92, 1, 2, 0, 93, 1, 2, 0, 94, 1, 2, 0, 95, 1, 2, 0, 96, 1, 2, 0, 97, 1, + 7, 0, 98, 1, 7, 0, 99, 1, 7, 0,100, 1, 7, 0,101, 1, 2, 0,102, 1, 2, 0, 43, 0, 2, 0,103, 1, 2, 0,104, 1, + 2, 0,105, 1, 2, 0,106, 1, 7, 0,107, 1, 7, 0,108, 1, 7, 0,109, 1, 7, 0,110, 1, 7, 0,111, 1, 7, 0,112, 1, + 7, 0,113, 1, 7, 0,114, 1, 7, 0,115, 1, 7, 0,116, 1, 7, 0,117, 1, 7, 0,118, 1, 2, 0,119, 1, 2, 0,120, 1, + 4, 0,121, 1, 4, 0,122, 1, 2, 0,123, 1, 2, 0,124, 1, 2, 0,125, 1, 2, 0,126, 1, 7, 0,127, 1, 7, 0,128, 1, + 7, 0,129, 1, 7, 0,130, 1, 2, 0,131, 1, 2, 0,132, 1, 36, 0, 80, 0, 51, 0,133, 1, 2, 0,134, 1, 2, 0,135, 1, + 30, 0,150, 0, 65, 0, 2, 0, 27, 0, 31, 0, 36, 0, 80, 0, 66, 0, 18, 0, 7, 0,136, 1, 7, 0,137, 1, 7, 0,138, 1, + 7, 0,139, 1, 7, 0,140, 1, 7, 0,141, 1, 7, 0,142, 1, 7, 0,143, 1, 7, 0,144, 1, 7, 0,145, 1, 2, 0,146, 1, + 2, 0,147, 1, 2, 0,148, 1, 2, 0,149, 1, 7, 0,150, 1, 7, 0,151, 1, 7, 0,152, 1, 4, 0,153, 1, 67, 0,124, 0, + 27, 0, 31, 0, 39, 0, 75, 0, 2, 0,154, 1, 2, 0, 19, 0, 7, 0,182, 0, 7, 0,183, 0, 7, 0,184, 0, 7, 0,155, 1, + 7, 0,156, 1, 7, 0,157, 1, 7, 0,158, 1, 7, 0,159, 1, 7, 0,160, 1, 7, 0,161, 1, 7, 0,162, 1, 7, 0,163, 1, + 7, 0,164, 1, 7, 0,165, 1, 7, 0,166, 1, 7, 0,167, 1, 7, 0,168, 1, 7, 0,169, 1, 7, 0,170, 1, 7, 0,171, 1, + 7, 0,172, 1, 7, 0,173, 1, 7, 0,174, 1, 66, 0,175, 1, 7, 0,176, 1, 7, 0,177, 1, 7, 0,178, 1, 7, 0,179, 1, + 7, 0,180, 1, 7, 0,181, 1, 7, 0,182, 1, 2, 0,183, 1, 2, 0,184, 1, 2, 0,185, 1, 0, 0,186, 1, 0, 0,187, 1, + 7, 0,188, 1, 7, 0,189, 1, 2, 0,190, 1, 2, 0,191, 1, 7, 0,192, 1, 7, 0,193, 1, 7, 0,194, 1, 7, 0,195, 1, + 2, 0,196, 1, 2, 0,197, 1, 4, 0, 70, 1, 4, 0,198, 1, 2, 0,199, 1, 2, 0,200, 1, 2, 0,201, 1, 2, 0,202, 1, + 7, 0,203, 1, 7, 0,204, 1, 7, 0,205, 1, 7, 0,206, 1, 7, 0,207, 1, 7, 0,208, 1, 7, 0,209, 1, 7, 0,210, 1, + 7, 0,211, 1, 7, 0,212, 1, 0, 0,213, 1, 7, 0,214, 1, 7, 0,215, 1, 7, 0,216, 1, 4, 0,217, 1, 0, 0,218, 1, + 0, 0,103, 1, 0, 0,219, 1, 0, 0, 64, 1, 2, 0,220, 1, 2, 0,221, 1, 2, 0,134, 1, 2, 0,222, 1, 2, 0,223, 1, + 2, 0,224, 1, 7, 0,225, 1, 7, 0,226, 1, 7, 0,227, 1, 7, 0,228, 1, 7, 0,229, 1, 2, 0,160, 0, 2, 0,161, 0, + 55, 0,230, 1, 55, 0,231, 1, 0, 0,232, 1, 0, 0,233, 1, 0, 0,234, 1, 0, 0,235, 1, 2, 0,236, 1, 2, 0,237, 1, + 7, 0,238, 1, 7, 0,239, 1, 51, 0,133, 1, 61, 0, 59, 1, 36, 0, 80, 0, 68, 0,240, 1, 30, 0,150, 0, 7, 0,241, 1, + 7, 0,242, 1, 7, 0,243, 1, 7, 0,244, 1, 7, 0,245, 1, 2, 0,246, 1, 2, 0, 70, 0, 7, 0,247, 1, 7, 0,248, 1, + 7, 0,249, 1, 7, 0,250, 1, 7, 0,251, 1, 7, 0,252, 1, 7, 0,253, 1, 7, 0,254, 1, 7, 0,255, 1, 2, 0, 0, 2, + 2, 0, 1, 2, 4, 0, 2, 2, 4, 0,120, 1, 12, 0, 3, 2, 69, 0, 4, 0, 27, 0, 31, 0, 0, 0, 4, 2, 70, 0, 2, 0, + 43, 0,149, 0, 71, 0, 26, 0, 71, 0, 0, 0, 71, 0, 1, 0, 72, 0, 5, 2, 4, 0, 6, 2, 4, 0, 7, 2, 4, 0, 8, 2, + 4, 0, 9, 2, 4, 0, 10, 2, 4, 0, 11, 2, 2, 0, 17, 0, 2, 0, 19, 0, 2, 0, 12, 2, 2, 0, 13, 2, 7, 0, 5, 0, + 7, 0, 6, 0, 7, 0, 7, 0, 7, 0, 14, 2, 7, 0, 15, 2, 7, 0, 16, 2, 7, 0, 17, 2, 7, 0, 18, 2, 7, 0, 19, 2, + 7, 0, 20, 2, 7, 0, 23, 0, 7, 0, 21, 2, 7, 0, 22, 2, 73, 0, 19, 0, 27, 0, 31, 0, 39, 0, 75, 0, 72, 0, 5, 2, + 12, 0, 23, 2, 12, 0, 24, 2, 12, 0, 25, 2, 36, 0, 80, 0, 67, 0, 26, 2, 0, 0, 19, 0, 0, 0, 27, 2, 2, 0, 28, 2, + 4, 0,174, 0, 7, 0, 65, 1, 7, 0,172, 0, 7, 0, 66, 1, 7, 0, 29, 2, 7, 0, 30, 2, 7, 0, 31, 2, 71, 0, 32, 2, + 35, 0, 11, 0, 7, 0, 33, 2, 7, 0, 34, 2, 7, 0, 35, 2, 7, 0,251, 0, 2, 0, 55, 0, 0, 0, 36, 2, 0, 0, 37, 2, + 0, 0, 38, 2, 0, 0, 39, 2, 0, 0, 40, 2, 0, 0, 41, 2, 34, 0, 7, 0, 7, 0, 42, 2, 7, 0, 34, 2, 7, 0, 35, 2, + 2, 0, 38, 2, 2, 0, 41, 2, 7, 0,251, 0, 7, 0, 37, 0, 74, 0, 21, 0, 74, 0, 0, 0, 74, 0, 1, 0, 2, 0, 17, 0, + 2, 0, 43, 2, 2, 0, 41, 2, 2, 0, 19, 0, 2, 0, 44, 2, 2, 0, 45, 2, 2, 0, 46, 2, 2, 0, 47, 2, 2, 0, 48, 2, + 2, 0, 49, 2, 2, 0, 50, 2, 2, 0, 51, 2, 7, 0, 52, 2, 7, 0, 53, 2, 34, 0, 49, 0, 35, 0, 50, 0, 2, 0, 54, 2, + 2, 0, 55, 2, 4, 0, 56, 2, 75, 0, 5, 0, 2, 0, 57, 2, 2, 0, 43, 2, 0, 0, 19, 0, 0, 0, 37, 0, 2, 0, 70, 0, + 76, 0, 4, 0, 7, 0, 5, 0, 7, 0, 6, 0, 7, 0, 8, 0, 7, 0, 58, 2, 77, 0, 67, 0, 27, 0, 31, 0, 39, 0, 75, 0, + 72, 0, 5, 2, 12, 0, 59, 2, 12, 0, 24, 2, 12, 0, 60, 2, 32, 0, 61, 2, 32, 0, 62, 2, 32, 0, 63, 2, 36, 0, 80, 0, + 78, 0, 64, 2, 38, 0, 65, 2, 67, 0, 26, 2, 12, 0, 66, 2, 7, 0, 65, 1, 7, 0,172, 0, 7, 0, 66, 1, 4, 0,174, 0, + 2, 0, 67, 2, 2, 0, 68, 2, 2, 0, 69, 2, 7, 0, 70, 2, 7, 0, 70, 0, 2, 0, 71, 2, 2, 0, 28, 2, 2, 0, 19, 0, + 2, 0, 72, 2, 7, 0, 73, 2, 7, 0, 74, 2, 7, 0, 75, 2, 2, 0, 46, 2, 2, 0, 47, 2, 2, 0, 76, 2, 2, 0, 77, 2, + 4, 0, 78, 2, 34, 0, 79, 2, 2, 0, 23, 0, 2, 0, 95, 0, 2, 0, 67, 0, 2, 0, 80, 2, 7, 0, 81, 2, 7, 0, 82, 2, + 7, 0, 83, 2, 7, 0, 84, 2, 7, 0, 85, 2, 7, 0, 86, 2, 7, 0, 87, 2, 7, 0, 88, 2, 7, 0, 89, 2, 7, 0, 90, 2, + 0, 0, 91, 2, 79, 0, 92, 2, 80, 0, 93, 2, 0, 0, 94, 2, 69, 0, 95, 2, 69, 0, 96, 2, 69, 0, 97, 2, 69, 0, 98, 2, + 4, 0, 99, 2, 7, 0,100, 2, 4, 0,101, 2, 4, 0,102, 2, 76, 0,103, 2, 4, 0,104, 2, 4, 0,105, 2, 75, 0,106, 2, + 75, 0,107, 2, 81, 0, 39, 0, 27, 0, 31, 0, 72, 0, 5, 2, 12, 0,108, 2, 36, 0, 80, 0, 38, 0, 65, 2, 67, 0, 26, 2, + 82, 0,109, 2, 83, 0,110, 2, 84, 0,111, 2, 85, 0,112, 2, 86, 0,113, 2, 87, 0,114, 2, 88, 0,115, 2, 89, 0,116, 2, + 81, 0,117, 2, 90, 0,118, 2, 91, 0,119, 2, 92, 0,120, 2, 92, 0,121, 2, 92, 0,122, 2, 4, 0, 54, 0, 4, 0,123, 2, + 4, 0,124, 2, 4, 0,125, 2, 4, 0,126, 2, 4, 0,174, 0, 7, 0, 65, 1, 7, 0,172, 0, 7, 0, 66, 1, 7, 0,127, 2, + 4, 0, 67, 2, 2, 0,128, 2, 2, 0, 19, 0, 2, 0,129, 2, 2, 0,130, 2, 2, 0, 28, 2, 2, 0,131, 2, 93, 0,132, 2, + 94, 0,133, 2, 84, 0, 8, 0, 9, 0,134, 2, 7, 0,135, 2, 4, 0,136, 2, 0, 0, 19, 0, 0, 0,137, 2, 2, 0, 70, 1, + 2, 0,138, 2, 2, 0,139, 2, 82, 0, 7, 0, 4, 0,140, 2, 4, 0,141, 2, 4, 0,142, 2, 4, 0,143, 2, 2, 0, 43, 2, + 0, 0,144, 2, 0, 0, 19, 0, 86, 0, 5, 0, 4, 0,140, 2, 4, 0,141, 2, 0, 0,145, 2, 0, 0,146, 2, 2, 0, 19, 0, + 95, 0, 2, 0, 4, 0,147, 2, 7, 0, 35, 2, 87, 0, 3, 0, 95, 0,148, 2, 4, 0,149, 2, 4, 0, 19, 0, 85, 0, 6, 0, + 7, 0,150, 2, 2, 0,151, 2, 2, 0, 43, 2, 0, 0, 19, 0, 0, 0,146, 2, 0, 0, 69, 2, 88, 0, 4, 0, 0, 0,236, 0, + 0, 0,182, 0, 0, 0,183, 0, 0, 0,184, 0, 96, 0, 6, 0, 47, 0,134, 2, 0, 0, 19, 0, 0, 0,137, 2, 2, 0, 70, 1, + 2, 0,138, 2, 2, 0,139, 2, 97, 0, 1, 0, 7, 0,152, 2, 98, 0, 5, 0, 0, 0,236, 0, 0, 0,182, 0, 0, 0,183, 0, + 0, 0,184, 0, 4, 0, 37, 0, 89, 0, 1, 0, 7, 0,153, 2, 90, 0, 2, 0, 4, 0,154, 2, 4, 0, 17, 0, 83, 0, 7, 0, + 7, 0,135, 2, 47, 0,134, 2, 0, 0, 19, 0, 0, 0,137, 2, 2, 0, 70, 1, 2, 0,138, 2, 2, 0,139, 2, 99, 0, 1, 0, + 7, 0,155, 2,100, 0, 1, 0, 4, 0,156, 2,101, 0, 1, 0, 0, 0,157, 2,102, 0, 1, 0, 7, 0,135, 2,103, 0, 3, 0, + 4, 0,158, 2, 0, 0, 92, 0, 7, 0,159, 2,105, 0, 4, 0, 7, 0,236, 0, 7, 0,182, 0, 7, 0,183, 0, 7, 0,184, 0, +106, 0, 1, 0,105, 0,136, 2,107, 0, 5, 0, 4, 0,160, 2, 4, 0,161, 2, 0, 0, 19, 0, 0, 0, 43, 2, 0, 0, 69, 2, +108, 0, 2, 0, 4, 0,162, 2, 4, 0,161, 2,109, 0, 10, 0,109, 0, 0, 0,109, 0, 1, 0,107, 0,163, 2,106, 0,164, 2, +108, 0,165, 2, 4, 0, 54, 0, 4, 0,124, 2, 4, 0,123, 2, 4, 0, 37, 0, 85, 0,166, 2, 93, 0, 14, 0, 12, 0,167, 2, + 85, 0,166, 2, 0, 0,168, 2, 0, 0,169, 2, 0, 0,170, 2, 0, 0,171, 2, 0, 0,172, 2, 0, 0,173, 2, 0, 0,174, 2, + 0, 0, 19, 0, 92, 0,120, 2, 92, 0,122, 2, 2, 0,175, 2, 0, 0,176, 2, 94, 0, 8, 0, 4, 0,177, 2, 4, 0,178, 2, + 82, 0,179, 2, 86, 0,180, 2, 4, 0,124, 2, 4, 0,123, 2, 4, 0, 54, 0, 4, 0, 37, 0,110, 0, 7, 0,110, 0, 0, 0, +110, 0, 1, 0, 4, 0, 17, 0, 4, 0, 70, 1, 0, 0, 20, 0, 46, 0,134, 0, 0, 0,181, 2,111, 0, 7, 0,110, 0,182, 2, + 2, 0,183, 2, 2, 0,167, 2, 2, 0,184, 2, 2, 0, 90, 0, 9, 0,185, 2, 9, 0,186, 2,112, 0, 3, 0,110, 0,182, 2, + 32, 0,164, 0, 0, 0, 20, 0,113, 0, 5, 0,110, 0,182, 2, 32, 0,164, 0, 0, 0, 20, 0, 2, 0,187, 2, 0, 0,188, 2, +114, 0, 5, 0,110, 0,182, 2, 7, 0, 88, 0, 7, 0,189, 2, 4, 0,190, 2, 4, 0,191, 2,115, 0, 5, 0,110, 0,182, 2, + 32, 0,192, 2, 0, 0, 72, 0, 4, 0, 70, 1, 4, 0, 19, 0,116, 0, 13, 0,110, 0,182, 2, 32, 0,193, 2, 32, 0,194, 2, + 32, 0,195, 2, 32, 0,196, 2, 7, 0,197, 2, 7, 0,198, 2, 7, 0,189, 2, 7, 0,199, 2, 4, 0,200, 2, 4, 0,201, 2, + 4, 0, 90, 0, 4, 0,202, 2,117, 0, 5, 0,110, 0,182, 2, 2, 0,203, 2, 2, 0, 19, 0, 7, 0,204, 2, 32, 0,205, 2, +118, 0, 3, 0,110, 0,182, 2, 7, 0,206, 2, 4, 0, 90, 0,119, 0, 10, 0,110, 0,182, 2, 7, 0,207, 2, 4, 0,208, 2, + 4, 0, 37, 0, 2, 0, 90, 0, 2, 0,209, 2, 2, 0,210, 2, 2, 0,211, 2, 7, 0,212, 2, 0, 0,213, 2,120, 0, 3, 0, +110, 0,182, 2, 7, 0, 37, 0, 4, 0, 17, 0,121, 0, 6, 0,110, 0,182, 2,122, 0,214, 2,123, 0,215, 2,124, 0,216, 2, + 7, 0,217, 2, 4, 0, 17, 0,125, 0, 11, 0,110, 0,182, 2, 52, 0,218, 2, 7, 0,219, 2, 4, 0,220, 2, 0, 0,213, 2, + 7, 0,221, 2, 4, 0,222, 2, 32, 0,223, 2, 0, 0,224, 2, 4, 0,225, 2, 4, 0, 37, 0,126, 0, 10, 0,110, 0,182, 2, + 32, 0,226, 2, 47, 0,227, 2, 4, 0, 90, 0, 4, 0,228, 2, 7, 0,229, 2, 7, 0,230, 2, 0, 0,224, 2, 4, 0,225, 2, + 4, 0, 37, 0,127, 0, 3, 0,110, 0,182, 2, 7, 0,231, 2, 4, 0,232, 2,128, 0, 5, 0,110, 0,182, 2, 7, 0,233, 2, + 0, 0,213, 2, 2, 0, 19, 0, 2, 0,234, 2,129, 0, 8, 0,110, 0,182, 2, 32, 0,164, 0, 7, 0,233, 2, 7, 0,251, 0, + 7, 0,106, 0, 0, 0,213, 2, 2, 0, 19, 0, 2, 0, 17, 0,130, 0, 21, 0,110, 0,182, 2, 32, 0,235, 2, 0, 0,213, 2, + 52, 0,218, 2, 32, 0,223, 2, 2, 0, 19, 0, 2, 0, 37, 0, 7, 0,236, 2, 7, 0,237, 2, 7, 0,238, 2, 7, 0, 73, 2, + 7, 0,239, 2, 7, 0,240, 2, 7, 0,241, 2, 7, 0,242, 2, 4, 0,222, 2, 4, 0,225, 2, 0, 0,224, 2, 7, 0,243, 2, + 7, 0,244, 2, 7, 0, 43, 0,131, 0, 7, 0,110, 0,182, 2, 2, 0,245, 2, 2, 0,246, 2, 4, 0, 70, 0, 32, 0,164, 0, + 7, 0,247, 2, 0, 0,213, 2,132, 0, 10, 0,110, 0,182, 2, 32, 0,164, 0, 0, 0,248, 2, 7, 0,249, 2, 7, 0,250, 2, + 7, 0,242, 2, 4, 0,251, 2, 4, 0,252, 2, 7, 0,253, 2, 0, 0, 20, 0,133, 0, 1, 0,110, 0,182, 2,134, 0, 7, 0, +110, 0,182, 2, 46, 0,134, 0,135, 0,254, 2,136, 0,255, 2,137, 0, 0, 3,138, 0, 1, 3, 12, 0, 2, 3,139, 0, 13, 0, +110, 0,182, 2, 85, 0, 3, 3, 85, 0, 4, 3, 85, 0, 5, 3, 85, 0, 6, 3, 85, 0, 7, 3, 85, 0, 8, 3, 82, 0, 9, 3, + 4, 0, 10, 3, 4, 0, 11, 3, 7, 0,217, 2, 7, 0, 37, 0,140, 0, 12, 3,141, 0, 7, 0,110, 0,182, 2, 85, 0, 3, 3, + 85, 0, 13, 3,142, 0, 14, 3,143, 0, 12, 3, 4, 0, 15, 3, 4, 0, 10, 3,144, 0, 4, 0,110, 0,182, 2, 32, 0,164, 0, + 4, 0, 16, 3, 4, 0, 37, 0,145, 0, 2, 0, 4, 0, 17, 3, 7, 0, 35, 2,146, 0, 2, 0, 4, 0,125, 0, 4, 0, 18, 3, +147, 0, 20, 0,110, 0,182, 2, 32, 0,164, 0, 0, 0,213, 2, 2, 0, 19, 3, 2, 0, 20, 3, 2, 0, 19, 0, 2, 0, 37, 0, + 7, 0, 21, 3, 7, 0, 22, 3, 4, 0, 54, 0, 4, 0, 23, 3,146, 0, 24, 3,145, 0, 25, 3, 4, 0, 26, 3, 4, 0, 27, 3, + 4, 0, 28, 3, 4, 0, 18, 3, 7, 0, 29, 3, 7, 0, 30, 3, 7, 0, 31, 3,148, 0, 8, 0,110, 0,182, 2, 59, 0,255, 0, +142, 0, 14, 3, 4, 0, 32, 3, 4, 0, 33, 3, 4, 0, 34, 3, 2, 0, 19, 0, 2, 0, 57, 0,149, 0, 8, 0,110, 0,182, 2, + 32, 0, 45, 0, 2, 0, 35, 3, 2, 0, 19, 0, 2, 0,203, 2, 2, 0, 57, 0, 7, 0, 36, 3, 7, 0, 37, 3,150, 0, 5, 0, +110, 0,182, 2, 4, 0, 38, 3, 2, 0, 19, 0, 2, 0, 39, 3, 7, 0, 40, 3,151, 0, 7, 0,110, 0,182, 2, 85, 0, 41, 3, + 4, 0, 42, 3, 0, 0, 43, 3, 0, 0, 44, 3, 0, 0, 45, 3, 0, 0, 46, 3,152, 0, 3, 0,110, 0,182, 2,153, 0, 47, 3, +138, 0, 1, 3,154, 0, 10, 0,110, 0,182, 2, 32, 0, 48, 3, 32, 0, 49, 3, 0, 0, 50, 3, 7, 0, 51, 3, 2, 0, 52, 3, + 2, 0, 53, 3, 0, 0, 54, 3, 0, 0, 55, 3, 0, 0,188, 2,155, 0, 9, 0,110, 0,182, 2, 32, 0, 56, 3, 0, 0, 50, 3, + 7, 0, 57, 3, 7, 0, 58, 3, 0, 0, 70, 1, 0, 0,203, 2, 0, 0, 59, 3, 0, 0, 37, 0,156, 0, 27, 0, 27, 0, 31, 0, + 2, 0, 44, 2, 2, 0, 45, 2, 2, 0, 60, 3, 2, 0, 19, 0, 2, 0, 61, 3, 2, 0, 62, 3, 2, 0, 63, 3, 2, 0, 70, 0, + 0, 0, 64, 3, 0, 0, 65, 3, 0, 0, 66, 3, 0, 0, 17, 0, 4, 0, 37, 0, 7, 0, 67, 3, 7, 0, 68, 3, 7, 0, 69, 3, + 7, 0, 70, 3, 7, 0, 71, 3, 7, 0, 72, 3, 34, 0, 73, 3, 36, 0, 80, 0, 38, 0, 65, 2, 87, 0,114, 2, 7, 0, 74, 3, + 7, 0, 75, 3,156, 0, 76, 3,157, 0, 3, 0,157, 0, 0, 0,157, 0, 1, 0, 0, 0, 20, 0, 72, 0, 3, 0, 7, 0, 77, 3, + 4, 0, 19, 0, 4, 0, 37, 0, 32, 0,120, 0, 27, 0, 31, 0, 39, 0, 75, 0,158, 0, 78, 3, 2, 0, 17, 0, 2, 0, 79, 3, + 4, 0, 80, 3, 4, 0, 81, 3, 4, 0, 82, 3, 0, 0, 83, 3, 32, 0, 38, 0, 32, 0, 84, 3, 32, 0, 85, 3, 32, 0, 86, 3, + 32, 0, 87, 3, 36, 0, 80, 0, 78, 0, 64, 2, 72, 0, 5, 2,159, 0, 88, 3,159, 0, 89, 3,160, 0, 90, 3, 9, 0, 2, 0, +161, 0, 91, 3, 12, 0, 92, 3, 12, 0,108, 2, 12, 0, 24, 2, 12, 0, 93, 3, 12, 0, 94, 3, 4, 0, 70, 1, 4, 0, 95, 3, + 67, 0, 26, 2, 0, 0, 96, 3, 4, 0, 28, 2, 4, 0, 97, 3, 7, 0, 65, 1, 7, 0, 98, 3, 7, 0, 99, 3, 7, 0,172, 0, + 7, 0,100, 3, 7, 0, 66, 1, 7, 0,101, 3, 7, 0, 14, 2, 7, 0,102, 3, 7, 0,103, 3, 7, 0,249, 2, 7, 0,104, 3, + 7, 0,240, 0, 4, 0,105, 3, 2, 0, 19, 0, 2, 0,106, 3, 2, 0,107, 3, 2, 0,108, 3, 2, 0,109, 3, 2, 0,110, 3, + 2, 0,111, 3, 2, 0,112, 3, 2, 0,113, 3, 2, 0,114, 3, 2, 0,115, 3, 2, 0,116, 3, 4, 0,117, 3, 4, 0,118, 3, + 4, 0,119, 3, 4, 0,120, 3, 7, 0,121, 3, 7, 0,100, 2, 7, 0,122, 3, 7, 0,123, 3, 7, 0,124, 3, 7, 0,125, 3, + 7, 0,126, 3, 7, 0,215, 0, 7, 0,127, 3, 7, 0,128, 3, 7, 0,129, 3, 7, 0,130, 3, 2, 0,131, 3, 0, 0,132, 3, + 0, 0,133, 3, 0, 0,134, 3, 0, 0,135, 3, 7, 0,136, 3, 7, 0,137, 3, 12, 0,138, 3, 12, 0,139, 3, 12, 0,140, 3, + 12, 0,141, 3, 7, 0,142, 3, 2, 0,154, 2, 2, 0,143, 3, 7, 0,136, 2, 4, 0,144, 3, 4, 0,145, 3,162, 0,146, 3, + 2, 0,147, 3, 2, 0,247, 0, 7, 0,148, 3, 12, 0,149, 3, 12, 0,150, 3, 12, 0,151, 3, 12, 0,152, 3,163, 0, 62, 1, +164, 0,153, 3, 68, 0,154, 3, 2, 0,155, 3, 2, 0,156, 3, 2, 0,157, 3, 2, 0,158, 3, 7, 0,128, 2, 2, 0,159, 3, + 2, 0,160, 3,153, 0,161, 3,142, 0,162, 3,142, 0,163, 3, 4, 0,164, 3, 4, 0,165, 3, 4, 0,166, 3, 4, 0, 70, 0, + 12, 0,167, 3, 12, 0,168, 3, 12, 0,169, 3,165, 0, 14, 0,165, 0, 0, 0,165, 0, 1, 0, 32, 0, 38, 0, 7, 0,249, 2, + 7, 0, 67, 1, 7, 0,250, 2, 7, 0,242, 2, 0, 0, 20, 0, 4, 0,251, 2, 4, 0,252, 2, 4, 0,170, 3, 2, 0, 17, 0, + 2, 0,171, 3, 7, 0,253, 2,166, 0, 12, 0,166, 0, 0, 0,166, 0, 1, 0, 32, 0, 45, 0, 4, 0,172, 3, 4, 0,154, 2, + 4, 0,173, 3, 4, 0, 17, 0, 4, 0,174, 3, 7, 0, 67, 1, 7, 0,175, 3, 7, 0,176, 3, 7, 0,152, 2,163, 0, 41, 0, + 2, 0,177, 3, 2, 0,178, 3, 2, 0, 19, 0, 2, 0,242, 2, 2, 0,179, 3, 2, 0,180, 3, 2, 0,181, 3, 2, 0,182, 3, + 2, 0,183, 3, 2, 0, 57, 0, 7, 0,184, 3, 7, 0,185, 3, 7, 0,186, 3, 7, 0,187, 3, 7, 0,188, 3, 7, 0,189, 3, + 7, 0,190, 3, 7, 0,191, 3, 7, 0,192, 3, 7, 0,193, 3, 7, 0,194, 3, 7, 0,195, 3, 7, 0,196, 3, 7, 0,197, 3, + 7, 0,198, 3, 7, 0,199, 3, 7, 0, 37, 0, 7, 0,200, 3, 7, 0,201, 3, 7, 0,202, 3, 7, 0,203, 3, 7, 0,204, 3, + 7, 0,205, 3, 7, 0,206, 3, 7, 0,207, 3, 7, 0,208, 3, 7, 0,209, 3, 52, 0,165, 0,167, 0,210, 3, 7, 0,211, 3, + 4, 0,191, 2,168, 0, 5, 0, 68, 0,240, 1, 7, 0,212, 3, 7, 0,213, 3, 2, 0, 19, 0, 2, 0,214, 3,169, 0, 9, 0, +169, 0, 0, 0,169, 0, 1, 0, 4, 0,215, 3, 4, 0,216, 3, 4, 0,217, 3, 4, 0, 19, 0, 4, 0,218, 3, 9, 0,219, 3, + 9, 0,220, 3,138, 0, 19, 0,138, 0, 0, 0,138, 0, 1, 0, 4, 0, 19, 0, 4, 0,221, 3, 4, 0,222, 3, 4, 0,223, 3, + 4, 0,224, 3, 4, 0,225, 3, 4, 0,226, 3, 4, 0,216, 3, 4, 0,154, 2, 4, 0, 57, 0, 0, 0,227, 3, 0, 0,228, 3, + 0, 0,229, 3, 0, 0,230, 3, 12, 0,231, 3,170, 0,232, 3, 9, 0,233, 3,171, 0, 1, 0, 7, 0, 42, 2,162, 0, 30, 0, + 4, 0, 19, 0, 7, 0,234, 3, 7, 0,235, 3, 7, 0,236, 3, 4, 0,237, 3, 4, 0,238, 3, 4, 0,239, 3, 4, 0,240, 3, + 7, 0,241, 3, 7, 0,242, 3, 7, 0,243, 3, 7, 0,244, 3, 7, 0,245, 3, 7, 0,246, 3, 7, 0,247, 3, 7, 0,248, 3, + 7, 0,249, 3, 7, 0,250, 3, 7, 0,251, 3, 7, 0,252, 3, 7, 0,253, 3, 7, 0,254, 3, 7, 0,255, 3, 7, 0, 0, 4, + 7, 0, 1, 4, 7, 0, 2, 4, 4, 0, 3, 4, 4, 0, 4, 4, 7, 0, 5, 4, 7, 0,127, 3,164, 0, 50, 0, 4, 0,216, 3, + 4, 0, 6, 4,172, 0, 7, 4,173, 0, 8, 4, 0, 0, 37, 0, 0, 0, 9, 4, 2, 0, 10, 4, 7, 0, 11, 4, 0, 0, 12, 4, + 7, 0, 13, 4, 7, 0, 14, 4, 7, 0, 15, 4, 7, 0, 16, 4, 7, 0, 17, 4, 7, 0, 18, 4, 7, 0, 19, 4, 7, 0, 20, 4, + 7, 0, 21, 4, 2, 0, 22, 4, 0, 0, 23, 4, 2, 0, 24, 4, 7, 0, 25, 4, 7, 0, 26, 4, 0, 0, 27, 4, 4, 0,126, 0, + 4, 0, 28, 4, 4, 0, 29, 4, 2, 0, 30, 4, 2, 0, 31, 4,171, 0, 32, 4, 4, 0, 33, 4, 4, 0, 82, 0, 7, 0, 34, 4, + 7, 0, 35, 4, 7, 0, 36, 4, 7, 0, 37, 4, 2, 0, 38, 4, 2, 0, 39, 4, 2, 0, 40, 4, 2, 0, 41, 4, 2, 0, 42, 4, + 2, 0, 43, 4, 2, 0, 44, 4, 2, 0, 45, 4,174, 0, 46, 4, 7, 0, 47, 4, 7, 0, 48, 4,138, 0, 49, 4, 12, 0, 2, 3, +168, 0, 50, 4,153, 0, 49, 0,152, 0, 51, 4, 2, 0, 17, 0, 2, 0, 52, 4, 2, 0, 53, 4, 2, 0, 54, 4, 7, 0, 55, 4, + 2, 0, 56, 4, 2, 0, 57, 4, 7, 0, 58, 4, 2, 0, 59, 4, 2, 0, 60, 4, 7, 0, 61, 4, 7, 0, 62, 4, 7, 0, 63, 4, + 7, 0, 64, 4, 7, 0, 65, 4, 7, 0, 66, 4, 4, 0, 67, 4, 7, 0, 68, 4, 7, 0, 69, 4, 7, 0, 70, 4, 81, 0, 71, 4, + 81, 0, 72, 4, 81, 0, 73, 4, 0, 0, 74, 4, 7, 0, 75, 4, 7, 0, 76, 4, 36, 0, 80, 0, 2, 0, 77, 4, 0, 0, 78, 4, + 0, 0, 79, 4, 7, 0, 80, 4, 4, 0, 81, 4, 7, 0, 82, 4, 7, 0, 83, 4, 4, 0, 84, 4, 4, 0, 19, 0, 7, 0, 85, 4, + 7, 0, 86, 4, 7, 0, 87, 4, 85, 0, 88, 4, 7, 0, 89, 4, 7, 0, 90, 4, 7, 0, 91, 4, 7, 0, 92, 4, 7, 0, 93, 4, + 7, 0, 94, 4, 7, 0, 95, 4, 4, 0, 96, 4,175, 0, 73, 0, 27, 0, 31, 0, 39, 0, 75, 0, 2, 0,175, 0, 2, 0, 71, 1, + 2, 0,103, 1, 2, 0, 97, 4, 7, 0, 98, 4, 7, 0, 99, 4, 7, 0,100, 4, 7, 0,101, 4, 7, 0,102, 4, 7, 0,103, 4, + 7, 0,104, 4, 7, 0,105, 4, 7, 0,161, 1, 7, 0,163, 1, 7, 0,162, 1, 7, 0,106, 4, 4, 0,107, 4, 7, 0,108, 4, + 7, 0,109, 4, 7, 0,110, 4, 7, 0,111, 4, 7, 0,112, 4, 7, 0,113, 4, 7, 0,114, 4, 2, 0,115, 4, 2, 0, 70, 1, + 2, 0,116, 4, 2, 0,117, 4, 2, 0,118, 4, 2, 0,119, 4, 2, 0,120, 4, 2, 0,121, 4, 7, 0,122, 4, 7, 0,123, 4, + 7, 0,124, 4, 7, 0,125, 4, 7, 0,126, 4, 7, 0,127, 4, 7, 0,128, 4, 7, 0,129, 4, 7, 0,130, 4, 7, 0,131, 4, + 7, 0,132, 4, 7, 0,133, 4, 2, 0,134, 4, 2, 0,135, 4, 2, 0,136, 4, 2, 0,137, 4, 7, 0,138, 4, 7, 0,139, 4, + 7, 0,140, 4, 7, 0,141, 4, 2, 0,142, 4, 2, 0,143, 4, 2, 0,144, 4, 2, 0,145, 4, 7, 0,146, 4, 7, 0,147, 4, + 7, 0,148, 4, 7, 0,149, 4, 2, 0,150, 4, 2, 0,151, 4, 2, 0,152, 4, 2, 0, 19, 0, 7, 0,153, 4, 7, 0,154, 4, + 36, 0, 80, 0, 51, 0,133, 1, 2, 0,134, 1, 2, 0,135, 1, 30, 0,150, 0,176, 0, 8, 0,176, 0, 0, 0,176, 0, 1, 0, + 4, 0,105, 3, 4, 0,155, 4, 4, 0, 19, 0, 2, 0,156, 4, 2, 0,157, 4, 32, 0,164, 0,177, 0, 13, 0, 9, 0,158, 4, + 9, 0,159, 4, 4, 0,160, 4, 4, 0,161, 4, 4, 0,162, 4, 4, 0,163, 4, 4, 0,164, 4, 4, 0,165, 4, 4, 0,166, 4, + 4, 0,167, 4, 4, 0,168, 4, 4, 0, 37, 0, 0, 0,169, 4,178, 0, 5, 0, 9, 0,170, 4, 9, 0,171, 4, 4, 0,172, 4, + 4, 0, 70, 0, 0, 0,173, 4,179, 0, 15, 0, 4, 0, 17, 0, 4, 0,174, 4, 4, 0,175, 4, 4, 0,176, 4, 4, 0,177, 4, + 4, 0,178, 4, 7, 0,179, 4, 4, 0,180, 4, 4, 0, 90, 0, 4, 0,181, 4, 4, 0,182, 4, 4, 0,183, 4, 4, 0,184, 4, + 4, 0,185, 4, 26, 0, 30, 0,180, 0, 7, 0, 4, 0,186, 4, 7, 0,187, 4, 7, 0,188, 4, 7, 0,189, 4, 4, 0,190, 4, + 2, 0, 19, 0, 2, 0, 37, 0,181, 0, 11, 0,181, 0, 0, 0,181, 0, 1, 0, 0, 0, 20, 0, 67, 0,191, 4, 68, 0,192, 4, + 4, 0,105, 3, 4, 0,193, 4, 4, 0,194, 4, 4, 0, 37, 0, 4, 0,195, 4, 4, 0,196, 4,182, 0,131, 0,177, 0,197, 4, +178, 0,198, 4,179, 0,199, 4, 4, 0, 15, 3, 4, 0,126, 0, 4, 0, 28, 4, 4, 0,200, 4, 4, 0,201, 4, 4, 0,202, 4, + 4, 0,203, 4, 2, 0, 19, 0, 2, 0,204, 4, 7, 0,100, 2, 7, 0,205, 4, 7, 0,206, 4, 7, 0,207, 4, 7, 0,208, 4, + 7, 0,209, 4, 2, 0,210, 4, 2, 0,211, 4, 2, 0,212, 4, 2, 0,213, 4, 2, 0,246, 0, 2, 0,214, 4, 2, 0,215, 4, + 2, 0,216, 4, 2, 0,217, 4, 2, 0,218, 4, 2, 0, 90, 1, 2, 0,106, 0, 2, 0,219, 4, 2, 0,220, 4, 2, 0,221, 4, + 2, 0,222, 4, 2, 0,223, 4, 2, 0,224, 4, 2, 0,225, 4, 2, 0,226, 4, 2, 0,227, 4, 2, 0, 91, 1, 2, 0,228, 4, + 2, 0,229, 4, 2, 0,230, 4, 2, 0,231, 4, 4, 0,232, 4, 4, 0, 70, 1, 2, 0,233, 4, 2, 0,234, 4, 2, 0,235, 4, + 2, 0,236, 4, 2, 0,237, 4, 2, 0,238, 4, 24, 0,239, 4, 24, 0,240, 4, 23, 0,241, 4, 12, 0,242, 4, 2, 0,243, 4, + 2, 0, 37, 0, 7, 0,244, 4, 7, 0,245, 4, 7, 0,246, 4, 7, 0,247, 4, 4, 0,248, 4, 7, 0,249, 4, 7, 0,250, 4, + 7, 0,251, 4, 7, 0,252, 4, 2, 0,253, 4, 2, 0,254, 4, 2, 0,255, 4, 2, 0, 0, 5, 2, 0, 1, 5, 2, 0, 2, 5, + 7, 0, 3, 5, 7, 0, 4, 5, 7, 0, 5, 5, 2, 0, 6, 5, 2, 0, 7, 5, 2, 0, 8, 5, 2, 0, 9, 5, 2, 0, 10, 5, + 2, 0, 11, 5, 2, 0, 12, 5, 2, 0, 13, 5, 2, 0, 14, 5, 2, 0, 15, 5, 4, 0, 16, 5, 4, 0, 17, 5, 4, 0, 18, 5, + 4, 0, 19, 5, 4, 0, 20, 5, 7, 0, 21, 5, 4, 0, 22, 5, 4, 0, 23, 5, 4, 0, 24, 5, 4, 0, 25, 5, 7, 0, 26, 5, + 7, 0, 27, 5, 7, 0, 28, 5, 7, 0, 29, 5, 7, 0, 30, 5, 7, 0, 31, 5, 7, 0, 32, 5, 7, 0, 33, 5, 7, 0, 34, 5, + 0, 0, 35, 5, 0, 0, 36, 5, 4, 0, 37, 5, 2, 0, 38, 5, 2, 0,237, 1, 0, 0, 39, 5, 7, 0, 40, 5, 7, 0, 41, 5, + 4, 0, 42, 5, 4, 0, 43, 5, 7, 0, 44, 5, 7, 0, 45, 5, 2, 0, 46, 5, 2, 0, 47, 5, 7, 0, 48, 5, 2, 0, 49, 5, + 2, 0, 50, 5, 4, 0, 51, 5, 2, 0, 52, 5, 2, 0, 53, 5, 2, 0, 54, 5, 2, 0, 55, 5, 7, 0, 56, 5, 7, 0, 70, 0, + 42, 0, 57, 5, 0, 0, 58, 5,183, 0, 9, 0,183, 0, 0, 0,183, 0, 1, 0, 0, 0, 20, 0, 2, 0, 59, 5, 2, 0, 60, 5, + 2, 0, 61, 5, 2, 0, 43, 0, 7, 0, 62, 5, 7, 0, 70, 0,184, 0, 7, 0, 2, 0,208, 2, 2, 0, 70, 1, 2, 0,109, 0, + 2, 0, 63, 5, 7, 0, 64, 5, 7, 0, 70, 0, 42, 0, 65, 5,185, 0, 5, 0, 7, 0, 66, 5, 0, 0, 17, 0, 0, 0, 43, 0, + 0, 0, 70, 0, 0, 0,237, 1,186, 0, 26, 0, 7, 0,113, 4, 7, 0,114, 4, 2, 0, 70, 1, 2, 0, 19, 0, 2, 0, 67, 5, + 2, 0,135, 1, 2, 0,116, 4, 2, 0,117, 4, 2, 0,118, 4, 2, 0,119, 4, 2, 0,120, 4, 2, 0,121, 4,185, 0, 68, 5, + 2, 0,210, 4, 2, 0,211, 4, 2, 0,212, 4, 2, 0,213, 4, 2, 0,246, 0, 2, 0,214, 4, 2, 0,215, 4, 2, 0,216, 4, +184, 0, 69, 5, 2, 0, 70, 5, 2, 0,217, 4, 2, 0,220, 4, 2, 0,221, 4,187, 0, 5, 0,187, 0, 0, 0,187, 0, 1, 0, + 4, 0,215, 3, 0, 0,227, 3, 4, 0, 19, 0,188, 0, 6, 0,189, 0, 71, 5, 4, 0, 72, 5, 4, 0, 73, 5, 9, 0, 74, 5, + 0, 0, 75, 5, 4, 0, 37, 0,190, 0, 6, 0,188, 0, 76, 5, 2, 0, 19, 0, 2, 0, 77, 5, 2, 0, 78, 5, 2, 0, 79, 5, + 9, 0, 80, 5,191, 0, 4, 0, 2, 0,106, 0, 2, 0,219, 2, 2, 0,221, 3, 2, 0, 81, 5,192, 0, 14, 0, 2, 0, 19, 0, + 2, 0, 82, 5, 2, 0, 83, 5, 2, 0, 84, 5,191, 0, 85, 5, 9, 0, 80, 5, 7, 0, 86, 5, 7, 0, 57, 0, 4, 0, 87, 5, + 4, 0, 88, 5, 4, 0, 89, 5, 4, 0, 90, 5, 46, 0,134, 0, 32, 0,164, 0,193, 0, 4, 0,193, 0, 0, 0,193, 0, 1, 0, + 0, 0, 91, 5, 7, 0, 92, 5,194, 0, 6, 0,188, 0, 76, 5, 7, 0, 93, 5, 4, 0, 90, 0, 0, 0, 94, 5, 0, 0, 95, 5, + 0, 0,188, 2,195, 0, 9, 0,188, 0, 76, 5, 7, 0, 96, 5, 7, 0, 97, 5, 2, 0, 70, 1, 2, 0, 19, 0, 4, 0, 36, 0, + 4, 0, 98, 5, 87, 0, 99, 5, 9, 0, 80, 5,196, 0, 72, 0,195, 0,100, 5,195, 0,101, 5,194, 0, 78, 3, 7, 0,102, 5, + 2, 0,103, 5, 2, 0,104, 5, 7, 0,105, 5, 7, 0,106, 5, 2, 0,221, 3, 2, 0,107, 5, 7, 0,108, 5, 7, 0,109, 5, + 7, 0,110, 5, 2, 0,111, 5, 2, 0, 87, 5, 2, 0,112, 5, 2, 0,113, 5, 2, 0,114, 5, 2, 0,115, 5, 7, 0,116, 5, + 7, 0,117, 5, 7, 0,118, 5, 2, 0,119, 5, 2, 0,120, 5, 2, 0,121, 5, 2, 0,122, 5, 2, 0,123, 5, 2, 0,124, 5, + 2, 0,125, 5,190, 0,126, 5,192, 0,127, 5, 7, 0,128, 5, 7, 0,129, 5, 7, 0,130, 5, 2, 0,131, 5, 2, 0,132, 5, + 0, 0,133, 5, 0, 0,134, 5, 0, 0,135, 5, 0, 0,136, 5, 0, 0,137, 5, 0, 0,138, 5, 2, 0,139, 5, 7, 0,140, 5, + 7, 0,141, 5, 7, 0,142, 5, 7, 0,143, 5, 7, 0,144, 5, 7, 0,145, 5, 7, 0,146, 5, 7, 0,147, 5, 7, 0,148, 5, + 7, 0,149, 5, 2, 0,150, 5, 0, 0,151, 5, 0, 0,152, 5, 0, 0,153, 5, 0, 0,154, 5, 32, 0,155, 5, 0, 0,156, 5, + 0, 0,157, 5, 0, 0,158, 5, 0, 0,159, 5, 0, 0,160, 5, 0, 0,161, 5, 0, 0,162, 5, 0, 0,163, 5, 2, 0,164, 5, + 2, 0,165, 5, 2, 0,166, 5, 2, 0,167, 5, 2, 0,168, 5,197, 0, 8, 0, 4, 0,169, 5, 4, 0,170, 5, 4, 0,171, 5, + 4, 0,172, 5, 4, 0,173, 5, 4, 0,174, 5, 4, 0, 54, 0, 4, 0,124, 2,198, 0, 3, 0, 7, 0,175, 5, 2, 0,176, 5, + 2, 0, 19, 0,199, 0, 2, 0, 7, 0,177, 5, 4, 0, 19, 0, 46, 0, 38, 0, 27, 0, 31, 0, 39, 0, 75, 0, 32, 0,178, 5, +175, 0,179, 5, 46, 0,180, 5, 47, 0,238, 0, 12, 0,181, 5,176, 0,182, 5, 32, 0,183, 5, 7, 0,184, 5, 7, 0,185, 5, + 7, 0,186, 5, 7, 0,187, 5, 4, 0,105, 3, 2, 0, 19, 0, 2, 0, 64, 1, 61, 0, 59, 1,200, 0,188, 5,196, 0,189, 5, +201, 0,190, 5,182, 0,182, 0,180, 0,191, 5, 12, 0,100, 0, 12, 0,192, 5, 12, 0,193, 5,202, 0,194, 5, 2, 0,195, 5, + 2, 0,196, 5, 2, 0,247, 0, 2, 0,197, 5, 4, 0,198, 5, 4, 0,199, 5, 12, 0,200, 5,185, 0, 68, 5,186, 0,201, 5, +198, 0,202, 5,161, 0, 91, 3,199, 0,203, 5,203, 0, 6, 0, 47, 0,238, 0, 45, 0, 58, 1, 7, 0, 88, 2, 7, 0, 89, 2, + 7, 0,106, 0, 7, 0,204, 5,204, 0, 35, 0, 7, 0,205, 5, 7, 0,206, 5, 7, 0,207, 5, 7, 0,208, 5, 7, 0,209, 5, + 7, 0,210, 5, 7, 0,211, 5, 7, 0,212, 5, 7, 0,213, 5, 7, 0, 77, 1, 7, 0,214, 5, 7, 0,215, 5, 7, 0,216, 5, + 7, 0,217, 5, 7, 0,171, 0, 2, 0,218, 5, 2, 0,219, 5, 2, 0, 69, 2, 2, 0,220, 5, 2, 0,221, 5, 2, 0,222, 5, + 2, 0,223, 5, 7, 0,224, 5, 72, 0,225, 5,161, 0, 91, 3,204, 0,226, 5,205, 0,227, 5,206, 0,228, 5,207, 0,229, 5, +208, 0,230, 5,209, 0,231, 5, 7, 0,232, 5, 2, 0,233, 5, 2, 0,234, 5, 4, 0,237, 1,210, 0, 54, 0,211, 0, 0, 0, +211, 0, 1, 0, 12, 0,235, 5, 4, 0,236, 5, 7, 0,237, 5, 2, 0,238, 5, 7, 0,213, 5, 7, 0, 77, 1, 7, 0, 43, 0, + 4, 0,239, 5, 2, 0,222, 5, 2, 0,223, 5, 32, 0,178, 5, 32, 0,240, 5,203, 0,241, 5,210, 0,226, 5, 0, 0,242, 5, + 4, 0,105, 3, 4, 0,243, 5, 2, 0,244, 5, 2, 0, 70, 0, 2, 0,245, 5, 2, 0,246, 5, 2, 0,237, 1, 2, 0, 19, 0, + 2, 0, 27, 2, 2, 0,247, 5, 7, 0,112, 0, 7, 0,248, 5, 7, 0,249, 5, 7, 0,250, 5, 7, 0,251, 5, 7, 0,252, 5, + 7, 0,171, 0, 7, 0,184, 5, 2, 0,253, 5, 2, 0,120, 1, 2, 0,254, 5, 2, 0,255, 5, 2, 0, 0, 6, 2, 0, 1, 6, + 2, 0, 2, 6, 2, 0, 3, 6, 2, 0, 4, 6, 2, 0, 5, 6, 4, 0, 6, 6, 12, 0, 7, 6, 2, 0, 8, 6, 2, 0,137, 2, + 2, 0, 9, 6, 0, 0, 10, 6, 0, 0, 11, 6, 9, 0, 12, 6,161, 0, 91, 3,212, 0, 25, 0, 24, 0, 36, 0, 24, 0, 64, 0, + 23, 0, 13, 6, 23, 0, 14, 6, 23, 0, 15, 6, 7, 0, 16, 6, 7, 0, 17, 6, 7, 0, 18, 6, 7, 0, 19, 6, 2, 0, 20, 6, + 2, 0, 21, 6, 2, 0, 22, 6, 2, 0, 23, 6, 2, 0, 24, 6, 2, 0, 19, 0, 2, 0, 25, 6, 2, 0, 26, 6, 2, 0, 27, 6, + 2, 0, 28, 6, 2, 0, 29, 6, 2, 0,246, 5, 7, 0, 30, 6, 7, 0, 31, 6, 4, 0, 32, 6, 4, 0, 33, 6,211, 0, 6, 0, +211, 0, 0, 0,211, 0, 1, 0, 12, 0,235, 5, 4, 0,236, 5, 7, 0,237, 5, 2, 0,238, 5,213, 0, 8, 0,211, 0, 0, 0, +211, 0, 1, 0, 12, 0,235, 5, 4, 0,236, 5, 7, 0,237, 5, 2, 0,238, 5,214, 0, 34, 6, 46, 0,134, 0,215, 0, 14, 0, +211, 0, 0, 0,211, 0, 1, 0, 12, 0,235, 5, 4, 0,236, 5, 7, 0,237, 5, 2, 0,238, 5,212, 0, 35, 6,216, 0, 36, 6, + 12, 0, 37, 6, 2, 0, 70, 1, 2, 0, 19, 0, 2, 0, 38, 6, 0, 0, 39, 6, 0, 0, 40, 6,217, 0, 20, 0,211, 0, 0, 0, +211, 0, 1, 0, 12, 0,235, 5, 4, 0,236, 5, 7, 0,237, 5, 2, 0,238, 5,205, 0,227, 5,212, 0, 35, 6, 2, 0, 41, 6, + 2, 0, 42, 6, 2, 0, 43, 6, 2, 0, 44, 6, 2, 0, 25, 6, 2, 0, 45, 6, 0, 0, 19, 0, 0, 0,135, 1, 9, 0, 64, 2, + 4, 0, 46, 6, 4, 0, 47, 6, 27, 0, 48, 6,218, 0, 16, 0,211, 0, 0, 0,211, 0, 1, 0, 12, 0,235, 5, 4, 0,236, 5, + 7, 0,237, 5, 2, 0,238, 5,212, 0, 35, 6, 7, 0, 88, 2, 7, 0, 89, 2, 2, 0, 41, 6, 2, 0, 49, 6, 2, 0, 50, 6, + 2, 0, 51, 6, 4, 0, 19, 0, 7, 0, 52, 6,161, 0, 91, 3,219, 0, 16, 0, 0, 0, 53, 6, 0, 0, 54, 6, 0, 0, 55, 6, + 0, 0, 56, 6, 2, 0, 17, 0, 2, 0, 19, 0, 2, 0, 57, 6, 2, 0, 58, 6, 2, 0,180, 1, 2, 0, 59, 6, 4, 0, 60, 6, + 4, 0, 61, 6, 2, 0, 62, 6, 2, 0, 63, 6, 0, 0, 64, 6, 0, 0, 65, 6,220, 0, 16, 0,211, 0, 0, 0,211, 0, 1, 0, + 12, 0,235, 5, 4, 0,236, 5, 4, 0, 37, 0,219, 0, 66, 6,221, 0, 67, 6, 12, 0, 68, 6, 12, 0, 69, 6,222, 0, 70, 6, +209, 0, 71, 6,223, 0, 72, 6, 2, 0, 73, 6, 2, 0, 74, 6, 2, 0, 75, 6, 2, 0, 70, 0,224, 0, 17, 0,211, 0, 0, 0, +211, 0, 1, 0, 12, 0,235, 5, 4, 0,236, 5, 7, 0,237, 5, 2, 0,238, 5,212, 0, 35, 6, 12, 0, 76, 6,225, 0, 77, 6, + 0, 0, 78, 6,226, 0, 79, 6, 4, 0, 80, 6, 4, 0, 81, 6, 2, 0, 19, 0, 2, 0, 82, 6, 2, 0, 83, 6, 2, 0, 37, 0, +227, 0, 29, 0,211, 0, 0, 0,211, 0, 1, 0, 12, 0,235, 5, 4, 0,236, 5, 7, 0,237, 5, 2, 0,238, 5, 47, 0,227, 2, + 45, 0, 58, 1, 64, 0, 84, 6, 2, 0,133, 0, 2, 0, 85, 6, 2, 0, 70, 0, 2, 0, 86, 6, 4, 0, 19, 0, 2, 0, 87, 6, + 2, 0, 40, 6, 2, 0, 39, 6, 2, 0,237, 1, 0, 0, 88, 6, 0, 0, 89, 6, 0, 0, 90, 6, 0, 0,246, 5, 7, 0, 88, 2, + 7, 0, 89, 2, 7, 0, 52, 6, 7, 0,120, 1, 7, 0, 91, 6, 7, 0, 92, 6,161, 0, 91, 3,228, 0, 11, 0,211, 0, 0, 0, +211, 0, 1, 0, 12, 0,235, 5, 4, 0,236, 5, 7, 0,237, 5, 2, 0,238, 5, 2, 0, 38, 6, 2, 0, 19, 0, 4, 0, 37, 0, +216, 0, 36, 6,212, 0, 35, 6,229, 0, 27, 0,211, 0, 0, 0,211, 0, 1, 0, 12, 0,235, 5, 4, 0,236, 5, 7, 0,237, 5, + 2, 0,238, 5, 42, 0, 93, 6, 4, 0, 94, 6, 4, 0, 95, 6, 2, 0, 90, 0, 2, 0,133, 0, 2, 0, 96, 6, 0, 0, 97, 6, + 0, 0, 98, 6, 4, 0, 99, 6, 4, 0,100, 6, 4, 0,101, 6, 4, 0,102, 6, 2, 0,103, 6, 2, 0,104, 6, 7, 0,105, 6, + 23, 0,106, 6, 23, 0,107, 6, 4, 0,108, 6, 4, 0,109, 6, 0, 0,110, 6, 0, 0,111, 6,230, 0, 10, 0, 27, 0, 31, 0, + 9, 0,112, 6, 9, 0,113, 6, 9, 0,114, 6, 9, 0,115, 6, 9, 0,116, 6, 4, 0, 90, 0, 4, 0,117, 6, 0, 0,118, 6, + 0, 0,119, 6,231, 0, 10, 0,211, 0, 0, 0,211, 0, 1, 0, 12, 0,235, 5, 4, 0,236, 5, 7, 0,237, 5,230, 0,120, 6, + 2, 0, 90, 0, 2, 0,133, 0, 4, 0, 43, 0, 9, 0,121, 6,232, 0, 8, 0,211, 0, 0, 0,211, 0, 1, 0, 12, 0,235, 5, + 4, 0,236, 5, 7, 0,237, 5,212, 0, 35, 6, 4, 0, 19, 0, 4, 0,122, 6,233, 0, 23, 0,211, 0, 0, 0,211, 0, 1, 0, + 12, 0,235, 5, 4, 0,236, 5, 7, 0,237, 5, 2, 0,238, 5,212, 0, 35, 6, 27, 0,123, 6, 27, 0, 81, 0, 2, 0, 19, 0, + 2, 0,133, 0, 7, 0,124, 6, 9, 0,125, 6, 7, 0, 88, 2, 7, 0, 89, 2, 7, 0,126, 6, 7, 0,127, 6, 61, 0, 59, 1, + 61, 0,128, 6, 4, 0,129, 6, 2, 0,130, 6, 2, 0, 37, 0,161, 0, 91, 3,234, 0, 10, 0,211, 0, 0, 0,211, 0, 1, 0, + 12, 0,235, 5, 4, 0,236, 5, 7, 0,237, 5, 2, 0,238, 5, 2, 0, 19, 0, 2, 0,114, 3, 4, 0, 37, 0,161, 0, 91, 3, +235, 0, 42, 0,211, 0, 0, 0,211, 0, 1, 0, 12, 0,235, 5, 4, 0,236, 5, 7, 0,237, 5, 2, 0,238, 5,212, 0, 35, 6, +221, 0, 67, 6, 0, 0, 53, 6, 0, 0, 54, 6, 0, 0, 55, 6, 2, 0, 17, 0, 2, 0, 63, 6, 2, 0, 19, 0, 2, 0, 57, 6, + 9, 0,125, 6, 4, 0, 60, 6, 4, 0,131, 6, 4, 0,132, 6, 4, 0, 61, 6, 23, 0,133, 6, 23, 0,134, 6, 7, 0,135, 6, + 7, 0,136, 6, 7, 0,137, 6, 7, 0,124, 6, 2, 0,138, 6, 2, 0,237, 0, 2, 0,180, 1, 2, 0, 59, 6, 2, 0, 37, 0, + 2, 0, 43, 0, 2, 0,139, 6, 2, 0,140, 6, 9, 0,141, 6, 9, 0,142, 6, 9, 0,143, 6, 9, 0,144, 6, 9, 0,145, 6, + 2, 0,146, 6, 0, 0, 65, 6, 57, 0,147, 6,236, 0, 7, 0,236, 0, 0, 0,236, 0, 1, 0, 4, 0,148, 6, 4, 0, 23, 0, + 0, 0, 84, 0, 4, 0,149, 6, 4, 0, 17, 0,237, 0, 13, 0,211, 0, 0, 0,211, 0, 1, 0, 12, 0,235, 5, 4, 0,236, 5, + 7, 0,237, 5, 2, 0,238, 5, 4, 0, 17, 0, 4, 0,150, 6, 4, 0, 19, 0, 4, 0, 96, 6, 12, 0,151, 6, 12, 0,152, 6, + 0, 0,153, 6,238, 0, 5, 0,211, 0, 0, 0,211, 0, 1, 0, 12, 0,235, 5, 4, 0,236, 5, 4, 0, 37, 0,239, 0, 7, 0, +239, 0, 0, 0,239, 0, 1, 0, 0, 0,154, 6, 2, 0,155, 6, 2, 0,156, 6, 2, 0,157, 6, 2, 0, 37, 0,240, 0, 12, 0, + 2, 0,156, 6, 2, 0,158, 6, 2, 0,159, 6, 0, 0,188, 2, 2, 0,160, 6, 2, 0,161, 6, 2, 0,162, 6, 2, 0,163, 6, + 2, 0,164, 6, 2, 0, 25, 6, 7, 0,165, 6, 7, 0,166, 6,241, 0, 18, 0,241, 0, 0, 0,241, 0, 1, 0, 0, 0,227, 3, +240, 0,167, 6,240, 0,168, 6,240, 0,169, 6,240, 0,170, 6, 7, 0,171, 6, 2, 0,172, 6, 2, 0,173, 6, 2, 0,174, 6, + 2, 0,175, 6, 2, 0,176, 6, 2, 0,177, 6, 2, 0,178, 6, 2, 0,179, 6, 2, 0,180, 6, 2, 0,181, 6,242, 0, 10, 0, + 0, 0,182, 6, 0, 0,183, 6, 0, 0,184, 6, 0, 0,185, 6, 0, 0,186, 6, 0, 0,187, 6, 2, 0,188, 6, 2, 0,189, 6, + 2, 0,190, 6, 2, 0, 37, 0,243, 0, 8, 0, 0, 0,191, 6, 0, 0,192, 6, 0, 0,193, 6, 0, 0,194, 6, 0, 0,195, 6, + 0, 0,196, 6, 7, 0,204, 5, 7, 0, 37, 0,244, 0, 17, 0,242, 0,197, 6,242, 0,198, 6,242, 0,199, 6,242, 0,200, 6, +242, 0,201, 6,242, 0,202, 6,242, 0,203, 6,242, 0,204, 6,242, 0,205, 6,242, 0,206, 6,242, 0,207, 6,242, 0,208, 6, +242, 0,209, 6,242, 0,210, 6,242, 0,211, 6,243, 0,212, 6, 0, 0,213, 6,245, 0, 71, 0, 0, 0,214, 6, 0, 0,215, 6, + 0, 0,186, 6, 0, 0,216, 6, 0, 0,217, 6, 0, 0,218, 6, 0, 0,219, 6, 0, 0,220, 6, 0, 0,221, 6, 0, 0,222, 6, + 0, 0,223, 6, 0, 0,224, 6, 0, 0,225, 6, 0, 0,226, 6, 0, 0,227, 6, 0, 0,228, 6, 0, 0,229, 6, 0, 0,230, 6, + 0, 0,231, 6, 0, 0,232, 6, 0, 0,233, 6, 0, 0,234, 6, 0, 0,235, 6, 0, 0,236, 6, 0, 0,237, 6, 0, 0,238, 6, + 0, 0,239, 6, 0, 0,240, 6, 0, 0,241, 6, 0, 0,242, 6, 0, 0,243, 6, 0, 0,244, 6, 0, 0,245, 6, 0, 0,246, 6, + 0, 0,247, 6, 0, 0,248, 6, 0, 0,249, 6, 0, 0,250, 6, 0, 0,251, 6, 0, 0,252, 6, 0, 0,253, 6, 0, 0,254, 6, + 0, 0,255, 6, 0, 0, 0, 7, 0, 0, 1, 7, 0, 0, 2, 7, 0, 0, 3, 7, 0, 0, 4, 7, 0, 0, 5, 7, 0, 0, 6, 7, + 0, 0, 7, 7, 0, 0, 8, 7, 0, 0, 9, 7, 0, 0, 10, 7, 0, 0, 11, 7, 0, 0, 12, 7, 0, 0, 13, 7, 0, 0, 14, 7, + 0, 0, 15, 7, 0, 0, 16, 7, 0, 0, 17, 7, 0, 0, 18, 7, 0, 0, 19, 7, 0, 0, 20, 7, 0, 0, 21, 7, 0, 0, 22, 7, + 0, 0, 23, 7, 0, 0, 24, 7, 0, 0, 25, 7, 0, 0, 26, 7, 0, 0, 92, 0,246, 0, 5, 0, 0, 0, 27, 7, 0, 0,238, 6, + 0, 0,240, 6, 2, 0, 19, 0, 2, 0, 37, 0,247, 0, 22, 0,247, 0, 0, 0,247, 0, 1, 0, 0, 0, 20, 0,244, 0, 28, 7, +245, 0, 29, 7,245, 0, 30, 7,245, 0, 31, 7,245, 0, 32, 7,245, 0, 33, 7,245, 0, 34, 7,245, 0, 35, 7,245, 0, 36, 7, +245, 0, 37, 7,245, 0, 38, 7,245, 0, 39, 7,245, 0, 40, 7,245, 0, 41, 7,245, 0, 42, 7,245, 0, 43, 7,245, 0, 44, 7, +245, 0, 45, 7,246, 0, 46, 7,248, 0, 5, 0, 4, 0, 19, 0, 4, 0, 37, 0, 7, 0,136, 2, 7, 0, 47, 7, 7, 0, 42, 2, +249, 0, 71, 0, 4, 0, 19, 0, 4, 0, 48, 7, 4, 0, 49, 7, 0, 0, 50, 7, 0, 0, 51, 7, 0, 0, 52, 7, 0, 0, 53, 7, + 0, 0, 54, 7, 0, 0, 55, 7, 0, 0, 56, 7, 0, 0, 57, 7, 0, 0, 58, 7, 2, 0, 59, 7, 2, 0, 37, 0, 4, 0, 60, 7, + 4, 0, 61, 7, 4, 0, 62, 7, 4, 0, 63, 7, 2, 0, 64, 7, 2, 0, 65, 7, 4, 0, 66, 7, 4, 0, 67, 7, 4, 0, 68, 7, + 4, 0, 69, 7, 4, 0, 70, 7, 4, 0,151, 6, 4, 0, 71, 7, 2, 0, 72, 7, 2, 0, 73, 7, 2, 0, 74, 7, 2, 0, 75, 7, + 12, 0, 76, 7, 12, 0, 77, 7, 12, 0, 78, 7, 2, 0, 79, 7, 2, 0, 80, 7, 2, 0, 81, 7, 2, 0, 82, 7, 2, 0, 83, 7, + 2, 0, 84, 7, 2, 0, 85, 7, 2, 0, 86, 7,248, 0, 87, 7, 2, 0, 88, 7, 2, 0, 89, 7, 2, 0, 90, 7, 2, 0, 91, 7, + 2, 0, 92, 7, 2, 0, 93, 7, 2, 0, 94, 7, 2, 0, 95, 7, 4, 0, 96, 7, 4, 0, 97, 7, 2, 0, 98, 7, 2, 0, 99, 7, + 2, 0,100, 7, 2, 0,101, 7, 2, 0,102, 7, 2, 0,103, 7, 2, 0,104, 7, 2, 0,105, 7, 2, 0,106, 7, 2, 0,107, 7, + 2, 0,108, 7, 2, 0,109, 7, 0, 0,110, 7, 0, 0,111, 7, 7, 0,112, 7, 2, 0,131, 5, 2, 0,132, 5, 55, 0,113, 7, +214, 0, 21, 0, 27, 0, 31, 0, 12, 0,114, 7, 12, 0,115, 7, 12, 0,116, 7, 12, 0,235, 5, 46, 0,134, 0, 46, 0,117, 7, + 2, 0,118, 7, 2, 0,119, 7, 2, 0,120, 7, 2, 0,121, 7, 2, 0,122, 7, 2, 0,123, 7, 2, 0,124, 7, 2, 0, 37, 0, + 2, 0,125, 7, 2, 0,126, 7, 4, 0, 70, 0,209, 0,127, 7, 9, 0,128, 7, 2, 0,129, 7,250, 0, 5, 0,250, 0, 0, 0, +250, 0, 1, 0,250, 0,130, 7, 13, 0,131, 7, 4, 0, 19, 0,251, 0, 7, 0,251, 0, 0, 0,251, 0, 1, 0,250, 0,132, 7, +250, 0,133, 7, 2, 0,240, 4, 2, 0, 19, 0, 4, 0, 37, 0,252, 0, 23, 0,252, 0, 0, 0,252, 0, 1, 0,253, 0,134, 7, +254, 0, 72, 6, 0, 0,135, 7, 0, 0,136, 7, 0, 0,137, 7, 2, 0,138, 7, 2, 0,139, 7, 2, 0,140, 7, 2, 0,141, 7, + 2, 0,142, 7, 2, 0, 37, 0, 2, 0, 19, 0, 2, 0,143, 7, 2, 0,144, 7, 2, 0,145, 7, 4, 0,146, 7,252, 0,147, 7, + 9, 0,148, 7, 4, 0,149, 7, 4, 0,150, 7, 0, 0,151, 7,255, 0, 22, 0,255, 0, 0, 0,255, 0, 1, 0,250, 0,132, 7, +250, 0,133, 7,250, 0,152, 7,250, 0,153, 7,214, 0,154, 7, 23, 0, 52, 0, 0, 0,236, 5, 0, 0,155, 7, 2, 0, 26, 6, + 2, 0, 27, 6, 2, 0,156, 7, 2, 0, 37, 0, 2, 0,121, 7, 2, 0,149, 6, 2, 0, 19, 0, 0, 1,134, 7, 12, 0,157, 7, + 12, 0,235, 5, 12, 0,158, 7, 12, 0,159, 7, 1, 1, 21, 0, 1, 1, 0, 0, 1, 1, 1, 0,212, 0, 35, 6, 23, 0,160, 7, + 23, 0,161, 7, 2, 0, 26, 6, 2, 0, 27, 6, 2, 0,162, 7, 2, 0,163, 7, 2, 0,164, 7, 2, 0, 19, 0, 7, 0, 84, 2, + 2, 0,120, 7, 2, 0,124, 7, 4, 0, 43, 0, 2, 1,134, 7, 12, 0,165, 7, 12, 0,166, 7, 12, 0,158, 7, 0, 0,167, 7, + 9, 0,168, 7, 3, 1, 11, 0, 0, 0,169, 7, 2, 0,170, 7, 2, 0,171, 7, 2, 0,172, 7, 2, 0,173, 7, 2, 0,229, 4, + 2, 0,224, 4,214, 0,174, 7, 46, 0,175, 7, 4, 0,176, 7, 4, 0,177, 7, 4, 1, 1, 0, 0, 0,178, 7, 5, 1, 8, 0, + 57, 0,179, 7, 57, 0,180, 7, 5, 1,181, 7, 5, 1,182, 7, 5, 1,183, 7, 2, 0,129, 0, 2, 0, 19, 0, 4, 0,184, 7, + 6, 1, 4, 0, 4, 0, 94, 6, 4, 0,185, 7, 4, 0, 99, 6, 4, 0,186, 7, 7, 1, 2, 0, 4, 0,187, 7, 4, 0,188, 7, + 8, 1, 7, 0, 7, 0,189, 7, 7, 0,190, 7, 7, 0,191, 7, 4, 0, 19, 0, 4, 0, 37, 0, 7, 0,108, 4, 7, 0,192, 7, + 9, 1, 6, 0, 0, 0,193, 7, 0, 0, 55, 6, 49, 0,137, 0, 2, 0,106, 0, 2, 0,228, 4, 4, 0, 37, 0, 10, 1, 21, 0, + 10, 1, 0, 0, 10, 1, 1, 0, 4, 0, 57, 0, 4, 0, 23, 0, 4, 0, 28, 0, 4, 0,194, 7, 4, 0,195, 7, 4, 0,196, 7, + 4, 1,197, 7, 0, 0,193, 7, 4, 0,198, 7, 4, 0,199, 7, 9, 1, 85, 3, 6, 1,200, 7, 7, 1,201, 7, 8, 1,202, 7, + 5, 1,203, 7, 5, 1,204, 7, 5, 1,205, 7, 57, 0,206, 7, 57, 0,207, 7, 11, 1, 12, 0, 0, 0, 4, 2, 9, 0,223, 0, + 0, 0,224, 0, 4, 0,227, 0, 4, 0,235, 0, 9, 0,228, 0, 7, 0,230, 0, 7, 0,231, 0, 9, 0,208, 7, 9, 0,209, 7, + 9, 0,232, 0, 9, 0,234, 0, 12, 1, 43, 0, 12, 1, 0, 0, 12, 1, 1, 0, 9, 0,210, 7, 9, 0, 26, 0, 0, 0, 27, 0, + 4, 0, 19, 0, 4, 0, 17, 0, 4, 0, 23, 0, 4, 0, 88, 0, 4, 0,211, 7, 4, 0,212, 7, 4, 0,195, 7, 4, 0,196, 7, + 4, 0,213, 7, 4, 0,246, 0, 4, 0,214, 7, 4, 0,215, 7, 7, 0, 97, 5, 7, 0,216, 7, 4, 0,126, 0, 4, 0,217, 7, + 10, 1,218, 7, 36, 0, 80, 0, 46, 0,134, 0, 49, 0,137, 0, 7, 0,219, 7, 7, 0,220, 7, 11, 1, 60, 1, 12, 1,221, 7, + 12, 1,222, 7, 12, 1,223, 7, 12, 0,224, 7, 13, 1,225, 7, 14, 1,226, 7, 7, 0,227, 7, 7, 0,228, 7, 4, 0,229, 7, + 7, 0,230, 7, 9, 0,231, 7, 4, 0,232, 7, 4, 0,233, 7, 4, 0,234, 7, 7, 0,235, 7, 15, 1, 4, 0, 15, 1, 0, 0, + 15, 1, 1, 0, 12, 0,236, 7, 12, 1,237, 7,200, 0, 6, 0, 12, 0,238, 7, 12, 0,224, 7, 12, 0,239, 7, 12, 1,240, 7, + 0, 0,241, 7, 0, 0,242, 7, 16, 1, 4, 0, 7, 0,243, 7, 7, 0,109, 0, 2, 0,244, 7, 2, 0,245, 7, 17, 1, 6, 0, + 7, 0,246, 7, 7, 0,247, 7, 7, 0,248, 7, 7, 0,249, 7, 4, 0,250, 7, 4, 0,251, 7, 18, 1, 12, 0, 7, 0,252, 7, + 7, 0,253, 7, 7, 0,254, 7, 7, 0,255, 7, 7, 0, 0, 8, 7, 0, 1, 8, 7, 0, 2, 8, 7, 0, 3, 8, 7, 0, 4, 8, + 7, 0, 5, 8, 4, 0,231, 2, 4, 0, 6, 8, 19, 1, 2, 0, 7, 0, 66, 5, 7, 0, 37, 0, 20, 1, 5, 0, 7, 0, 7, 8, + 7, 0, 8, 8, 4, 0, 90, 0, 4, 0,189, 2, 4, 0, 9, 8, 21, 1, 6, 0, 21, 1, 0, 0, 21, 1, 1, 0, 2, 0, 17, 0, + 2, 0, 19, 0, 2, 0, 10, 8, 2, 0, 57, 0, 22, 1, 8, 0, 22, 1, 0, 0, 22, 1, 1, 0, 2, 0, 17, 0, 2, 0, 19, 0, + 2, 0, 10, 8, 2, 0, 57, 0, 7, 0, 23, 0, 7, 0,126, 0, 23, 1, 45, 0, 23, 1, 0, 0, 23, 1, 1, 0, 2, 0, 17, 0, + 2, 0, 19, 0, 2, 0, 10, 8, 2, 0,242, 0, 2, 0, 22, 4, 2, 0, 11, 8, 7, 0, 12, 8, 7, 0, 89, 0, 7, 0,244, 2, + 4, 0, 13, 8, 4, 0, 82, 0, 4, 0,191, 2, 7, 0, 14, 8, 7, 0, 15, 8, 7, 0, 16, 8, 7, 0, 17, 8, 7, 0, 18, 8, + 7, 0, 19, 8, 7, 0,241, 2, 7, 0, 57, 1, 7, 0, 20, 8, 7, 0, 21, 8, 7, 0, 37, 0, 7, 0, 22, 8, 7, 0, 23, 8, + 7, 0, 24, 8, 2, 0, 25, 8, 2, 0, 26, 8, 2, 0, 27, 8, 2, 0, 28, 8, 2, 0, 29, 8, 2, 0, 30, 8, 2, 0, 31, 8, + 2, 0, 32, 8, 2, 0, 27, 2, 2, 0, 33, 8, 2, 0, 24, 2, 2, 0, 34, 8, 0, 0, 35, 8, 0, 0, 36, 8, 7, 0,240, 0, + 24, 1, 37, 8, 68, 0,240, 1, 25, 1, 16, 0, 25, 1, 0, 0, 25, 1, 1, 0, 2, 0, 17, 0, 2, 0, 19, 0, 2, 0, 10, 8, + 2, 0,242, 0, 7, 0,236, 2, 7, 0,237, 2, 7, 0,238, 2, 7, 0, 73, 2, 7, 0,239, 2, 7, 0,240, 2, 7, 0, 38, 8, + 7, 0,241, 2, 7, 0,243, 2, 7, 0,244, 2,226, 0, 5, 0, 2, 0, 17, 0, 2, 0,184, 7, 2, 0, 19, 0, 2, 0, 39, 8, + 27, 0,123, 6,225, 0, 3, 0, 4, 0, 69, 0, 4, 0, 40, 8,226, 0, 2, 0, 26, 1, 7, 0, 26, 1, 0, 0, 26, 1, 1, 0, + 0, 0, 20, 0, 2, 0, 17, 0, 2, 0, 19, 0, 4, 0, 22, 0, 9, 0, 41, 8, 27, 1, 5, 0, 0, 0, 20, 0, 7, 0, 77, 1, + 7, 0, 42, 8, 4, 0, 43, 8, 4, 0, 37, 0, 28, 1, 4, 0, 2, 0, 17, 0, 2, 0, 19, 0, 2, 0, 43, 0, 2, 0, 70, 0, + 29, 1, 4, 0, 0, 0, 20, 0, 67, 0, 44, 8, 7, 0, 77, 1, 7, 0, 37, 0, 30, 1, 6, 0, 2, 0, 45, 8, 2, 0, 46, 8, + 2, 0, 17, 0, 2, 0, 47, 8, 0, 0, 48, 8, 0, 0, 49, 8, 31, 1, 5, 0, 4, 0, 17, 0, 4, 0, 37, 0, 0, 0, 20, 0, + 0, 0, 50, 8, 0, 0, 51, 8, 32, 1, 3, 0, 4, 0, 17, 0, 4, 0, 37, 0, 0, 0, 20, 0, 33, 1, 4, 0, 2, 0, 52, 8, + 2, 0, 53, 8, 2, 0, 19, 0, 2, 0, 37, 0, 34, 1, 6, 0, 0, 0, 20, 0, 0, 0, 54, 8, 2, 0, 55, 8, 2, 0,241, 2, + 2, 0, 70, 1, 2, 0, 70, 0, 35, 1, 5, 0, 0, 0, 20, 0, 7, 0,109, 0, 7, 0,110, 4, 2, 0, 19, 0, 2, 0,203, 2, + 36, 1, 3, 0, 0, 0, 20, 0, 4, 0,191, 2, 4, 0, 52, 8, 37, 1, 7, 0, 0, 0, 20, 0, 7, 0,110, 4, 0, 0, 56, 8, + 0, 0, 57, 8, 2, 0, 70, 1, 2, 0, 43, 0, 4, 0, 58, 8, 38, 1, 4, 0, 0, 0, 59, 8, 0, 0, 60, 8, 4, 0, 17, 0, + 7, 0,207, 2, 39, 1, 3, 0, 32, 0, 61, 8, 0, 0, 62, 8, 0, 0, 63, 8, 40, 1, 18, 0, 40, 1, 0, 0, 40, 1, 1, 0, + 2, 0, 17, 0, 2, 0, 64, 8, 2, 0, 19, 0, 2, 0, 65, 8, 2, 0, 66, 8, 2, 0, 67, 8, 2, 0, 43, 0, 2, 0, 70, 0, + 0, 0, 20, 0, 9, 0, 2, 0, 41, 1, 68, 8, 32, 0, 45, 0, 2, 0, 81, 5, 2, 0,227, 7, 2, 0, 69, 8, 2, 0, 37, 0, + 42, 1, 11, 0, 0, 0, 20, 0, 0, 0, 17, 0, 0, 0, 70, 8, 2, 0, 19, 0, 2, 0,203, 2, 2, 0, 71, 8, 4, 0, 72, 8, + 4, 0, 73, 8, 4, 0, 74, 8, 4, 0, 75, 8, 4, 0, 76, 8, 43, 1, 1, 0, 0, 0, 77, 8, 44, 1, 4, 0, 42, 0, 93, 6, + 0, 0, 78, 8, 4, 0, 70, 1, 4, 0, 19, 0, 41, 1, 18, 0, 41, 1, 0, 0, 41, 1, 1, 0, 41, 1, 79, 8, 2, 0, 17, 0, + 2, 0, 19, 0, 2, 0, 80, 8, 2, 0, 67, 8, 2, 0, 64, 8, 2, 0, 81, 8, 2, 0, 70, 0, 2, 0,237, 1, 0, 0, 20, 0, + 9, 0, 2, 0, 45, 1, 68, 8, 40, 1, 82, 8, 2, 0, 15, 0, 2, 0, 83, 8, 4, 0, 84, 8, 46, 1, 3, 0, 4, 0,217, 2, + 4, 0, 37, 0, 32, 0, 45, 0, 47, 1, 12, 0,159, 0, 85, 8, 2, 0, 17, 0, 2, 0, 19, 0, 4, 0, 12, 8, 4, 0, 89, 0, + 0, 0, 20, 0, 0, 0, 86, 8, 2, 0, 87, 8, 2, 0, 88, 8, 2, 0, 89, 8, 2, 0, 90, 8, 7, 0, 91, 8, 48, 1, 13, 0, + 2, 0, 19, 0, 2, 0, 92, 8, 4, 0, 12, 8, 4, 0, 89, 0, 2, 0, 93, 8, 7, 0,236, 3, 7, 0, 94, 8, 13, 1,225, 7, + 49, 1, 95, 8, 2, 0, 17, 0, 2, 0, 96, 8, 2, 0, 97, 8, 2, 0, 98, 8, 50, 1, 11, 0, 4, 0,217, 2, 2, 0, 17, 0, + 2, 0, 19, 0, 32, 0, 45, 0, 81, 0, 99, 8, 0, 0, 20, 0, 7, 0,100, 8, 7, 0,101, 8, 7, 0,122, 3, 2, 0,102, 8, + 2, 0,103, 8, 51, 1, 5, 0, 2, 0, 17, 0, 2, 0, 19, 0, 4, 0, 37, 0, 46, 0,134, 0, 32, 0,178, 5, 52, 1, 5, 0, + 4, 0, 19, 0, 4, 0, 17, 0, 0, 0, 20, 0, 0, 0, 50, 8, 32, 0, 45, 0, 53, 1, 13, 0, 2, 0, 19, 0, 2, 0, 17, 0, + 2, 0, 64, 8, 2, 0,123, 3, 7, 0,104, 8, 7, 0,105, 8, 7, 0, 65, 1, 7, 0, 66, 1, 7, 0, 98, 3, 7, 0,101, 3, + 7, 0,106, 8, 7, 0,107, 8, 32, 0,108, 8, 54, 1, 10, 0, 2, 0, 19, 0, 2, 0, 17, 0, 4, 0, 12, 8, 4, 0, 89, 0, + 0, 0, 20, 0, 0, 0, 86, 8, 2, 0, 43, 0, 2, 0, 64, 0, 2, 0,109, 8, 2, 0,110, 8, 55, 1, 8, 0, 32, 0, 45, 0, + 7, 0,238, 2, 7, 0,111, 8, 7, 0,112, 8, 7, 0,233, 2, 2, 0, 19, 0, 2, 0,203, 2, 7, 0,113, 8, 56, 1, 12, 0, + 2, 0, 17, 0, 2, 0, 70, 1, 2, 0, 19, 0, 2, 0,241, 2, 2, 0,217, 2, 2, 0,114, 8, 4, 0, 37, 0, 7, 0,115, 8, + 7, 0,116, 8, 7, 0,117, 8, 7, 0,118, 8, 0, 0,119, 8, 57, 1, 9, 0, 2, 0, 19, 0, 2, 0, 17, 0, 4, 0, 12, 8, + 4, 0, 89, 0, 0, 0, 20, 0, 2, 0,135, 1, 2, 0, 64, 0, 2, 0,109, 8, 2, 0,110, 8, 58, 1, 7, 0, 4, 0,191, 2, + 4, 0,120, 8, 4, 0,121, 8, 4, 0,122, 8, 7, 0,123, 8, 7, 0,124, 8, 0, 0, 56, 8, 59, 1, 7, 0, 0, 0,125, 8, + 32, 0,126, 8, 0, 0, 62, 8, 2, 0,127, 8, 2, 0, 43, 0, 4, 0, 70, 0, 0, 0, 63, 8, 60, 1, 6, 0, 2, 0, 19, 0, + 2, 0, 17, 0, 4, 0, 12, 8, 4, 0, 89, 0, 0, 0,128, 8, 0, 0,129, 8, 61, 1, 1, 0, 4, 0, 19, 0, 62, 1, 6, 0, + 0, 0, 92, 0, 2, 0, 17, 0, 2, 0, 19, 0, 4, 0,130, 8, 7, 0,131, 8, 42, 0, 93, 6, 63, 1, 4, 0, 0, 0, 69, 2, + 2, 0, 19, 0, 4, 0, 17, 0, 32, 0, 45, 0, 64, 1, 2, 0, 4, 0, 17, 0, 4, 0, 15, 6, 65, 1, 6, 0, 0, 0, 59, 8, + 0, 0, 60, 8, 4, 0, 17, 0, 7, 0, 35, 2, 32, 0, 48, 3, 32, 0,132, 8, 45, 1, 10, 0, 45, 1, 0, 0, 45, 1, 1, 0, + 45, 1, 79, 8, 2, 0, 17, 0, 2, 0, 19, 0, 2, 0, 64, 8, 2, 0,133, 8, 0, 0, 20, 0, 9, 0, 2, 0, 32, 0, 45, 0, + 66, 1, 10, 0, 7, 0,122, 3, 7, 0,134, 8, 7, 0,135, 8, 7, 0,136, 8, 7, 0,137, 8, 4, 0, 19, 0, 7, 0,114, 8, + 7, 0,138, 8, 7, 0,139, 8, 7, 0, 37, 0, 14, 1, 12, 0, 14, 1, 0, 0, 14, 1, 1, 0, 13, 1,140, 8, 9, 0,223, 0, + 4, 0,165, 3, 4, 0,223, 3, 4, 0,224, 3, 4, 0,141, 8, 4, 0,142, 8, 4, 0,143, 8, 7, 0,236, 3, 7, 0, 37, 0, + 49, 1, 8, 0, 7, 0,144, 8, 7, 0,145, 8, 7, 0,146, 8, 7, 0,147, 8, 7, 0,148, 8, 7, 0,149, 8, 7, 0,150, 8, + 7, 0,151, 8, 13, 1, 15, 0, 27, 0, 31, 0, 0, 0,222, 0, 43, 0,149, 0, 9, 0,223, 0, 43, 0,152, 8, 36, 0, 80, 0, + 7, 0,236, 3, 7, 0,153, 8, 7, 0, 94, 8, 7, 0,144, 8, 7, 0,145, 8, 7, 0,154, 8, 4, 0, 90, 0, 4, 0,143, 8, + 9, 0,155, 8, 67, 1, 15, 0,211, 0, 0, 0,211, 0, 1, 0, 12, 0,235, 5, 4, 0,236, 5, 7, 0,237, 5,255, 0,156, 8, +212, 0, 35, 6, 13, 1,225, 7, 2, 0, 70, 1, 2, 0, 92, 8, 2, 0, 88, 2, 2, 0, 89, 2, 2, 0, 19, 0, 2, 0, 40, 6, + 4, 0, 70, 0, 68, 1, 6, 0, 68, 1, 0, 0, 68, 1, 1, 0, 32, 0, 45, 0, 9, 0,157, 8, 4, 0,247, 0, 4, 0, 37, 0, + 68, 0, 4, 0, 27, 0, 31, 0, 12, 0,158, 8, 4, 0,131, 0, 7, 0,159, 8, 69, 1, 25, 0, 69, 1, 0, 0, 69, 1, 1, 0, + 69, 1, 38, 0, 12, 0,160, 8, 0, 0, 20, 0, 7, 0,161, 8, 7, 0,162, 8, 7, 0,163, 8, 7, 0,164, 8, 4, 0, 19, 0, + 7, 0,165, 8, 7, 0,166, 8, 7, 0,167, 8, 7, 0, 77, 1, 7, 0, 35, 2, 7, 0,168, 8, 7, 0,189, 2, 7, 0,169, 8, + 7, 0,170, 8, 7, 0,171, 8, 7, 0,172, 8, 7, 0,173, 8, 7, 0,172, 0, 2, 0,131, 0, 2, 0,112, 5, 70, 1, 22, 0, + 27, 0, 31, 0, 39, 0, 75, 0, 12, 0,174, 8, 12, 0,175, 8, 12, 0,176, 8, 9, 0,177, 8, 4, 0, 19, 0, 4, 0,244, 5, + 2, 0,245, 2, 2, 0, 46, 6, 2, 0,131, 0, 2, 0,178, 8, 2, 0,179, 8, 2, 0,180, 8, 2, 0,181, 8, 2, 0,182, 8, + 4, 0,183, 8, 4, 0,184, 8, 4, 0,185, 8, 4, 0,186, 8, 4, 0,187, 8, 4, 0,188, 8, 71, 1, 2, 0, 7, 0,150, 2, + 4, 0, 19, 0, 72, 1, 5, 0, 71, 1,189, 8, 4, 0,189, 2, 4, 0,190, 8, 4, 0,191, 8, 4, 0, 19, 0, 73, 1, 6, 0, + 4, 0, 37, 0, 4, 0, 46, 6, 4, 0,185, 8, 4, 0,186, 8, 4, 0,187, 8, 4, 0,188, 8, 74, 1, 40, 0, 74, 1, 0, 0, + 74, 1, 1, 0, 26, 0,192, 8, 12, 0,149, 3, 0, 0, 20, 0, 2, 0, 19, 0, 2, 0,193, 8, 2, 0,194, 8, 2, 0,195, 8, + 2, 0,108, 3, 2, 0,196, 8, 4, 0, 71, 2, 4, 0,185, 8, 4, 0,186, 8, 69, 1,197, 8, 74, 1, 38, 0, 74, 1,198, 8, + 12, 0,199, 8, 9, 0,200, 8, 9, 0,201, 8, 9, 0,202, 8, 7, 0, 65, 1, 7, 0,172, 0, 7, 0,203, 8, 7, 0, 14, 2, + 2, 0,131, 3, 2, 0, 37, 0, 7, 0,204, 8, 7, 0,205, 8, 7, 0,104, 3, 7, 0,206, 8, 7, 0,207, 8, 7, 0,208, 8, + 7, 0,209, 8, 7, 0,210, 8, 7, 0,211, 8, 7, 0,212, 8, 7, 0,213, 8, 7, 0, 64, 2, 32, 0,214, 8,160, 0, 11, 0, + 12, 0,215, 8, 2, 0, 19, 0, 2, 0,216, 8, 7, 0,100, 2, 7, 0,217, 8, 7, 0,218, 8, 12, 0,219, 8, 4, 0,220, 8, + 4, 0,221, 8, 9, 0,222, 8, 9, 0,223, 8, 75, 1, 1, 0, 4, 0,221, 8, 76, 1, 12, 0, 4, 0,221, 8, 7, 0, 76, 8, + 2, 0,224, 8, 2, 0,225, 8, 7, 0,226, 8, 7, 0,227, 8, 2, 0,228, 8, 2, 0, 19, 0, 7, 0,229, 8, 7, 0,230, 8, + 7, 0,231, 8, 7, 0,232, 8, 77, 1, 7, 0, 77, 1, 0, 0, 77, 1, 1, 0, 12, 0,233, 8, 4, 0, 19, 0, 4, 0,234, 8, + 0, 0,227, 3,246, 0,235, 8,159, 0, 7, 0, 27, 0, 31, 0, 12, 0,236, 8, 12, 0,215, 8, 12, 0,237, 8, 12, 0,100, 0, + 4, 0, 19, 0, 4, 0,238, 8,216, 0, 4, 0, 27, 0,140, 8, 12, 0,215, 8, 4, 0,239, 8, 4, 0, 19, 0, 78, 1, 17, 0, +211, 0, 0, 0,211, 0, 1, 0, 12, 0,235, 5, 4, 0,236, 5, 7, 0,237, 5, 2, 0,238, 5,212, 0, 35, 6,159, 0, 88, 3, +216, 0,240, 8, 0, 0, 70, 1, 0, 0, 38, 6, 2, 0, 19, 0, 2, 0,241, 8, 2, 0, 39, 6, 2, 0, 40, 6, 2, 0,242, 8, + 7, 0,243, 8, 79, 1, 8, 0, 79, 1, 0, 0, 79, 1, 1, 0, 77, 1,244, 8, 36, 0, 80, 0, 12, 0, 92, 3, 4, 0, 19, 0, + 0, 0, 20, 0, 4, 0,245, 8, 80, 1, 5, 0, 80, 1, 0, 0, 80, 1, 1, 0, 36, 0, 80, 0, 2, 0, 19, 0, 0, 0,246, 8, + 81, 1, 14, 0, 81, 1, 0, 0, 81, 1, 1, 0, 9, 0, 2, 0, 2, 0, 17, 0, 2, 0, 19, 0, 0, 0,247, 8, 0, 0,248, 8, + 0, 0,246, 8, 7, 0,249, 8, 7, 0,250, 8, 4, 0, 37, 0, 36, 0, 80, 0, 7, 0,251, 8, 7, 0,252, 8, 82, 1, 9, 0, + 82, 1, 0, 0, 82, 1, 1, 0, 32, 0,253, 8, 0, 0,248, 2, 7, 0,254, 8, 2, 0,255, 8, 2, 0, 19, 0, 2, 0, 17, 0, + 2, 0, 0, 9, 83, 1, 7, 0, 42, 0, 93, 6, 26, 0,192, 8, 4, 0, 19, 0, 4, 0, 1, 9, 12, 0, 2, 9, 32, 0,253, 8, + 0, 0,248, 2, 84, 1, 15, 0, 32, 0,253, 8, 2, 0, 3, 9, 2, 0, 19, 0, 2, 0, 4, 9, 2, 0, 5, 9, 0, 0,248, 2, + 32, 0, 6, 9, 0, 0, 7, 9, 7, 0, 8, 9, 7, 0, 35, 2, 7, 0, 9, 9, 7, 0, 10, 9, 2, 0, 17, 0, 2, 0, 70, 1, + 7, 0, 77, 1, 85, 1, 6, 0, 32, 0,253, 8, 4, 0, 11, 9, 4, 0, 12, 9, 4, 0, 90, 0, 4, 0, 37, 0, 0, 0,248, 2, + 86, 1, 4, 0, 32, 0,253, 8, 4, 0, 19, 0, 4, 0, 11, 9, 0, 0,248, 2, 87, 1, 4, 0, 32, 0,253, 8, 4, 0, 19, 0, + 4, 0, 11, 9, 0, 0,248, 2, 88, 1, 10, 0, 32, 0,253, 8, 4, 0, 13, 9, 7, 0,125, 0, 4, 0, 19, 0, 2, 0, 89, 6, + 2, 0, 14, 9, 2, 0, 43, 0, 2, 0, 70, 0, 7, 0, 15, 9, 0, 0,248, 2, 89, 1, 4, 0, 32, 0,253, 8, 4, 0, 19, 0, + 4, 0, 11, 9, 0, 0,248, 2, 90, 1, 10, 0, 32, 0,253, 8, 2, 0, 17, 0, 2, 0, 30, 4, 4, 0, 88, 0, 4, 0, 89, 0, + 7, 0,111, 8, 7, 0,112, 8, 4, 0, 37, 0,159, 0, 85, 8, 0, 0,248, 2, 91, 1, 4, 0, 32, 0,253, 8, 4, 0,109, 3, + 4, 0, 16, 9, 0, 0,248, 2, 92, 1, 5, 0, 32, 0,253, 8, 7, 0,125, 0, 4, 0, 17, 9, 4, 0,109, 3, 4, 0,110, 3, + 93, 1, 6, 0, 32, 0,253, 8, 4, 0, 18, 9, 4, 0, 19, 9, 7, 0, 20, 9, 7, 0, 21, 9, 0, 0,248, 2, 94, 1, 16, 0, + 32, 0,253, 8, 32, 0,198, 8, 4, 0, 17, 0, 7, 0, 22, 9, 7, 0, 23, 9, 7, 0, 24, 9, 7, 0, 25, 9, 7, 0, 26, 9, + 7, 0, 27, 9, 7, 0, 28, 9, 7, 0, 29, 9, 7, 0, 30, 9, 2, 0, 19, 0, 2, 0, 37, 0, 2, 0, 43, 0, 2, 0, 70, 0, + 95, 1, 3, 0, 32, 0,253, 8, 4, 0, 19, 0, 4, 0, 27, 2, 96, 1, 5, 0, 32, 0,253, 8, 4, 0, 19, 0, 4, 0, 37, 0, + 7, 0, 31, 9, 0, 0,248, 2, 97, 1, 10, 0, 32, 0,253, 8, 0, 0,248, 2, 2, 0, 32, 9, 2, 0, 33, 9, 0, 0, 34, 9, + 0, 0, 35, 9, 7, 0, 36, 9, 7, 0, 37, 9, 7, 0, 38, 9, 7, 0, 39, 9, 98, 1, 8, 0, 7, 0, 9, 0, 7, 0, 10, 0, + 7, 0, 11, 0, 7, 0, 12, 0, 7, 0, 40, 9, 7, 0, 41, 9, 2, 0, 19, 0, 2, 0, 27, 2, 99, 1, 8, 0, 7, 0, 9, 0, + 7, 0, 10, 0, 7, 0, 11, 0, 7, 0, 12, 0, 7, 0, 40, 9, 7, 0, 41, 9, 2, 0, 19, 0, 2, 0, 27, 2,100, 1, 8, 0, + 7, 0, 9, 0, 7, 0, 10, 0, 7, 0, 11, 0, 7, 0, 12, 0, 7, 0, 40, 9, 7, 0, 41, 9, 2, 0, 19, 0, 2, 0, 27, 2, +101, 1, 7, 0, 32, 0,253, 8, 0, 0,248, 2, 7, 0, 77, 1, 7, 0, 86, 1, 2, 0, 19, 0, 2, 0, 70, 1, 4, 0, 37, 0, +102, 1, 5, 0, 32, 0, 48, 3, 7, 0, 77, 1, 2, 0, 52, 3, 0, 0, 54, 3, 0, 0, 42, 9,103, 1, 10, 0,103, 1, 0, 0, +103, 1, 1, 0, 2, 0, 17, 0, 2, 0, 19, 0, 0, 0, 43, 9, 7, 0, 21, 1, 7, 0, 22, 1, 2, 0,233, 8, 2, 0, 44, 9, + 32, 0, 45, 0,104, 1, 22, 0,104, 1, 0, 0,104, 1, 1, 0, 2, 0, 19, 0, 2, 0, 70, 1, 2, 0, 45, 9, 2, 0, 46, 9, + 36, 0, 80, 0,159, 0, 85, 8, 32, 0,164, 0, 7, 0, 88, 0, 7, 0, 89, 0, 7, 0, 47, 9, 7, 0, 48, 9, 7, 0, 49, 9, + 7, 0, 50, 9, 7, 0,234, 2, 7, 0, 51, 9, 7, 0, 87, 8, 7, 0, 52, 9, 0, 0, 53, 9, 0, 0, 54, 9, 12, 0, 94, 3, +105, 1, 8, 0, 7, 0, 42, 2, 7, 0,111, 8, 7, 0,112, 8, 9, 0, 2, 0, 2, 0, 55, 9, 2, 0, 56, 9, 2, 0, 57, 9, + 2, 0, 58, 9,106, 1, 18, 0,106, 1, 0, 0,106, 1, 1, 0,106, 1, 59, 9, 0, 0, 20, 0,105, 1, 60, 9, 2, 0, 17, 0, + 2, 0, 19, 0, 2, 0, 61, 9, 2, 0, 62, 9, 2, 0, 63, 9, 2, 0, 64, 9, 4, 0, 43, 0, 7, 0, 65, 9, 7, 0, 66, 9, + 4, 0, 67, 9, 4, 0, 68, 9,106, 1, 69, 9,107, 1, 70, 9,108, 1, 34, 0,108, 1, 0, 0,108, 1, 1, 0,108, 1, 71, 9, + 0, 0, 20, 0, 0, 0, 72, 9, 2, 0, 17, 0, 2, 0, 19, 0, 2, 0,194, 7, 2, 0,227, 7, 2, 0, 73, 9, 2, 0,133, 0, + 2, 0, 62, 9, 2, 0,184, 7, 12, 0, 80, 8, 12, 0, 74, 9, 27, 0,123, 6, 9, 0, 75, 9, 7, 0, 65, 9, 7, 0, 66, 9, + 7, 0, 73, 2, 7, 0, 76, 9, 2, 0, 77, 9, 2, 0, 78, 9, 7, 0, 79, 9, 7, 0, 80, 9, 2, 0, 81, 9, 2, 0, 82, 9, + 9, 0, 83, 9, 24, 0, 84, 9, 24, 0, 85, 9, 24, 0, 86, 9,109, 1,150, 0,110, 1, 87, 9,111, 1, 88, 9,107, 1, 8, 0, +107, 1, 0, 0,107, 1, 1, 0,108, 1, 89, 9,108, 1, 90, 9,106, 1, 91, 9,106, 1, 69, 9, 4, 0, 19, 0, 4, 0, 37, 0, + 61, 0, 20, 0, 27, 0, 31, 0, 39, 0, 75, 0, 12, 0, 92, 9, 12, 0, 93, 9,105, 1, 94, 9, 12, 0, 95, 9, 4, 0, 17, 0, + 4, 0, 96, 9, 4, 0, 97, 9, 4, 0, 98, 9, 12, 0, 99, 9,111, 1,100, 9,106, 1,101, 9,106, 1,102, 9, 9, 0,103, 9, + 9, 0,104, 9, 4, 0,105, 9, 9, 0,106, 9, 9, 0,107, 9, 9, 0,108, 9,112, 1, 6, 0, 4, 0,124, 0, 4, 0,126, 0, + 4, 0,184, 7, 0, 0,109, 9, 0, 0,110, 9, 2, 0, 37, 0,113, 1, 16, 0, 2, 0,140, 7, 2, 0,141, 7, 2, 0,111, 9, + 2, 0,135, 8, 2, 0,112, 9, 2, 0, 68, 0, 7, 0,233, 2, 7, 0,113, 9, 7, 0,114, 9, 2, 0, 90, 1, 0, 0,115, 9, + 0, 0, 96, 5, 2, 0,116, 9, 2, 0, 37, 0, 4, 0,117, 9, 4, 0,118, 9,114, 1, 9, 0, 7, 0,119, 9, 7, 0,120, 9, + 7, 0,154, 8, 7, 0,109, 0, 7, 0,121, 9, 7, 0, 52, 6, 2, 0,122, 9, 0, 0,123, 9, 0, 0, 37, 0,115, 1, 4, 0, + 7, 0,124, 9, 7, 0,125, 9, 2, 0,122, 9, 2, 0, 37, 0,116, 1, 3, 0, 7, 0,126, 9, 7, 0,127, 9, 7, 0, 15, 0, +117, 1, 7, 0, 0, 0, 4, 2, 2, 0,226, 4, 2, 0,227, 4, 2, 0,228, 4, 2, 0,174, 4, 4, 0,126, 0, 4, 0, 28, 4, +118, 1, 7, 0, 7, 0,128, 9, 7, 0,129, 9, 7, 0,130, 9, 7, 0, 84, 2, 7, 0,131, 9, 7, 0,132, 9, 7, 0,133, 9, +119, 1, 4, 0, 2, 0,134, 9, 2, 0,135, 9, 2, 0,136, 9, 2, 0,137, 9,120, 1, 2, 0, 7, 0, 5, 0, 7, 0, 6, 0, +121, 1, 2, 0, 0, 0,166, 0, 0, 0,138, 9,122, 1, 1, 0, 0, 0, 20, 0,123, 1, 10, 0, 0, 0,139, 9, 0, 0,140, 9, + 0, 0, 45, 6, 0, 0,141, 9, 2, 0,111, 9, 2, 0,142, 9, 7, 0,143, 9, 7, 0,144, 9, 7, 0,145, 9, 7, 0, 51, 9, +124, 1, 2, 0, 9, 0,146, 9, 9, 0,147, 9,125, 1, 11, 0, 0, 0,228, 4, 0, 0, 17, 0, 0, 0,122, 9, 0, 0,109, 0, + 0, 0,148, 9, 0, 0,106, 0, 0, 0, 69, 2, 7, 0,149, 9, 7, 0,150, 9, 7, 0,151, 9, 7, 0,152, 9,126, 1, 8, 0, + 7, 0, 45, 8, 7, 0,125, 0, 7, 0, 96, 5, 7, 0,155, 2, 7, 0,153, 9, 7, 0,236, 0, 7, 0,154, 9, 4, 0, 17, 0, +127, 1, 4, 0, 2, 0,155, 9, 2, 0,156, 9, 2, 0,157, 9, 2, 0, 37, 0,128, 1, 1, 0, 0, 0, 20, 0,129, 1, 4, 0, + 7, 0, 5, 0, 7, 0, 6, 0, 2, 0, 19, 0, 2, 0,158, 9,130, 1, 10, 0, 2, 0,216, 3, 2, 0, 19, 0, 7, 0,110, 4, + 7, 0,159, 9, 7, 0,160, 9, 7, 0,161, 9, 7, 0,162, 9,129, 1,163, 9,129, 1,164, 9,129, 1,165, 9, 64, 0, 9, 0, + 4, 0, 19, 0, 4, 0, 64, 0, 24, 0,166, 9, 24, 0,167, 9,130, 1,168, 9, 7, 0,169, 9, 7, 0,170, 9, 7, 0,171, 9, + 7, 0,172, 9,131, 1, 4, 0, 47, 0,227, 2, 7, 0,173, 9, 7, 0,169, 1, 7, 0, 37, 0,189, 0, 17, 0, 27, 0, 31, 0, +131, 1,174, 9, 64, 0,163, 9, 51, 0,133, 1, 2, 0, 19, 0, 2, 0,204, 5, 4, 0,106, 0, 7, 0,175, 9, 7, 0, 81, 2, + 4, 0,176, 9, 7, 0,177, 9, 7, 0,178, 9, 7, 0,179, 9, 7, 0,169, 1, 2, 0,103, 1, 0, 0,180, 9, 0, 0,181, 6, +132, 1, 10, 0, 4, 0, 17, 0, 4, 0,125, 0, 4, 0, 19, 0, 4, 0,171, 3, 4, 0,181, 9, 4, 0,182, 9, 4, 0,183, 9, + 0, 0, 92, 0, 0, 0, 20, 0, 9, 0, 2, 0, 92, 0, 6, 0,132, 1,184, 9, 4, 0,185, 9, 4, 0,186, 9, 4, 0,187, 9, + 4, 0, 37, 0, 9, 0,188, 9,133, 1, 5, 0, 7, 0,150, 2, 7, 0,217, 2, 7, 0, 35, 2, 2, 0,189, 9, 2, 0, 37, 0, +134, 1, 5, 0, 7, 0,150, 2, 7, 0,190, 9, 7, 0,191, 9, 7, 0,192, 9, 7, 0,217, 2,135, 1, 5, 0, 32, 0,193, 9, +136, 1, 22, 0, 7, 0,177, 5, 7, 0,194, 9, 7, 0, 57, 0,137, 1, 7, 0, 4, 0,195, 9, 4, 0,196, 9, 4, 0,197, 9, + 7, 0,198, 9, 7, 0,199, 9, 7, 0,200, 9, 7, 0, 57, 0,138, 1, 8, 0,138, 1, 0, 0,138, 1, 1, 0, 32, 0, 45, 0, + 4, 0, 35, 3, 2, 0, 19, 0, 2, 0, 70, 1, 7, 0,217, 2, 7, 0, 53, 8,139, 1, 18, 0,134, 1,165, 3,134, 1,201, 9, +133, 1,202, 9,134, 1, 37, 8,135, 1,203, 9, 4, 0, 82, 0, 7, 0,217, 2, 7, 0,244, 2, 7, 0,204, 9, 4, 0,195, 9, + 4, 0,205, 9, 7, 0,199, 9, 7, 0,200, 9, 7, 0,106, 0, 2, 0, 19, 0, 2, 0,206, 9, 2, 0,207, 9, 2, 0,208, 9, +140, 1,107, 0, 27, 0, 31, 0, 39, 0, 75, 0,141, 1,209, 9,168, 0, 50, 4, 4, 0, 19, 0, 2, 0, 17, 0, 2, 0, 32, 9, + 2, 0,210, 9, 2, 0,211, 9, 2, 0,131, 3, 2, 0,212, 9, 2, 0,213, 9, 2, 0,214, 9, 2, 0,215, 9, 2, 0,216, 9, + 2, 0,217, 9, 2, 0,218, 9, 2, 0,216, 4, 2, 0, 89, 5, 2, 0,219, 9, 2, 0,220, 9, 2, 0,221, 9, 2, 0,222, 9, + 2, 0,223, 9, 2, 0, 24, 2, 2, 0, 30, 8, 2, 0, 6, 8, 2, 0,224, 9, 2, 0,225, 9, 2, 0,181, 3, 2, 0,182, 3, + 2, 0,226, 9, 2, 0,227, 9, 2, 0,228, 9, 2, 0,229, 9, 7, 0,230, 9, 7, 0,231, 9, 7, 0,232, 9, 2, 0,233, 9, + 2, 0,234, 9, 7, 0,235, 9, 7, 0,236, 9, 7, 0,237, 9, 7, 0, 12, 8, 7, 0, 89, 0, 7, 0,244, 2, 7, 0, 18, 8, + 7, 0,238, 9, 7, 0,239, 9, 7, 0,240, 9, 4, 0, 13, 8, 4, 0, 11, 8, 4, 0,241, 9, 7, 0, 14, 8, 7, 0, 15, 8, + 7, 0, 16, 8, 7, 0,242, 9, 7, 0,243, 9, 7, 0,244, 9, 7, 0,245, 9, 7, 0,246, 9, 7, 0,247, 9, 7, 0,248, 9, + 7, 0,249, 9, 7, 0,122, 3, 7, 0,106, 0, 7, 0,250, 9, 7, 0,251, 9, 7, 0,252, 9, 7, 0,253, 9, 7, 0,254, 9, + 7, 0,255, 9, 7, 0, 0, 10, 4, 0, 1, 10, 4, 0, 2, 10, 7, 0, 3, 10, 7, 0, 4, 10, 7, 0, 5, 10, 7, 0, 6, 10, + 7, 0, 7, 10, 7, 0,210, 0, 7, 0, 8, 10, 7, 0,207, 3, 7, 0,205, 3, 7, 0,206, 3, 7, 0, 9, 10, 7, 0, 10, 10, + 7, 0, 11, 10, 7, 0, 12, 10, 7, 0, 13, 10, 7, 0, 14, 10, 7, 0, 15, 10, 7, 0, 16, 10, 7, 0, 17, 10, 7, 0, 18, 10, + 7, 0, 19, 10, 7, 0, 20, 10, 7, 0, 21, 10, 4, 0, 22, 10, 4, 0, 23, 10, 68, 0,154, 3, 68, 0, 24, 10, 32, 0, 25, 10, + 32, 0, 26, 10, 36, 0, 80, 0,163, 0, 62, 1,163, 0, 27, 10, 59, 0, 44, 0, 59, 0, 0, 0, 59, 0, 1, 0,140, 1, 28, 10, +139, 1, 29, 10,137, 1,198, 8,170, 0,232, 3, 9, 0,233, 3,142, 1, 30, 10,142, 1, 31, 10, 12, 0, 32, 10, 12, 0, 33, 10, +134, 0, 34, 10,142, 0, 35, 10,142, 0, 36, 10, 32, 0, 37, 10, 32, 0, 38, 10, 32, 0, 38, 0, 12, 0, 2, 9, 0, 0, 20, 0, + 7, 0,240, 0, 7, 0, 15, 3, 7, 0, 39, 10, 4, 0,191, 2, 4, 0, 57, 0, 4, 0, 19, 0, 4, 0, 13, 8, 4, 0, 40, 10, + 4, 0, 41, 10, 4, 0, 42, 10, 2, 0,247, 0, 2, 0, 43, 10, 2, 0, 44, 10, 2, 0, 45, 10, 0, 0, 46, 10, 2, 0, 47, 10, + 2, 0, 48, 10, 2, 0, 49, 10, 9, 0, 50, 10,138, 0, 49, 4, 12, 0, 2, 3, 12, 0, 51, 10,143, 1, 52, 10,144, 1, 53, 10, + 7, 0, 54, 10,136, 0, 35, 0,145, 1,155, 8, 7, 0, 19, 4, 7, 0, 55, 10, 7, 0, 56, 10, 7, 0,113, 4, 7, 0, 57, 10, + 7, 0,132, 3, 7, 0,122, 3, 7, 0, 58, 10, 7, 0, 83, 2, 7, 0, 59, 10, 7, 0, 60, 10, 7, 0, 61, 10, 7, 0, 62, 10, + 7, 0, 63, 10, 7, 0, 64, 10, 7, 0, 20, 4, 7, 0, 65, 10, 7, 0, 66, 10, 7, 0, 67, 10, 7, 0, 21, 4, 7, 0, 17, 4, + 7, 0, 18, 4, 7, 0, 68, 10, 4, 0, 69, 10, 4, 0, 90, 0, 4, 0, 70, 10, 4, 0, 71, 10, 2, 0, 72, 10, 2, 0, 73, 10, + 2, 0, 74, 10, 2, 0, 75, 10, 2, 0, 76, 10, 2, 0, 37, 0,168, 0, 50, 4,137, 0, 8, 0,145, 1, 77, 10, 7, 0, 78, 10, + 7, 0, 79, 10, 7, 0,241, 1, 7, 0, 80, 10, 4, 0, 90, 0, 2, 0, 81, 10, 2, 0, 82, 10,146, 1, 4, 0, 7, 0, 5, 0, + 7, 0, 6, 0, 7, 0, 7, 0, 7, 0, 83, 10,147, 1, 6, 0,147, 1, 0, 0,147, 1, 1, 0,146, 1,189, 8, 4, 0,253, 0, + 2, 0, 84, 10, 2, 0, 19, 0,148, 1, 5, 0,148, 1, 0, 0,148, 1, 1, 0, 12, 0, 85, 10, 4, 0, 86, 10, 4, 0, 19, 0, +149, 1, 9, 0,149, 1, 0, 0,149, 1, 1, 0, 12, 0,124, 0,148, 1, 87, 10, 4, 0, 19, 0, 2, 0, 84, 10, 2, 0, 88, 10, + 7, 0, 91, 0, 0, 0, 89, 10,161, 0, 6, 0, 27, 0, 31, 0, 12, 0,242, 4, 4, 0, 19, 0, 2, 0, 90, 10, 2, 0, 91, 10, + 9, 0, 92, 10,150, 1, 7, 0,150, 1, 0, 0,150, 1, 1, 0, 2, 0, 17, 0, 2, 0, 19, 0, 4, 0, 23, 0, 0, 0, 93, 10, + 0, 0, 94, 10,151, 1, 5, 0, 12, 0, 95, 10, 4, 0, 96, 10, 4, 0, 97, 10, 4, 0, 19, 0, 4, 0, 37, 0,152, 1, 13, 0, + 27, 0, 31, 0,153, 1, 98, 10,153, 1, 99, 10, 12, 0,100, 10, 4, 0,101, 10, 2, 0,102, 10, 2, 0, 37, 0, 12, 0,103, 10, + 12, 0,104, 10,151, 1,105, 10, 12, 0,106, 10, 12, 0,107, 10, 12, 0,108, 10,153, 1, 31, 0,153, 1, 0, 0,153, 1, 1, 0, + 9, 0,109, 10, 4, 0,119, 7, 4, 0, 37, 0,214, 0, 34, 6,214, 0,110, 10, 0, 0,111, 10, 2, 0,112, 10, 2, 0,113, 10, + 2, 0,140, 7, 2, 0,141, 7, 2, 0,114, 10, 2, 0,115, 10, 2, 0,171, 3, 2, 0,149, 6, 2, 0,116, 10, 2, 0,117, 10, + 4, 0,237, 1,154, 1,118, 10,155, 1,119, 10,156, 1,120, 10, 4, 0,121, 10, 4, 0,122, 10, 9, 0,123, 10, 12, 0,124, 10, + 12, 0,104, 10, 12, 0,158, 7, 12, 0,125, 10, 12, 0,126, 10, 12, 0,127, 10,157, 1, 16, 0,157, 1, 0, 0,157, 1, 1, 0, + 0, 0,128, 10,158, 1,129, 10, 2, 0, 17, 0, 2, 0, 15, 0, 2, 0,130, 10, 2, 0,131, 10, 2, 0,132, 10, 2, 0,133, 10, + 2, 0,134, 10, 2, 0,135, 10, 2, 0,136, 10, 2, 0,137, 10, 2, 0, 70, 0, 2, 0,237, 1,159, 1, 10, 0,159, 1, 0, 0, +159, 1, 1, 0, 12, 0,138, 10, 0, 0,139, 10, 2, 0,140, 10, 2, 0,141, 10, 2, 0,142, 10, 2, 0, 37, 0, 9, 0,143, 10, + 4, 0,144, 10,222, 0, 12, 0,222, 0, 0, 0,222, 0, 1, 0, 0, 0,128, 10, 26, 0, 30, 0,160, 1,134, 7, 9, 0,145, 10, +158, 1,129, 10,151, 1,146, 10, 12, 0,147, 10,222, 0,148, 10, 2, 0, 19, 0, 2, 0,135, 1,154, 1, 23, 0,154, 1, 0, 0, +154, 1, 1, 0, 2, 0, 17, 0, 2, 0, 15, 0, 2, 0, 5, 0, 2, 0, 6, 0, 2, 0,149, 10, 2, 0,150, 10, 2, 0,151, 10, + 2, 0,152, 10, 0, 0,153, 10, 0, 0, 37, 0, 2, 0,130, 10, 2, 0,131, 10, 2, 0,132, 10, 2, 0,133, 10, 2, 0,134, 10, + 2, 0, 43, 0, 0, 0,154, 10, 2, 0,155, 10, 2, 0,156, 10, 4, 0, 70, 0, 9, 0,145, 10,161, 1, 8, 0,161, 1, 0, 0, +161, 1, 1, 0, 9, 0, 2, 0, 9, 0,157, 10, 0, 0,227, 3, 2, 0, 17, 0, 2, 0, 19, 0, 7, 0,158, 10,162, 1, 5, 0, + 7, 0,159, 10, 4, 0,160, 10, 4, 0,161, 10, 4, 0, 70, 1, 4, 0, 19, 0,163, 1, 6, 0, 7, 0,162, 10, 7, 0,163, 10, + 7, 0,164, 10, 7, 0,165, 10, 4, 0, 17, 0, 4, 0, 19, 0,164, 1, 5, 0, 7, 0,111, 8, 7, 0,112, 8, 7, 0,217, 2, + 2, 0, 38, 2, 2, 0, 39, 2,165, 1, 5, 0,164, 1, 2, 0, 4, 0, 54, 0, 7, 0,166, 10, 7, 0,111, 8, 7, 0,112, 8, +166, 1, 4, 0, 2, 0,167, 10, 2, 0,168, 10, 2, 0,169, 10, 2, 0,170, 10,167, 1, 2, 0, 42, 0,120, 6, 26, 0,192, 8, +168, 1, 3, 0, 24, 0,171, 10, 4, 0, 19, 0, 4, 0, 37, 0,169, 1, 6, 0, 7, 0,106, 0, 7, 0,219, 2, 7, 0,172, 10, + 7, 0, 37, 0, 2, 0,246, 0, 2, 0,173, 10,170, 1, 7, 0,170, 1, 0, 0,170, 1, 1, 0, 27, 0,123, 6, 0, 0,174, 10, + 4, 0,175, 10, 4, 0, 90, 0, 0, 0,227, 3,171, 1, 6, 0, 12, 0, 2, 9, 0, 0,176, 10, 7, 0, 61, 0, 7, 0,158, 10, + 4, 0, 17, 0, 4, 0, 19, 0,172, 1, 3, 0, 7, 0,177, 10, 4, 0, 19, 0, 4, 0, 37, 0,173, 1, 15, 0,173, 1, 0, 0, +173, 1, 1, 0, 77, 1,244, 8,171, 1, 62, 0, 12, 0, 94, 3, 35, 0, 50, 0,172, 1,178, 10, 4, 0, 54, 0, 7, 0, 61, 0, + 2, 0, 19, 0, 2, 0, 16, 1, 4, 0,175, 10, 0, 0,174, 10, 4, 0,179, 10, 7, 0,180, 10,174, 1, 2, 0, 0, 0,181, 10, + 0, 0,182, 10,175, 1, 4, 0,175, 1, 0, 0,175, 1, 1, 0,159, 0, 48, 3, 12, 0,183, 10,176, 1, 24, 0,176, 1, 0, 0, +176, 1, 1, 0, 12, 0,184, 10,159, 0, 85, 8,175, 1,185, 10, 12, 0,186, 10, 12, 0, 94, 3, 0, 0,227, 3, 7, 0,158, 10, + 7, 0,187, 10, 7, 0, 88, 0, 7, 0, 89, 0, 7, 0, 47, 9, 7, 0, 48, 9, 7, 0,234, 2, 7, 0, 51, 9, 7, 0, 87, 8, + 7, 0, 52, 9, 2, 0,188, 10, 2, 0,189, 10, 2, 0, 43, 0, 2, 0, 17, 0, 4, 0, 19, 0, 4, 0, 70, 0,177, 1, 6, 0, +177, 1, 0, 0,177, 1, 1, 0, 12, 0,184, 10, 4, 0, 19, 0, 4, 0,154, 2, 0, 0,227, 3,178, 1, 10, 0,178, 1, 0, 0, +178, 1, 1, 0, 27, 0,123, 6, 0, 0,190, 10, 4, 0,191, 10, 4, 0,192, 10, 0, 0,174, 10, 4, 0,175, 10, 2, 0, 19, 0, + 2, 0,193, 10,179, 1, 7, 0,179, 1, 0, 0,179, 1, 1, 0, 12, 0,194, 10, 0, 0,227, 3, 2, 0, 19, 0, 2, 0,195, 10, + 4, 0,196, 10,180, 1, 5, 0,180, 1, 0, 0,180, 1, 1, 0, 0, 0,174, 10, 4, 0,175, 10, 7, 0,207, 2, 39, 0, 12, 0, +159, 0, 88, 3,159, 0,197, 10,175, 1,185, 10, 12, 0,198, 10,176, 1,199, 10, 12, 0,200, 10, 12, 0,201, 10, 4, 0, 19, 0, + 4, 0,247, 0, 2, 0,202, 10, 2, 0,203, 10, 7, 0,204, 10,181, 1, 2, 0, 27, 0, 31, 0, 39, 0, 75, 0,182, 1, 5, 0, +182, 1, 0, 0,182, 1, 1, 0, 4, 0, 17, 0, 4, 0, 19, 0, 0, 0, 20, 0,183, 1, 6, 0,182, 1,205, 10, 32, 0, 45, 0, + 4, 0,206, 10, 7, 0,207, 10, 4, 0,208, 10, 4, 0,233, 8,184, 1, 3, 0,182, 1,205, 10, 4, 0,206, 10, 7, 0,209, 10, +185, 1, 8, 0,182, 1,205, 10, 32, 0, 45, 0, 7, 0, 65, 1, 7, 0,210, 10, 7, 0, 15, 3, 7, 0,154, 8, 4, 0,206, 10, + 4, 0,211, 10,186, 1, 5, 0,182, 1,205, 10, 7, 0,212, 10, 7, 0,227, 7, 7, 0,240, 2, 7, 0, 57, 0,187, 1, 3, 0, +182, 1,205, 10, 7, 0,154, 8, 7, 0,213, 10,136, 1, 4, 0, 7, 0,214, 10, 7, 0,252, 9, 2, 0,215, 10, 2, 0, 70, 1, +188, 1, 14, 0,188, 1, 0, 0,188, 1, 1, 0, 12, 0,216, 10, 12, 0,217, 10, 12, 0,218, 10, 0, 0, 20, 0, 4, 0, 31, 0, + 4, 0, 19, 0, 4, 0,219, 10, 7, 0,220, 10, 4, 0,208, 10, 4, 0,233, 8, 7, 0,236, 3, 7, 0,242, 2,141, 1, 23, 0, + 4, 0,206, 10, 4, 0,221, 10, 7, 0,222, 10, 7, 0, 57, 0, 7, 0,223, 10, 7, 0,238, 2, 7, 0,214, 10, 7, 0,224, 10, + 7, 0,219, 2, 7, 0,225, 10, 7, 0,110, 4, 7, 0,226, 10, 7, 0,227, 10, 7, 0,228, 10, 7, 0,229, 10, 7, 0,230, 10, + 7, 0,231, 10, 7, 0,232, 10, 7, 0,233, 10, 7, 0,234, 10, 7, 0,235, 10, 7, 0,236, 10, 12, 0,237, 10,122, 0, 33, 0, +121, 0,238, 10,189, 1,239, 10, 68, 0,240, 10, 68, 0, 24, 10, 68, 0,241, 10,190, 1,242, 10, 48, 0,165, 0, 48, 0,243, 10, + 48, 0,244, 10, 7, 0,245, 10, 7, 0,246, 10, 7, 0,247, 10, 7, 0,248, 10, 7, 0,249, 10, 7, 0,245, 8, 7, 0,250, 10, + 7, 0,169, 1, 7, 0,251, 10, 4, 0,252, 10, 4, 0,253, 10, 4, 0,254, 10, 4, 0, 90, 0, 4, 0, 37, 0, 4, 0,255, 10, + 2, 0, 0, 11, 2, 0, 1, 11, 4, 0, 2, 11, 7, 0,219, 2, 4, 0, 3, 11, 7, 0, 4, 11, 4, 0, 5, 11,138, 0, 6, 11, + 12, 0, 7, 11,123, 0, 11, 0,121, 0,238, 10, 59, 0,255, 0, 7, 0,136, 1, 7, 0,245, 8, 7, 0, 8, 11, 7, 0, 9, 11, + 2, 0, 10, 11, 2, 0, 11, 11, 2, 0, 12, 11, 2, 0, 17, 0, 4, 0, 37, 0,124, 0, 13, 0,121, 0,238, 10,140, 0, 12, 3, +142, 0, 14, 3, 7, 0,189, 8, 7, 0, 13, 11, 7, 0, 14, 11, 7, 0, 67, 1, 7, 0, 15, 11, 4, 0, 16, 11, 4, 0, 10, 3, 2, 0, 17, 0, 2, 0, 37, 0, 4, 0, 70, 0, 69, 78, 68, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; From 89df4a46fcbbe11ca478418af59161c87ddbb9f1 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Sun, 4 Oct 2009 20:11:55 +0000 Subject: [PATCH 097/138] * Unzip python bundle at the end of the build process. Patch by b333rt, thanks! * remove /ARCH setting - is used only when building x86 --- config/win64-vc-config.py | 2 +- tools/Blender.py | 67 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/config/win64-vc-config.py b/config/win64-vc-config.py index 5bb01ff16b5..5f088489b34 100644 --- a/config/win64-vc-config.py +++ b/config/win64-vc-config.py @@ -164,7 +164,7 @@ CXX = 'cl.exe' CFLAGS = [] CCFLAGS = ['/nologo', '/Ob1', '/J', '/W3', '/Gd', '/wd4244', '/wd4305', '/wd4800', '/wd4065', '/wd4267'] CXXFLAGS = ['/EHsc'] -BGE_CXXFLAGS = ['/O2', '/EHsc', '/GR', '/fp:fast', '/arch:SSE2'] +BGE_CXXFLAGS = ['/O2', '/EHsc', '/GR', '/fp:fast'] BF_DEBUG_CCFLAGS = ['/Zi', '/FR${TARGET}.sbr'] diff --git a/tools/Blender.py b/tools/Blender.py index 1b0573cfda4..04f2676deb3 100644 --- a/tools/Blender.py +++ b/tools/Blender.py @@ -327,6 +327,59 @@ def set_quiet_output(env): env['BUILDERS']['Library'] = static_lib env['BUILDERS']['Program'] = program + +def unzip_pybundle(from_zip,to_dir,exclude_re): + import zipfile + + zip= zipfile.ZipFile(from_zip, mode='r') + exclude_re= list(exclude_re) #single re object or list of re objects + debug= 0 #list files instead of unpacking + good= [] + if debug: print '\nFiles not being unpacked:\n' + for name in zip.namelist(): + is_bad= 0 + for r in exclude_re: + if r.match(name): + is_bad=1 + if debug: print name + break + if not is_bad: + good.append(name) + if debug: + print '\nFiles being unpacked:\n' + for g in good: + print g + else: + zip.extractall(to_dir, good) + +def my_winpybundle_print(target, source, env): + pass + +def WinPyBundle(target=None, source=None, env=None): + import shutil, re + py_zip= env.subst( env['LCGDIR'] ) + if py_zip[0]=='#': + py_zip= py_zip[1:] + py_zip+= '/release/python' + env['BF_PYTHON_VERSION'].replace('.','') + '.zip' + + py_target = env.subst( env['BF_INSTALLDIR'] ) + if py_target[0]=='#': + py_target=py_target[1:] + py_target+= '/.blender/python/lib/' + def printexception(func,path,ex): + if os.path.exists(path): #do not report if path does not exist. eg on a fresh build. + print str(func) + ' failed on ' + str(path) + print "Trying to remove existing py bundle." + shutil.rmtree(py_target, False, printexception) + exclude_re=[re.compile('.*/test/.*'), + re.compile('^config/.*'), + re.compile('^distutils/.*'), + re.compile('^idlelib/.*'), + re.compile('^lib2to3/.*'), + re.compile('^tkinter/.*')] + print "Unpacking '" + py_zip + "' to '" + py_target + "'" + unzip_pybundle(py_zip,py_target,exclude_re) + def my_appit_print(target, source, env): a = '%s' % (target[0]) d, f = os.path.split(a) @@ -392,10 +445,10 @@ def AppIt(target=None, source=None, env=None): # extract copy system python, be sure to update other build systems # when making changes to the files that are copied. -def my_pyinst_print(target, source, env): +def my_unixpybundle_print(target, source, env): pass -def PyInstall(target=None, source=None, env=None): +def UnixPyBundle(target=None, source=None, env=None): # Any Unix except osx #-- .blender/python/lib/python3.1 @@ -522,6 +575,9 @@ class BlenderEnvironment(SConsEnvironment): lenv.Append(CCFLAGS = lenv['CC_WARN']) lenv.Append(CXXFLAGS = lenv['CXX_WARN']) + if lenv['OURPLATFORM'] == 'win64-vc': + lenv.Append(LINKFLAGS = ['/MACHINE:X64']) + if lenv['OURPLATFORM'] in ('win32-vc', 'win64-vc'): if lenv['BF_DEBUG']: lenv.Append(CCFLAGS = ['/MTd']) @@ -602,8 +658,11 @@ class BlenderEnvironment(SConsEnvironment): elif os.sep == '/': # any unix if lenv['WITH_BF_PYTHON']: if not lenv['WITHOUT_BF_INSTALL'] and not lenv['WITHOUT_BF_PYTHON_INSTALL']: - lenv.AddPostAction(prog,Action(PyInstall,strfunction=my_pyinst_print)) - + lenv.AddPostAction(prog,Action(UnixPyBundle,strfunction=my_unixpybundle_print)) + elif lenv['OURPLATFORM'].startswith('win'): # windows + if lenv['WITH_BF_PYTHON']: + if not lenv['WITHOUT_BF_PYTHON_INSTALL']: + lenv.AddPostAction(prog,Action(WinPyBundle,strfunction=my_winpybundle_print)) return prog def Glob(lenv, pattern): From af522abf33bd3b8caf61f596d1e0a35285e45f9a Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Mon, 5 Oct 2009 02:59:47 +0000 Subject: [PATCH 098/138] * changes/additions to volume lighting Volumes can now receive shadows from external objects, either raytraced shadows or shadow maps. To use external shadows, enable 'external shadows' in volume material 'lighting' panel. This an extra toggle since it causes a performance hit, but this can probably be revisited/optimised when the new raytrace accelerator is integrated. For shadow maps at least, it's still very quick. Renamed 'scattering mode' to 'lighting mode' (a bit simpler to understand), and the options inside. Now there's: - Shadeless takes light contribution, but without shadowing or self-shading (fast) good for fog-like volumes, such as mist, or underwater effects - Shadowed (new) takes light contribution with shadows, but no self-shading. (medium) good for mist etc. with directional light sources eg. http://vimeo.com/6901636 - Shaded takes light contribution with internal/external shadows, and self shading (slower) good for thicker/textured volumes like smoke - Multiple scattering etc (still doesn't work properly, on the todo). --- release/scripts/ui/buttons_material.py | 7 +- source/blender/blenkernel/intern/material.c | 2 +- source/blender/blenloader/intern/readfile.c | 2 +- source/blender/makesdna/DNA_material_types.h | 12 ++-- source/blender/makesrna/intern/rna_material.c | 20 ++++-- .../render/intern/source/convertblender.c | 5 +- .../render/intern/source/volume_precache.c | 8 +-- .../blender/render/intern/source/volumetric.c | 67 ++++++++++++++++++- 8 files changed, 99 insertions(+), 24 deletions(-) diff --git a/release/scripts/ui/buttons_material.py b/release/scripts/ui/buttons_material.py index ee7193da301..2415d636dab 100644 --- a/release/scripts/ui/buttons_material.py +++ b/release/scripts/ui/buttons_material.py @@ -665,16 +665,17 @@ class MATERIAL_PT_volume_lighting(VolumeButtonsPanel): split = layout.split() col = split.column() - col.itemR(vol, "scattering_mode", text="") + col.itemR(vol, "lighting_mode", text="") col = split.column() - if vol.scattering_mode == 'SINGLE_SCATTERING': + if vol.lighting_mode == 'SHADED': + col.itemR(vol, "external_shadows") col.itemR(vol, "light_cache") sub = col.column() sub.active = vol.light_cache sub.itemR(vol, "cache_resolution") - elif vol.scattering_mode in ('MULTIPLE_SCATTERING', 'SINGLE_PLUS_MULTIPLE_SCATTERING'): + elif vol.lighting_mode in ('MULTIPLE_SCATTERING', 'SHADED_PLUS_MULTIPLE_SCATTERING'): sub = col.column() sub.enabled = True sub.active = False diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index cbd306f6d87..7e742dc5631 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -181,7 +181,7 @@ void init_material(Material *ma) ma->vol.depth_cutoff = 0.01f; ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED; ma->vol.stepsize = 0.2f; - ma->vol.shade_type = MA_VOL_SHADE_SINGLE; + ma->vol.shade_type = MA_VOL_SHADE_SHADED; ma->vol.shadeflag |= MA_VOL_PRECACHESHADING; ma->vol.precache_resolution = 50; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 9367e2f4247..a3a56e9a075 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -9680,7 +9680,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) ma->vol.depth_cutoff = 0.01f; ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED; ma->vol.stepsize = 0.2f; - ma->vol.shade_type = MA_VOL_SHADE_SINGLE; + ma->vol.shade_type = MA_VOL_SHADE_SHADED; ma->vol.shadeflag |= MA_VOL_PRECACHESHADING; ma->vol.precache_resolution = 50; } diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index a925b60ac33..36de890e6dc 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -374,15 +374,15 @@ typedef struct Material { #define MA_VOL_STEP_ADAPTIVE 2 /* vol_shadeflag */ -#define MA_VOL_SHADED 1 -#define MA_VOL_RECVSHADOW 4 +#define MA_VOL_RECV_EXT_SHADOW 1 #define MA_VOL_PRECACHESHADING 8 /* vol_shading_type */ -#define MA_VOL_SHADE_NONE 0 -#define MA_VOL_SHADE_SINGLE 1 -#define MA_VOL_SHADE_MULTIPLE 2 -#define MA_VOL_SHADE_SINGLEPLUSMULTIPLE 3 +#define MA_VOL_SHADE_SHADELESS 0 +#define MA_VOL_SHADE_SHADOWED 2 +#define MA_VOL_SHADE_SHADED 1 +#define MA_VOL_SHADE_MULTIPLE 3 +#define MA_VOL_SHADE_SHADEDPLUSMULTIPLE 4 #endif diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 661b1c5e1c3..b05a7e59cc3 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -953,11 +953,12 @@ static void rna_def_material_volume(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - static EnumPropertyItem prop_scattering_items[] = { - {MA_VOL_SHADE_NONE, "NONE", 0, "None", ""}, - {MA_VOL_SHADE_SINGLE, "SINGLE_SCATTERING", 0, "Single Scattering", ""}, + static EnumPropertyItem prop_lighting_items[] = { + {MA_VOL_SHADE_SHADELESS, "SHADELESS", 0, "Shadeless", ""}, + {MA_VOL_SHADE_SHADOWED, "SHADOWED", 0, "Shadowed", ""}, + {MA_VOL_SHADE_SHADED, "SHADED", 0, "Shaded", ""}, {MA_VOL_SHADE_MULTIPLE, "MULTIPLE_SCATTERING", 0, "Multiple Scattering", ""}, - {MA_VOL_SHADE_SINGLEPLUSMULTIPLE, "SINGLE_PLUS_MULTIPLE_SCATTERING", 0, "Single + Multiple Scattering", ""}, + {MA_VOL_SHADE_SHADEDPLUSMULTIPLE, "SHADED_PLUS_MULTIPLE_SCATTERING", 0, "Shaded + Multiple Scattering", ""}, {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem prop_stepsize_items[] = { @@ -984,10 +985,15 @@ static void rna_def_material_volume(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Step Size", "Distance between subsequent volume depth samples."); RNA_def_property_update(prop, 0, "rna_Material_update"); - prop= RNA_def_property(srna, "scattering_mode", PROP_ENUM, PROP_NONE); + prop= RNA_def_property(srna, "lighting_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "shade_type"); - RNA_def_property_enum_items(prop, prop_scattering_items); - RNA_def_property_ui_text(prop, "Scattering Mode", "Method of shading, attenuating, and scattering light through the volume"); + RNA_def_property_enum_items(prop, prop_lighting_items); + RNA_def_property_ui_text(prop, "Lighting Mode", "Method of shading, attenuating, and scattering light through the volume"); + RNA_def_property_update(prop, 0, "rna_Material_update"); + + prop= RNA_def_property(srna, "external_shadows", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "shadeflag", MA_VOL_RECV_EXT_SHADOW); /* use bitflags */ + RNA_def_property_ui_text(prop, "External Shadows", "Receive shadows from sources outside the volume (temporary)"); RNA_def_property_update(prop, 0, "rna_Material_update"); prop= RNA_def_property(srna, "light_cache", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index b3784f26048..655c453eee7 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -942,7 +942,10 @@ static Material *give_render_material(Render *re, Object *ob, int nr) if(re->r.mode & R_SPEED) ma->texco |= NEED_UV; - if(ma->material_type == MA_TYPE_VOLUME) ma->mode |= MA_TRANSP; + if(ma->material_type == MA_TYPE_VOLUME) { + ma->mode |= MA_TRANSP; + ma->mode &= ~MA_SHADBUF; + } if((ma->mode & MA_TRANSP) && (ma->mode & MA_ZTRANSP)) re->flag |= R_ZTRA; diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c index 7ecaf83ae27..2d5d38a394f 100644 --- a/source/blender/render/intern/source/volume_precache.c +++ b/source/blender/render/intern/source/volume_precache.c @@ -401,7 +401,7 @@ void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Material *ma) fac *= (energy_ss / energy_ms); /* blend multiple scattering back in the light cache */ - if (shade_type == MA_VOL_SHADE_SINGLEPLUSMULTIPLE) { + if (shade_type == MA_VOL_SHADE_SHADEDPLUSMULTIPLE) { /* conserve energy - half single, half multiple */ origf = 0.5f; fac *= 0.5f; @@ -713,7 +713,7 @@ void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *obi, Mat lightcache_filter(obi->volume_precache); - if (ELEM(ma->vol.shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SINGLEPLUSMULTIPLE)) + if (ELEM(ma->vol.shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE)) { multiple_scattering_diffusion(re, vp, ma); } @@ -721,8 +721,8 @@ void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *obi, Mat static int using_lightcache(Material *ma) { - return (((ma->vol.shadeflag & MA_VOL_PRECACHESHADING) && (ma->vol.shade_type == MA_VOL_SHADE_SINGLE)) - || (ELEM(ma->vol.shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SINGLEPLUSMULTIPLE))); + return (((ma->vol.shadeflag & MA_VOL_PRECACHESHADING) && (ma->vol.shade_type == MA_VOL_SHADE_SHADED)) + || (ELEM(ma->vol.shade_type, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE))); } /* loop through all objects (and their associated materials) diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c index 381a32de027..cbb74ab752f 100644 --- a/source/blender/render/intern/source/volumetric.c +++ b/source/blender/render/intern/source/volumetric.c @@ -51,6 +51,7 @@ #include "render_types.h" #include "pixelshading.h" #include "shading.h" +#include "shadbuf.h" #include "texture.h" #include "volumetric.h" #include "volume_precache.h" @@ -73,6 +74,61 @@ inline float luminance(float* col) /* tracing */ +static int vlr_check_intersect_solid(Isect *is, int ob, RayFace *face) +{ + VlakRen *vlr = (VlakRen*)face; + + /* solid material types only */ + if (vlr->mat->material_type == MA_TYPE_SURFACE) + return 1; + else + return 0; +} + +static float vol_get_shadow(ShadeInput *shi, LampRen *lar, float *co) +{ + float visibility = 1.f; + + if(lar->shb) { + float dot=1.f; + float dxco[3]={0.f, 0.f, 0.f}, dyco[3]={0.f, 0.f, 0.f}; + + visibility = testshadowbuf(&R, lar->shb, co, dxco, dyco, 1.0, 0.0); + } else if (lar->mode & LA_SHAD_RAY) { + /* trace shadow manually, no good lamp api atm */ + Isect is; + const float maxsize = RE_ray_tree_max_size(R.raytree); + + + VecCopyf(is.start, co); + if(lar->type==LA_SUN || lar->type==LA_HEMI) { + is.end[0] = co[0] - lar->vec[0] * maxsize; + is.end[1] = co[1] - lar->vec[1] * maxsize; + is.end[2] = co[2] - lar->vec[2] * maxsize; + } else { + VecCopyf(is.end, lar->co); + } + + is.mode= RE_RAY_MIRROR; + if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) + is.lay= lar->lay; + else + is.lay= -1; + is.face_last= (RayFace*)lar->vlr_last[shi->thread]; + is.ob_last= RAY_OBJECT_SET(&R, lar->obi_last[shi->thread]); + is.faceorig= NULL; + is.oborig= RAY_OBJECT_SET(&R, shi->obi); + + if(RE_ray_tree_intersect_check(R.raytree, &is, vlr_check_intersect_solid)) { + visibility = 0.f; + } + + lar->vlr_last[shi->thread]= (VlakRen*)is.face_last; + lar->obi_last[shi->thread]= RAY_OBJECT_GET(&R, is.ob_last); + } + return visibility; +} + static int vol_get_bounds(ShadeInput *shi, float *co, float *vec, float *hitco, Isect *isect, int intersect_type) { float maxsize = RE_ray_tree_max_size(R.raytree); @@ -448,9 +504,18 @@ void vol_shade_one_lamp(struct ShadeInput *shi, float *co, LampRen *lar, float * VECCOPY(lv, lar->vec); VecMulf(lv, -1.0f); - if (shi->mat->vol.shade_type != MA_VOL_SHADE_NONE) { + if (shi->mat->vol.shade_type == MA_VOL_SHADE_SHADOWED) { + VecMulf(lacol, vol_get_shadow(shi, lar, co)); + } + else if (shi->mat->vol.shade_type == MA_VOL_SHADE_SHADED) + { Isect is; + if (shi->mat->vol.shadeflag & MA_VOL_RECV_EXT_SHADOW) { + VecMulf(lacol, vol_get_shadow(shi, lar, co)); + if (luminance(lacol) < 0.001f) return; + } + /* find minimum of volume bounds, or lamp coord */ if (vol_get_bounds(shi, co, lv, hitco, &is, VOL_BOUNDS_SS)) { float dist = VecLenf(co, hitco); From 0f07bea06bcaaa9db9568c9b28bd00da18e5f56f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 5 Oct 2009 07:08:59 +0000 Subject: [PATCH 099/138] remove unused defines, cant check every case but from grepping the souece it should go ok. --- extern/bullet2/CMakeLists.txt | 6 ++---- extern/bullet2/src/SConscript | 4 ++-- source/blender/nodes/CMakeLists.txt | 14 -------------- source/blender/nodes/SConscript | 11 ----------- source/blender/python/CMakeLists.txt | 2 -- source/blender/render/CMakeLists.txt | 4 ---- source/blender/render/SConscript | 3 --- 7 files changed, 4 insertions(+), 40 deletions(-) diff --git a/extern/bullet2/CMakeLists.txt b/extern/bullet2/CMakeLists.txt index 2e2d8920781..3054ed98908 100644 --- a/extern/bullet2/CMakeLists.txt +++ b/extern/bullet2/CMakeLists.txt @@ -32,14 +32,12 @@ FILE(GLOB SRC src/BulletCollision/CollisionShapes/*.cpp src/BulletCollision/NarrowPhaseCollision/*.cpp src/BulletCollision/Gimpact/*.cpp - src/BulletCollision//CollisionDispatch/*.cpp + src/BulletCollision/CollisionDispatch/*.cpp src/BulletDynamics/ConstraintSolver/*.cpp src/BulletDynamics/Vehicle/*.cpp src/BulletDynamics/Dynamics/*.cpp src/BulletSoftBody/*.cpp ) -ADD_DEFINITIONS(-D_LIB) - BLENDERLIB(extern_bullet "${SRC}" "${INC}") -#, libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) + diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript index 3d0c645e7a0..c0ee56045d8 100644 --- a/extern/bullet2/src/SConscript +++ b/extern/bullet2/src/SConscript @@ -4,11 +4,11 @@ import os Import('env') -defs = 'USE_DOUBLES QHULL _LIB' +defs = '' cflags = [] if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): - defs += ' WIN32 NDEBUG _WINDOWS _LIB' + defs += ' WIN32 NDEBUG _WINDOWS' #cflags += ['/MT', '/W3', '/GX', '/O2', '/Op'] cflags += ['/MT', '/W3', '/GX', '/Og', '/Ot', '/Ob1', '/Op', '/G6', '/O3', '/EHcs'] elif env['OURPLATFORM']=='win32-mingw': diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 58bee7e3acf..ee4b9a81ccd 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -38,20 +38,6 @@ IF(WIN32) SET(INC ${INC} ${PTHREADS_INC}) ENDIF(WIN32) -IF(WITH_OPENEXR) - ADD_DEFINITIONS(-DWITH_OPENEXR) -ENDIF(WITH_OPENEXR) - -IF(WITH_QUICKTIME) - SET(INC ${INC} ../quicktime ${QUICKTIME_INC}) - ADD_DEFINITIONS(-DWITH_QUICKTIME) -ENDIF(WITH_QUICKTIME) - -IF(WITH_FFMPEG) - SET(INC ${INC} ${FFMPEG_INC}) - ADD_DEFINITIONS(-DWITH_FFMPEG) -ENDIF(WITH_FFMPEG) - IF(WITH_PYTHON) SET(INC ${INC} ../python ${PYTHON_INC}) ELSE(WITH_PYTHON) diff --git a/source/blender/nodes/SConscript b/source/blender/nodes/SConscript index 01319dc1eb4..548f4973574 100644 --- a/source/blender/nodes/SConscript +++ b/source/blender/nodes/SConscript @@ -27,17 +27,6 @@ if env['WITH_BF_PYTHON']: else: defs.append('DISABLE_PYTHON') -if env['WITH_BF_OPENEXR']: - defs.append('WITH_OPENEXR') - -if env['WITH_BF_FFMPEG']: - defs.append('WITH_FFMPEG') - incs += ' ' + env['BF_FFMPEG_INC'] - -if env['WITH_BF_QUICKTIME']: - defs.append('WITH_QUICKTIME') - incs += ' ' + env['BF_QUICKTIME_INC'] - if env['OURPLATFORM'] == 'linux2': cflags='-pthread' incs += ' ../../../extern/binreloc/include' diff --git a/source/blender/python/CMakeLists.txt b/source/blender/python/CMakeLists.txt index 7abec566505..a83e29e2fab 100644 --- a/source/blender/python/CMakeLists.txt +++ b/source/blender/python/CMakeLists.txt @@ -46,8 +46,6 @@ IF(WITH_FFMPEG) ADD_DEFINITIONS(-DWITH_FFMPEG) ENDIF(WITH_FFMPEG) -ADD_DEFINITIONS(-DWITH_CCGSUBSURF) - BLENDERLIB(bf_python "${SRC}" "${INC}") BLENDERLIB(bf_gen_python "${GENSRC}" "${INC}") diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt index b30bc4936a5..29539fa4d17 100644 --- a/source/blender/render/CMakeLists.txt +++ b/source/blender/render/CMakeLists.txt @@ -47,10 +47,6 @@ IF(WITH_QUICKTIME) ADD_DEFINITIONS(-DWITH_QUICKTIME) ENDIF(WITH_QUICKTIME) -IF(WITH_FFMPEG) - ADD_DEFINITIONS(-DWITH_FFMPEG) -ENDIF(WITH_FFMPEG) - #TODO #if env['OURPLATFORM']=='linux2': # cflags='-pthread' diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript index f6193c29eba..9b2480cc437 100644 --- a/source/blender/render/SConscript +++ b/source/blender/render/SConscript @@ -14,9 +14,6 @@ if env['WITH_BF_QUICKTIME']: defs.append('WITH_QUICKTIME') incs += ' ../quicktime ' + env['BF_QUICKTIME_INC'] -if env['WITH_BF_FFMPEG']: - defs.append('WITH_FFMPEG') - if env['WITH_BF_OPENEXR']: defs.append('WITH_OPENEXR') From 3ec79d79e9f07346136fed4ead210c0d127ce00e Mon Sep 17 00:00:00 2001 From: Lukas Steiblys Date: Mon, 5 Oct 2009 09:03:35 +0000 Subject: [PATCH 100/138] normals were updated incorrectly in buffers when sculpting. Still not perfect. --- source/blender/editors/sculpt_paint/sculpt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 470a10b5e50..01a2ff3fdee 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1014,9 +1014,9 @@ static void update_damaged_vert(SculptSession *ss, ListBase *lb) CalcNormFloat4(ss->mvert[ss->mface[i].v1].co, ss->mvert[ss->mface[i].v2].co, ss->mvert[ss->mface[i].v3].co, ss->mvert[ss->mface[i].v4].co, norm); else CalcNormFloat(ss->mvert[ss->mface[i].v1].co, ss->mvert[ss->mface[i].v2].co, ss->mvert[ss->mface[i].v3].co, norm); - VECCOPY(&buffer[cur->element*3],norm); - VECCOPY(&buffer[cur->element*3],norm); - VECCOPY(&buffer[cur->element*3],norm); + VECCOPY(&buffer[(cur->element-cur->element%3)*3],norm); + VECCOPY(&buffer[(cur->element-cur->element%3+1)*3],norm); + VECCOPY(&buffer[(cur->element-cur->element%3+2)*3],norm); } //VECCOPY(&buffer[cur->element*3],ss->mvert[vert->Index].no); From a3449771476955fd4a27eadd17ff4dce2655cc16 Mon Sep 17 00:00:00 2001 From: Damien Plisson Date: Mon, 5 Oct 2009 12:55:16 +0000 Subject: [PATCH 101/138] Cocoa port : - Window creation at preferred size Implement in Ghost the use of Cocoa functions to get the maximum visible rect (size and position) for the window contents (all screen excluding dock, top menu, and window title bar) Thus Apple specific code in window creation (wm_window.c & wm_apple.c) is no more needed => removed in case of Cocoa build - Alert on exiting despite unsaved changes Add to GHOST method to maintain an all platforms (not apple specific anymore) status on unsaved changes Update GHOST_SystemCocoa to use this for asking or not user to confirm exit without saving changes --- intern/ghost/GHOST_C-api.h | 10 ++ intern/ghost/GHOST_IWindow.h | 13 ++ intern/ghost/GHOST_Types.h | 6 + intern/ghost/intern/GHOST_C-api.cpp | 7 ++ intern/ghost/intern/GHOST_SystemCocoa.h | 24 ++-- intern/ghost/intern/GHOST_SystemCocoa.mm | 117 +++++++++++++----- intern/ghost/intern/GHOST_Window.cpp | 14 +++ intern/ghost/intern/GHOST_Window.h | 16 +++ intern/ghost/intern/GHOST_WindowCocoa.h | 7 ++ intern/ghost/intern/GHOST_WindowCocoa.mm | 18 ++- intern/ghost/intern/GHOST_WindowManager.cpp | 19 ++- intern/ghost/intern/GHOST_WindowManager.h | 10 +- source/blender/windowmanager/CMakeLists.txt | 4 + .../blender/windowmanager/intern/wm_window.c | 17 ++- 14 files changed, 219 insertions(+), 63 deletions(-) diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index c0b7077fb53..9460fb504a9 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -598,6 +598,16 @@ extern GHOST_TWindowState GHOST_GetWindowState(GHOST_WindowHandle windowhandle); extern GHOST_TSuccess GHOST_SetWindowState(GHOST_WindowHandle windowhandle, GHOST_TWindowState state); + +/** + * Sets the window "modified" status, indicating unsaved changes + * @param windowhandle The handle to the window + * @param isUnsavedChanges Unsaved changes or not + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_SetWindowModifiedState(GHOST_WindowHandle windowhandle, + GHOST_TUns8 isUnsavedChanges); + /** * Sets the order of the window (bottom, top). * @param windowhandle The handle to the window diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index d91995e35ec..ff1484909b0 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -161,6 +161,19 @@ public: */ virtual GHOST_TSuccess setState(GHOST_TWindowState state) = 0; + /** + * Sets the window "modified" status, indicating unsaved changes + * @param isUnsavedChanges Unsaved changes or not + * @return Indication of success. + */ + virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges) = 0; + + /** + * Gets the window "modified" status, indicating unsaved changes + * @return True if there are unsaved changes + */ + virtual bool getModifiedState() = 0; + /** * Sets the order of the window (bottom, top). * @param order The order of the window. diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 31819f341a0..14e3c4bb5f7 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -116,6 +116,12 @@ typedef enum { } GHOST_TWindowState; +/** Constants for the answer to the blender exit request */ +typedef enum { + GHOST_kExitCancel = 0, + GHOST_kExitNow +} GHOST_TExitRequestResponse; + typedef enum { GHOST_kWindowOrderTop = 0, GHOST_kWindowOrderBottom diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 5c23b6c42a3..d14945d1bf8 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -629,6 +629,13 @@ GHOST_TSuccess GHOST_SetWindowState(GHOST_WindowHandle windowhandle, } +GHOST_TSuccess GHOST_SetWindowModifiedState(GHOST_WindowHandle windowhandle, GHOST_TUns8 isUnsavedChanges) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->setModifiedState(isUnsavedChanges); +} + GHOST_TSuccess GHOST_SetWindowOrder(GHOST_WindowHandle windowhandle, GHOST_TWindowOrder order) diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index cd2cf12daa1..3e499f3d136 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -133,6 +133,12 @@ public: */ virtual bool processEvents(bool waitForEvent); + /** + * Handle User request to quit, from Menu bar Quit, and Cmd+Q + * Display alert panel if changes performed since last save + */ + GHOST_TUns8 handleQuitRequest(); + /*************************************************************************************** ** Cursor management functionality ***************************************************************************************/ @@ -193,39 +199,33 @@ protected: */ virtual GHOST_TSuccess init(); - /** - * Closes the system down. - * @return A success value. - */ - virtual GHOST_TSuccess exit(); - - /** * Handles a tablet event. * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) * @return Indication whether the event was handled. */ - int handleTabletEvent(void *eventPtr); - /** + GHOST_TSuccess handleTabletEvent(void *eventPtr); + + /** * Handles a mouse event. * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) * @return Indication whether the event was handled. */ - int handleMouseEvent(void *eventPtr); + GHOST_TSuccess handleMouseEvent(void *eventPtr); /** * Handles a key event. * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) * @return Indication whether the event was handled. */ - int handleKeyEvent(void *eventPtr); + GHOST_TSuccess handleKeyEvent(void *eventPtr); /** * Handles a window event. * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) * @return Indication whether the event was handled. */ - int handleWindowEvent(void *eventPtr); + GHOST_TSuccess handleWindowEvent(void *eventPtr); /** * Handles all basic Mac application stuff for a mouse down event. diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index d0c382e1469..c66153ab670 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -414,6 +414,7 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) { } -(void)setSystemCocoa:(GHOST_SystemCocoa *)sysCocoa; - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender; +- (void)applicationWillTerminate:(NSNotification *)aNotification; @end @implementation CocoaAppDelegate : NSObject @@ -424,15 +425,21 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) { - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { + //TODO: implement graceful termination through Cocoa mechanism to avoid session log off to be cancelled //Note that Cmd+Q is already handled by keyhandler - //FIXME: Need an event "QuitRequest" - int shouldQuit = NSRunAlertPanel(@"Exit Blender", @"Some changes may not have been saved. Do you really want to quit ?", - @"No", @"Yes", nil); - - if (shouldQuit == NSAlertAlternateReturn) - systemCocoa->pushEvent( new GHOST_Event(systemCocoa->getMilliSeconds(), GHOST_kEventQuit, NULL) ); - - return NSTerminateCancel; + if (systemCocoa->handleQuitRequest() == GHOST_kExitNow) + return NSTerminateCancel;//NSTerminateNow; + else + return NSTerminateCancel; +} + +// To avoid cancelling a log off process, we must use Cocoa termination process +// And this function is the only chance to perform clean up +// So WM_exit needs to be called directly, as the event loop will never run before termination +- (void)applicationWillTerminate:(NSNotification *)aNotification +{ + /*G.afbreek = 0; //Let Cocoa perform the termination at the end + WM_exit(C);*/ } @end @@ -440,7 +447,6 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) { #pragma mark initialization/finalization -/***/ GHOST_SystemCocoa::GHOST_SystemCocoa() { @@ -468,6 +474,8 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() GHOST_SystemCocoa::~GHOST_SystemCocoa() { + NSAutoreleasePool* pool = (NSAutoreleasePool *)m_autoReleasePool; + [pool drain]; } @@ -478,7 +486,7 @@ GHOST_TSuccess GHOST_SystemCocoa::init() if (success) { //ProcessSerialNumber psn; - //FIXME: Carbon stuff to move window & menu to foreground + //Carbon stuff to move window & menu to foreground /*if (!GetCurrentProcess(&psn)) { TransformProcessType(&psn, kProcessTransformToForegroundApplication); SetFrontProcess(&psn); @@ -566,13 +574,6 @@ GHOST_TSuccess GHOST_SystemCocoa::init() } -GHOST_TSuccess GHOST_SystemCocoa::exit() -{ - NSAutoreleasePool* pool = (NSAutoreleasePool *)m_autoReleasePool; - [pool drain]; - return GHOST_System::exit(); -} - #pragma mark window management GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const @@ -602,11 +603,15 @@ GHOST_TUns8 GHOST_SystemCocoa::getNumDisplays() const void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const { - //TODO: Provide visible frame or total frame, check for consistency with rest of code + //Get visible frame, that is frame excluding dock and top menu bar NSRect frame = [[NSScreen mainScreen] visibleFrame]; - width = frame.size.width; - height = frame.size.height; + //Returns max window contents (excluding title bar...) + NSRect contentRect = [NSWindow contentRectForFrameRect:frame + styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)]; + + width = contentRect.size.width; + height = contentRect.size.height; } @@ -623,7 +628,16 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow( ) { GHOST_IWindow* window = 0; - + + //Get the available rect for including window contents + NSRect frame = [[NSScreen mainScreen] visibleFrame]; + NSRect contentRect = [NSWindow contentRectForFrameRect:frame + styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)]; + + //Ensures window top left is inside this available rect + left = left > contentRect.origin.x ? left : contentRect.origin.x; + top = top > contentRect.origin.y ? top : contentRect.origin.y; + window = new GHOST_WindowCocoa (title, left, top, width, height, state, type); if (window) { @@ -847,7 +861,7 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) } //TODO: To be called from NSWindow delegate -int GHOST_SystemCocoa::handleWindowEvent(void *eventPtr) +GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(void *eventPtr) { /*WindowRef windowRef; GHOST_WindowCocoa *window; @@ -900,7 +914,29 @@ int GHOST_SystemCocoa::handleWindowEvent(void *eventPtr) return GHOST_kSuccess; } -int GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) +GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest() +{ + //Check open windows if some changes are not saved + if (m_windowManager->getAnyModifiedState()) + { + int shouldQuit = NSRunAlertPanel(@"Exit Blender", @"Some changes have not been saved. Do you really want to quit ?", + @"Cancel", @"Quit anyway", nil); + if (shouldQuit == NSAlertAlternateReturn) + { + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL) ); + return GHOST_kExitNow; + } + } + else { + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL) ); + return GHOST_kExitNow; + } + + return GHOST_kExitCancel; +} + + +GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) { NSEvent *event = (NSEvent *)eventPtr; GHOST_IWindow* window = m_windowManager->getActiveWindow(); @@ -964,7 +1000,7 @@ int GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) } -int GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) +GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) { NSEvent *event = (NSEvent *)eventPtr; GHOST_IWindow* window = m_windowManager->getActiveWindow(); @@ -1018,11 +1054,12 @@ int GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) } -int GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) +GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) { NSEvent *event = (NSEvent *)eventPtr; GHOST_IWindow* window = m_windowManager->getActiveWindow(); NSUInteger modifiers; + NSString *characters; GHOST_TKey keyCode; unsigned char ascii; @@ -1036,9 +1073,16 @@ int GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) switch ([event type]) { case NSKeyDown: case NSKeyUp: - keyCode = convertKey([event keyCode], - [[event charactersIgnoringModifiers] characterAtIndex:0]); - ascii= convertRomanToLatin((char)[[event characters] characterAtIndex:0]); + characters = [event characters]; + if ([characters length]) { //Check for dead keys + keyCode = convertKey([event keyCode], + [[event charactersIgnoringModifiers] characterAtIndex:0]); + ascii= convertRomanToLatin((char)[characters characterAtIndex:0]); + } else { + keyCode = convertKey([event keyCode],0); + ascii= 0; + } + if ((keyCode == GHOST_kKeyQ) && (m_modifierMask & NSCommandKeyMask)) break; //Cmd-Q is directly handled by Cocoa @@ -1223,9 +1267,12 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const GHOST_TUns8 * temp_buff; size_t pastedTextSize; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; if (pasteBoard = nil) { + [pool drain]; return NULL; } @@ -1235,7 +1282,10 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const NSString *bestType = [[NSPasteboard generalPasteboard] availableTypeFromArray:supportedTypes]; - if (bestType == nil) { return NULL; } + if (bestType == nil) { + [pool drain]; + return NULL; + } NSString * textPasted = [pasteBoard stringForType:@"public.utf8-plain-text"]; @@ -1249,6 +1299,8 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const temp_buff[pastedTextSize] = '\0'; + [pool drain]; + if(temp_buff) { return temp_buff; } else { @@ -1262,10 +1314,12 @@ void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const if(selection) {return;} // for copying the selection, used on X11 - + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; if (pasteBoard = nil) { + [pool drain]; return; } @@ -1277,8 +1331,7 @@ void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const [pasteBoard setString:textToCopy forType:@"public.utf8-plain-text"]; - printf("\nCopy"); - + [pool drain]; } #pragma mark Carbon stuff to remove diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp index 951c3bc381d..34e9f519a07 100644 --- a/intern/ghost/intern/GHOST_Window.cpp +++ b/intern/ghost/intern/GHOST_Window.cpp @@ -52,6 +52,8 @@ GHOST_Window::GHOST_Window( m_cursorShape(GHOST_kStandardCursorDefault), m_stereoVisual(stereoVisual) { + m_isUnsavedChanges = false; + m_fullScreen = state == GHOST_kWindowStateFullScreen; if (m_fullScreen) { m_fullScreenWidth = width; @@ -137,3 +139,15 @@ GHOST_TSuccess GHOST_Window::setCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUn } } + +GHOST_TSuccess GHOST_Window::setModifiedState(bool isUnsavedChanges) +{ + m_isUnsavedChanges = isUnsavedChanges; + + return GHOST_kSuccess; +} + +bool GHOST_Window::getModifiedState() +{ + return m_isUnsavedChanges; +} \ No newline at end of file diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index 88178bae5b3..a2d1675f6ab 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -173,6 +173,19 @@ public: */ virtual GHOST_TSuccess setCursorGrab(bool grab); + /** + * Sets the window "modified" status, indicating unsaved changes + * @param isUnsavedChanges Unsaved changes or not + * @return Indication of success. + */ + virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges); + + /** + * Gets the window "modified" status, indicating unsaved changes + * @return True if there are unsaved changes + */ + virtual bool getModifiedState(); + /** * Returns the type of drawing context used in this window. * @return The current type of drawing context. @@ -262,6 +275,9 @@ protected: /** The current shape of the cursor */ GHOST_TStandardCursor m_cursorShape; + /** Modified state : are there unsaved changes */ + bool m_isUnsavedChanges; + /** Stores wether this is a full screen window. */ bool m_fullScreen; diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h index 146d0ff47de..f383e3a7a81 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.h +++ b/intern/ghost/intern/GHOST_WindowCocoa.h @@ -143,6 +143,13 @@ public: */ virtual GHOST_TWindowState getState() const; + /** + * Sets the window "modified" status, indicating unsaved changes + * @param isUnsavedChanges Unsaved changes or not + * @return Indication of success. + */ + virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges); + /** * Converts a point in screen coordinates to client rectangle coordinates * @param inX The x-coordinate on the screen. diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 53d7fa9b245..092443814b0 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -378,12 +378,6 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) case GHOST_kWindowStateMinimized: ::HideWindow(m_windowRef); break; - case GHOST_kWindowStateModified: - SetWindowModified(m_windowRef, 1); - break; - case GHOST_kWindowStateUnModified: - SetWindowModified(m_windowRef, 0); - break; case GHOST_kWindowStateMaximized: case GHOST_kWindowStateNormal: default: @@ -393,6 +387,18 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) return GHOST_kSuccess; } +GHOST_TSuccess GHOST_WindowCocoa::setModifiedState(bool isUnsavedChanges) +{ + if (isUnsavedChanges) { + SetWindowModified(m_windowRef, 1); + } else { + SetWindowModified(m_windowRef, 0); + } + + return GHOST_Window::setModifiedState(isUnsavedChanges); +} + + GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order) { diff --git a/intern/ghost/intern/GHOST_WindowManager.cpp b/intern/ghost/intern/GHOST_WindowManager.cpp index af96653db13..15ee41e3dce 100644 --- a/intern/ghost/intern/GHOST_WindowManager.cpp +++ b/intern/ghost/intern/GHOST_WindowManager.cpp @@ -187,10 +187,21 @@ void GHOST_WindowManager::setWindowInactive(const GHOST_IWindow* window) } - std::vector & -GHOST_WindowManager:: -getWindows( -){ +std::vector &GHOST_WindowManager::getWindows() +{ return m_windows; } + +bool GHOST_WindowManager::getAnyModifiedState() +{ + bool isAnyModified = false; + std::vector::iterator iter; + + for (iter = m_windows.begin(); iter != m_windows.end(); iter++) { + if ((*iter)->getModifiedState()) + isAnyModified = true; + } + + return isAnyModified; +} \ No newline at end of file diff --git a/intern/ghost/intern/GHOST_WindowManager.h b/intern/ghost/intern/GHOST_WindowManager.h index 46e80d2c603..3690ad41e2c 100644 --- a/intern/ghost/intern/GHOST_WindowManager.h +++ b/intern/ghost/intern/GHOST_WindowManager.h @@ -133,11 +133,13 @@ public: * this vector. Please do not destroy or add windows use the * interface above for this, */ + std::vector & getWindows(); - std::vector & - getWindows( - ); - + /** + * Return true if any windows has a modified status + * @return True if any window has unsaved changes + */ + bool getAnyModifiedState(); protected: /** The list of windows managed */ diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index cb2fc92a1b6..7deac8a4aa0 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -70,6 +70,10 @@ IF(WIN32) SET(INC ${INC} ${PTHREADS_INC}) ENDIF(WIN32) +IF(WITH_COCOA) + LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/wm_apple.c") +ENDIF(WITH_COCOA) + # TODO buildinfo IF(BF_BUILDINFO) ADD_DEFINITIONS(-DNAN_BUILDINFO) diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index c853afe4507..466e5868723 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -71,7 +71,8 @@ static int prefsizx= 0, prefsizy= 0, prefstax= 0, prefstay= 0; /* ******** win open & close ************ */ -/* XXX this one should correctly check for apple top header... */ +/* XXX this one should correctly check for apple top header... + done for Cocoa : returns window contents (and not frame) max size*/ static void wm_get_screensize(int *width_r, int *height_r) { unsigned int uiwidth; @@ -90,7 +91,7 @@ static void wm_window_check_position(rcti *rect) wm_get_screensize(&width, &height); -#ifdef __APPLE__ +#if defined(__APPLE__) && !defined(GHOST_COCOA) height -= 70; #endif @@ -269,7 +270,12 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win) else GHOST_SetTitle(win->ghostwin, "Blender"); -#ifdef __APPLE__ + /* Informs GHOST of unsaved changes, to set window modified visual indicator (MAC OS X) + and to give hint of unsaved changes for a user warning mechanism + in case of OS application terminate request (e.g. OS Shortcut Alt+F4, Cmd+Q, (...), or session end) */ + GHOST_SetWindowModifiedState(win->ghostwin, (GHOST_TUns8)!wm->file_saved); + +#if defined(__APPLE__) && !defined(GHOST_COCOA) if(wm->file_saved) GHOST_SetWindowState(win->ghostwin, GHOST_kWindowStateUnModified); else @@ -292,7 +298,7 @@ static void wm_window_add_ghostwindow(wmWindowManager *wm, char *title, wmWindow // inital_state = GHOST_kWindowStateMaximized; inital_state = GHOST_kWindowStateNormal; -#ifdef __APPLE__ +#if defined(__APPLE__) && !defined(GHOST_COCOA) { extern int macPrefState; /* creator.c */ inital_state += macPrefState; @@ -339,7 +345,8 @@ void wm_window_add_ghostwindows(wmWindowManager *wm) if (!prefsizx) { wm_get_screensize(&prefsizx, &prefsizy); -#ifdef __APPLE__ +#if defined(__APPLE__) && !defined(GHOST_COCOA) +//Cocoa provides functions to get correct max window size { extern void wm_set_apple_prefsize(int, int); /* wm_apple.c */ From 3816554cbc1a40dc5199c8e56e45817ec09128d5 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Mon, 5 Oct 2009 13:25:56 +0000 Subject: [PATCH 102/138] General particle bug fixes + few small goodies The goodies: * Curves can be used as normal dynamic effectors too with the new "curve" field shape. * Group visualization has optional duplication counts for each object in the specified group. * Object & group visualizations, which are done without taking the dupliobject's global position into account (unless the whole group is used). This is much nicer than the previous behavior, but I added a "Use Global Location" option for those who want to use it the old way. * The active particle system's particles are now drawn a with theme coloured outline instead of pure white. * Added object aligned velocity factors (buttons categorized and re-organized too). Bug fixes: * Absorption didn't work as the ui toggle button was forgotten. * Some other force field ui tweaks. * Crash after adding children and changing trails count. * Display types "cross" and "axis" crashed. * Particles weren't drawn with correct coloring. * Billboards didn't update properly in viewport to camera location changes. * Particle rotation wasn't recreated correctly from point cache. * Changing particles amount crashed sometimes. * Some files with child hair crashed on loading. * Compiler warning fixes. * Adding boids crashed on frame 1; --- release/scripts/ui/buttons_particle.py | 106 ++-- release/scripts/ui/buttons_physics_common.py | 5 +- source/blender/blenkernel/BKE_bvhutils.h | 4 + source/blender/blenkernel/BKE_effect.h | 1 + source/blender/blenkernel/BKE_particle.h | 2 + source/blender/blenkernel/intern/anim.c | 43 +- source/blender/blenkernel/intern/boids.c | 5 +- source/blender/blenkernel/intern/bvhutils.c | 88 +++ source/blender/blenkernel/intern/effect.c | 21 +- source/blender/blenkernel/intern/modifier.c | 8 +- source/blender/blenkernel/intern/particle.c | 81 ++- .../blenkernel/intern/particle_system.c | 28 +- source/blender/blenkernel/intern/pointcache.c | 24 +- source/blender/blenloader/intern/readfile.c | 7 + source/blender/blenloader/intern/writefile.c | 5 + .../blender/editors/physics/particle_object.c | 76 +++ .../blender/editors/physics/physics_intern.h | 3 + source/blender/editors/physics/physics_ops.c | 3 + .../blender/editors/space_view3d/drawobject.c | 519 ++++++++++-------- source/blender/makesdna/DNA_object_force.h | 4 +- source/blender/makesdna/DNA_particle_types.h | 16 +- .../makesrna/intern/rna_object_force.c | 35 +- source/blender/makesrna/intern/rna_particle.c | 131 ++++- 23 files changed, 883 insertions(+), 332 deletions(-) diff --git a/release/scripts/ui/buttons_particle.py b/release/scripts/ui/buttons_particle.py index 1a800fc4dfd..81ddab40ec9 100644 --- a/release/scripts/ui/buttons_particle.py +++ b/release/scripts/ui/buttons_particle.py @@ -121,17 +121,19 @@ class PARTICLE_PT_emission(ParticleButtonsPanel): layout.enabled = particle_panel_enabled(psys) and not psys.multiple_caches row = layout.row() + row.active = part.distribution != 'GRID' row.itemR(part, "amount") - split = layout.split() - - col = split.column(align=True) - col.itemR(part, "start") - col.itemR(part, "end") + if part.type != 'HAIR': + split = layout.split() + + col = split.column(align=True) + col.itemR(part, "start") + col.itemR(part, "end") - col = split.column(align=True) - col.itemR(part, "lifetime") - col.itemR(part, "random_lifetime", slider=True) + col = split.column(align=True) + col.itemR(part, "lifetime") + col.itemR(part, "random_lifetime", slider=True) layout.row().itemL(text="Emit From:") @@ -221,7 +223,7 @@ class PARTICLE_PT_cache(ParticleButtonsPanel): point_cache_ui(self, psys.point_cache, particle_panel_enabled(psys), not psys.hair_dynamics, 0) -class PARTICLE_PT_initial(ParticleButtonsPanel): +class PARTICLE_PT_velocity(ParticleButtonsPanel): __label__ = "Velocity" def poll(self, context): @@ -238,48 +240,66 @@ class PARTICLE_PT_initial(ParticleButtonsPanel): part = psys.settings layout.enabled = particle_panel_enabled(psys) - - layout.row().itemL(text="Direction:") split = layout.split() sub = split.column() + sub.itemL(text="Emitter Geometry:") sub.itemR(part, "normal_factor") + subsub = sub.column(align=True) + subsub.itemR(part, "tangent_factor") + subsub.itemR(part, "tangent_phase", slider=True) + + sub = split.column() + sub.itemL(text="Emitter Object") + sub.itemR(part, "object_aligned_factor", text="") + + layout.row().itemL(text="Other:") + split = layout.split() + sub = split.column() if part.emit_from=='PARTICLE': sub.itemR(part, "particle_factor") else: sub.itemR(part, "object_factor", slider=True) + sub = split.column() sub.itemR(part, "random_factor") - sub.itemR(part, "tangent_factor") - sub.itemR(part, "tangent_phase", slider=True) - sub = split.column() - sub.itemL(text="TODO:") - sub.itemL(text="Object aligned") - sub.itemL(text="direction: X, Y, Z") + #if part.type=='REACTOR': + # sub.itemR(part, "reactor_factor") + # sub.itemR(part, "reaction_shape", slider=True) - if part.type=='REACTOR': - sub.itemR(part, "reactor_factor") - sub.itemR(part, "reaction_shape", slider=True) +class PARTICLE_PT_rotation(ParticleButtonsPanel): + __label__ = "Rotation" + + def poll(self, context): + if particle_panel_poll(context): + psys = context.particle_system + return psys.settings.physics_type != 'BOIDS' and not psys.point_cache.external else: - sub.itemL(text="") + return False + + def draw(self, context): + layout = self.layout + + psys = context.particle_system + part = psys.settings - layout.row().itemL(text="Rotation:") + layout.enabled = particle_panel_enabled(psys) + + split = layout.split() + split.itemL(text="Initial Rotation:") + split.itemR(part, "rotation_dynamic") split = layout.split() - sub = split.column() - - sub.itemR(part, "rotation_mode", text="Axis") - split = layout.split() + sub = split.column(align=True) + sub.itemR(part, "rotation_mode", text="") + sub.itemR(part, "random_rotation_factor", slider=True, text="Random") - sub = split.column() - sub.itemR(part, "rotation_dynamic") - sub.itemR(part, "random_rotation_factor", slider=True) - sub = split.column() + sub = split.column(align=True) sub.itemR(part, "phase_factor", slider=True) sub.itemR(part, "random_phase_factor", text="Random", slider=True) - layout.row().itemL(text="Angular velocity:") + layout.row().itemL(text="Angular Velocity:") layout.row().itemR(part, "angular_velocity_mode", expand=True) split = layout.split() @@ -607,16 +627,37 @@ class PARTICLE_PT_render(ParticleButtonsPanel): elif part.ren_as == 'OBJECT': sub.itemR(part, "dupli_object") + sub.itemR(part, "use_global_dupli") elif part.ren_as == 'GROUP': sub.itemR(part, "dupli_group") split = layout.split() sub = split.column() sub.itemR(part, "whole_group") + colsub = sub.column() + colsub.active = part.whole_group == False + colsub.itemR(part, "use_group_count") + sub = split.column() colsub = sub.column() colsub.active = part.whole_group == False + colsub.itemR(part, "use_global_dupli") colsub.itemR(part, "rand_group") + if part.use_group_count and not part.whole_group: + row = layout.row() + row.template_list(part, "dupliweights", part, "active_dupliweight_index") + + col = row.column() + subrow = col.row() + subcol = subrow.column(align=True) + subcol.itemO("particle.dupliob_move_up", icon='VICON_MOVE_UP', text="") + subcol.itemO("particle.dupliob_move_down", icon='VICON_MOVE_DOWN', text="") + + weight = part.active_dupliweight + if weight: + row = layout.row() + row.itemR(weight, "count") + elif part.ren_as == 'BILLBOARD': sub.itemL(text="Align:") @@ -898,7 +939,8 @@ bpy.types.register(PARTICLE_PT_particles) bpy.types.register(PARTICLE_PT_hair_dynamics) bpy.types.register(PARTICLE_PT_cache) bpy.types.register(PARTICLE_PT_emission) -bpy.types.register(PARTICLE_PT_initial) +bpy.types.register(PARTICLE_PT_velocity) +bpy.types.register(PARTICLE_PT_rotation) bpy.types.register(PARTICLE_PT_physics) bpy.types.register(PARTICLE_PT_boidbrain) bpy.types.register(PARTICLE_PT_render) diff --git a/release/scripts/ui/buttons_physics_common.py b/release/scripts/ui/buttons_physics_common.py index b65d092fcfa..17ac1b2bbaa 100644 --- a/release/scripts/ui/buttons_physics_common.py +++ b/release/scripts/ui/buttons_physics_common.py @@ -78,7 +78,7 @@ def effector_weights_ui(self, weights): layout.itemS() flow = layout.column_flow() - flow.itemR(weights, "spherical", slider=True) + flow.itemR(weights, "force", slider=True) flow.itemR(weights, "vortex", slider=True) flow.itemR(weights, "magnetic", slider=True) flow.itemR(weights, "wind", slider=True) @@ -110,7 +110,7 @@ def basic_force_field_settings_ui(self, field): col.itemR(field, "flow") elif field.type == 'HARMONIC': col.itemR(field, "harmonic_damping", text="Damping") - elif field.type == 'VORTEX' and field.shape == 'PLANE': + elif field.type == 'VORTEX' and field.shape != 'POINT': col.itemR(field, "inflow") elif field.type == 'DRAG': col.itemR(field, "quadratic_drag", text="Quadratic") @@ -140,6 +140,7 @@ def basic_force_field_falloff_ui(self, field): col.itemR(field, "z_direction", text="") col.itemR(field, "use_min_distance", text="Use Minimum") col.itemR(field, "use_max_distance", text="Use Maximum") + col.itemR(field, "do_absorption") col = split.column() col.itemR(field, "falloff_power", text="Power") diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h index 66c8d99959a..e2911a30b25 100644 --- a/source/blender/blenkernel/BKE_bvhutils.h +++ b/source/blender/blenkernel/BKE_bvhutils.h @@ -57,6 +57,7 @@ typedef struct BVHTreeFromMesh /* Vertex array, so that callbacks have instante access to data */ struct MVert *vert; + struct MEdge *edge; /* only used for BVHTreeFromMeshEdges */ struct MFace *face; /* radius for raycast */ @@ -96,6 +97,8 @@ BVHTree* bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct DerivedMes */ BVHTree* bvhtree_from_mesh_faces(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis); +BVHTree* bvhtree_from_mesh_edges(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis); + /* * Frees data allocated by a call to bvhtree_from_mesh_*. */ @@ -109,6 +112,7 @@ void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data); //Using local coordinates #define BVHTREE_FROM_FACES 0 #define BVHTREE_FROM_VERTICES 1 +#define BVHTREE_FROM_EDGES 2 typedef LinkNode* BVHCache; diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index 83ec7c13946..9a0a724ab9a 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -138,6 +138,7 @@ int get_effector_data(struct EffectorCache *eff, struct EffectorData *efd, struc /* EffectedPoint->flag */ #define PE_WIND_AS_SPEED 1 #define PE_DYNAMIC_ROTATION 2 +#define PE_USE_NORMAL_DATA 4 /* EffectorData->flag */ #define PE_VELOCITY_TO_IMPULSE 1 diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index e0259ff10dd..e9285782a1e 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -201,6 +201,8 @@ struct Object *psys_get_lattice(struct ParticleSimulationData *sim); int psys_in_edit_mode(struct Scene *scene, struct ParticleSystem *psys); int psys_check_enabled(struct Object *ob, struct ParticleSystem *psys); +void psys_check_group_weights(struct ParticleSettings *part); + /* free */ void psys_free_settings(struct ParticleSettings *part); void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit); diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index bd779935d55..5cd901066f8 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -776,6 +776,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p GroupObject *go; Object *ob=0, **oblist=0, obcopy, *obcopylist=0; DupliObject *dob; + ParticleDupliWeight *dw; ParticleSimulationData sim = {scene, par, psys, psys_get_modifier(par, psys)}; ParticleSettings *part; ParticleData *pa; @@ -783,7 +784,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p ParticleKey state; ParticleCacheKey *cache; float ctime, pa_time, scale = 1.0f; - float tmat[4][4], mat[4][4], pamat[4][4], size=0.0; + float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size=0.0; float (*obmat)[4], (*oldobmat)[4]; int lay, a, b, counter, hair = 0; int totpart, totchild, totgroup=0, pa_num; @@ -813,6 +814,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p ((part->ren_as == PART_DRAW_OB && part->dup_ob) || (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first))) { + psys_check_group_weights(part); + /* if we have a hair particle system, use the path cache */ if(part->type == PART_HAIR) { if(psys->flag & PSYS_HAIR_DONE) @@ -831,18 +834,37 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p if(part->ren_as==PART_DRAW_GR) { group_handle_recalc_and_update(scene, par, part->dup_group); - for(go=part->dup_group->gobject.first; go; go=go->next) - totgroup++; + if(part->draw & PART_DRAW_COUNT_GR) { + for(dw=part->dupliweights.first; dw; dw=dw->next) + totgroup += dw->count; + } + else { + for(go=part->dup_group->gobject.first; go; go=go->next) + totgroup++; + } /* we also copy the actual objects to restore afterwards, since * where_is_object_time will change the object which breaks transform */ oblist = MEM_callocN(totgroup*sizeof(Object *), "dupgroup object list"); obcopylist = MEM_callocN(totgroup*sizeof(Object), "dupgroup copy list"); - go = part->dup_group->gobject.first; - for(a=0; anext) { - oblist[a] = go->ob; - obcopylist[a] = *go->ob; + + if(part->draw & PART_DRAW_COUNT_GR && totgroup) { + dw = part->dupliweights.first; + + for(a=0; anext) { + for(b=0; bcount; b++, a++) { + oblist[a] = dw->ob; + obcopylist[a] = *dw->ob; + } + } + } + else { + go = part->dup_group->gobject.first; + for(a=0; anext) { + oblist[a] = go->ob; + obcopylist[a] = *go->ob; + } } } else { @@ -936,11 +958,18 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p else { /* to give ipos in object correct offset */ where_is_object_time(scene, ob, ctime-pa_time); + + VECCOPY(vec, obmat[3]); + obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f; Mat4CpyMat4(mat, pamat); Mat4MulMat4(tmat, obmat, mat); Mat4MulFloat3((float *)tmat, size*scale); + + if(part->draw & PART_DRAW_GLOBAL_OB) + VECADD(tmat[3], tmat[3], vec); + if(par_space_mat) Mat4MulMat4(mat, tmat, par_space_mat); else diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index 76824d3a34a..712fb13cfc0 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -73,13 +73,11 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, { BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid*) rule; BoidSettings *boids = bbd->part->boids; - Object *priority_ob = NULL; BoidParticle *bpa = pa->boid; EffectedPoint epoint; ListBase *effectors = bbd->sim->psys->effectors; EffectorCache *cur, *eff = NULL; EffectorData efd, cur_efd; - float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f}; float mul = (rule->type == eBoidRuleType_Avoid ? 1.0 : -1.0); float priority = 0.0f, len = 0.0f; int ret = 0; @@ -1051,9 +1049,8 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) float wanted_dir[3]; float q[4], mat[3][3]; /* rotation */ float ground_co[3] = {0.0f, 0.0f, 0.0f}, ground_nor[3] = {0.0f, 0.0f, 1.0f}; - float force[3] = {0.0f, 0.0f, 0.0f}, tvel[3] = {0.0f, 0.0f, 1.0f}; + float force[3] = {0.0f, 0.0f, 0.0f}; float pa_mass=bbd->part->mass, dtime=bbd->dfra*bbd->timestep; - int p = pa - bbd->sim->psys->particles; set_boid_values(&val, boids, pa); diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index d9e005811d0..f2526231d50 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -479,6 +479,32 @@ static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *r } while(t2); } +// Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_edges. +// userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. +static void mesh_edges_nearest_point(void *userdata, int index, const float *co, BVHTreeNearest *nearest) +{ + const BVHTreeFromMesh *data = (BVHTreeFromMesh*) userdata; + MVert *vert = data->vert; + MEdge *edge = data->edge + index; + float nearest_tmp[3], dist; + + float *t0, *t1; + t0 = vert[ edge->v1 ].co; + t1 = vert[ edge->v2 ].co; + + PclosestVL3Dfl(nearest_tmp, co, t0, t1); + dist = VecLenf(nearest_tmp, co); + + if(dist < nearest->dist) + { + nearest->index = index; + nearest->dist = dist; + VECCOPY(nearest->co, nearest_tmp); + VecSubf(nearest->no, t0, t1); + Normalize(nearest->no); + } +} + /* * BVH builders */ @@ -605,6 +631,68 @@ BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float } +// Builds a bvh tree.. where nodes are the faces of the given mesh. +BVHTree* bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis) +{ + BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_EDGES); + + //Not in cache + if(tree == NULL) + { + int i; + int numEdges= mesh->getNumEdges(mesh); + MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT); + MEdge *edge = mesh->getEdgeDataArray(mesh, CD_MEDGE); + + if(vert != NULL && edge != NULL) + { + /* Create a bvh-tree of the given target */ + tree = BLI_bvhtree_new(numEdges, epsilon, tree_type, axis); + if(tree != NULL) + { + for(i = 0; i < numEdges; i++) + { + float co[4][3]; + VECCOPY(co[0], vert[ edge[i].v1 ].co); + VECCOPY(co[1], vert[ edge[i].v2 ].co); + + BLI_bvhtree_insert(tree, i, co[0], 2); + } + BLI_bvhtree_balance(tree); + + //Save on cache for later use +// printf("BVHTree built and saved on cache\n"); + bvhcache_insert(&mesh->bvhCache, tree, BVHTREE_FROM_EDGES); + } + } + } + else + { +// printf("BVHTree is already build, using cached tree\n"); + } + + + //Setup BVHTreeFromMesh + memset(data, 0, sizeof(*data)); + data->tree = tree; + + if(data->tree) + { + data->cached = TRUE; + + data->nearest_callback = mesh_edges_nearest_point; + data->raycast_callback = NULL; + + data->mesh = mesh; + data->vert = mesh->getVertDataArray(mesh, CD_MVERT); + data->edge = mesh->getEdgeDataArray(mesh, CD_MEDGE); + + data->sphere_radius = epsilon; + } + return data->tree; + +} + // Frees data allocated by a call to bvhtree_from_mesh_*. void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data) { diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 7cc65de827a..9b648e2c05c 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -228,6 +228,8 @@ static void precalculate_effector(EffectorCache *eff) } else if(eff->pd->shape == PFIELD_SHAPE_SURFACE) { eff->surmd = (SurfaceModifierData *)modifiers_findByType ( eff->ob, eModifierType_Surface ); + if(eff->ob->type == OB_CURVE) + eff->flag |= PE_USE_NORMAL_DATA; } else if(eff->psys) psys_update_particle_tree(eff->psys, eff->scene->r.cfra); @@ -518,7 +520,7 @@ float effector_falloff(EffectorCache *eff, EffectorData *efd, EffectedPoint *poi float falloff = weights ? weights->weight[0] * weights->weight[eff->pd->forcefield] : 1.0f; float fac, r_fac; - fac = Inpf(efd->nor, efd->vec_to_point); + fac = Inpf(efd->nor, efd->vec_to_point2); if(eff->pd->zdir == PFIELD_Z_POS && fac < 0.0f) falloff=0.0f; @@ -691,10 +693,16 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin VecSubf(efd->vec_to_point, point->loc, efd->loc); efd->distance = VecLength(efd->vec_to_point); - /* for some effectors we need the object center every time */ - VecSubf(efd->vec_to_point2, point->loc, eff->ob->obmat[3]); - VECCOPY(efd->nor2, eff->ob->obmat[2]); - Normalize(efd->nor2); + if(eff->flag & PE_USE_NORMAL_DATA) { + VECCOPY(efd->vec_to_point2, efd->vec_to_point); + VECCOPY(efd->nor2, efd->nor); + } + else { + /* for some effectors we need the object center every time */ + VecSubf(efd->vec_to_point2, point->loc, eff->ob->obmat[3]); + VECCOPY(efd->nor2, eff->ob->obmat[2]); + Normalize(efd->nor2); + } } return ret; @@ -835,8 +843,7 @@ void do_physical_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint * switch(pd->forcefield){ case PFIELD_WIND: - Normalize(force); - strength *= (Inpf(force, efd->nor) >= 0.0f ? 1.0f : -1.0f); + VECCOPY(force, efd->nor); VecMulf(force, strength * efd->falloff); break; case PFIELD_FORCE: diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 3b47c2f1830..55fb9f45bb3 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -6211,7 +6211,8 @@ static void surfaceModifier_freeData(ModifierData *md) MEM_freeN(surmd->bvhtree); } - surmd->dm->release(surmd->dm); + if(surmd->dm) + surmd->dm->release(surmd->dm); if(surmd->x) MEM_freeN(surmd->x); @@ -6298,7 +6299,10 @@ static void surfaceModifier_deformVerts( else surmd->bvhtree = MEM_callocN(sizeof(BVHTreeFromMesh), "BVHTreeFromMesh"); - bvhtree_from_mesh_faces(surmd->bvhtree, surmd->dm, 0.0, 2, 6); + if(surmd->dm->getNumFaces(surmd->dm)) + bvhtree_from_mesh_faces(surmd->bvhtree, surmd->dm, 0.0, 2, 6); + else + bvhtree_from_mesh_edges(surmd->bvhtree, surmd->dm, 0.0, 2, 6); } } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index f4f5a1364a3..011d5c3f134 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -37,6 +37,7 @@ #include "DNA_scene_types.h" #include "DNA_boid_types.h" +#include "DNA_group_types.h" #include "DNA_particle_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -63,6 +64,7 @@ #include "BKE_cloth.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_group.h" #include "BKE_main.h" #include "BKE_lattice.h" #include "BKE_utildefines.h" @@ -296,6 +298,60 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys) return 1; } +void psys_check_group_weights(ParticleSettings *part) +{ + ParticleDupliWeight *dw, *tdw; + GroupObject *go; + int current = 0; + + if(part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first) { + /* first remove all weights that don't have an object in the group */ + dw = part->dupliweights.first; + while(dw) { + if(!object_in_group(dw->ob, part->dup_group)) { + tdw = dw->next; + BLI_freelinkN(&part->dupliweights, dw); + dw = tdw; + } + else + dw = dw->next; + } + + /* then add objects in the group to new list */ + go = part->dup_group->gobject.first; + while(go) { + dw = part->dupliweights.first; + while(dw && dw->ob != go->ob) + dw = dw->next; + + if(!dw) { + dw = MEM_callocN(sizeof(ParticleDupliWeight), "ParticleDupliWeight"); + dw->ob = go->ob; + dw->count = 1; + BLI_addtail(&part->dupliweights, dw); + } + + go = go->next; + } + + dw = part->dupliweights.first; + for(; dw; dw=dw->next) { + if(dw->flag & PART_DUPLIW_CURRENT) { + current = 1; + break; + } + } + + if(!current) { + dw = part->dupliweights.first; + if(dw) + dw->flag |= PART_DUPLIW_CURRENT; + } + } + else { + BLI_freelistN(&part->dupliweights); + } +} /************************************************/ /* Freeing stuff */ /************************************************/ @@ -307,6 +363,8 @@ void psys_free_settings(ParticleSettings *part) if(part->effector_weights) MEM_freeN(part->effector_weights); + BLI_freelistN(&part->dupliweights); + boid_free_settings(part->boids); } @@ -439,6 +497,9 @@ void psys_free_pdd(ParticleSystem *psys) if(psys->pdd->vedata) MEM_freeN(psys->pdd->vedata); psys->pdd->vedata = NULL; + + psys->pdd->totpoint = 0; + psys->pdd->tot_vec_size = 0; } } /* free everything */ @@ -2047,10 +2108,10 @@ static void do_rough_end(float *loc, float mat[4][4], float t, float fac, float float roughfac; roughfac=fac*(float)pow((double)t,shape); - VECCOPY(rough,loc); + Vec2Copyf(rough,loc); rough[0]=-1.0f+2.0f*rough[0]; rough[1]=-1.0f+2.0f*rough[1]; - VecMulf(rough,roughfac); + Vec2Mulf(rough,roughfac); VECADDFAC(state->co,state->co,mat[0],rough[0]); VECADDFAC(state->co,state->co,mat[1],rough[1]); @@ -3235,6 +3296,9 @@ static void default_particle_settings(ParticleSettings *part) part->size=0.05; part->childsize=1.0; + part->rotmode = PART_ROT_VEL; + part->avemode = PART_AVE_SPIN; + part->child_nbr=10; part->ren_child_nbr=100; part->childrad=0.2f; @@ -3788,6 +3852,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * /* get different child parameters from textures & vgroups */ memset(&ctx, 0, sizeof(ParticleThreadContext)); + ctx.sim = *sim; ctx.dm = psmd->dm; ctx.ma = ma; /* TODO: assign vertex groups */ @@ -3856,6 +3921,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta ChildParticle *cpa = NULL; float cfra; int totpart = psys->totpart; + float timestep = psys_get_timestep(sim); /* negative time means "use current time" */ cfra = state->time > 0 ? state->time : bsystem_time(sim->scene, 0, (float)sim->scene->r.cfra, 0.0); @@ -3924,13 +3990,14 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta calc_latt_deform(sim->psys->lattice, state->co,1.0f); } else{ - if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED)) + if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED) + || pa->prev_state.time <= 0.0f) copy_particle_key(state, &pa->state, 1); else if(pa->prev_state.time==state->time) copy_particle_key(state, &pa->prev_state, 1); else { /* let's interpolate to try to be as accurate as possible */ - if(pa->state.time + 1.0f > state->time && pa->prev_state.time - 1.0f < state->time) { + if(pa->state.time + 2.0f > state->time && pa->prev_state.time - 2.0f < state->time) { ParticleKey keys[4]; float dfra, keytime, frs_sec = sim->scene->r.frs_sec; @@ -3949,13 +4016,13 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta keytime = (state->time - keys[1].time) / dfra; /* convert velocity to timestep size */ - VecMulf(keys[1].vel, dfra / frs_sec); - VecMulf(keys[2].vel, dfra / frs_sec); + VecMulf(keys[1].vel, dfra * timestep); + VecMulf(keys[2].vel, dfra * timestep); psys_interpolate_particle(-1, keys, keytime, state, 1); /* convert back to real velocity */ - VecMulf(state->vel, frs_sec / dfra); + VecMulf(state->vel, 1.0f / (dfra * timestep)); VecLerpf(state->ave, keys[1].ave, keys[2].ave, keytime); QuatInterpol(state->rot, keys[1].rot, keys[2].rot, keytime); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index d757372f17b..45050127582 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -183,6 +183,8 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart) if(totpart && totpart != psys->totpart) { newpars= MEM_callocN(totpart*sizeof(ParticleData), "particles"); + if(psys->part->phystype == PART_PHYS_BOIDS) + newboids= MEM_callocN(totpart*sizeof(BoidParticle), "boid particles"); if(psys->particles) { totsaved=MIN2(psys->totpart,totpart); @@ -215,13 +217,12 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart) } psys->particles=newpars; + psys->totpart=totpart; if(newboids) { LOOP_PARTICLES pa->boid = newboids++; } - - psys->totpart=totpart; } if(psys->child) { @@ -1660,7 +1661,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, ParticleKey state; //IpoCurve *icu=0; // XXX old animation system float fac, phasefac, nor[3]={0,0,0},loc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4]; - float r_vel[3],r_ave[3],r_rot[4],p_vel[3]={0.0,0.0,0.0}; + float r_vel[3],r_ave[3],r_rot[4],vec[3],p_vel[3]={0.0,0.0,0.0}; float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0}; float q_phase[4], r_phase; int p = pa - psys->particles; @@ -1773,7 +1774,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, } } - if(part->phystype==PART_PHYS_BOIDS) { + if(part->phystype==PART_PHYS_BOIDS && pa->boid) { BoidParticle *bpa = pa->boid; float dvec[3], q[4], mat[3][3]; @@ -1839,6 +1840,23 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, VECADDFAC(vel,vel,vtan,part->tanfac); //VECADDFAC(vel,vel,vtan,part->tanfac*(vg_tan?psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_tan):1.0f)); + /* *emitter object orientation */ + if(part->ob_vel[0]!=0.0) { + VECCOPY(vec, ob->obmat[0]); + Normalize(vec); + VECADDFAC(vel, vel, vec, part->ob_vel[0]); + } + if(part->ob_vel[1]!=0.0) { + VECCOPY(vec, ob->obmat[1]); + Normalize(vec); + VECADDFAC(vel, vel, vec, part->ob_vel[1]); + } + if(part->ob_vel[2]!=0.0) { + VECCOPY(vec, ob->obmat[2]); + Normalize(vec); + VECADDFAC(vel, vel, vec, part->ob_vel[2]); + } + /* *texture */ /* TODO */ @@ -3135,7 +3153,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) ParticleSystem *psys = sim->psys; ParticleSettings *part=psys->part; KDTree *tree=0; - //IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system + //IpoCurve *icu_esize=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system /* Material *ma=give_current_material(sim->ob, part->omat); */ BoidBrainData bbd; PARTICLE_P; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index bffe4566f74..fa0d5cba604 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -269,7 +269,7 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr /* determine rotation from velocity */ if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) { - vectoquat(pa->state.vel, OB_POSX, OB_POSZ, pa->state.rot); + vectoquat(pa->state.vel, OB_NEGX, OB_POSZ, pa->state.rot); } } static void ptcache_interpolate_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) @@ -292,6 +292,23 @@ static void ptcache_interpolate_particle(int index, void *psys_v, void **data, f else BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2); + /* determine velocity from previous location */ + if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { + if(keys[1].time > keys[2].time) { + VecSubf(keys[2].vel, keys[1].co, keys[2].co); + VecMulf(keys[2].vel, (keys[1].time - keys[2].time) / frs_sec); + } + else { + VecSubf(keys[2].vel, keys[2].co, keys[1].co); + VecMulf(keys[2].vel, (keys[2].time - keys[1].time) / frs_sec); + } + } + + /* determine rotation from velocity */ + if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) { + vectoquat(keys[2].vel, OB_NEGX, OB_POSZ, keys[2].rot); + } + if(cfra > pa->time) cfra1 = MAX2(cfra1, pa->time); @@ -301,7 +318,7 @@ static void ptcache_interpolate_particle(int index, void *psys_v, void **data, f VecMulf(keys[2].vel, dfra / frs_sec); psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1); - QuatInterpol(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra); + QuatInterpol(pa->state.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra); VecMulf(pa->state.vel, frs_sec / dfra); @@ -594,7 +611,8 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p if(psys->part->phystype == PART_PHYS_BOIDS) pid->data_types|= (1<part->rotmode || psys->part->avemode) + if(psys->part->rotmode!=PART_ROT_VEL + || psys->part->avemode!=PART_AVE_SPIN || psys->part->avefac!=0.0f) pid->data_types|= (1<part->flag & PART_ROT_DYN) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index a3a56e9a075..989e2b3fa9e 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3033,6 +3033,7 @@ static void direct_link_pointcache_list(FileData *fd, ListBase *ptcaches, PointC static void lib_link_particlesettings(FileData *fd, Main *main) { ParticleSettings *part; + ParticleDupliWeight *dw; part= main->particle.first; while(part) { @@ -3048,6 +3049,10 @@ static void lib_link_particlesettings(FileData *fd, Main *main) if(part->effector_weights) part->effector_weights->group = newlibadr(fd, part->id.lib, part->effector_weights->group); + dw = part->dupliweights.first; + for(; dw; dw=dw->next) + dw->ob = newlibadr(fd, part->id.lib, dw->ob); + if(part->boids) { BoidState *state = part->boids->states.first; BoidRule *rule; @@ -3088,6 +3093,8 @@ static void direct_link_particlesettings(FileData *fd, ParticleSettings *part) else part->effector_weights = BKE_add_effector_weights(part->eff_group); + link_list(fd, &part->dupliweights); + part->boids= newdataadr(fd, part->boids); if(part->boids) { diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 1f46446dc2a..c92c0909d3b 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -610,6 +610,7 @@ static void write_pointcaches(WriteData *wd, ListBase *ptcaches) static void write_particlesettings(WriteData *wd, ListBase *idbase) { ParticleSettings *part; + ParticleDupliWeight *dw; part= idbase->first; while(part) { @@ -622,6 +623,10 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase) writestruct(wd, DATA, "PartDeflect", 1, part->pd2); writestruct(wd, DATA, "EffectorWeights", 1, part->effector_weights); + dw = part->dupliweights.first; + for(; dw; dw=dw->next) + writestruct(wd, DATA, "ParticleDupliWeight", 1, dw); + if(part->boids && part->phystype == PART_PHYS_BOIDS) { BoidState *state = part->boids->states.first; diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index cef630b6711..1dc08a162b7 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -348,6 +348,82 @@ void PARTICLE_OT_target_move_down(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } +/************************ move up particle dupliweight operator *********************/ + +static int dupliob_move_up_exec(bContext *C, wmOperator *op) +{ + PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); + ParticleSystem *psys= ptr.data; + ParticleSettings *part; + ParticleDupliWeight *dw; + + if(!psys) + return OPERATOR_CANCELLED; + + part = psys->part; + for(dw=part->dupliweights.first; dw; dw=dw->next) { + if(dw->flag & PART_DUPLIW_CURRENT && dw->prev) { + BLI_remlink(&part->dupliweights, dw); + BLI_insertlink(&part->dupliweights, dw->prev->prev, dw); + + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL); + break; + } + } + + return OPERATOR_FINISHED; +} + +void PARTICLE_OT_dupliob_move_up(wmOperatorType *ot) +{ + ot->name= "Move Up Dupli Object"; + ot->idname= "PARTICLE_OT_dupliob_move_up"; + ot->description= "Move dupli object up in the list."; + + ot->exec= dupliob_move_up_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/************************ move down particle dupliweight operator *********************/ + +static int dupliob_move_down_exec(bContext *C, wmOperator *op) +{ + PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); + ParticleSystem *psys= ptr.data; + ParticleSettings *part; + ParticleDupliWeight *dw; + + if(!psys) + return OPERATOR_CANCELLED; + + part = psys->part; + for(dw=part->dupliweights.first; dw; dw=dw->next) { + if(dw->flag & PART_DUPLIW_CURRENT && dw->next) { + BLI_remlink(&part->dupliweights, dw); + BLI_insertlink(&part->dupliweights, dw->next, dw); + + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL); + break; + } + } + + return OPERATOR_FINISHED; +} + +void PARTICLE_OT_dupliob_move_down(wmOperatorType *ot) +{ + ot->name= "Move Down Dupli Object"; + ot->idname= "PARTICLE_OT_dupliob_move_down"; + ot->description= "Move dupli object down in the list."; + + ot->exec= dupliob_move_down_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + /************************ connect/disconnect hair operators *********************/ static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys) diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h index 956f26c478d..3847ec8032a 100644 --- a/source/blender/editors/physics/physics_intern.h +++ b/source/blender/editors/physics/physics_intern.h @@ -77,6 +77,9 @@ void PARTICLE_OT_target_move_down(struct wmOperatorType *ot); void PARTICLE_OT_connect_hair(struct wmOperatorType *ot); void PARTICLE_OT_disconnect_hair(struct wmOperatorType *ot); +void PARTICLE_OT_dupliob_move_up(struct wmOperatorType *ot); +void PARTICLE_OT_dupliob_move_down(struct wmOperatorType *ot); + /* particle_boids.c */ void BOID_OT_rule_add(struct wmOperatorType *ot); void BOID_OT_rule_del(struct wmOperatorType *ot); diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c index a62d3d8fd78..ddc5fb9c9b6 100644 --- a/source/blender/editors/physics/physics_ops.c +++ b/source/blender/editors/physics/physics_ops.c @@ -78,6 +78,9 @@ static void operatortypes_particle(void) WM_operatortype_append(PARTICLE_OT_target_move_down); WM_operatortype_append(PARTICLE_OT_connect_hair); WM_operatortype_append(PARTICLE_OT_disconnect_hair); + + WM_operatortype_append(PARTICLE_OT_dupliob_move_up); + WM_operatortype_append(PARTICLE_OT_dupliob_move_down); } static void keymap_particle(wmWindowManager *wm) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 0f2a57d881c..0659b5cfd11 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -3358,7 +3358,30 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas } /* *********** drawing for particles ************* */ +static void draw_particle_arrays(int draw_as, int totpoint, int ob_dt, int select) +{ + /* draw created data arrays */ + 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(ob_dt<=OB_WIRE || select) + glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); + else + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glDrawArrays(GL_QUADS, 0, 4*totpoint); + break; + default: + glDrawArrays(GL_POINTS, 0, totpoint); + break; + } +} static void draw_particle(ParticleKey *state, int draw_as, short draw, float pixsize, float imat[4][4], float *draw_line, ParticleBillboardData *bb, ParticleDrawData *pdd) { float vec[3], vec2[3]; @@ -3401,7 +3424,7 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix cd[7]=cd[10]=1.0; cd[13]=cd[12]=cd[15]=cd[16]=0.0; cd[14]=cd[17]=1.0; - cd+=18; + pdd->cd+=18; VECCOPY(vec2,state->co); } @@ -3552,7 +3575,13 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if(psys_in_edit_mode(scene, psys) && (pset->flag & PE_DRAW_PART)==0) return; - if(part->draw_as==PART_DRAW_NOT) return; + if(part->draw_as == PART_DRAW_REND) + draw_as = part->ren_as; + else + draw_as = part->draw_as; + + if(draw_as == PART_DRAW_NOT) + return; /* 2. */ sim.psmd = psmd = psys_get_modifier(ob,psys); @@ -3582,26 +3611,22 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if(v3d->zbuf) glDepthMask(1); - if(select) - cpack(0xFFFFFF); - else if((ma) && (part->draw&PART_DRAW_MAT_COL)) { + if((ma) && (part->draw&PART_DRAW_MAT_COL)) { glColor3f(ma->r,ma->g,ma->b); ma_r = ma->r; ma_g = ma->g; ma_b = ma->b; - - if(pdd) { - pdd->ma_r = &ma_r; - pdd->ma_g = &ma_g; - pdd->ma_b = &ma_b; - } - - create_cdata = 1; } else cpack(0); + if(pdd) { + pdd->ma_r = &ma_r; + pdd->ma_g = &ma_g; + pdd->ma_b = &ma_b; + } + timestep= psys_get_timestep(&sim); if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) { @@ -3612,11 +3637,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv totpart=psys->totpart; - if(part->draw_as==PART_DRAW_REND) - draw_as = part->ren_as; - else - draw_as = part->draw_as; - //if(part->flag&PART_GLOB_TIME) cfra=bsystem_time(scene, 0, (float)CFRA, 0.0f); @@ -3646,6 +3666,9 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv pixsize*=2.0; else pixsize*=part->draw_size; + + if(draw_as==PART_DRAW_AXIS) + create_cdata = 1; break; case PART_DRAW_OB: if(part->dup_ob==0) @@ -3693,9 +3716,15 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv Normalize(imat[1]); } + if(!create_cdata && pdd && pdd->cdata) { + MEM_freeN(pdd->cdata); + pdd->cdata = pdd->cd = NULL; + } + /* 4. */ - if(draw_as && draw_as!=PART_DRAW_PATH) { + if(draw_as && ELEM(draw_as, PART_DRAW_PATH, PART_DRAW_CIRC)==0) { int tot_vec_size = (totpart + totchild) * 3 * sizeof(float); + int create_ndata = 0; if(!pdd) pdd = psys->pdd = MEM_callocN(sizeof(ParticleDrawData), "ParticlDrawData"); @@ -3705,37 +3734,36 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv psys_make_temp_pointcache(ob, psys); } + switch(draw_as) { + case PART_DRAW_AXIS: + case PART_DRAW_CROSS: + tot_vec_size *= 6; + if(draw_as != PART_DRAW_CROSS) + create_cdata = 1; + break; + case PART_DRAW_LINE: + tot_vec_size *= 2; + break; + case PART_DRAW_BB: + tot_vec_size *= 4; + create_ndata = 1; + break; + } + if(pdd->tot_vec_size != tot_vec_size) psys_free_pdd(psys); - 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) - if(!pdd->cdata) pdd->cdata = MEM_callocN(tot_vec_size * 6, "particle_cdata"); - if(!pdd->vdata) pdd->vdata = MEM_callocN(tot_vec_size * 6, "particle_vdata"); - break; - case PART_DRAW_LINE: - if(create_cdata) - if(!pdd->cdata) pdd->cdata = MEM_callocN(tot_vec_size * 2, "particle_cdata"); - if(!pdd->vdata) pdd->vdata = MEM_callocN(tot_vec_size * 2, "particle_vdata"); - break; - case PART_DRAW_BB: - if(create_cdata) - if(!pdd->cdata) pdd->cdata = MEM_callocN(tot_vec_size * 4, "particle_cdata"); - if(!pdd->vdata) pdd->vdata = MEM_callocN(tot_vec_size * 4, "particle_vdata"); - if(!pdd->ndata) pdd->ndata = MEM_callocN(tot_vec_size * 4, "particle_vdata"); - break; - default: - if(create_cdata) - if(!pdd->cdata) pdd->cdata=MEM_callocN(tot_vec_size, "particle_cdata"); - if(!pdd->vdata) pdd->vdata=MEM_callocN(tot_vec_size, "particle_vdata"); - } - } + if(!pdd->vdata) + pdd->vdata = MEM_callocN(tot_vec_size, "particle_vdata"); + if(create_cdata && !pdd->cdata) + pdd->cdata = MEM_callocN(tot_vec_size, "particle_cdata"); + if(create_ndata && !pdd->ndata) + pdd->ndata = MEM_callocN(tot_vec_size, "particle_vdata"); if(part->draw & PART_DRAW_VEL && draw_as != PART_DRAW_LINE) { - if(!pdd->vedata) pdd->vedata = MEM_callocN(tot_vec_size * 2, "particle_vedata"); + if(!pdd->vedata) + pdd->vedata = MEM_callocN(2 * (totpart + totchild) * 3 * sizeof(float), "particle_vedata"); + need_v = 1; } @@ -3744,11 +3772,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv pdd->cd= pdd->cdata; pdd->nd= pdd->ndata; pdd->tot_vec_size= tot_vec_size; - - psys->lattice= psys_get_lattice(&sim); } - if(draw_as){ + psys->lattice= psys_get_lattice(&sim); + + if(draw_as!=PART_DRAW_PATH){ /* 5. */ if((pdd->flag & PARTICLE_DRAW_DATA_UPDATED) && (pdd->vedata || part->draw & (PART_DRAW_SIZE|PART_DRAW_NUM|PART_DRAW_HEALTH))==0) { @@ -3836,156 +3864,139 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv r_length = PSYS_FRAND(a + 22); } - if(draw_as!=PART_DRAW_PATH){ - drawn = 0; - if(part->draw_as == PART_DRAW_REND && part->trail_count > 1) { - float length = part->path_end * (1.0 - part->randlength * r_length); - int trail_count = part->trail_count * (1.0 - part->randlength * r_length); - float ct = ((part->draw & PART_ABS_PATH_TIME) ? cfra : pa_time) - length; - float dt = length / (trail_count ? (float)trail_count : 1.0f); - int i=0; + drawn = 0; + if(part->draw_as == PART_DRAW_REND && part->trail_count > 1) { + float length = part->path_end * (1.0 - part->randlength * r_length); + int trail_count = part->trail_count * (1.0 - part->randlength * r_length); + float ct = ((part->draw & PART_ABS_PATH_TIME) ? cfra : pa_time) - length; + float dt = length / (trail_count ? (float)trail_count : 1.0f); + int i=0; - ct+=dt; - for(i=0; i < trail_count; i++, ct += dt) { - if(part->draw & PART_ABS_PATH_TIME) { - if(ct < pa_birthtime || ct > pa_dietime) - continue; - } - else if(ct < 0.0f || ct > 1.0f) + ct+=dt; + for(i=0; i < trail_count; i++, ct += dt) { + if(part->draw & PART_ABS_PATH_TIME) { + if(ct < pa_birthtime || ct > pa_dietime) continue; - - state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : -(pa_birthtime + ct * (pa_dietime - pa_birthtime)); - psys_get_particle_on_path(&sim,a,&state,need_v); - - if(psys->parent) - Mat4MulVecfl(psys->parent->obmat, state.co); - - /* create actiual particle data */ - if(draw_as == PART_DRAW_BB) { - bb.size = pa_size; - bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt); - bb.time = ct; - } - - draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, psys->pdd); - - totpoint++; - drawn = 1; } + else if(ct < 0.0f || ct > 1.0f) + continue; + + state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : -(pa_birthtime + ct * (pa_dietime - pa_birthtime)); + psys_get_particle_on_path(&sim,a,&state,need_v); + + if(psys->parent) + Mat4MulVecfl(psys->parent->obmat, state.co); + + /* create actiual particle data */ + if(draw_as == PART_DRAW_BB) { + bb.size = pa_size; + bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt); + bb.time = ct; + } + + draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, psys->pdd); + + totpoint++; + drawn = 1; } - else - { - state.time=cfra; - if(psys_get_particle_state(&sim,a,&state,0)){ - if(psys->parent) - Mat4MulVecfl(psys->parent->obmat, state.co); + } + else + { + state.time=cfra; + if(psys_get_particle_state(&sim,a,&state,0)){ + if(psys->parent) + Mat4MulVecfl(psys->parent->obmat, state.co); - /* create actiual particle data */ - if(draw_as == PART_DRAW_BB) { - bb.size = pa_size; - bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt); - bb.time = pa_time; - } - - draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, pdd); - - totpoint++; - drawn = 1; + /* create actiual particle data */ + if(draw_as == PART_DRAW_BB) { + bb.size = pa_size; + bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt); + bb.time = pa_time; } + + draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, pdd); + + totpoint++; + drawn = 1; + } + } + + if(drawn) { + /* additional things to draw for each particle */ + /* (velocity, size and number) */ + if(pdd->vedata){ + VECCOPY(pdd->ved,state.co); + pdd->ved+=3; + VECCOPY(vel,state.vel); + VecMulf(vel,timestep); + VECADD(pdd->ved,state.co,vel); + pdd->ved+=3; + + totve++; } - if(drawn) { - /* additional things to draw for each particle */ - /* (velocity, size and number) */ - if(pdd->vedata){ - VECCOPY(pdd->ved,state.co); - pdd->ved+=3; - VECCOPY(vel,state.vel); - VecMulf(vel,timestep); - VECADD(pdd->ved,state.co,vel); - pdd->ved+=3; + if(part->draw & PART_DRAW_SIZE){ + setlinestyle(3); + drawcircball(GL_LINE_LOOP, state.co, pa_size, imat); + setlinestyle(0); + } - totve++; - } + if((part->draw&PART_DRAW_NUM || part->draw&PART_DRAW_HEALTH) && !(G.f & G_RENDER_SHADOW)){ + val[0]= '\0'; + + if(part->draw&PART_DRAW_NUM) + sprintf(val, " %i", a); - if(part->draw & PART_DRAW_SIZE){ - setlinestyle(3); - drawcircball(GL_LINE_LOOP, state.co, pa_size, imat); - setlinestyle(0); - } + if(part->draw&PART_DRAW_NUM && part->draw&PART_DRAW_HEALTH) + sprintf(val, "%s:", val); - if((part->draw&PART_DRAW_NUM || part->draw&PART_DRAW_HEALTH) && !(G.f & G_RENDER_SHADOW)){ - val[0]= '\0'; - - if(part->draw&PART_DRAW_NUM) - sprintf(val, " %i", a); + if(part->draw&PART_DRAW_HEALTH && a < totpart && part->phystype==PART_PHYS_BOIDS) + sprintf(val, "%s %.2f", val, pa_health); - if(part->draw&PART_DRAW_NUM && part->draw&PART_DRAW_HEALTH) - sprintf(val, "%s:", val); - - if(part->draw&PART_DRAW_HEALTH && a < totpart && part->phystype==PART_PHYS_BOIDS) - sprintf(val, "%s %.2f", val, pa_health); - - /* in path drawing state.co is the end point */ - view3d_cached_text_draw_add(state.co[0], state.co[1], state.co[2], val, 0); - } + /* in path drawing state.co is the end point */ + view3d_cached_text_draw_add(state.co[0], state.co[1], state.co[2], val, 0); } } } + } /* 6. */ - glGetIntegerv(GL_POLYGON_MODE, polygonmode); - glDisableClientState(GL_NORMAL_ARRAY); + glGetIntegerv(GL_POLYGON_MODE, polygonmode); + glDisableClientState(GL_NORMAL_ARRAY); - if(draw_as==PART_DRAW_PATH){ - ParticleCacheKey **cache, *path; - float *cd2=0,*cdata2=0; + if(draw_as==PART_DRAW_PATH){ + ParticleCacheKey **cache, *path; + float *cd2=0,*cdata2=0; - glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); - /* setup gl flags */ - if(ob_dt > OB_WIRE) { - glEnableClientState(GL_NORMAL_ARRAY); + /* setup gl flags */ + if(ob_dt > OB_WIRE) { + glEnableClientState(GL_NORMAL_ARRAY); - if(part->draw&PART_DRAW_MAT_COL) - glEnableClientState(GL_COLOR_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); + 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); - } + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_LIGHTING); + UI_ThemeColor(TH_WIRE); + } - if(totchild && (part->draw&PART_DRAW_PARENT)==0) - totpart=0; + if(totchild && (part->draw&PART_DRAW_PARENT)==0) + totpart=0; - /* draw actual/parent particles */ - cache=psys->pathcache; - for(a=0, pa=psys->particles; asteps > 0) { - glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co); - - if(ob_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); - } - } - - /* draw child particles */ - cache=psys->childcache; - for(a=0; apathcache; + for(a=0, pa=psys->particles; asteps > 0) { glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co); if(ob_dt > OB_WIRE) { @@ -3996,85 +4007,103 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1); } + } + + /* draw child particles */ + cache=psys->childcache; + for(a=0; aco); - - /* restore & clean up */ if(ob_dt > OB_WIRE) { + glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel); if(part->draw&PART_DRAW_MAT_COL) - glDisable(GL_COLOR_ARRAY); - glDisable(GL_COLOR_MATERIAL); + glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col); } - if(cdata2) - MEM_freeN(cdata2); - cd2=cdata2=0; - - glLineWidth(1.0f); - } - else if(draw_as!=PART_DRAW_CIRC){ - glDisableClientState(GL_COLOR_ARRAY); - - /* setup created data arrays */ - if(pdd->vdata){ - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, pdd->vdata); - } - else - glDisableClientState(GL_VERTEX_ARRAY); - - /* billboards are drawn this way */ - if(pdd->ndata && ob_dt>OB_WIRE){ - glEnableClientState(GL_NORMAL_ARRAY); - glNormalPointer(GL_FLOAT, 0, pdd->ndata); - glEnable(GL_LIGHTING); - } - else{ - glDisableClientState(GL_NORMAL_ARRAY); - glDisable(GL_LIGHTING); - } - - if(pdd->cdata){ - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(3, GL_FLOAT, 0, pdd->cdata); - } - - /* draw created data arrays */ - 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(ob_dt<=OB_WIRE) - glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); - - glDrawArrays(GL_QUADS, 0, 4*totpoint); - break; - default: - glDrawArrays(GL_POINTS, 0, totpoint); - break; - } - - pdd->flag |= PARTICLE_DRAW_DATA_UPDATED; - pdd->totpoint = totpoint; + glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1); } - if(pdd->vedata){ - glDisableClientState(GL_COLOR_ARRAY); - cpack(0xC0C0C0); - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, pdd->vedata); - - glDrawArrays(GL_LINES, 0, 2*totve); + + /* restore & clean up */ + if(ob_dt > OB_WIRE) { + if(part->draw&PART_DRAW_MAT_COL) + glDisable(GL_COLOR_ARRAY); + glDisable(GL_COLOR_MATERIAL); } - glPolygonMode(GL_FRONT, polygonmode[0]); - glPolygonMode(GL_BACK, polygonmode[1]); + if(cdata2) + MEM_freeN(cdata2); + cd2=cdata2=0; + + glLineWidth(1.0f); } + else if(ELEM(draw_as, 0, PART_DRAW_CIRC)==0){ + int point_size = 1; + glDisableClientState(GL_COLOR_ARRAY); + + /* enable point data array */ + if(pdd->vdata){ + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, pdd->vdata); + } + else + glDisableClientState(GL_VERTEX_ARRAY); + + if(select) { + UI_ThemeColor(TH_ACTIVE); + + if(part->draw_size) + glPointSize(part->draw_size + 2); + else + glPointSize(4.0); + + glLineWidth(3.0); + + draw_particle_arrays(draw_as, totpoint, ob_dt, 1); + } + + /* restore from select */ + glColor3f(ma_r,ma_g,ma_b); + glPointSize(part->draw_size ? part->draw_size : 2.0); + glLineWidth(1.0); + + /* enable other data arrays */ + + /* billboards are drawn this way */ + if(pdd->ndata && ob_dt>OB_WIRE){ + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, 0, pdd->ndata); + glEnable(GL_LIGHTING); + } + else{ + glDisableClientState(GL_NORMAL_ARRAY); + glDisable(GL_LIGHTING); + } + + if(pdd->cdata){ + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(3, GL_FLOAT, 0, pdd->cdata); + } + + draw_particle_arrays(draw_as, totpoint, ob_dt, 0); + + pdd->flag |= PARTICLE_DRAW_DATA_UPDATED; + pdd->totpoint = totpoint; + } + + if(pdd && pdd->vedata){ + glDisableClientState(GL_COLOR_ARRAY); + cpack(0xC0C0C0); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, pdd->vedata); + + glDrawArrays(GL_LINES, 0, 2*totve); + } + + glPolygonMode(GL_FRONT, polygonmode[0]); + glPolygonMode(GL_BACK, polygonmode[1]); /* 7. */ @@ -4087,6 +4116,12 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv psys->flag &= ~PSYS_DRAWING; + /* draw data can't be saved for billboards as they must update to target changes */ + if(draw_as == PART_DRAW_BB) { + psys_free_pdd(psys); + pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED; + } + if(psys->lattice){ end_latt_deform(psys->lattice); psys->lattice= NULL; diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h index e7e785e605b..1376a08eb3e 100644 --- a/source/blender/makesdna/DNA_object_force.h +++ b/source/blender/makesdna/DNA_object_force.h @@ -56,14 +56,14 @@ typedef enum PFieldType { } PFieldType; typedef struct PartDeflect { + int flag; /* general settings flag */ short deflect; /* Deflection flag - does mesh deflect particles */ short forcefield; /* Force field type, do the vertices attract / repel particles? */ - short flag; /* general settings flag */ short falloff; /* fall-off type */ short shape; /* point, plane or surface */ short tex_mode; /* texture effector */ short kink, kink_axis; /* for curve guide */ - short zdir, rt; + short zdir; /* Main effector values */ float f_strength; /* The strength of the force (+ or - ) */ diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 4c620ae527e..157767e1d13 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -78,6 +78,13 @@ typedef struct ParticleTarget { float time, duration; } ParticleTarget; +typedef struct ParticleDupliWeight { + struct ParticleDupliWeight *next, *prev; + struct Object *ob; + short count; + short flag, rt[2]; +} ParticleDupliWeight; + typedef struct ParticleData { ParticleKey state; /* current global coordinates */ @@ -148,6 +155,7 @@ typedef struct ParticleSettings { /* initial velocity factors */ float normfac, obfac, randfac, partfac, tanfac, tanphase, reactfac; + float ob_vel[3], rt; float avefac, phasefac, randrotfac, randphasefac; /* physical properties */ float mass, size, randsize, reactshape; @@ -179,6 +187,7 @@ typedef struct ParticleSettings { int keyed_loops; struct Group *dup_group; + struct ListBase dupliweights; struct Group *eff_group; // deprecated struct Object *dup_ob; struct Object *bb_ob; @@ -324,12 +333,12 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in /* part->draw */ #define PART_DRAW_VEL 1 -//#define PART_DRAW_PATH_LEN 2 +#define PART_DRAW_GLOBAL_OB 2 #define PART_DRAW_SIZE 4 #define PART_DRAW_EMITTER 8 /* render emitter also */ #define PART_DRAW_HEALTH 16 #define PART_ABS_PATH_TIME 32 -//#define PART_DRAW_TRAIL 64 /* deprecated */ +#define PART_DRAW_COUNT_GR 64 #define PART_DRAW_BB_LOCK 128 #define PART_DRAW_PARENT 256 #define PART_DRAW_NUM 512 @@ -444,6 +453,9 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in #define PARS_ALIVE 3 #define PARS_DYING 4 +/* ParticleDupliWeight->flag */ +#define PART_DUPLIW_CURRENT 1 + /* psys->vg */ #define PSYS_TOT_VG 12 diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 022c04240af..404223ab590 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -45,6 +45,13 @@ EnumPropertyItem effector_shape_items[] = { {0, NULL, 0, NULL, NULL} }; +EnumPropertyItem curve_shape_items[] = { + {PFIELD_SHAPE_POINT, "POINT", 0, "Point", ""}, + {PFIELD_SHAPE_PLANE, "PLANE", 0, "Plane", ""}, + {PFIELD_SHAPE_SURFACE, "SURFACE", 0, "Curve", ""}, + {0, NULL, 0, NULL, NULL} +}; + EnumPropertyItem empty_shape_items[] = { {PFIELD_SHAPE_POINT, "POINT", 0, "Point", ""}, {PFIELD_SHAPE_PLANE, "PLANE", 0, "Plane", ""}, @@ -59,6 +66,13 @@ EnumPropertyItem vortex_shape_items[] = { {0, NULL, 0, NULL, NULL} }; +EnumPropertyItem curve_vortex_shape_items[] = { + {PFIELD_SHAPE_POINT, "POINT", 0, "Old", ""}, + {PFIELD_SHAPE_PLANE, "PLANE", 0, "New", ""}, + {PFIELD_SHAPE_SURFACE, "SURFACE", 0, "Curve (New)", ""}, + {0, NULL, 0, NULL, NULL} +}; + EnumPropertyItem empty_vortex_shape_items[] = { {PFIELD_SHAPE_POINT, "POINT", 0, "Old", ""}, {PFIELD_SHAPE_PLANE, "PLANE", 0, "New", ""}, @@ -538,9 +552,11 @@ static EnumPropertyItem *rna_Effector_shape_itemf(bContext *C, PointerRNA *ptr, /* needed for doc generation */ RNA_enum_items_add(&item, &totitem, effector_shape_items); + RNA_enum_items_add(&item, &totitem, curve_shape_items); RNA_enum_items_add(&item, &totitem, empty_shape_items); RNA_enum_items_add(&item, &totitem, vortex_shape_items); - RNA_enum_items_add(&item, &totitem, empty_shape_items); + RNA_enum_items_add(&item, &totitem, curve_vortex_shape_items); + RNA_enum_items_add(&item, &totitem, empty_vortex_shape_items); RNA_enum_item_end(&item, &totitem); *free= 1; @@ -553,7 +569,13 @@ static EnumPropertyItem *rna_Effector_shape_itemf(bContext *C, PointerRNA *ptr, ob= (Object*)ptr->id.data; - if(ELEM4(ob->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE)) { + if(ob->type == OB_CURVE) { + if(ob->pd->forcefield == PFIELD_VORTEX) + return curve_vortex_shape_items; + + return curve_shape_items; + } + else if(ELEM3(ob->type, OB_MESH, OB_SURF, OB_FONT)) { if(ob->pd->forcefield == PFIELD_VORTEX) return vortex_shape_items; @@ -783,11 +805,11 @@ static void rna_def_effector_weight(BlenderRNA *brna) RNA_def_property_ui_text(prop, "All", "All effector's weight."); RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); - prop= RNA_def_property(srna, "spherical", PROP_FLOAT, PROP_NONE); + prop= RNA_def_property(srna, "force", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "weight[1]"); RNA_def_property_range(prop, -200.0f, 200.0f); RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); - RNA_def_property_ui_text(prop, "Spherical", "Spherical effector weight."); + RNA_def_property_ui_text(prop, "Force", "Force effector weight."); RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); prop= RNA_def_property(srna, "vortex", PROP_FLOAT, PROP_NONE); @@ -1113,6 +1135,11 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_DO_ROTATION); RNA_def_property_ui_text(prop, "Rotation", "Effect particles' dynamic rotation"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); + + prop= RNA_def_property(srna, "do_absorption", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_VISIBILITY); + RNA_def_property_ui_text(prop, "Absorption", "Force gets absorbed by collision objects"); + RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); /* Pointer */ diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 453b5f9f91a..2c81bda121f 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -105,6 +105,7 @@ EnumPropertyItem part_hair_ren_as_items[] = { #include "BKE_pointcache.h" #include "BLI_arithb.h" +#include "BLI_listbase.h" /* property update functions */ static void particle_recalc(bContext *C, PointerRNA *ptr, short flag) @@ -433,6 +434,71 @@ static int rna_ParticleSystem_edited_get(PointerRNA *ptr) else return (psys->pointcache->edit && psys->pointcache->edit->edited); } +static PointerRNA rna_ParticleDupliWeight_active_get(PointerRNA *ptr) +{ + ParticleSettings *part= (ParticleSettings*)ptr->id.data; + ParticleDupliWeight *dw = part->dupliweights.first; + + for(; dw; dw=dw->next) { + if(dw->flag & PART_DUPLIW_CURRENT) + return rna_pointer_inherit_refine(ptr, &RNA_ParticleDupliWeight, dw); + } + return rna_pointer_inherit_refine(ptr, &RNA_ParticleTarget, NULL); +} +static void rna_ParticleDupliWeight_active_index_range(PointerRNA *ptr, int *min, int *max) +{ + ParticleSettings *part= (ParticleSettings*)ptr->id.data; + *min= 0; + *max= BLI_countlist(&part->dupliweights)-1; + *max= MAX2(0, *max); +} + +static int rna_ParticleDupliWeight_active_index_get(PointerRNA *ptr) +{ + ParticleSettings *part= (ParticleSettings*)ptr->id.data; + ParticleDupliWeight *dw = part->dupliweights.first; + int i=0; + + for(; dw; dw=dw->next, i++) + if(dw->flag & PART_DUPLIW_CURRENT) + return i; + + return 0; +} + +static void rna_ParticleDupliWeight_active_index_set(struct PointerRNA *ptr, int value) +{ + ParticleSettings *part= (ParticleSettings*)ptr->id.data; + ParticleDupliWeight *dw = part->dupliweights.first; + int i=0; + + for(; dw; dw=dw->next, i++) { + if(i==value) + dw->flag |= PART_DUPLIW_CURRENT; + else + dw->flag &= ~PART_DUPLIW_CURRENT; + } +} + +static int rna_ParticleDupliWeight_name_length(PointerRNA *ptr) +{ + ParticleDupliWeight *dw= ptr->data; + + if(dw->ob) + return strlen(dw->ob->id.name+2) + 7; + else + return 9 + 7; +} + +static void rna_ParticleDupliWeight_name_get(PointerRNA *ptr, char *str) +{ + ParticleDupliWeight *dw= ptr->data; + + if(dw->ob) + sprintf(str, "%s: %i", dw->ob->id.name+2, dw->count); + else + strcpy(str, "No object"); +} EnumPropertyItem from_items[] = { {PART_FROM_VERT, "VERT", 0, "Vertexes", ""}, {PART_FROM_FACE, "FACE", 0, "Faces", ""}, @@ -726,6 +792,27 @@ static void rna_def_particle(BlenderRNA *brna) // short rt2; } +static void rna_def_particle_dupliweight(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "ParticleDupliWeight", NULL); + RNA_def_struct_ui_text(srna, "Particle Dupliobject Weight", "Weight of a particle dupliobject in a group."); + RNA_def_struct_sdna(srna, "ParticleDupliWeight"); + + prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, "rna_ParticleDupliWeight_name_get", "rna_ParticleDupliWeight_name_length", NULL); + RNA_def_property_ui_text(prop, "Name", "Particle dupliobject name."); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_struct_name_property(srna, prop); + + prop= RNA_def_property(srna, "count", PROP_INT, PROP_UNSIGNED); + RNA_def_property_range(prop, 0, INT_MAX); + RNA_def_property_ui_text(prop, "Count", "The number of times this object is repeated with respect to other objects."); + RNA_def_property_update(prop, 0, "rna_Particle_redo"); +} + static void rna_def_particle_settings(BlenderRNA *brna) { StructRNA *srna; @@ -1069,6 +1156,16 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Pick Random", "Pick objects from group randomly"); RNA_def_property_update(prop, 0, "rna_Particle_redo"); + prop= RNA_def_property(srna, "use_group_count", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_COUNT_GR); + RNA_def_property_ui_text(prop, "Use Count", "Use object multiple times in the same group"); + RNA_def_property_update(prop, 0, "rna_Particle_redo"); + + prop= RNA_def_property(srna, "use_global_dupli", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_GLOBAL_OB); + RNA_def_property_ui_text(prop, "Use Global", "Use object's global coordinates for duplication."); + RNA_def_property_update(prop, 0, "rna_Particle_redo"); + prop= RNA_def_property(srna, "render_adaptive", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_REN_ADAPT); RNA_def_property_ui_text(prop, "Adaptive render", "Draw steps of the particle path"); @@ -1374,6 +1471,13 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Reactor", "Let the vector away from the target particles location give the particle a starting speed."); RNA_def_property_update(prop, 0, "rna_Particle_reset"); + prop= RNA_def_property(srna, "object_aligned_factor", PROP_FLOAT, PROP_VELOCITY); + RNA_def_property_float_sdna(prop, NULL, "ob_vel"); + RNA_def_property_array(prop, 3); + RNA_def_property_range(prop, -200.0f, 200.0f); + RNA_def_property_ui_text(prop, "Object Aligned", "Let the emitter object orientation give the particle a starting speed"); + RNA_def_property_update(prop, 0, "rna_Particle_reset"); + prop= RNA_def_property(srna, "angular_velocity_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "avefac"); RNA_def_property_range(prop, -200.0f, 200.0f); @@ -1426,19 +1530,6 @@ static void rna_def_particle_settings(BlenderRNA *brna) /* global physical properties */ - prop= RNA_def_property(srna, "acceleration", PROP_FLOAT, PROP_ACCELERATION); - RNA_def_property_float_sdna(prop, NULL, "acc"); - RNA_def_property_array(prop, 3); - RNA_def_property_range(prop, -200.0f, 200.0f); - RNA_def_property_ui_text(prop, "Acceleration", "Constant acceleration"); - RNA_def_property_update(prop, 0, "rna_Particle_reset"); - - prop= RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_ACCELERATION); - RNA_def_property_float_sdna(prop, NULL, "acc[2]"); - RNA_def_property_range(prop, -200.0f, 200.0f); - RNA_def_property_ui_text(prop, "Gravity", "Constant acceleration in global Z axis direction"); - RNA_def_property_update(prop, 0, "rna_Particle_reset"); - prop= RNA_def_property(srna, "drag_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "dragfac"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -1665,6 +1756,19 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Dupli Group", "Show Objects in this Group in place of particles"); RNA_def_property_update(prop, 0, "rna_Particle_redo"); + prop= RNA_def_property(srna, "dupliweights", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "ParticleDupliWeight"); + RNA_def_property_ui_text(prop, "Dupli Group Weights", "Weights for all of the objects in the dupli group."); + + prop= RNA_def_property(srna, "active_dupliweight", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "ParticleDupliWeight"); + RNA_def_property_pointer_funcs(prop, "rna_ParticleDupliWeight_active_get", NULL, NULL); + RNA_def_property_ui_text(prop, "Active Dupli Object", ""); + + prop= RNA_def_property(srna, "active_dupliweight_index", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_funcs(prop, "rna_ParticleDupliWeight_active_index_get", "rna_ParticleDupliWeight_active_index_set", "rna_ParticleDupliWeight_active_index_range"); + RNA_def_property_ui_text(prop, "Active Dupli Object Index", ""); + prop= RNA_def_property(srna, "dupli_object", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "dup_ob"); RNA_def_property_struct_type(prop, "Object"); @@ -2024,6 +2128,7 @@ void RNA_def_particle(BlenderRNA *brna) rna_def_child_particle(brna); rna_def_particle(brna); + rna_def_particle_dupliweight(brna); rna_def_particle_system(brna); rna_def_particle_settings(brna); } From 77b8be6e1390f167bf83f0ca8b10f77fb758d4a0 Mon Sep 17 00:00:00 2001 From: Damien Plisson Date: Mon, 5 Oct 2009 15:00:07 +0000 Subject: [PATCH 103/138] Cocoa port : Fix bugs in clipboard operations --- intern/ghost/intern/GHOST_SystemCocoa.mm | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index c66153ab670..06ce2882beb 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -1271,7 +1271,7 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; - if (pasteBoard = nil) { + if (pasteBoard == nil) { [pool drain]; return NULL; } @@ -1289,11 +1289,19 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const NSString * textPasted = [pasteBoard stringForType:@"public.utf8-plain-text"]; + if (textPasted == nil) { + [pool drain]; + return NULL; + } + pastedTextSize = [textPasted lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1); - if (temp_buff == NULL) return NULL; + if (temp_buff == NULL) { + [pool drain]; + return NULL; + } strncpy((char*)temp_buff, [textPasted UTF8String], pastedTextSize); @@ -1318,12 +1326,12 @@ void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; - if (pasteBoard = nil) { + if (pasteBoard == nil) { [pool drain]; return; } - NSArray *supportedTypes = [NSArray arrayWithObjects: @"public.utf8-plain-text",nil]; + NSArray *supportedTypes = [NSArray arrayWithObject:@"public.utf8-plain-text"]; [pasteBoard declareTypes:supportedTypes owner:nil]; From 4df1e400066b30a0bf378b17b6c2168456920be1 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Mon, 5 Oct 2009 15:59:12 +0000 Subject: [PATCH 104/138] Fixed [#19539] Texture > RGB Factor property doesn't appear in the UI --- release/scripts/ui/buttons_texture.py | 9 +++++++-- source/blender/makesrna/intern/rna_texture.c | 20 ++++++++++++++++---- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/release/scripts/ui/buttons_texture.py b/release/scripts/ui/buttons_texture.py index 6eab84afc42..c4866edcaaa 100644 --- a/release/scripts/ui/buttons_texture.py +++ b/release/scripts/ui/buttons_texture.py @@ -99,8 +99,13 @@ class TEXTURE_PT_colors(TextureButtonsPanel): layout.template_color_ramp(tex, "color_ramp", expand=True) split = layout.split() - - split.itemR(tex, "rgb_factor", text="Multiply RGB") + + col = split.column() + col.itemL(text="RGB Multiply:") + sub = col.column(align=True) + sub.itemR(tex, "factor_red", text="R") + sub.itemR(tex, "factor_green", text="G") + sub.itemR(tex, "factor_blue", text="B") col = split.column() col.itemL(text="Adjust:") diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index 5c7a097a54d..78d7f012487 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -1653,12 +1653,24 @@ static void rna_def_texture(BlenderRNA *brna) RNA_def_property_range(prop, 0.01, 5); RNA_def_property_ui_text(prop, "Contrast", ""); RNA_def_property_update(prop, 0, "rna_Texture_update"); - - prop= RNA_def_property(srna, "rgb_factor", PROP_FLOAT, PROP_RGB); + + /* RGB Factor */ + prop= RNA_def_property(srna, "factor_red", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rfac"); - RNA_def_property_array(prop, 3); RNA_def_property_range(prop, 0, 2); - RNA_def_property_ui_text(prop, "RGB Factor", ""); + RNA_def_property_ui_text(prop, "Factor Red", ""); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "factor_green", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "gfac"); + RNA_def_property_range(prop, 0, 2); + RNA_def_property_ui_text(prop, "Factor Green", ""); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + + prop= RNA_def_property(srna, "factor_blue", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "bfac"); + RNA_def_property_range(prop, 0, 2); + RNA_def_property_ui_text(prop, "Factor Blue", ""); RNA_def_property_update(prop, 0, "rna_Texture_update"); /* nodetree */ From 4211e1a58ad14cfb4641a01ae27d31ce30db1bba Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 5 Oct 2009 16:18:08 +0000 Subject: [PATCH 105/138] Raytrace Acceleration: small tweak to RNA and UI, hiding buttons when they are not applicable. --- release/scripts/ui/buttons_scene.py | 8 +++++--- source/blender/makesrna/intern/rna_scene.c | 13 ++++++------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/release/scripts/ui/buttons_scene.py b/release/scripts/ui/buttons_scene.py index 10a0efae33d..69cf79ddc85 100644 --- a/release/scripts/ui/buttons_scene.py +++ b/release/scripts/ui/buttons_scene.py @@ -173,9 +173,11 @@ class SCENE_PT_performance(RenderButtonsPanel): sub.active = rd.render_raytracing sub.itemL(text="Acceleration structure:") sub.itemR(rd, "raytrace_structure", text="") - sub.itemR(rd, "use_instances", text="Instance support") - sub.itemR(rd, "use_local_coords", text="Local coords") - sub.itemR(rd, "octree_resolution", text="Octree resolution") + if rd.raytrace_structure == "OCTREE": + sub.itemR(rd, "octree_resolution", text="Resolution") + else: + sub.itemR(rd, "use_instances", text="Instances") + sub.itemR(rd, "use_local_coords", text="Local Coordinates") class SCENE_PT_post_processing(RenderButtonsPanel): __label__ = "Post Processing" diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 267e29d7018..5ef746adf1f 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1179,12 +1179,12 @@ static void rna_def_scene_render_data(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem raytrace_structure_items[] = { - {R_RAYSTRUCTURE_AUTO, "{R_RAYSTRUCTURE_AUTO", 0, "auto", ""}, - {R_RAYSTRUCTURE_OCTREE, "R_RAYSTRUCTURE_OCTREE", 0, "octree", "Use old octree structure (no support for instances)"}, - {R_RAYSTRUCTURE_BLIBVH, "R_RAYSTRUCTURE_BLIBVH", 0, "blibvh", "Use BLI_kdopbvh.c"}, - {R_RAYSTRUCTURE_VBVH, "R_RAYSTRUCTURE_VBVH", 0, "vBVH", ""}, - {R_RAYSTRUCTURE_SIMD_SVBVH, "R_RAYSTRUCTURE_SIMD_SVBVH", 0, "SIMD SVBVH", "Requires SIMD"}, - {R_RAYSTRUCTURE_SIMD_QBVH, "R_RAYSTRUCTURE_SIMD_QBVH", 0, "SIMD QBVH", "Requires SIMD"}, + {R_RAYSTRUCTURE_AUTO, "AUTO", 0, "Auto", ""}, + {R_RAYSTRUCTURE_OCTREE, "OCTREE", 0, "Octree", "Use old Octree structure."}, + {R_RAYSTRUCTURE_BLIBVH, "BLIBVH", 0, "BLI BVH", "Use BLI K-Dop BVH.c"}, + {R_RAYSTRUCTURE_VBVH, "VBVH", 0, "vBVH", ""}, + {R_RAYSTRUCTURE_SIMD_SVBVH, "SIMD_SVBVH", 0, "SIMD SVBVH", ""}, + {R_RAYSTRUCTURE_SIMD_QBVH, "SIMD_QBVH", 0, "SIMD QBVH", ""}, {0, NULL, 0, NULL, NULL} }; @@ -1632,7 +1632,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Use Local Coords", "Vertex coordinates are stored localy on each primitive. Increases memory usage, but may have impact on speed."); RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); - prop= RNA_def_property(srna, "antialiasing", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_OSA); RNA_def_property_ui_text(prop, "Anti-Aliasing", "Render and combine multiple samples per pixel to prevent jagged edges."); From 5f1b4334e2e8eb6eacf921a43548e0de2cd7c23b Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 5 Oct 2009 16:40:13 +0000 Subject: [PATCH 106/138] VBO: disable VBO's by default. Not sure why this was not done, we agreed on this as a condition for the project to be merged. --- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/editors/interface/resources.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 3549d3e372d..a79bf43c354 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -43,7 +43,7 @@ struct bContext; struct ReportList; #define BLENDER_VERSION 250 -#define BLENDER_SUBVERSION 4 +#define BLENDER_SUBVERSION 5 #define BLENDER_MINVERSION 250 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 87026bd1a5d..ee7db07f3c8 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -1259,6 +1259,9 @@ void init_userdef_do_versions(void) if(U.audiorate == 0) U.audiorate = 44100; } + + if (G.main->versionfile < 250 || (G.main->versionfile == 250 && G.main->subversionfile < 5)) + U.gameflags |= USER_DISABLE_VBO; /* GL Texture Garbage Collection (variable abused above!) */ if (U.textimeout == 0) { From e61e1c5ca827caafb4d7ee2f2a042c9a7ec44863 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 5 Oct 2009 16:48:52 +0000 Subject: [PATCH 107/138] VBO: * Fix slowdown/freeze entering editmode on a high poly mesh, dm->getNumFaces can be slow, don't call it in a loop. * Fix 64bit pointer casting warnings. --- source/blender/gpu/intern/gpu_buffers.c | 63 +++++++++++++++---------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index f19edb61df1..e750a3d05fd 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -34,14 +34,18 @@ #include "GL/glew.h" +#include "MEM_guardedalloc.h" + +#include "BLI_arithb.h" + +#include "DNA_meshdata_types.h" + +#include "BKE_DerivedMesh.h" +#include "BKE_utildefines.h" + #include "DNA_userdef_types.h" #include "gpu_buffers.h" -#include "MEM_guardedalloc.h" -#include "BKE_DerivedMesh.h" -#include "BKE_utildefines.h" -#include "DNA_meshdata_types.h" -#include "BLI_arithb.h" #define GPU_BUFFER_VERTEX_STATE 1 #define GPU_BUFFER_NORMAL_STATE 2 @@ -248,7 +252,7 @@ GPUDrawObject *GPU_drawobject_new( DerivedMesh *dm ) int redir[32768]; /* material number is an 16-bit short so there's at most 32768 materials */ int *index; int i; - int curmat, curverts; + int curmat, curverts, numfaces; DEBUG_VBO("GPU_drawobject_new\n"); @@ -267,7 +271,8 @@ GPUDrawObject *GPU_drawobject_new( DerivedMesh *dm ) mvert = dm->getVertArray(dm); mface = dm->getFaceArray(dm); - for( i=0; i < dm->getNumFaces(dm); i++ ) { + numfaces= dm->getNumFaces(dm); + for( i=0; i < numfaces; i++ ) { if( mface[i].v4 ) numverts[mface[i].mat_nr+16383] += 6; /* split every quad into two triangles */ else @@ -313,7 +318,7 @@ GPUDrawObject *GPU_drawobject_new( DerivedMesh *dm ) object->indexMemUsage++; \ } - for( i=0; i < dm->getNumFaces(dm); i++ ) { + for( i=0; i < numfaces; i++ ) { int curInd = index[redir[mface[i].mat_nr+16383]]; object->faceRemap[curInd] = i; ADDLINK( mface[i].v1, curInd*3 ); @@ -461,7 +466,7 @@ GPUBuffer *GPU_buffer_setup( DerivedMesh *dm, GPUDrawObject *object, int size, G void GPU_buffer_copy_vertex( DerivedMesh *dm, float *varray, int *index, int *redir, void *user ) { int start; - int i, j; + int i, j, numfaces; MVert *mvert; MFace *mface; @@ -471,7 +476,8 @@ void GPU_buffer_copy_vertex( DerivedMesh *dm, float *varray, int *index, int *re mvert = dm->getVertArray(dm); mface = dm->getFaceArray(dm); - for( i=0; i < dm->getNumFaces(dm); i++ ) { + numfaces= dm->getNumFaces(dm); + for( i=0; i < numfaces; i++ ) { start = index[redir[mface[i].mat_nr+16383]]; if( mface[i].v4 ) index[redir[mface[i].mat_nr+16383]] += 18; @@ -508,7 +514,7 @@ GPUBuffer *GPU_buffer_vertex( DerivedMesh *dm ) void GPU_buffer_copy_normal( DerivedMesh *dm, float *varray, int *index, int *redir, void *user ) { - int i; + int i, numfaces; int start; float norm[3]; @@ -518,7 +524,8 @@ void GPU_buffer_copy_normal( DerivedMesh *dm, float *varray, int *index, int *re DEBUG_VBO("GPU_buffer_copy_normal\n"); - for( i=0; i < dm->getNumFaces(dm); i++ ) { + numfaces= dm->getNumFaces(dm); + for( i=0; i < numfaces; i++ ) { start = index[redir[mface[i].mat_nr+16383]]; if( mface[i].v4 ) index[redir[mface[i].mat_nr+16383]] += 18; @@ -572,7 +579,7 @@ GPUBuffer *GPU_buffer_normal( DerivedMesh *dm ) void GPU_buffer_copy_uv( DerivedMesh *dm, float *varray, int *index, int *redir, void *user ) { int start; - int i; + int i, numfaces; MTFace *mtface; MFace *mface; @@ -587,7 +594,8 @@ void GPU_buffer_copy_uv( DerivedMesh *dm, float *varray, int *index, int *redir, return; } - for( i=0; i < dm->getNumFaces(dm); i++ ) { + numfaces= dm->getNumFaces(dm); + for( i=0; i < numfaces; i++ ) { start = index[redir[mface[i].mat_nr+16383]]; if( mface[i].v4 ) index[redir[mface[i].mat_nr+16383]] += 12; @@ -619,14 +627,15 @@ GPUBuffer *GPU_buffer_uv( DerivedMesh *dm ) void GPU_buffer_copy_color3( DerivedMesh *dm, float *varray_, int *index, int *redir, void *user ) { - int i; + int i, numfaces; unsigned char *varray = (unsigned char *)varray_; unsigned char *mcol = (unsigned char *)user; MFace *mface = dm->getFaceArray(dm); DEBUG_VBO("GPU_buffer_copy_color3\n"); - for( i=0; i < dm->getNumFaces(dm); i++ ) { + numfaces= dm->getNumFaces(dm); + for( i=0; i < numfaces; i++ ) { int start = index[redir[mface[i].mat_nr+16383]]; if( mface[i].v4 ) index[redir[mface[i].mat_nr+16383]] += 18; @@ -648,14 +657,15 @@ void GPU_buffer_copy_color3( DerivedMesh *dm, float *varray_, int *index, int *r void GPU_buffer_copy_color4( DerivedMesh *dm, float *varray_, int *index, int *redir, void *user ) { - int i; + int i, numfaces; unsigned char *varray = (unsigned char *)varray_; unsigned char *mcol = (unsigned char *)user; MFace *mface = dm->getFaceArray(dm); DEBUG_VBO("GPU_buffer_copy_color4\n"); - for( i=0; i < dm->getNumFaces(dm); i++ ) { + numfaces= dm->getNumFaces(dm); + for( i=0; i < numfaces; i++ ) { int start = index[redir[mface[i].mat_nr+16383]]; if( mface[i].v4 ) index[redir[mface[i].mat_nr+16383]] += 18; @@ -678,7 +688,7 @@ void GPU_buffer_copy_color4( DerivedMesh *dm, float *varray_, int *index, int *r GPUBuffer *GPU_buffer_color( DerivedMesh *dm ) { unsigned char *colors; - int i; + int i, numfaces; MCol *mcol; GPUBuffer *result; DEBUG_VBO("GPU_buffer_color\n"); @@ -694,8 +704,9 @@ GPUBuffer *GPU_buffer_color( DerivedMesh *dm ) dm->drawObject->colType = CD_MCOL; } - colors = MEM_mallocN(dm->getNumFaces(dm)*12*sizeof(unsigned char), "GPU_buffer_color"); - for( i=0; i < dm->getNumFaces(dm)*4; i++ ) { + numfaces= dm->getNumFaces(dm); + colors = MEM_mallocN(numfaces*12*sizeof(unsigned char), "GPU_buffer_color"); + for( i=0; i < numfaces*4; i++ ) { colors[i*3] = mcol[i].b; colors[i*3+1] = mcol[i].g; colors[i*3+2] = mcol[i].r; @@ -714,13 +725,15 @@ void GPU_buffer_copy_edge( DerivedMesh *dm, float *varray, int *index, int *redi MVert *mvert; MEdge *medge; unsigned int *varray_ = (unsigned int *)varray; + int numedges; DEBUG_VBO("GPU_buffer_copy_edge\n"); mvert = dm->getVertArray(dm); medge = dm->getEdgeArray(dm); - for(i = 0; i < dm->getNumEdges(dm); i++) { + numedges= dm->getNumEdges(dm); + for(i = 0; i < numedges; i++) { varray_[i*2] = (unsigned int)dm->drawObject->indices[medge[i].v1].element; varray_[i*2+1] = (unsigned int)dm->drawObject->indices[medge[i].v2].element; } @@ -933,7 +946,7 @@ void GPU_uvedge_setup( DerivedMesh *dm ) void GPU_interleaved_setup( GPUBuffer *buffer, int data[] ) { int i; int elementsize = 0; - int offset = 0; + intptr_t offset = 0; DEBUG_VBO("GPU_interleaved_setup\n"); @@ -1068,7 +1081,7 @@ int GPU_attrib_element_size( GPUAttrib data[], int numdata ) { void GPU_interleaved_attrib_setup( GPUBuffer *buffer, GPUAttrib data[], int numdata ) { int i; int elementsize; - int offset = 0; + intptr_t offset = 0; DEBUG_VBO("GPU_interleaved_attrib_setup\n"); @@ -1245,4 +1258,4 @@ void GPU_buffer_draw_elements( GPUBuffer *elements, unsigned int mode, int start else { glDrawElements( mode, count, GL_UNSIGNED_INT, ((int *)elements->pointer)+start ); } -} \ No newline at end of file +} From 2072e7c6c7be0502961247deee21e69f9a8fa383 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 5 Oct 2009 17:29:56 +0000 Subject: [PATCH 108/138] VBO: * Disable use of EditMeshDerivedMesh for VBO drawing in editmode. This is crashed when using e.g. subsurf in editmode, as the DM is not an EditMeshDerivedMesh. --- .../blender/editors/space_view3d/drawobject.c | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 0659b5cfd11..79412480d95 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -1552,6 +1552,12 @@ static void draw_dm_verts__mapFunc(void *userData, int index, float *co, float * } } } + +/* disabled because it crashes combined with e.g. subsurf modifier, + * the derivedmesh can't be assumed to be an EditMeshDerivedMesh, + * nor should this struct be copied around, it should be defined in + * a single place only to avoid them getting out of sync */ +#if 0 /* originally defined in DerivedMesh.c */ typedef struct { DerivedMesh dm; @@ -1561,15 +1567,17 @@ typedef struct { float (*vertexNos)[3]; float (*faceNos)[3]; } EditMeshDerivedMesh; +#endif static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act) { struct { int sel; EditVert *eve_act; } data; - GPUBuffer *buffer; - float *varray; + //GPUBuffer *buffer; + //float *varray; data.sel = sel; data.eve_act = eve_act; +#if 0 /* first come the unselected vertices, then the selected */ buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( sizeof(float)*3*dm->getNumVerts(dm)*2, 0 ); @@ -1612,12 +1620,15 @@ static void draw_dm_verts(DerivedMesh *dm, int sel, EditVert *eve_act) UI_ThemeColor4(data.sel?TH_VERTEX_SELECT:TH_VERTEX); GPU_buffer_unbind(); } - else { + { +#endif bglBegin(GL_POINTS); dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data); bglEnd(); +#if 0 } GPU_buffer_free( buffer, 0 ); +#endif } /* Draw edges with color set based on selection */ @@ -1688,15 +1699,14 @@ static void draw_dm_edges_sel_interp__setDrawInterpOptions(void *userData, int i static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol) { - unsigned char *cols[2]; + unsigned char *cols[2] = {baseCol, selCol}; +#if 0 int elemsize = sizeof(float)*3+sizeof(unsigned char)*4; EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm; EditMesh *em= emdm->em; unsigned char *varray; int i; GPUBuffer *buffer; - cols[0] = baseCol; - cols[1] = selCol; buffer = GPU_buffer_legacy(dm)?0:GPU_buffer_alloc( elemsize*em->totedge*2, 0 ); if( (varray = GPU_buffer_lock_stream( buffer )) ) { @@ -1733,9 +1743,12 @@ static void draw_dm_edges_sel_interp(DerivedMesh *dm, unsigned char *baseCol, un GPU_buffer_unbind(); } else { +#endif dm->drawMappedEdgesInterp(dm, draw_dm_edges_sel_interp__setDrawOptions, draw_dm_edges_sel_interp__setDrawInterpOptions, cols); +#if 0 } GPU_buffer_free( buffer, 0 ); +#endif } /* Draw only seam edges */ @@ -1792,11 +1805,10 @@ static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned //EditMeshDerivedMesh *emdm = (EditMeshDerivedMesh *)dm; EditFace *efa; unsigned char *col; - unsigned char *colors; GPUBuffer *buffer; unsigned char *varray; unsigned char black[] = { 0, 0, 0, 0 }; - int i,j,draw=0; + int i, draw=0; int elemsize = (sizeof(float)*6+sizeof(unsigned char)*4); data.cols[0] = baseCol; data.cols[1] = selCol; @@ -4039,7 +4051,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv glLineWidth(1.0f); } else if(ELEM(draw_as, 0, PART_DRAW_CIRC)==0){ - int point_size = 1; glDisableClientState(GL_COLOR_ARRAY); /* enable point data array */ From a0d8d7afe08426dbc0eba72306bc5db3f5c65e47 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 5 Oct 2009 19:42:48 +0000 Subject: [PATCH 109/138] edge loop delete, should be a c macro but they cant do settings atm --- release/scripts/modules/bpy_ops.py | 17 +++++++++++++++++ source/blender/editors/mesh/editmesh_tools.c | 6 +++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/release/scripts/modules/bpy_ops.py b/release/scripts/modules/bpy_ops.py index 83c2e82bf6c..834a33d305d 100644 --- a/release/scripts/modules/bpy_ops.py +++ b/release/scripts/modules/bpy_ops.py @@ -139,3 +139,20 @@ class bpy_ops_submodule_op(object): import bpy bpy.ops = bpy_ops() + +# TODO, C macro's cant define settings :| + +class MESH_OT_delete_edgeloop(bpy.types.Operator): + '''Export a single object as a stanford PLY with normals, colours and texture coordinates.''' + __idname__ = "mesh.delete_edgeloop" + __label__ = "Export PLY" + + def execute(self, context): + bpy.ops.tfm.edge_slide(value=1.0) + bpy.ops.mesh.select_more() + bpy.ops.mesh.remove_doubles() + return ('FINISHED',) + + +bpy.ops.add(MESH_OT_delete_edgeloop) + diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 510f6ab464b..88d08efe95e 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -1305,8 +1305,12 @@ static int delete_mesh_exec(bContext *C, wmOperator *op) { Object *obedit= CTX_data_edit_object(C); EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + int type= RNA_enum_get(op->ptr, "type"); - delete_mesh(obedit, em, op, RNA_enum_get(op->ptr, "type")); + if(type==6) + return WM_operator_name_call(C, "MESH_OT_delete_edgeloop", WM_OP_EXEC_DEFAULT, NULL); + + delete_mesh(obedit, em, op, type); DAG_id_flush_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); From 4e60007102c1a9cf8dad068e1d4b8ab6e46ca89b Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 5 Oct 2009 20:30:47 +0000 Subject: [PATCH 110/138] [#19542] Correct spacing with snapping buttons in 3d view header. --- source/blender/editors/space_view3d/view3d_header.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 19c48bb5006..0d19a720cdb 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -2145,9 +2145,9 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) xco+= XIC; } uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_SNAP_VERTEX, snapmode_pup(), xco,yco,XIC+10,YIC, &(ts->snap_mode), 0.0, 0.0, 0, 0, "Snapping mode"); - xco+= XIC; + xco+= XIC + 10; uiDefButS(block, MENU, B_NOP, "Snap Mode%t|Closest%x0|Center%x1|Median%x2|Active%x3",xco,yco,70,YIC, &ts->snap_target, 0, 0, 0, 0, "Snap Target Mode"); - xco+= XIC; + xco+= 70; } else { uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEAR,xco,yco,XIC,YIC, &ts->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab)"); xco+= XIC; From 1f0ee67579f39343fbc8f5be7a74a7cf25d33a92 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 5 Oct 2009 20:31:41 +0000 Subject: [PATCH 111/138] [#19535] Save back proportional editing size to toolsettings after transform. --- source/blender/editors/transform/transform.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 84e42294946..b109157d859 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1326,6 +1326,7 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) if ((t->options & CTX_NO_PET) == 0) { ts->proportional = proportional; + ts->proportional_size = t->prop_size; } if(t->spacetype == SPACE_VIEW3D) From 69a24325742c617a9902376b061006dfb24f0a3c Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Mon, 5 Oct 2009 23:04:40 +0000 Subject: [PATCH 112/138] Small fix for some old files crashing in particle drawing. --- source/blender/editors/space_view3d/drawobject.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 79412480d95..1bad1b3215c 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -3788,7 +3788,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv psys->lattice= psys_get_lattice(&sim); - if(draw_as!=PART_DRAW_PATH){ + if(pdd && draw_as!=PART_DRAW_PATH){ /* 5. */ if((pdd->flag & PARTICLE_DRAW_DATA_UPDATED) && (pdd->vedata || part->draw & (PART_DRAW_SIZE|PART_DRAW_NUM|PART_DRAW_HEALTH))==0) { @@ -4050,7 +4050,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv glLineWidth(1.0f); } - else if(ELEM(draw_as, 0, PART_DRAW_CIRC)==0){ + else if(pdd && ELEM(draw_as, 0, PART_DRAW_CIRC)==0){ glDisableClientState(GL_COLOR_ARRAY); /* enable point data array */ From a62e37bfbe5a1430b204b39dcc2e1156d2a6f2bc Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 5 Oct 2009 23:30:00 +0000 Subject: [PATCH 113/138] blibvh safe for 64bits --- .../render/intern/source/rayobject_blibvh.c | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/source/blender/render/intern/source/rayobject_blibvh.c b/source/blender/render/intern/source/rayobject_blibvh.c index 487193ef1f2..3fd71862f54 100644 --- a/source/blender/render/intern/source/rayobject_blibvh.c +++ b/source/blender/render/intern/source/rayobject_blibvh.c @@ -67,6 +67,7 @@ static RayObjectAPI bvh_api = typedef struct BVHObject { RayObject rayobj; + RayObject **leafs, **next_leaf; BVHTree *bvh; float bb[2][3]; @@ -80,15 +81,23 @@ RayObject *RE_rayobject_blibvh_create(int size) obj->rayobj.api = &bvh_api; obj->bvh = BLI_bvhtree_new(size, 0.0, 4, 6); + obj->next_leaf = obj->leafs = (RayObject**)MEM_callocN(size*sizeof(RayObject*), "BVHObject leafs"); INIT_MINMAX(obj->bb[0], obj->bb[1]); return RE_rayobject_unalignRayAPI((RayObject*) obj); } +struct BVHCallbackUserData +{ + Isect *isec; + RayObject **leafs; +}; + static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) { - Isect *isec = (Isect*)userdata; - RayObject *face = (RayObject*)index; + struct BVHCallbackUserData *data = (struct BVHCallbackUserData*)userdata; + Isect *isec = data->isec; + RayObject *face = data->leafs[index]; if(RE_rayobject_intersect(face,isec)) { @@ -106,6 +115,9 @@ static int RE_rayobject_blibvh_intersect(RayObject *o, Isect *isec) BVHObject *obj = (BVHObject*)o; BVHTreeRayHit hit; float dir[3]; + struct BVHCallbackUserData data; + data.isec = isec; + data.leafs = obj->leafs; VECCOPY(dir, isec->vec); Normalize(dir); @@ -113,7 +125,7 @@ static int RE_rayobject_blibvh_intersect(RayObject *o, Isect *isec) hit.index = 0; hit.dist = isec->labda*isec->dist; - return BLI_bvhtree_ray_cast(obj->bvh, isec->start, dir, 0.0, &hit, bvh_callback, isec); + return BLI_bvhtree_ray_cast(obj->bvh, isec->start, dir, 0.0, &hit, bvh_callback, (void*)&data); } static void RE_rayobject_blibvh_add(RayObject *o, RayObject *ob) @@ -126,7 +138,8 @@ static void RE_rayobject_blibvh_add(RayObject *o, RayObject *ob) DO_MIN(min_max , obj->bb[0]); DO_MAX(min_max+3, obj->bb[1]); - BLI_bvhtree_insert(obj->bvh, (int)ob, min_max, 2 ); + BLI_bvhtree_insert(obj->bvh, obj->next_leaf - obj->leafs, min_max, 2 ); + *(obj->next_leaf++) = ob; } static void RE_rayobject_blibvh_done(RayObject *o) @@ -142,6 +155,9 @@ static void RE_rayobject_blibvh_free(RayObject *o) if(obj->bvh) BLI_bvhtree_free(obj->bvh); + if(obj->leafs) + MEM_freeN(obj->leafs); + MEM_freeN(obj); } From 11bdf6ea10ee7bc5e2862cdddbf42eddb06c42fa Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 6 Oct 2009 00:28:07 +0000 Subject: [PATCH 114/138] Added #ifdef __SSE__ so it can still build when SSE is disabled at compile time --- source/blender/render/intern/raytrace/bvh.h | 7 ++++++ .../render/intern/raytrace/rayobject_qbvh.cpp | 13 +++++++++++ .../intern/raytrace/rayobject_svbvh.cpp | 11 ++++++++++ source/blender/render/intern/raytrace/svbvh.h | 4 ++++ .../blender/render/intern/source/rayshade.c | 22 +++++++++++++++---- 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h index f0302ddba3a..0e74bbc923b 100644 --- a/source/blender/render/intern/raytrace/bvh.h +++ b/source/blender/render/intern/raytrace/bvh.h @@ -33,11 +33,15 @@ #include "rayobject_hint.h" #include + +#ifdef __SSE__ #include +#endif #ifndef RE_RAYTRACE_BVH_H #define RE_RAYTRACE_BVH_H +#ifdef __SSE__ inline int test_bb_group4(__m128 *bb_group, const Isect *isec) { @@ -53,6 +57,7 @@ inline int test_bb_group4(__m128 *bb_group, const Isect *isec) return _mm_movemask_ps(_mm_cmpge_ps(tmax3, tmin3)); } +#endif /* bvh tree generics */ @@ -159,6 +164,7 @@ static int bvh_node_stack_raycast(Node *root, Isect *isec) } +#ifdef __SSE__ /* * Generic SIMD bvh recursion * this was created to be able to use any simd (with the cost of some memmoves) @@ -287,6 +293,7 @@ static int bvh_node_stack_raycast_simd(Node *root, Isect *isec) } return hit; } +#endif /* * recursively transverse a BVH looking for a rayhit using system stack diff --git a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp index b18ee0824cf..8d35848c9ec 100644 --- a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp @@ -30,6 +30,8 @@ #include "svbvh.h" #include "reorganize.h" +#ifdef __SSE__ + #define DFS_STACK_SIZE 256 struct QBVHTree @@ -134,3 +136,14 @@ RayObject *RE_rayobject_qbvh_create(int size) { return bvh_create_tree(size); } + + +#else + +RayObject *RE_rayobject_qbvh_create(int size) +{ + puts("WARNING: SSE disabled at compile time\n"); + return NULL; +} + +#endif \ No newline at end of file diff --git a/source/blender/render/intern/raytrace/rayobject_svbvh.cpp b/source/blender/render/intern/raytrace/rayobject_svbvh.cpp index 229e82dfa68..a877b91e2ff 100644 --- a/source/blender/render/intern/raytrace/rayobject_svbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_svbvh.cpp @@ -30,6 +30,8 @@ #include "svbvh.h" #include "reorganize.h" +#ifdef __SSE__ + #define DFS_STACK_SIZE 256 struct SVBVHTree @@ -168,3 +170,12 @@ RayObject *RE_rayobject_svbvh_create(int size) { return bvh_create_tree(size); } +#else + +RayObject *RE_rayobject_svbvh_create(int size) +{ + puts("WARNING: SSE disabled at compile time\n"); + return NULL; +} + +#endif diff --git a/source/blender/render/intern/raytrace/svbvh.h b/source/blender/render/intern/raytrace/svbvh.h index 840ccc24d1a..3c733b6b402 100644 --- a/source/blender/render/intern/raytrace/svbvh.h +++ b/source/blender/render/intern/raytrace/svbvh.h @@ -26,6 +26,8 @@ * * ***** END GPL LICENSE BLOCK ***** */ +#ifdef __SSE__ + #ifndef RE_RAYTRACE_SVBVH_H #define RE_RAYTRACE_SVBVH_H @@ -243,3 +245,5 @@ struct Reorganize_SVBVH }; #endif + +#endif //__SSE__ \ No newline at end of file diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 9ef8aa3aba2..7f112f2e79c 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -78,7 +78,7 @@ static int test_break(void *data) return re->test_break(re->tbh); } -static RE_rayobject_config_control(RayObject *r, Render *re) +static void RE_rayobject_config_control(RayObject *r, Render *re) { if(RE_rayobject_isRayAPI(r)) { @@ -96,10 +96,21 @@ RayObject* RE_rayobject_create(Render *re, int type, int size) { //TODO //if(detect_simd()) - type = R_RAYSTRUCTURE_SIMD_SVBVH; - //else - // type = R_RAYSTRUCTURE_VBVH; +#ifdef __SSE__ + type = R_RAYSTRUCTURE_SIMD_SVBVH; +#else + type = R_RAYSTRUCTURE_VBVH; +#endif } + +#ifndef __SSE__ + if(type == R_RAYSTRUCTURE_SIMD_SVBVH || type == R_RAYSTRUCTURE_SIMD_QBVH) + { + puts("Warning: Using VBVH (SSE was disabled at compile time)"); + type = R_RAYSTRUCTURE_VBVH; + } +#endif + if(type == R_RAYSTRUCTURE_OCTREE) //TODO dynamic ocres res = RE_rayobject_octree_create(re->r.ocres, size); @@ -111,6 +122,9 @@ RayObject* RE_rayobject_create(Render *re, int type, int size) res = RE_rayobject_svbvh_create(size); else if(type == R_RAYSTRUCTURE_SIMD_QBVH) res = RE_rayobject_qbvh_create(size); + else + res = RE_rayobject_vbvh_create(size); //Fallback + if(res) RE_rayobject_config_control( res, re ); From d28d3194f4460a28f5ea83246725193d6c18cec8 Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Tue, 6 Oct 2009 02:45:42 +0000 Subject: [PATCH 115/138] * Added 'set object as camera' operator 3D View: View -> Cameras -> Set Object as Camera (Ctrl Numpad 0) --- .../editors/space_view3d/view3d_intern.h | 1 + .../blender/editors/space_view3d/view3d_ops.c | 2 ++ .../editors/space_view3d/view3d_view.c | 32 +++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index e7ab79ab955..d80cec9ad48 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -122,6 +122,7 @@ void VIEW3D_OT_select_lasso(struct wmOperatorType *ot); /* view3d_view.c */ void VIEW3D_OT_smoothview(struct wmOperatorType *ot); void VIEW3D_OT_setcameratoview(struct wmOperatorType *ot); +void VIEW3D_OT_setobjectascamera(struct wmOperatorType *ot); void VIEW3D_OT_localview(struct wmOperatorType *ot); void VIEW3D_OT_game_start(struct wmOperatorType *ot); void VIEW3D_OT_fly(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index f9cedbd28a1..a151ff3e73a 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -82,6 +82,7 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_cursor3d); WM_operatortype_append(VIEW3D_OT_select_lasso); WM_operatortype_append(VIEW3D_OT_setcameratoview); + WM_operatortype_append(VIEW3D_OT_setobjectascamera); WM_operatortype_append(VIEW3D_OT_drawtype); WM_operatortype_append(VIEW3D_OT_localview); WM_operatortype_append(VIEW3D_OT_game_start); @@ -216,6 +217,7 @@ void view3d_keymap(wmWindowManager *wm) WM_keymap_add_item(keymap, "VIEW3D_OT_render_border", BKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "VIEW3D_OT_camera_to_view", PAD0, KM_PRESS, KM_ALT|KM_CTRL, 0); + WM_keymap_add_item(keymap, "VIEW3D_OT_object_as_camera", PAD0, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "VIEW3D_OT_snap_menu", SKEY, KM_PRESS, KM_SHIFT, 0); diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index f722a97963d..fc332cf6293 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -434,6 +434,38 @@ void VIEW3D_OT_setcameratoview(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } +static int view3d_setobjectascamera_exec(bContext *C, wmOperator *op) +{ + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d= CTX_wm_region_view3d(C); + Scene *scene= CTX_data_scene(C); + + if(BASACT) { + rv3d->persp= V3D_CAMOB; + v3d->camera= OBACT; + smooth_view(C, NULL, v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, &v3d->lens); + } + + WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, CTX_data_scene(C)); + + return OPERATOR_FINISHED; +} + +void VIEW3D_OT_setobjectascamera(wmOperatorType *ot) +{ + + /* identifiers */ + ot->name= "Set Active Object as Camera"; + ot->description= "Set the active object as the active camera for this view or scene."; + ot->idname= "VIEW3D_OT_object_as_camera"; + + /* api callbacks */ + ot->exec= view3d_setobjectascamera_exec; + ot->poll= ED_operator_view3d_active; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} /* ********************************** */ /* create intersection coordinates in view Z direction at mouse coordinates */ From 3fe274b072df205614da150df9c3743f2b1b422a Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 6 Oct 2009 03:05:20 +0000 Subject: [PATCH 116/138] Several fixes: * Code for generating 'Object' summary of Keyframes for DopeSheet (which is also used by the TimeLine for getting keyframes to draw) now considers materials, object data, and particles too. * Rearranged the way that keyframing-related settings were presented in the User Preferences. The way the settings were grouped was plain confusing, and based on biased views from the old system. For the record, 'needed'+'visual' are always considered when inserting keyframes, 'always' is for autokeyframing, and default interpolation is only used for newly created F-Curves. * Fixed bug #19472 - Scroll wheel scrolls in the wrong direction for enum-menus that were flipped (i.e. window type menu and 3d-view mode selector). --- release/scripts/ui/space_userpref.py | 11 +- .../editors/animation/keyframes_draw.c | 100 ++++++++++++++--- .../editors/animation/keyframes_edit.c | 103 +++++++++++++++++- .../editors/interface/interface_handlers.c | 24 ++-- .../blender/editors/space_graph/graph_edit.c | 6 +- 5 files changed, 195 insertions(+), 49 deletions(-) diff --git a/release/scripts/ui/space_userpref.py b/release/scripts/ui/space_userpref.py index a9126d2c7f1..15e6c7ee4be 100644 --- a/release/scripts/ui/space_userpref.py +++ b/release/scripts/ui/space_userpref.py @@ -199,14 +199,13 @@ class USERPREF_PT_edit(bpy.types.Panel): sub1 = sub.column() sub1.itemL(text="Keyframing:") sub1.itemR(edit, "use_visual_keying") - sub1.itemR(edit, "new_interpolation_type", text="New F-Curves") + sub1.itemR(edit, "auto_keyframe_insert_available", text="Only Insert Available") + sub1.itemR(edit, "auto_keyframe_insert_needed", text="Only Insert Needed") + sub1.itemS() + sub1.itemL(text="New F-Curve Defaults:") + sub1.itemR(edit, "new_interpolation_type", text="Interpolation") sub1.itemS() sub1.itemR(edit, "auto_keying_enable", text="Auto Keyframing") - sub2 = sub1.column() - sub2.enabled = edit.auto_keying_enable - sub2.row().itemR(edit, "auto_keying_mode", expand=True) - sub2.itemR(edit, "auto_keyframe_insert_available", text="Only Insert Available") - sub2.itemR(edit, "auto_keyframe_insert_needed", text="Only Insert Needed") sub1.itemS() sub1.itemS() diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index e8b25f70b06..d0b5e12c9df 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -54,10 +54,11 @@ #include "DNA_screen_types.h" #include "DNA_scene_types.h" #include "DNA_space_types.h" -#include "DNA_constraint_types.h" #include "DNA_key_types.h" #include "DNA_lamp_types.h" #include "DNA_material_types.h" +#include "DNA_meta_types.h" +#include "DNA_particle_types.h" #include "DNA_userdef_types.h" #include "DNA_gpencil_types.h" #include "DNA_windowmanager_types.h" @@ -656,25 +657,90 @@ void scene_to_keylist(bDopeSheet *ads, Scene *sce, DLRBT_Tree *keys, DLRBT_Tree void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *blocks) { Key *key= ob_get_key(ob); - - if (ob) { - int filterflag; + int filterflag= (ads)? ads->filterflag : 0; + + /* sanity check */ + if (ob == NULL) + return; - /* get filterflag */ - if (ads) - filterflag= ads->filterflag; - else - filterflag= 0; + /* Add action keyframes */ + if (ob->adt && ob->adt->action) + action_to_keylist(ob->adt, ob->adt->action, keys, blocks); + + /* Add shapekey keyframes (only if dopesheet allows, if it is available) */ + if ((key && key->adt && key->adt->action) && !(filterflag & ADS_FILTER_NOSHAPEKEYS)) + action_to_keylist(key->adt, key->adt->action, keys, blocks); + + /* Add material keyframes */ + if ((ob->totcol) && !(filterflag & ADS_FILTER_NOMAT)) { + int a; - /* Add action keyframes */ - if (ob->adt && ob->adt->action) - action_to_keylist(ob->adt, ob->adt->action, keys, blocks); - - /* Add shapekey keyframes (only if dopesheet allows, if it is available) */ - if ((key && key->adt && key->adt->action) && !(filterflag & ADS_FILTER_NOSHAPEKEYS)) - action_to_keylist(key->adt, key->adt->action, keys, blocks); + for (a=0; a < ob->totcol; a++) { + Material *ma= give_current_material(ob, a); - // TODO: restore materials, and object data, etc. + /* there might not be a material */ + if (ELEM(NULL, ma, ma->adt)) + continue; + + /* add material's data */ + action_to_keylist(ma->adt, ma->adt->action, keys, blocks); + } + } + + /* Add object data keyframes */ + switch (ob->type) { + case OB_CAMERA: /* ------- Camera ------------ */ + { + Camera *ca= (Camera *)ob->data; + + if ((ca->adt) && !(filterflag & ADS_FILTER_NOCAM)) + action_to_keylist(ca->adt, ca->adt->action, keys, blocks); + } + break; + case OB_LAMP: /* ---------- Lamp ----------- */ + { + Lamp *la= (Lamp *)ob->data; + + if ((la->adt) && !(filterflag & ADS_FILTER_NOLAM)) + action_to_keylist(la->adt, la->adt->action, keys, blocks); + } + break; + case OB_CURVE: /* ------- Curve ---------- */ + { + Curve *cu= (Curve *)ob->data; + + if ((cu->adt) && !(filterflag & ADS_FILTER_NOCUR)) + action_to_keylist(cu->adt, cu->adt->action, keys, blocks); + } + break; + case OB_MBALL: /* ------- MetaBall ---------- */ + { + MetaBall *mb= (MetaBall *)ob->data; + + if ((mb->adt) && !(filterflag & ADS_FILTER_NOMBA)) + action_to_keylist(mb->adt, mb->adt->action, keys, blocks); + } + break; + case OB_ARMATURE: /* ------- Armature ---------- */ + { + bArmature *arm= (bArmature *)ob->data; + + if ((arm->adt) && !(filterflag & ADS_FILTER_NOARM)) + action_to_keylist(arm->adt, arm->adt->action, keys, blocks); + } + break; + } + + /* Add Particle System Keyframes */ + if ((ob->particlesystem.first) && !(filterflag & ADS_FILTER_NOPART)) { + ParticleSystem *psys = ob->particlesystem.first; + + for(; psys; psys=psys->next) { + if (ELEM(NULL, psys->part, psys->part->adt)) + continue; + else + action_to_keylist(psys->part->adt, psys->part->adt->action, keys, blocks); + } } } diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index 65f7d845b29..7f0d3b4503d 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -36,9 +36,15 @@ #include "DNA_anim_types.h" #include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_camera_types.h" #include "DNA_curve_types.h" #include "DNA_key_types.h" +#include "DNA_lamp_types.h" +#include "DNA_material_types.h" #include "DNA_object_types.h" +#include "DNA_meta_types.h" +#include "DNA_particle_types.h" #include "DNA_space_types.h" #include "DNA_scene_types.h" #include "DNA_world_types.h" @@ -46,6 +52,7 @@ #include "BKE_action.h" #include "BKE_fcurve.h" #include "BKE_key.h" +#include "BKE_material.h" #include "BKE_utildefines.h" #include "ED_anim_api.h" @@ -195,14 +202,100 @@ static short ob_keys_bezier_loop(BeztEditData *bed, Object *ob, BeztEditFunc bez return 0; /* firstly, Object's own AnimData */ - if (ob->adt) - adt_keys_bezier_loop(bed, ob->adt, bezt_ok, bezt_cb, fcu_cb, filterflag); + if (ob->adt) { + if (adt_keys_bezier_loop(bed, ob->adt, bezt_ok, bezt_cb, fcu_cb, filterflag)) + return 1; + } /* shapekeys */ - if ((key && key->adt) && !(filterflag & ADS_FILTER_NOSHAPEKEYS)) - adt_keys_bezier_loop(bed, key->adt, bezt_ok, bezt_cb, fcu_cb, filterflag); + if ((key && key->adt) && !(filterflag & ADS_FILTER_NOSHAPEKEYS)) { + if (adt_keys_bezier_loop(bed, key->adt, bezt_ok, bezt_cb, fcu_cb, filterflag)) + return 1; + } - // FIXME: add materials, etc. (but drawing code doesn't do it yet too! :) + /* Add material keyframes */ + if ((ob->totcol) && !(filterflag & ADS_FILTER_NOMAT)) { + int a; + + for (a=0; a < ob->totcol; a++) { + Material *ma= give_current_material(ob, a); + + /* there might not be a material */ + if (ELEM(NULL, ma, ma->adt)) + continue; + + /* add material's data */ + if (adt_keys_bezier_loop(bed, ma->adt, bezt_ok, bezt_cb, fcu_cb, filterflag)) + return 1; + } + } + + /* Add object data keyframes */ + switch (ob->type) { + case OB_CAMERA: /* ------- Camera ------------ */ + { + Camera *ca= (Camera *)ob->data; + + if ((ca->adt) && !(filterflag & ADS_FILTER_NOCAM)) { + if (adt_keys_bezier_loop(bed, ca->adt, bezt_ok, bezt_cb, fcu_cb, filterflag)) + return 1; + } + } + break; + case OB_LAMP: /* ---------- Lamp ----------- */ + { + Lamp *la= (Lamp *)ob->data; + + if ((la->adt) && !(filterflag & ADS_FILTER_NOLAM)) { + if (adt_keys_bezier_loop(bed, la->adt, bezt_ok, bezt_cb, fcu_cb, filterflag)) + return 1; + } + } + break; + case OB_CURVE: /* ------- Curve ---------- */ + { + Curve *cu= (Curve *)ob->data; + + if ((cu->adt) && !(filterflag & ADS_FILTER_NOCUR)) { + if (adt_keys_bezier_loop(bed, cu->adt, bezt_ok, bezt_cb, fcu_cb, filterflag)) + return 1; + } + } + break; + case OB_MBALL: /* ------- MetaBall ---------- */ + { + MetaBall *mb= (MetaBall *)ob->data; + + if ((mb->adt) && !(filterflag & ADS_FILTER_NOMBA)) { + if (adt_keys_bezier_loop(bed, mb->adt, bezt_ok, bezt_cb, fcu_cb, filterflag)) + return 1; + } + } + break; + case OB_ARMATURE: /* ------- Armature ---------- */ + { + bArmature *arm= (bArmature *)ob->data; + + if ((arm->adt) && !(filterflag & ADS_FILTER_NOARM)) { + if (adt_keys_bezier_loop(bed, arm->adt, bezt_ok, bezt_cb, fcu_cb, filterflag)) + return 1; + } + } + break; + } + + /* Add Particle System Keyframes */ + if ((ob->particlesystem.first) && !(filterflag & ADS_FILTER_NOPART)) { + ParticleSystem *psys = ob->particlesystem.first; + + for(; psys; psys=psys->next) { + if (ELEM(NULL, psys->part, psys->part->adt)) + continue; + + if (adt_keys_bezier_loop(bed, psys->part->adt, bezt_ok, bezt_cb, fcu_cb, filterflag)) + return 1; + } + } return 0; } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index c60c94a9c4d..bbf8df00b88 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -4230,28 +4230,20 @@ int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle *menu, if(event->val==KM_PRESS) { but= ui_but_find_activated(ar); if(but) { - if(ELEM(event->type, DOWNARROWKEY, WHEELDOWNMOUSE)) { - if(block->direction & UI_TOP) but= ui_but_prev(but); - else but= ui_but_next(but); - } - else { - if(block->direction & UI_TOP) but= ui_but_next(but); - else but= ui_but_prev(but); - } + if(ELEM(event->type, DOWNARROWKEY, WHEELDOWNMOUSE)) + but= ui_but_next(but); + else + but= ui_but_prev(but); if(but) ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE); } if(!but) { - if(ELEM(event->type, UPARROWKEY, WHEELUPMOUSE)) { - if(block->direction & UI_TOP) bt= ui_but_first(block); - else bt= ui_but_last(block); - } - else { - if(block->direction & UI_TOP) bt= ui_but_last(block); - else bt= ui_but_first(block); - } + if(ELEM(event->type, UPARROWKEY, WHEELUPMOUSE)) + bt= ui_but_last(block); + else + bt= ui_but_first(block); if(bt) ui_handle_button_activate(C, ar, bt, BUTTON_ACTIVATE); diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 3e0f9760773..22272479e4a 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -1332,12 +1332,8 @@ static int graphkeys_euler_filter_exec (bContext *C, wmOperator *op) * - only rotation curves * - for pchan curves, make sure we're only using the euler curves */ - if (ELEM(0, fcu->rna_path, strstr(fcu->rna_path, "rotation"))) + if (strstr(fcu->rna_path, "rotation_euler") == 0) continue; - if (strstr(fcu->rna_path, "pose.pose_channels")) { - if (strstr(fcu->rna_path, "rotation_euler") == 0) - continue; - } /* check if current set of 3-curves is suitable to add this curve to * - things like whether the current set of curves is 'full' should be checked later only From 1c940d7677ceca15976b69b8bab1aede6ad6d4aa Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 6 Oct 2009 03:40:50 +0000 Subject: [PATCH 117/138] Attempts at some compile fixes for jaguarandi's code: * mingw almost compiles again cleanly, except for a linking error when linking blender http://www.pasteall.org/8297 * win64 should compile again too to a similar degree? * silenced warnings about no newlines... --- source/blender/render/intern/include/rayobject.h | 6 +++--- source/blender/render/intern/raytrace/rayobject_qbvh.cpp | 2 +- source/blender/render/intern/raytrace/svbvh.h | 2 +- source/blender/render/intern/raytrace/vbvh.h | 2 +- source/blender/render/intern/source/rayshade.c | 1 + 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index 9e35c0feac5..5579f3896c1 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -35,6 +35,7 @@ extern "C" { #include "RE_raytrace.h" #include "render_types.h" +#include #include @@ -174,11 +175,10 @@ int RE_rayobjectcontrol_test_break(RayObjectControl *c); -#if !defined(_WIN32) +#if !defined(_WIN32) && !defined(_WIN64) #include #include -#include #define BENCH(a,name) \ do { \ @@ -194,7 +194,7 @@ int RE_rayobjectcontrol_test_break(RayObjectControl *c); } while(0) #else -#define BENCH(a) (a) +#define BENCH(a,name) (a) #endif diff --git a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp index 8d35848c9ec..2719675e3b8 100644 --- a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp @@ -146,4 +146,4 @@ RayObject *RE_rayobject_qbvh_create(int size) return NULL; } -#endif \ No newline at end of file +#endif diff --git a/source/blender/render/intern/raytrace/svbvh.h b/source/blender/render/intern/raytrace/svbvh.h index 3c733b6b402..5837d51d3d4 100644 --- a/source/blender/render/intern/raytrace/svbvh.h +++ b/source/blender/render/intern/raytrace/svbvh.h @@ -246,4 +246,4 @@ struct Reorganize_SVBVH #endif -#endif //__SSE__ \ No newline at end of file +#endif //__SSE__ diff --git a/source/blender/render/intern/raytrace/vbvh.h b/source/blender/render/intern/raytrace/vbvh.h index 1ff51786e52..7d3dbffd125 100644 --- a/source/blender/render/intern/raytrace/vbvh.h +++ b/source/blender/render/intern/raytrace/vbvh.h @@ -234,4 +234,4 @@ struct Reorganize_VBVH return node; } }; -*/ \ No newline at end of file +*/ diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index f2d61e01f50..08d1785446f 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -25,6 +25,7 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include #include #include #include From 2936d791a2383d1f1026a5cf3d0572d5a4768c44 Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Tue, 6 Oct 2009 04:37:01 +0000 Subject: [PATCH 118/138] * missed this in last commit --- release/scripts/ui/space_view3d.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/release/scripts/ui/space_view3d.py b/release/scripts/ui/space_view3d.py index a270e053126..5827739aa53 100644 --- a/release/scripts/ui/space_view3d.py +++ b/release/scripts/ui/space_view3d.py @@ -156,6 +156,8 @@ class VIEW3D_MT_view_cameras(bpy.types.Menu): def draw(self, context): layout = self.layout + + layout.itemO("view3d.object_as_camera") # ********** Select menus, suffix from context.mode ********** From 58557ea737713dc654f4f313530b1acf920763c6 Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Tue, 6 Oct 2009 04:37:25 +0000 Subject: [PATCH 119/138] * Cmake fix for raytrace accel, still not 100% but getting there... --- source/blender/render/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt index 29539fa4d17..279ba7698b7 100644 --- a/source/blender/render/CMakeLists.txt +++ b/source/blender/render/CMakeLists.txt @@ -24,7 +24,7 @@ # # ***** END GPL LICENSE BLOCK ***** -FILE(GLOB SRC intern/source/*.c) +FILE(GLOB SRC intern/source/*.c intern/raytrace/*.cpp) SET(INC intern/include ../../../intern/guardedalloc ../blenlib ../makesdna From c93127d06fd7fc0219ec103bfab94b11cc13f9e0 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 6 Oct 2009 10:23:25 +0000 Subject: [PATCH 120/138] Some more compile fixes for jaguarandi's commit, this time for msvc+scons * Replaced ... = {}; with ... = {0}; * Solved problem with logf(), where msvc couldn't figure out which version of log() to call (solved by casting the int argument to a float, but could also have been to double)... * The cflags and cxxflags for scons when compiling the rendering module were only valid for gcc compiles. These will still need to get added for msvc sometime, but for now, there are no more warnings about unknown options... --- source/blender/render/SConscript | 10 ++++++++-- .../render/intern/raytrace/rayobject_rtbuild.cpp | 4 ++-- source/blender/render/intern/source/rayshade.c | 4 ++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript index 88942ced027..17c20e8807a 100644 --- a/source/blender/render/SConscript +++ b/source/blender/render/SConscript @@ -1,8 +1,14 @@ #!/usr/bin/python Import ('env') -cflags = ['-O2','-msse2','-mfpmath=sse'] -cxxflags = ['-O2','-msse2','-mfpmath=sse'] +if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): + # FIXME: need to set the appropriate flags for msvc, otherwise we get warnings + cflags = [] + cxxflags = [] +else: + cflags = ['-O2','-msse2','-mfpmath=sse'] + cxxflags = ['-O2','-msse2','-mfpmath=sse'] + sources = env.Glob('intern/source/*.c') raysources = env.Glob('intern/raytrace/*.cpp') diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp index 9523e725893..a16499d4f91 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp @@ -362,8 +362,8 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) //Worst case heuristic (cost of each child is linear) float hcost, left_side, right_side; - left_side = bb_area(sweep_left.bb, sweep_left.bb+3)*(sweep_left.cost+logf(i)); - right_side= bb_area(sweep[i].bb, sweep[i].bb+3)*(sweep[i].cost+logf(size-i)); + left_side = bb_area(sweep_left.bb, sweep_left.bb+3)*(sweep_left.cost+logf((float)i)); + right_side= bb_area(sweep[i].bb, sweep[i].bb+3)*(sweep[i].cost+logf((float)size-i)); hcost = left_side+right_side; assert(left_side >= 0); diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 08d1785446f..8c0920a93fa 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -134,7 +134,7 @@ RayObject* RE_rayobject_create(Render *re, int type, int size) } #ifdef RE_RAYCOUNTER -RayCounter re_rc_counter[BLENDER_MAX_THREADS] = {}; +RayCounter re_rc_counter[BLENDER_MAX_THREADS] = {0}; #endif @@ -180,7 +180,7 @@ void freeraytree(Render *re) #ifdef RE_RAYCOUNTER { - RayCounter sum = {}; + RayCounter sum = {0}; int i; for(i=0; i Date: Tue, 6 Oct 2009 10:32:07 +0000 Subject: [PATCH 121/138] One last try - this should fix the remaining issues: * Made bvh_node_merge() in svbvh.h static (fix suggested by jaguarandi). This makes mingw link again. * Also, patched my previous fix for ... = {}; since mingw didn't like the other fix (which was for msvc). --- source/blender/render/intern/raytrace/svbvh.h | 2 +- source/blender/render/intern/source/rayshade.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/render/intern/raytrace/svbvh.h b/source/blender/render/intern/raytrace/svbvh.h index 5837d51d3d4..0303740ee9d 100644 --- a/source/blender/render/intern/raytrace/svbvh.h +++ b/source/blender/render/intern/raytrace/svbvh.h @@ -76,7 +76,7 @@ inline void bvh_node_push_childs(SVBVHNode *node, Isect *isec, SVBVHN } template<> -void bvh_node_merge_bb(SVBVHNode *node, float *min, float *max) +static void bvh_node_merge_bb(SVBVHNode *node, float *min, float *max) { if(is_leaf(node)) { diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 8c0920a93fa..7886e237c97 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -134,7 +134,7 @@ RayObject* RE_rayobject_create(Render *re, int type, int size) } #ifdef RE_RAYCOUNTER -RayCounter re_rc_counter[BLENDER_MAX_THREADS] = {0}; +RayCounter re_rc_counter[BLENDER_MAX_THREADS]; #endif @@ -180,7 +180,7 @@ void freeraytree(Render *re) #ifdef RE_RAYCOUNTER { - RayCounter sum = {0}; + RayCounter sum; int i; for(i=0; i Date: Tue, 6 Oct 2009 10:52:14 +0000 Subject: [PATCH 122/138] *Added memset's to make sure counters start on zero *Disabled ray counter (can be enabled on render/extern/include/RE_raytrace.h by commenting out the define) *marked bvh_node_merge() as static inline (hopping it now compiles on gcc and mingw) --- source/blender/render/extern/include/RE_raytrace.h | 2 +- source/blender/render/intern/raytrace/bvh.h | 2 +- source/blender/render/intern/raytrace/svbvh.h | 2 +- source/blender/render/intern/source/rayshade.c | 7 +++++++ 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index 6a171a98f12..22d55bb1a91 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -35,7 +35,7 @@ extern "C" { #endif -#define RE_RAYCOUNTER /* enable counters per ray, usefull for measuring raytrace structures performance */ +// #define RE_RAYCOUNTER /* enable counters per ray, usefull for measuring raytrace structures performance */ #define RE_RAY_LCTS_MAX_SIZE 256 #define RT_USE_LAST_HIT /* last shadow hit is reused before raycasting on whole tree */ diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h index 0e74bbc923b..ad7f44acb8d 100644 --- a/source/blender/render/intern/raytrace/bvh.h +++ b/source/blender/render/intern/raytrace/bvh.h @@ -112,7 +112,7 @@ template static inline int bvh_node_hit_test(Node *node, Isect *isec template -static void bvh_node_merge_bb(Node *node, float *min, float *max) +static inline void bvh_node_merge_bb(Node *node, float *min, float *max) { if(is_leaf(node)) { diff --git a/source/blender/render/intern/raytrace/svbvh.h b/source/blender/render/intern/raytrace/svbvh.h index 0303740ee9d..5837d51d3d4 100644 --- a/source/blender/render/intern/raytrace/svbvh.h +++ b/source/blender/render/intern/raytrace/svbvh.h @@ -76,7 +76,7 @@ inline void bvh_node_push_childs(SVBVHNode *node, Isect *isec, SVBVHN } template<> -static void bvh_node_merge_bb(SVBVHNode *node, float *min, float *max) +void bvh_node_merge_bb(SVBVHNode *node, float *min, float *max) { if(is_leaf(node)) { diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 7886e237c97..881a549ad96 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -181,6 +181,7 @@ void freeraytree(Render *re) #ifdef RE_RAYCOUNTER { RayCounter sum; + memset( &sum, 0, sizeof(sum) ); int i; for(i=0; ii.infostr= "Raytree finished"; re->stats_draw(re->sdh, &re->i); } + +#ifdef RE_RAYCOUNTER + memset( re_rc_counter, 0, sizeof(re_rc_counter) ); +#endif } + + void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr) { ObjectInstanceRen *obi= (ObjectInstanceRen*)is->hit.ob; From c12cb02c56ef575720f468ed1de7dc065f153580 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 6 Oct 2009 11:21:57 +0000 Subject: [PATCH 123/138] sculpt was checking if multires was the last modifier, instead check if its the last displayed modifier --- source/blender/editors/sculpt_paint/sculpt.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 01a2ff3fdee..982bd315b99 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1099,8 +1099,18 @@ static struct MultiresModifierData *sculpt_multires_active(Object *ob) ModifierData *md; for(md= modifiers_getVirtualModifierList(ob); md; md= md->next) { - if(md->type == eModifierType_Multires && !md->next) { - MultiresModifierData *mmd = (MultiresModifierData*)md; + if(md->type == eModifierType_Multires) { + MultiresModifierData *mmd; + + /* Check if any of the modifiers after multires are active + * if not it can use the multires struct */ + ModifierData *md_next; + for (md_next= md->next; md_next; md_next= md_next->next) { + if(md_next->mode & eModifierMode_Realtime) + return NULL; + } + + mmd = (MultiresModifierData*)md; if(mmd->lvl != 1) return mmd; } From 22605ec759a564428b82a3de1053c0152e9d9374 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 6 Oct 2009 11:33:58 +0000 Subject: [PATCH 124/138] Bone Selections: Ability to set bones as unselectable In the Outliner, it is now possible to toggle per bone the selectability of the bone in the viewport, as for Objects using the restriction columns. This can also be set using the RNA-api. I've tested all commonly used tools IMO, but there may still be a few which I've missed. Please report those cases. PS. For some reason, the define was already there, but not connected up to anything. Can't remember why anymore, but here it is... --- .../blender/editors/armature/editarmature.c | 188 ++++++++++-------- source/blender/editors/armature/poseobject.c | 10 +- source/blender/editors/object/object_select.c | 2 +- .../blender/editors/space_outliner/outliner.c | 12 +- source/blender/makesrna/intern/rna_armature.c | 5 + 5 files changed, 124 insertions(+), 93 deletions(-) diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 402715dbb02..c32837be420 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -110,17 +110,20 @@ void ED_armature_sync_selection(ListBase *edbo) EditBone *ebo; for (ebo=edbo->first; ebo; ebo= ebo->next) { - if ((ebo->flag & BONE_CONNECTED) && (ebo->parent)) { - if (ebo->parent->flag & BONE_TIPSEL) - ebo->flag |= BONE_ROOTSEL; + /* if bone is not selectable, we shouldn't alter this setting... */ + if ((ebo->flag & BONE_UNSELECTABLE) == 0) { + if ((ebo->flag & BONE_CONNECTED) && (ebo->parent)) { + if (ebo->parent->flag & BONE_TIPSEL) + ebo->flag |= BONE_ROOTSEL; + else + ebo->flag &= ~BONE_ROOTSEL; + } + + if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL)) + ebo->flag |= BONE_SELECTED; else - ebo->flag &= ~BONE_ROOTSEL; + ebo->flag &= ~BONE_SELECTED; } - - if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL)) - ebo->flag |= BONE_SELECTED; - else - ebo->flag &= ~BONE_SELECTED; } } @@ -1127,7 +1130,7 @@ static void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int * /* no singular posemode, so check for correct object */ if(base->selcol == (hitresult & 0xFFFF)) { bone = get_indexed_bone(base->object, hitresult); - + if (findunsel) sel = (bone->flag & BONE_SELECTED); else @@ -1347,45 +1350,42 @@ void POSE_OT_flags_set (wmOperatorType *ot) /* **************** Posemode stuff ********************** */ -static void selectconnected_posebonechildren (Object *ob, Bone *bone) +static void selectconnected_posebonechildren (Object *ob, Bone *bone, int extend) { Bone *curBone; - int shift= 0; // XXX - if (!(bone->flag & BONE_CONNECTED)) + /* stop when unconnected child is encontered, or when unselectable bone is encountered */ + if (!(bone->flag & BONE_CONNECTED) || (bone->flag & BONE_UNSELECTABLE)) return; // XXX old cruft! use notifiers instead //select_actionchannel_by_name (ob->action, bone->name, !(shift)); - if (shift) + if (extend) bone->flag &= ~BONE_SELECTED; else bone->flag |= BONE_SELECTED; - for (curBone=bone->childbase.first; curBone; curBone=curBone->next){ - selectconnected_posebonechildren (ob, curBone); - } + for (curBone=bone->childbase.first; curBone; curBone=curBone->next) + selectconnected_posebonechildren(ob, curBone, extend); } /* within active object context */ /* previously known as "selectconnected_posearmature" */ static int pose_select_connected_invoke(bContext *C, wmOperator *op, wmEvent *event) { - Bone *bone, *curBone, *next= NULL; - int shift= 0; // XXX in pose mode, Shift+L is bound to another command - // named "PoseLib Add Current Pose" - int x, y; - ARegion *ar; + ARegion *ar= CTX_wm_region(C); Object *ob= CTX_data_edit_object(C); - ar= CTX_wm_region(C); - + Bone *bone, *curBone, *next= NULL; + int extend= RNA_boolean_get(op->ptr, "extend"); + int x, y; + x= event->x - ar->winrct.xmin; y= event->y - ar->winrct.ymin; view3d_operator_needs_opengl(C); - if (shift) + if (extend) bone= get_nearest_bone(C, 0, x, y); else bone= get_nearest_bone(C, 1, x, y); @@ -1395,26 +1395,29 @@ static int pose_select_connected_invoke(bContext *C, wmOperator *op, wmEvent *ev /* Select parents */ for (curBone=bone; curBone; curBone=next){ - // XXX old cruft! use notifiers instead - //select_actionchannel_by_name (ob->action, curBone->name, !(shift)); - if (shift) - curBone->flag &= ~BONE_SELECTED; + /* ignore bone if cannot be selected */ + if ((curBone->flag & BONE_UNSELECTABLE) == 0) { + // XXX old cruft! use notifiers instead + //select_actionchannel_by_name (ob->action, curBone->name, !(shift)); + + if (extend) + curBone->flag &= ~BONE_SELECTED; + else + curBone->flag |= BONE_SELECTED; + + if (curBone->flag & BONE_CONNECTED) + next=curBone->parent; + else + next=NULL; + } else - curBone->flag |= BONE_SELECTED; - - if (curBone->flag & BONE_CONNECTED) - next=curBone->parent; - else - next=NULL; + next= NULL; } /* Select children */ - for (curBone=bone->childbase.first; curBone; curBone=next){ - selectconnected_posebonechildren (ob, curBone); - } + for (curBone=bone->childbase.first; curBone; curBone=next) + selectconnected_posebonechildren(ob, curBone, extend); - // XXX this only counted the number of pose channels selected - //countall(); // flushes selection! WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob); return OPERATOR_FINISHED; @@ -1435,6 +1438,7 @@ void POSE_OT_select_linked(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* props */ + RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first."); } /* **************** END Posemode stuff ********************** */ @@ -1446,7 +1450,7 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e { bArmature *arm; EditBone *bone, *curBone, *next; - int shift= 0; // XXX + int extend= RNA_boolean_get(op->ptr, "extend"); int x, y; ARegion *ar; Object *obedit= CTX_data_edit_object(C); @@ -1458,7 +1462,7 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e view3d_operator_needs_opengl(C); - if (shift) + if (extend) bone= get_nearest_bone(C, 0, x, y); else bone= get_nearest_bone(C, 1, x, y); @@ -1467,14 +1471,16 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e return OPERATOR_CANCELLED; /* Select parents */ - for (curBone=bone; curBone; curBone=next){ - if (shift){ - curBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + for (curBone=bone; curBone; curBone=next) { + if ((curBone->flag & BONE_UNSELECTABLE) == 0) { + if (extend) { + curBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + } + else{ + curBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + } } - else{ - curBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); - } - + if (curBone->flag & BONE_CONNECTED) next=curBone->parent; else @@ -1482,19 +1488,19 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e } /* Select children */ - while (bone){ - for (curBone=arm->edbo->first; curBone; curBone=next){ + while (bone) { + for (curBone=arm->edbo->first; curBone; curBone=next) { next = curBone->next; - if (curBone->parent == bone){ - if (curBone->flag & BONE_CONNECTED){ - if (shift) + if ((curBone->parent == bone) && (curBone->flag & BONE_UNSELECTABLE)==0) { + if (curBone->flag & BONE_CONNECTED) { + if (extend) curBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); else curBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); bone=curBone; break; } - else{ + else { bone=NULL; break; } @@ -1502,15 +1508,12 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e } if (!curBone) bone=NULL; - } - + ED_armature_sync_selection(arm->edbo); - - /* BIF_undo_push("Select connected"); */ - + WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, obedit); - + return OPERATOR_FINISHED; } @@ -1527,6 +1530,9 @@ void ARMATURE_OT_select_linked(wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties s*/ + RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first."); } /* does bones and points */ @@ -3966,9 +3972,12 @@ static int armature_select_inverse_exec(bContext *C, wmOperator *op) { /* Set the flags */ CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) { - /* select bone */ - ebone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - ebone->flag &= ~BONE_ACTIVE; + /* ignore bone if selection can't change */ + if ((ebone->flag & BONE_UNSELECTABLE) == 0) { + /* select bone */ + ebone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + ebone->flag &= ~BONE_ACTIVE; + } } CTX_DATA_END; @@ -3979,7 +3988,6 @@ static int armature_select_inverse_exec(bContext *C, wmOperator *op) void ARMATURE_OT_select_inverse(wmOperatorType *ot) { - /* identifiers */ ot->name= "Select Inverse"; ot->idname= "ARMATURE_OT_select_inverse"; @@ -4002,15 +4010,18 @@ static int armature_de_select_all_exec(bContext *C, wmOperator *op) /* Set the flags */ CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) { - if (sel==1) { - /* select bone */ - ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - if(ebone->parent) - ebone->parent->flag |= (BONE_TIPSEL); - } - else { - /* deselect bone */ - ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE); + /* ignore bone if selection can't change */ + if ((ebone->flag & BONE_UNSELECTABLE) == 0) { + if (sel==1) { + /* select bone */ + ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + if(ebone->parent) + ebone->parent->flag |= (BONE_TIPSEL); + } + else { + /* deselect bone */ + ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL | BONE_ACTIVE); + } } } CTX_DATA_END; @@ -4051,7 +4062,8 @@ static int armature_select_hierarchy_exec(bContext *C, wmOperator *op) arm= (bArmature *)ob->data; for (curbone= arm->edbo->first; curbone; curbone= curbone->next) { - if (EBONE_VISIBLE(arm, curbone)) { + /* only work on bone if it is visible and its selection can change */ + if (EBONE_VISIBLE(arm, curbone) && (curbone->flag & BONE_UNSELECTABLE)==0) { if (curbone->flag & (BONE_ACTIVE)) { if (direction == BONE_SELECT_PARENT) { if (curbone->parent == NULL) continue; @@ -4071,7 +4083,7 @@ static int armature_select_hierarchy_exec(bContext *C, wmOperator *op) chbone = editbone_get_child(arm, curbone, 1); if (chbone == NULL) continue; - if (EBONE_VISIBLE(arm, chbone)) { + if (EBONE_VISIBLE(arm, chbone) && (chbone->flag & BONE_UNSELECTABLE)==0) { chbone->flag |= (BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); if (!add_to_sel) { @@ -4301,8 +4313,9 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor if (!ob || !ob->pose) return 0; nearBone= get_bone_from_selectbuffer(scene, base, buffer, hits, 1); - - if (nearBone) { + + /* if the bone cannot be affected, don't do anything */ + if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) { bArmature *arm= ob->data; /* since we do unified select, we don't shift+select a bone if the armature object was not active yet */ @@ -4381,7 +4394,8 @@ void ED_pose_deselectall (Object *ob, int test, int doundo) /* Set the flags accordingly */ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if ((pchan->bone->layer & arm->layer) && !(pchan->bone->flag & BONE_HIDDEN_P)) { + /* ignore the pchan if it isn't visible or if its selection cannot be changed */ + if ((pchan->bone->layer & arm->layer) && !(pchan->bone->flag & (BONE_HIDDEN_P|BONE_UNSELECTABLE))) { if (test==3) { pchan->bone->flag ^= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); pchan->bone->flag &= ~BONE_ACTIVE; @@ -4960,8 +4974,10 @@ static int pose_select_inverse_exec(bContext *C, wmOperator *op) /* Set the flags */ CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pchans) { - pchan->bone->flag ^= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); - pchan->bone->flag &= ~BONE_ACTIVE; + if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) { + pchan->bone->flag ^= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL); + pchan->bone->flag &= ~BONE_ACTIVE; + } } CTX_DATA_END; @@ -4995,9 +5011,11 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op) /* Set the flags */ CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pchans) { - /* select pchan */ - if (sel==0) pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE); - else pchan->bone->flag |= BONE_SELECTED; + /* select pchan, only if selectable */ + if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) { + if (sel==0) pchan->bone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL|BONE_ACTIVE); + else pchan->bone->flag |= BONE_SELECTED; + } } CTX_DATA_END; @@ -5031,7 +5049,7 @@ static int pose_select_parent_exec(bContext *C, wmOperator *op) pchan=CTX_data_active_pchan(C); if (pchan) { parent=pchan->parent; - if ((parent) && !(parent->bone->flag & BONE_HIDDEN_P)) { + if ((parent) && !(parent->bone->flag & (BONE_HIDDEN_P|BONE_UNSELECTABLE))) { parent->bone->flag |= BONE_SELECTED; parent->bone->flag |= BONE_ACTIVE; pchan->bone->flag &= ~BONE_ACTIVE; diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index d4b7aa149df..edbc7b9ae9b 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -543,7 +543,7 @@ void pose_select_constraint_target(Scene *scene) for (ct= targets.first; ct; ct= ct->next) { if ((ct->tar == ob) && (ct->subtarget[0])) { bPoseChannel *pchanc= get_pose_channel(ob->pose, ct->subtarget); - if(pchanc) + if((pchanc) && !(pchanc->bone->flag & BONE_UNSELECTABLE)) pchanc->bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; } } @@ -582,7 +582,7 @@ static int pose_select_constraint_target_exec(bContext *C, wmOperator *op) for (ct= targets.first; ct; ct= ct->next) { if ((ct->tar == ob) && (ct->subtarget[0])) { bPoseChannel *pchanc= get_pose_channel(ob->pose, ct->subtarget); - if(pchanc) { + if((pchanc) && !(pchanc->bone->flag & BONE_UNSELECTABLE)) { pchanc->bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL; found= 1; } @@ -634,7 +634,7 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op) for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { curbone= pchan->bone; - if (arm->layer & curbone->layer) { + if ((arm->layer & curbone->layer) && (curbone->flag & BONE_UNSELECTABLE)==0) { if (curbone->flag & (BONE_ACTIVE)) { if (direction == BONE_SELECT_PARENT) { @@ -646,7 +646,7 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op) if (!add_to_sel) curbone->flag &= ~BONE_SELECTED; curbone->flag &= ~BONE_ACTIVE; pabone->flag |= (BONE_ACTIVE|BONE_SELECTED); - + found= 1; break; } @@ -660,7 +660,7 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op) if (!add_to_sel) curbone->flag &= ~BONE_SELECTED; curbone->flag &= ~BONE_ACTIVE; chbone->flag |= (BONE_ACTIVE|BONE_SELECTED); - + found= 1; break; } diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index 98603ee843a..4fa0e04728f 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -82,7 +82,7 @@ void ED_base_object_select(Base *base, short mode) if (base) { if (mode==BA_SELECT) { if (!(base->object->restrictflag & OB_RESTRICT_SELECT)) - if (mode==BA_SELECT) base->flag |= SELECT; + base->flag |= SELECT; } else if (mode==BA_DESELECT) { base->flag &= ~SELECT; diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c index e62c1dedb1b..3c10375c14b 100644 --- a/source/blender/editors/space_outliner/outliner.c +++ b/source/blender/editors/space_outliner/outliner.c @@ -4875,19 +4875,27 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar else if(tselem->type==TSE_POSE_CHANNEL) { bPoseChannel *pchan= (bPoseChannel *)te->directdata; Bone *bone = pchan->bone; - + uiBlockSetEmboss(block, UI_EMBOSSN); bt= uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_P, 0, ICON_RESTRICT_VIEW_OFF, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View"); uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL); + + bt= uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, + (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (short)te->ys, 17, OL_H-1, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View"); + uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL); } else if(tselem->type==TSE_EBONE) { EditBone *ebone= (EditBone *)te->directdata; - + uiBlockSetEmboss(block, UI_EMBOSSN); bt= uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_A, 0, ICON_RESTRICT_VIEW_OFF, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (short)te->ys, 17, OL_H-1, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View"); uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL); + + bt= uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, + (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (short)te->ys, 17, OL_H-1, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View"); + uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL); } } diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 5dbfdd3e6f1..6c9d9263eeb 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -380,6 +380,11 @@ static void rna_def_bone_common(StructRNA *srna, int editbone) RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_NO_CYCLICOFFSET); RNA_def_property_ui_text(prop, "Cyclic Offset", "When bone doesn't have a parent, it receives cyclic offset effects."); RNA_def_property_update(prop, 0, "rna_Armature_update_data"); + + prop= RNA_def_property(srna, "selectable", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_UNSELECTABLE); + RNA_def_property_ui_text(prop, "Selectable", "Bone is able to be selected"); + RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); /* Number values */ /* envelope deform settings */ From 2011ba50c84d61eff998812944354d444bd00041 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 6 Oct 2009 12:23:25 +0000 Subject: [PATCH 125/138] Last fix still failed to link under mingw. This time it works! (gcc and mingw can handle compile and link) --- source/blender/render/intern/raytrace/svbvh.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/render/intern/raytrace/svbvh.h b/source/blender/render/intern/raytrace/svbvh.h index 5837d51d3d4..80e6e2ea190 100644 --- a/source/blender/render/intern/raytrace/svbvh.h +++ b/source/blender/render/intern/raytrace/svbvh.h @@ -76,7 +76,7 @@ inline void bvh_node_push_childs(SVBVHNode *node, Isect *isec, SVBVHN } template<> -void bvh_node_merge_bb(SVBVHNode *node, float *min, float *max) +inline void bvh_node_merge_bb(SVBVHNode *node, float *min, float *max) { if(is_leaf(node)) { From dd8e2897ba19daac5191a341add9955e00798262 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 6 Oct 2009 13:04:31 +0000 Subject: [PATCH 126/138] new operator - bpy.ops.wm.call_menu(name="SOME_MT_menu") This calls a registered menu as a popup so we can reuse header menus , currently used for Node editor and Sequencer add menu (Shift+A), can be used for toolbox too. --- source/blender/blenkernel/BKE_screen.h | 2 ++ source/blender/blenkernel/intern/screen.c | 22 +++++++++++++++ source/blender/editors/include/UI_interface.h | 1 + .../editors/interface/interface_layout.c | 23 +++++++-------- .../editors/interface/interface_regions.c | 28 +++++++++++++++++++ source/blender/editors/space_node/node_ops.c | 4 +++ .../editors/space_sequencer/sequencer_ops.c | 3 ++ source/blender/makesdna/DNA_space_types.h | 2 +- source/blender/makesrna/intern/rna_ui.c | 10 ++----- .../windowmanager/intern/wm_operators.c | 21 ++++++++++++++ 10 files changed, 95 insertions(+), 21 deletions(-) diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index ee04d4f47bc..b983c6f7dc4 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -222,6 +222,8 @@ const struct ListBase *BKE_spacetypes_list(void); void BKE_spacetype_register(struct SpaceType *st); void BKE_spacetypes_free(void); /* only for quitting blender */ +MenuType *BKE_spacemenu_find(const char *idname, int spacetype); + /* spacedata */ void BKE_spacedata_freelist(ListBase *lb); void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2); diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 661d0da1550..3567de5df40 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -343,3 +343,25 @@ unsigned int BKE_screen_visible_layers(bScreen *screen) return layer; } +MenuType *BKE_spacemenu_find(const char *idname, int spacetype) +{ + SpaceType *st= BKE_spacetype_from_id(spacetype); + ARegionType *art; + MenuType* mt; + + if(st==NULL) { + printf("space type %d is invalid\n", spacetype); + return NULL; + } + + if(idname==NULL) + return NULL; + + for(art= st->regiontypes.first; art; art= art->next) + for(mt=art->menutypes.first; mt; mt=mt->next) + if(strcmp(idname, mt->idname)==0) + return mt; + + return NULL; +} + diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 7fea4b10ed9..35598db9e02 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -256,6 +256,7 @@ void uiPupMenuSaveOver(struct bContext *C, struct wmOperator *op, char *filename void uiPupMenuNotice(struct bContext *C, char *str, ...); void uiPupMenuError(struct bContext *C, char *str, ...); void uiPupMenuReports(struct bContext *C, struct ReportList *reports); +void uiPupMenuInvoke(struct bContext *C, const char *idname, int spacetype); /* popup registered menu */ /* Popup Blocks * diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 11dfc44906a..b15be940eef 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -1202,24 +1202,21 @@ static void ui_item_menu(uiLayout *layout, char *name, int icon, uiMenuCreateFun void uiItemM(uiLayout *layout, bContext *C, char *name, int icon, char *menuname) { - ARegion *ar= CTX_wm_region(C); MenuType *mt; - if(!menuname) - return; + mt= BKE_spacemenu_find(menuname, CTX_wm_area(C)->spacetype); - for(mt=ar->type->menutypes.first; mt; mt=mt->next) { - if(strcmp(menuname, mt->idname) == 0) { - if(!name) - name= mt->label; - if(layout->root->type == UI_LAYOUT_MENU && !icon) - icon= ICON_BLANK1; - ui_item_menu(layout, name, icon, ui_item_menutype_func, mt, NULL); - return; - } + if(mt==NULL) { + printf("uiItemM: not found %s\n", menuname); + return; } - printf("uiItemM: not found %s\n", menuname); + if(!name) + name= mt->label; + if(layout->root->type == UI_LAYOUT_MENU && !icon) + icon= ICON_BLANK1; + + ui_item_menu(layout, name, icon, ui_item_menutype_func, mt, NULL); } /* label item */ diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 0f04333c6c5..dae4a54c233 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -2481,6 +2481,34 @@ void uiPupMenuReports(bContext *C, ReportList *reports) BLI_dynstr_free(ds); } +void uiPupMenuInvoke(bContext *C, const char *idname, int spacetype) +{ + uiPopupMenu *pup; + uiLayout *layout; + MenuType *mt= BKE_spacemenu_find(idname, spacetype); + + if(mt==NULL) { + printf("uiPupMenuInvoke: named menu \"%s\" not found\n", idname); + return; + } + + if(mt->poll && mt->poll(C, mt)==0) + return; + + pup= uiPupMenuBegin(C, mt->label, 0); + layout= uiPupMenuLayout(pup); + + Menu menu; + + menu.layout= layout; + menu.type= mt; + + mt->draw(C, &menu); + + uiPupMenuEnd(C, pup); +} + + /*************************** Popup Block API **************************/ void uiPupBlockO(bContext *C, uiBlockCreateFunc func, void *arg, char *opname, int opcontext) diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index f47e9aa2a6f..880cc489838 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -70,6 +70,7 @@ void node_operatortypes(void) void node_keymap(struct wmWindowManager *wm) { wmKeyMap *keymap= WM_keymap_find(wm, "Node", SPACE_NODE, 0); + wmKeymapItem *kmi; /* mouse select in nodes used to be both keys, it's UI elements... */ RNA_enum_set(WM_keymap_add_item(keymap, "NODE_OT_select", ACTIONMOUSE, KM_PRESS, 0, 0)->ptr, "select_type", NODE_SELECT_MOUSE); @@ -97,5 +98,8 @@ void node_keymap(struct wmWindowManager *wm) WM_keymap_add_item(keymap, "NODE_OT_group_ungroup", GKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, 0, 0); + kmi= WM_keymap_add_item(keymap, "WM_OT_call_menu", AKEY, KM_PRESS, KM_SHIFT, 0); + RNA_string_set(kmi->ptr, "name", "NODE_MT_add"); + transform_keymap_for_space(wm, keymap, SPACE_NODE); } diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c index ac125c10b2d..1541b32f566 100644 --- a/source/blender/editors/space_sequencer/sequencer_ops.c +++ b/source/blender/editors/space_sequencer/sequencer_ops.c @@ -177,6 +177,9 @@ void sequencer_keymap(wmWindowManager *wm) WM_keymap_add_item(keymap, "SEQUENCER_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "SEQUENCER_OT_select_border", BKEY, KM_PRESS, 0, 0); + + kmi= WM_keymap_add_item(keymap, "WM_OT_call_menu", AKEY, KM_PRESS, KM_SHIFT, 0); + RNA_string_set(kmi->ptr, "name", "SEQUENCER_MT_add"); WM_keymap_verify_item(keymap, "ANIM_OT_change_frame", LEFTMOUSE, KM_PRESS, 0, 0); diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 2cd47e340bd..ce4f0bc8737 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -139,7 +139,7 @@ typedef struct SpaceSeq { View2D v2d; /* deprecated, copied to region */ float xof, yof; /* offset for drawing the image preview */ - short mainb; + short mainb; /* weird name for the sequencer subtype (seq, image, luma... etc) */ short render_size; short chanshown; short zebra; diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index f16180451a7..1a1172247fc 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -381,13 +381,9 @@ static StructRNA *rna_Menu_register(const bContext *C, ReportList *reports, void return NULL; /* check if we have registered this menu type before, and remove it */ - for(mt=art->menutypes.first; mt; mt=mt->next) { - if(strcmp(mt->idname, dummymt.idname) == 0) { - if(mt->ext.srna) - rna_Menu_unregister(C, mt->ext.srna); - break; - } - } + mt= BKE_spacemenu_find(dummymt.idname, dummymt.space_type); + if(mt && mt->ext.srna) + rna_Menu_unregister(C, mt->ext.srna); /* create a new menu type */ mt= MEM_callocN(sizeof(MenuType), "python buttons menu"); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 486a887b354..9ec0ce0df8d 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -58,6 +58,7 @@ #include "BKE_main.h" #include "BKE_report.h" #include "BKE_scene.h" +#include "BKE_screen.h" /* BKE_ST_MAXNAME */ #include "BKE_utildefines.h" #include "BIF_gl.h" @@ -766,6 +767,25 @@ static void WM_OT_search_menu(wmOperatorType *ot) ot->poll= wm_search_menu_poll; } +static int wm_call_menu_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + char idname[BKE_ST_MAXNAME]; + RNA_string_get(op->ptr, "name", idname); + + uiPupMenuInvoke(C, idname, CTX_wm_area(C)->spacetype); + + return OPERATOR_CANCELLED; +} + +static void WM_OT_call_menu(wmOperatorType *ot) +{ + ot->name= "Call Menu"; + ot->idname= "WM_OT_call_menu"; + + ot->invoke= wm_call_menu_invoke; + + RNA_def_string(ot->srna, "name", "", BKE_ST_MAXNAME, "Name", "Name of the new sequence strip"); +} /* ************ window / screen operator definitions ************** */ @@ -2122,6 +2142,7 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_redraw_timer); WM_operatortype_append(WM_OT_debug_menu); WM_operatortype_append(WM_OT_search_menu); + WM_operatortype_append(WM_OT_call_menu); } /* default keymap for windows and screens, only call once per WM */ From 76019d5fb9812941eb9b70fe47fde386b18be286 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 6 Oct 2009 14:09:40 +0000 Subject: [PATCH 127/138] * Remember, C-style declarations at the *beginning* of a scope, not C++ style wherever one pleases (before first usage). --- source/blender/editors/interface/interface_regions.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index dae4a54c233..cdb62d0a4b4 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -2485,6 +2485,7 @@ void uiPupMenuInvoke(bContext *C, const char *idname, int spacetype) { uiPopupMenu *pup; uiLayout *layout; + Menu menu; MenuType *mt= BKE_spacemenu_find(idname, spacetype); if(mt==NULL) { @@ -2498,8 +2499,6 @@ void uiPupMenuInvoke(bContext *C, const char *idname, int spacetype) pup= uiPupMenuBegin(C, mt->label, 0); layout= uiPupMenuLayout(pup); - Menu menu; - menu.layout= layout; menu.type= mt; From 6282b7998b212ae5ecda8bf26f4adebd747ba918 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 6 Oct 2009 14:25:55 +0000 Subject: [PATCH 128/138] * copying of python31.zip and zlip.pyd is not necessary anymore, since the zip is unpacked by default to .blender/python/lib --- SConstruct | 4 ---- 1 file changed, 4 deletions(-) diff --git a/SConstruct b/SConstruct index 4d6ef7ccb49..6d18000a984 100644 --- a/SConstruct +++ b/SConstruct @@ -578,10 +578,6 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc'): else: dllsources.append('${BF_SDL_LIBPATH}/SDL.dll') if env['WITH_BF_PYTHON']: - ver = env["BF_PYTHON_VERSION"].replace(".", "") - - dllsources.append('${LCGDIR}/release/python' + ver + '.zip') - dllsources.append('${LCGDIR}/release/zlib.pyd') if env['BF_DEBUG']: dllsources.append('${BF_PYTHON_LIBPATH}/${BF_PYTHON_DLL}_d.dll') else: From 86307b58c0991472b25bd0c24ba8d2cdbf332bc3 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 6 Oct 2009 15:01:46 +0000 Subject: [PATCH 129/138] == SCons == * Unzip of python31.zip now works also for Python 2.5. Patch by b333rt (thanks again!) --- tools/Blender.py | 78 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/tools/Blender.py b/tools/Blender.py index 04f2676deb3..fec11685525 100644 --- a/tools/Blender.py +++ b/tools/Blender.py @@ -20,6 +20,9 @@ import string import glob import time import sys +import zipfile +import shutil +import cStringIO from SCons.Script.SConscript import SConsEnvironment import SCons.Action @@ -327,11 +330,80 @@ def set_quiet_output(env): env['BUILDERS']['Library'] = static_lib env['BUILDERS']['Program'] = program + +class CompZipFile(zipfile.ZipFile): + """Partial copy of python2.6's zipfile.ZipFile (see http://www.python.org) + to get a extractall() that works on py2.5 and probably earlier distributions.""" + def __init__(self, file, mode="r", compression=zipfile.ZIP_STORED, allowZip64=False): + zipfile.ZipFile.__init__(self, file, mode, compression, allowZip64) + if not hasattr(self,"extractall"): # use our method + print "Debug: Using comp_extractall!" + self.extractall= self.comp_extractall + + def comp_extractall(self, path=None, members=None, pwd=None): #renamed method + """Extract all members from the archive to the current working + directory. `path' specifies a different directory to extract to. + `members' is optional and must be a subset of the list returned + by namelist(). + """ + if members is None: + members = self.namelist() + + for zipinfo in members: + self.comp_extract(zipinfo, path, pwd) # use our method + + def comp_extract(self, member, path=None, pwd=None): #renamed method + """Extract a member from the archive to the current working directory, + using its full name. Its file information is extracted as accurately + as possible. `member' may be a filename or a ZipInfo object. You can + specify a different directory using `path'. + """ + if not isinstance(member, zipfile.ZipInfo): + member = self.getinfo(member) + + if path is None: + path = os.getcwd() + + return self.comp_extract_member(member, path, pwd) # use our method + + def comp_extract_member(self, member, targetpath, pwd): #renamed method + """Extract the ZipInfo object 'member' to a physical + file on the path targetpath. + """ + # build the destination pathname, replacing + # forward slashes to platform specific separators. + if targetpath[-1:] in (os.path.sep, os.path.altsep): + targetpath = targetpath[:-1] + + # don't include leading "/" from file name if present + if member.filename[0] == '/': + targetpath = os.path.join(targetpath, member.filename[1:]) + else: + targetpath = os.path.join(targetpath, member.filename) + + targetpath = os.path.normpath(targetpath) + + # Create all upper directories if necessary. + upperdirs = os.path.dirname(targetpath) + if upperdirs and not os.path.exists(upperdirs): + os.makedirs(upperdirs) + + if member.filename[-1] == '/': + os.mkdir(targetpath) + return targetpath + + #use StrinIO instead so we don't have to reproduce more functionality. + source = cStringIO.StringIO(self.read(member.filename)) + target = file(targetpath, "wb") + shutil.copyfileobj(source, target) + source.close() + target.close() + + return targetpath def unzip_pybundle(from_zip,to_dir,exclude_re): - import zipfile - zip= zipfile.ZipFile(from_zip, mode='r') + zip= CompZipFile(from_zip, mode='r') exclude_re= list(exclude_re) #single re object or list of re objects debug= 0 #list files instead of unpacking good= [] @@ -356,7 +428,7 @@ def my_winpybundle_print(target, source, env): pass def WinPyBundle(target=None, source=None, env=None): - import shutil, re + import re py_zip= env.subst( env['LCGDIR'] ) if py_zip[0]=='#': py_zip= py_zip[1:] From 8d54982f37cf48d510fa2de0b2b45c635164a7f3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 6 Oct 2009 15:31:25 +0000 Subject: [PATCH 130/138] Material buttons now view the active node material shading settings. Selecting a material in the node tree sets this as the active material and the buttons view redraws. Added rna prop material.active_node_material Currently its not clear what settings are used by the node material and the base material (needs some tedious research) so I made most panels use the node material with the exceptions of volumetrics, physics and halo settings. We'll probably need to split the panels up to do this properly. --- release/scripts/ui/buttons_material.py | 68 +++++++++++-------- source/blender/blenkernel/BKE_node.h | 1 + source/blender/blenkernel/intern/node.c | 31 +++++++++ source/blender/editors/sculpt_paint/sculpt.c | 8 +-- .../blender/editors/space_node/node_select.c | 17 ++++- source/blender/makesrna/intern/rna_material.c | 34 ++++++++++ 6 files changed, 123 insertions(+), 36 deletions(-) diff --git a/release/scripts/ui/buttons_material.py b/release/scripts/ui/buttons_material.py index 2415d636dab..dee927415e6 100644 --- a/release/scripts/ui/buttons_material.py +++ b/release/scripts/ui/buttons_material.py @@ -1,6 +1,17 @@ import bpy +def active_node_mat(mat): + # TODO, 2.4x has a pipeline section, for 2.5 we need to communicate + # which settings from node-materials are used + if mat: + mat_node = mat.active_node_material + if mat_node: + return mat_node + + return None + + class MaterialButtonsPanel(bpy.types.Panel): __space_type__ = 'PROPERTIES' __region_type__ = 'WINDOW' @@ -74,14 +85,14 @@ class MATERIAL_PT_shading(MaterialButtonsPanel): COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME']) def poll(self, context): - mat = context.material + mat = active_node_mat(context.material) engine = context.scene.render_data.engine return mat and (mat.type in ('SURFACE', 'WIRE', 'HALO')) and (engine in self.COMPAT_ENGINES) def draw(self, context): layout = self.layout - mat = context.material + mat = active_node_mat(context.material) if mat.type in ('SURFACE', 'WIRE'): split = layout.split() @@ -117,7 +128,7 @@ class MATERIAL_PT_strand(MaterialButtonsPanel): def draw(self, context): layout = self.layout - mat = context.material + mat = context.material # dont use node material tan = mat.strand split = layout.split() @@ -152,7 +163,7 @@ class MATERIAL_PT_physics(MaterialButtonsPanel): def draw(self, context): layout = self.layout - phys = context.material.physics + phys = context.material.physics # dont use node material split = layout.split() @@ -171,14 +182,14 @@ class MATERIAL_PT_options(MaterialButtonsPanel): COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME']) def poll(self, context): - mat = context.material + mat = active_node_mat(context.material) engine = context.scene.render_data.engine return mat and (mat.type in ('SURFACE', 'WIRE', 'HALO')) and (engine in self.COMPAT_ENGINES) def draw(self, context): layout = self.layout - mat = context.material + mat = active_node_mat(context.material) split = layout.split() @@ -211,14 +222,14 @@ class MATERIAL_PT_shadow(MaterialButtonsPanel): COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME']) def poll(self, context): - mat = context.material + mat = active_node_mat(context.material) engine = context.scene.render_data.engine return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES) def draw(self, context): layout = self.layout - mat = context.material + mat = active_node_mat(context.material) split = layout.split() @@ -244,14 +255,14 @@ class MATERIAL_PT_diffuse(MaterialButtonsPanel): COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME']) def poll(self, context): - mat = context.material + mat = active_node_mat(context.material) engine = context.scene.render_data.engine return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES) def draw(self, context): layout = self.layout - mat = context.material + mat = active_node_mat(context.material) split = layout.split() @@ -298,14 +309,14 @@ class MATERIAL_PT_specular(MaterialButtonsPanel): COMPAT_ENGINES = set(['BLENDER_RENDER', 'BLENDER_GAME']) def poll(self, context): - mat = context.material + mat = active_node_mat(context.material) engine = context.scene.render_data.engine return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES) def draw(self, context): layout = self.layout - mat = context.material + mat = active_node_mat(context.material) layout.active = (not mat.shadeless) @@ -351,12 +362,12 @@ class MATERIAL_PT_sss(MaterialButtonsPanel): COMPAT_ENGINES = set(['BLENDER_RENDER']) def poll(self, context): - mat = context.material + mat = active_node_mat(context.material) engine = context.scene.render_data.engine return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES) def draw_header(self, context): - mat = context.material + mat = active_node_mat(context.material) sss = mat.subsurface_scattering self.layout.active = (not mat.shadeless) @@ -365,7 +376,7 @@ class MATERIAL_PT_sss(MaterialButtonsPanel): def draw(self, context): layout = self.layout - mat = context.material + mat = active_node_mat(context.material) sss = mat.subsurface_scattering layout.active = sss.enabled @@ -396,19 +407,19 @@ class MATERIAL_PT_mirror(MaterialButtonsPanel): COMPAT_ENGINES = set(['BLENDER_RENDER']) def poll(self, context): - mat = context.material + mat = active_node_mat(context.material) engine = context.scene.render_data.engine return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES) def draw_header(self, context): - raym = context.material.raytrace_mirror + raym = active_node_mat(context.material).raytrace_mirror self.layout.itemR(raym, "enabled", text="") def draw(self, context): layout = self.layout - mat = context.material + mat = active_node_mat(context.material) raym = mat.raytrace_mirror layout.active = raym.enabled @@ -451,19 +462,19 @@ class MATERIAL_PT_transp(MaterialButtonsPanel): COMPAT_ENGINES = set(['BLENDER_RENDER']) def poll(self, context): - mat = context.material + mat = active_node_mat(context.material) engine = context.scene.render_data.engine return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in self.COMPAT_ENGINES) def draw_header(self, context): - mat = context.material + mat = active_node_mat(context.material) self.layout.itemR(mat, "transparency", text="") def draw(self, context): layout = self.layout - mat = context.material + mat = active_node_mat(context.material) rayt = mat.raytrace_transparency row = layout.row() @@ -517,7 +528,7 @@ class MATERIAL_PT_halo(MaterialButtonsPanel): def draw(self, context): layout = self.layout - mat = context.material + mat = context.material # dont use node material halo = mat.halo split = layout.split() @@ -569,7 +580,7 @@ class MATERIAL_PT_flare(MaterialButtonsPanel): def draw(self, context): layout = self.layout - mat = context.material + mat = context.material # dont use node material halo = mat.halo layout.active = halo.flare_mode @@ -618,8 +629,7 @@ class MATERIAL_PT_volume_density(VolumeButtonsPanel): def draw(self, context): layout = self.layout - mat = context.material - vol = context.material.volume + vol = context.material.volume # dont use node material split = layout.split() row = split.row() @@ -635,7 +645,7 @@ class MATERIAL_PT_volume_shading(VolumeButtonsPanel): def draw(self, context): layout = self.layout - vol = context.material.volume + vol = context.material.volume # dont use node material split = layout.split() @@ -660,7 +670,7 @@ class MATERIAL_PT_volume_lighting(VolumeButtonsPanel): def draw(self, context): layout = self.layout - vol = context.material.volume + vol = context.material.volume # dont use node material split = layout.split() @@ -695,7 +705,7 @@ class MATERIAL_PT_volume_transp(VolumeButtonsPanel): def draw(self, context): layout = self.layout - mat = context.material + mat = context.material # dont use node material layout.itemR(mat, "transparency_method", expand=True) @@ -707,7 +717,7 @@ class MATERIAL_PT_volume_integration(VolumeButtonsPanel): def draw(self, context): layout = self.layout - vol = context.material.volume + vol = context.material.volume # dont use node material split = layout.split() diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index b1e7dcaff02..66776d086d6 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -181,6 +181,7 @@ int nodeCountSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock); void nodeSetActive(struct bNodeTree *ntree, struct bNode *node); struct bNode *nodeGetActive(struct bNodeTree *ntree); struct bNode *nodeGetActiveID(struct bNodeTree *ntree, short idtype); +int nodeSetActiveID(struct bNodeTree *ntree, short idtype, struct ID *id); void nodeClearActiveID(struct bNodeTree *ntree, short idtype); void NodeTagChanged(struct bNodeTree *ntree, struct bNode *node); diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index aa12894feb9..fad866a7201 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1575,6 +1575,37 @@ bNode *nodeGetActiveID(bNodeTree *ntree, short idtype) return node; } +int nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id) +{ + bNode *node; + int ok= FALSE; + + if(ntree==NULL) return ok; + + /* check for group edit */ + for(node= ntree->nodes.first; node; node= node->next) + if(node->flag & NODE_GROUP_EDIT) + break; + + if(node) + ntree= (bNodeTree*)node->id; + + /* now find active node with this id */ + for(node= ntree->nodes.first; node; node= node->next) { + if(node->id && GS(node->id->name)==idtype) { + if(id && ok==FALSE && node->id==id) { + node->flag |= NODE_ACTIVE_ID; + ok= TRUE; + } else { + node->flag &= ~NODE_ACTIVE_ID; + } + } + } + + return ok; +} + + /* two active flags, ID nodes have special flag for buttons display */ void nodeClearActiveID(bNodeTree *ntree, short idtype) { diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 982bd315b99..c9353f697db 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1100,17 +1100,15 @@ static struct MultiresModifierData *sculpt_multires_active(Object *ob) for(md= modifiers_getVirtualModifierList(ob); md; md= md->next) { if(md->type == eModifierType_Multires) { - MultiresModifierData *mmd; + MultiresModifierData *mmd= (MultiresModifierData*)md; /* Check if any of the modifiers after multires are active * if not it can use the multires struct */ - ModifierData *md_next; - for (md_next= md->next; md_next; md_next= md_next->next) { - if(md_next->mode & eModifierMode_Realtime) + for (md= md->next; md; md= md->next) { + if(md->mode & eModifierMode_Realtime) return NULL; } - mmd = (MultiresModifierData*)md; if(mmd->lvl != 1) return mmd; } diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index 5e482758c9d..ecbd46b720f 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -38,6 +38,7 @@ #include "BKE_context.h" #include "BKE_node.h" #include "BKE_global.h" +#include "BKE_utildefines.h" #include "BLI_rect.h" @@ -55,7 +56,7 @@ #include "node_intern.h" -static void node_mouse_select(SpaceNode *snode, ARegion *ar, short *mval, short extend) +static bNode *node_mouse_select(SpaceNode *snode, ARegion *ar, short *mval, short extend) { bNode *node; float mx, my; @@ -101,7 +102,10 @@ static void node_mouse_select(SpaceNode *snode, ARegion *ar, short *mval, short ;// node_link_viewer(snode, node); //std_rmouse_transform(node_transform_ext); /* does undo push for select */ + } + + return node; } static int node_select_exec(bContext *C, wmOperator *op) @@ -112,6 +116,7 @@ static int node_select_exec(bContext *C, wmOperator *op) int select_type; short mval[2]; short extend; + bNode *node= NULL; select_type = RNA_enum_get(op->ptr, "select_type"); @@ -120,12 +125,20 @@ static int node_select_exec(bContext *C, wmOperator *op) mval[0] = RNA_int_get(op->ptr, "mouse_x"); mval[1] = RNA_int_get(op->ptr, "mouse_y"); extend = RNA_boolean_get(op->ptr, "extend"); - node_mouse_select(snode, ar, mval, extend); + node= node_mouse_select(snode, ar, mval, extend); break; } /* need refresh/a notifier vs compo notifier */ // XXX WM_event_add_notifier(C, NC_SCENE|ND_NODES, NULL); /* Do we need to pass the scene? */ + + /* WATCH THIS, there are a few other ways to change the active material */ + if(node) { + if (node->id && GS(node->id->name)== ID_MA) { + WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING_DRAW, node->id); + } + } + ED_region_tag_redraw(ar); /* allow tweak event to work too */ diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index b05a7e59cc3..efcf4de062e 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -54,6 +54,8 @@ static EnumPropertyItem prop_texture_coordinates_items[] = { #include "MEM_guardedalloc.h" +#include "DNA_node_types.h" + #include "BKE_depsgraph.h" #include "BKE_main.h" #include "BKE_texture.h" @@ -152,6 +154,31 @@ static void rna_Material_active_texture_set(PointerRNA *ptr, PointerRNA value) } } +static PointerRNA rna_Material_active_node_material_get(PointerRNA *ptr) +{ + Material *ma= (Material*)ptr->data; + Material *ma_node= NULL; + + /* used in buttons to check context, also checks for edited groups */ + + if(ma && ma->use_nodes && ma->nodetree) { + bNode *node= nodeGetActiveID(ma->nodetree, ID_MA); + + if(node) + ma_node= (Material *)node->id; + } + + return rna_pointer_inherit_refine(ptr, &RNA_Material, ma_node); +} + +static void rna_Material_active_node_material_set(PointerRNA *ptr, PointerRNA value) +{ + Material *ma= (Material*)ptr->data; + Material *ma_act= value.data; + + nodeSetActiveID(ma->nodetree, ID_MA, ma_act); +} + static void rna_MaterialStrand_start_size_range(PointerRNA *ptr, float *min, float *max) { Material *ma= (Material*)ptr->id.data; @@ -1690,6 +1717,13 @@ void RNA_def_material(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes to render the material."); RNA_def_property_update(prop, NC_MATERIAL, NULL); + prop= RNA_def_property(srna, "active_node_material", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "Material"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_pointer_funcs(prop, "rna_Material_active_node_material_get", "rna_Material_active_node_material_set", NULL); + RNA_def_property_ui_text(prop, "Material", "Active node material."); + RNA_def_property_update(prop, NC_MATERIAL, NULL); + /* common */ rna_def_animdata_common(srna); rna_def_mtex_common(srna, "rna_Material_mtex_begin", "rna_Material_active_texture_get", From 07aba4f933279e5940b3bf96825773dfde196455 Mon Sep 17 00:00:00 2001 From: Damien Plisson Date: Tue, 6 Oct 2009 16:56:22 +0000 Subject: [PATCH 131/138] Cocoa port : First pure Cocoa version ! (Mostly for very early testers) Cocoa uses coordinates with y=0 at bottom : updated wm_window.c and wm_event_system.c for COCOA build to avoid double conversions in response to mouse move events and GHOST_getCursorPosition Known limitations: No fullscreen support Font issue in preference panel libSDL uses some Carbon functions --- intern/ghost/intern/GHOST_SystemCocoa.h | 20 +- intern/ghost/intern/GHOST_SystemCocoa.mm | 259 +++++-- intern/ghost/intern/GHOST_WindowCocoa.h | 55 +- intern/ghost/intern/GHOST_WindowCocoa.mm | 642 +++++++++++------- .../windowmanager/intern/wm_event_system.c | 10 +- .../blender/windowmanager/intern/wm_window.c | 6 + 6 files changed, 655 insertions(+), 337 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index 3e499f3d136..eab5a5b28aa 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -46,6 +46,7 @@ class GHOST_EventCursor; class GHOST_EventKey; class GHOST_EventWindow; +class GHOST_WindowCocoa; class GHOST_SystemCocoa : public GHOST_System { @@ -191,6 +192,13 @@ public: */ virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const; + /** + * Handles a window event. Called by GHOST_WindowCocoa window delegate + * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) + * @return Indication whether the event was handled. + */ + GHOST_TSuccess handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window); + protected: /** * Initializes the system. @@ -220,13 +228,6 @@ protected: */ GHOST_TSuccess handleKeyEvent(void *eventPtr); - /** - * Handles a window event. - * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) - * @return Indication whether the event was handled. - */ - GHOST_TSuccess handleWindowEvent(void *eventPtr); - /** * Handles all basic Mac application stuff for a mouse down event. * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) @@ -250,10 +251,7 @@ protected: * @param tmTask Pointer to the timer task that expired. */ //static void s_timerCallback(TMTaskPtr tmTask); - - /** Cocoa autoReleasePool (void*) used for enablign standard C++ compilation */ - void* m_autoReleasePool; - + /** Event handler reference. */ //EventHandlerRef m_handler; diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 06ce2882beb..fe3cd80f265 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -89,7 +89,157 @@ const EventTypeSpec kEvents[] = };*/ -static GHOST_TButtonMask convertButton(EventMouseButton button) +/* Keycodes from Carbon include file */ +/* + * Summary: + * Virtual keycodes + * + * Discussion: + * These constants are the virtual keycodes defined originally in + * Inside Mac Volume V, pg. V-191. They identify physical keys on a + * keyboard. Those constants with "ANSI" in the name are labeled + * according to the key position on an ANSI-standard US keyboard. + * For example, kVK_ANSI_A indicates the virtual keycode for the key + * with the letter 'A' in the US keyboard layout. Other keyboard + * layouts may have the 'A' key label on a different physical key; + * in this case, pressing 'A' will generate a different virtual + * keycode. + */ +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +/* ISO keyboards only*/ +enum { + kVK_ISO_Section = 0x0A +}; + +/* JIS keyboards only*/ +enum { + kVK_JIS_Yen = 0x5D, + kVK_JIS_Underscore = 0x5E, + kVK_JIS_KeypadComma = 0x5F, + kVK_JIS_Eisu = 0x66, + kVK_JIS_Kana = 0x68 +}; + + +static GHOST_TButtonMask convertButton(int button) { switch (button) { case 0: @@ -474,8 +624,6 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() GHOST_SystemCocoa::~GHOST_SystemCocoa() { - NSAutoreleasePool* pool = (NSAutoreleasePool *)m_autoReleasePool; - [pool drain]; } @@ -492,16 +640,18 @@ GHOST_TSuccess GHOST_SystemCocoa::init() SetFrontProcess(&psn); }*/ - m_autoReleasePool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; if (NSApp == nil) { [NSApplication sharedApplication]; if ([NSApp mainMenu] == nil) { NSMenu *mainMenubar = [[NSMenu alloc] init]; NSMenuItem *menuItem; + NSMenu *windowMenu; + NSMenu *appMenu; //Create the application menu - NSMenu *appMenu = [[NSMenu alloc] initWithTitle:@"Blender"]; + appMenu = [[NSMenu alloc] initWithTitle:@"Blender"]; [appMenu addItemWithTitle:@"About Blender" action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; [appMenu addItem:[NSMenuItem separatorItem]]; @@ -525,7 +675,7 @@ GHOST_TSuccess GHOST_SystemCocoa::init() [appMenu release]; //Create the window menu - NSMenu *windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; + windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; menuItem = [windowMenu addItemWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask]; @@ -549,7 +699,8 @@ GHOST_TSuccess GHOST_SystemCocoa::init() [appDelegate setSystemCocoa:this]; [NSApp setDelegate:appDelegate]; } - + + [pool drain]; /* * Initialize the cursor to the standard arrow shape (so that we can change it later on). @@ -597,12 +748,18 @@ GHOST_TUns8 GHOST_SystemCocoa::getNumDisplays() const { //Note that OS X supports monitor hot plug // We do not support multiple monitors at the moment - return [[NSScreen screens] count]; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + GHOST_TUns8 count = [[NSScreen screens] count]; + + [pool drain]; + return count; } void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; //Get visible frame, that is frame excluding dock and top menu bar NSRect frame = [[NSScreen mainScreen] visibleFrame]; @@ -612,6 +769,8 @@ void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns width = contentRect.size.width; height = contentRect.size.height; + + [pool drain]; } @@ -627,7 +786,8 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow( const GHOST_TEmbedderWindowID parentWindow ) { - GHOST_IWindow* window = 0; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + GHOST_IWindow* window = 0; //Get the available rect for including window contents NSRect frame = [[NSScreen mainScreen] visibleFrame]; @@ -638,7 +798,7 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow( left = left > contentRect.origin.x ? left : contentRect.origin.x; top = top > contentRect.origin.y ? top : contentRect.origin.y; - window = new GHOST_WindowCocoa (title, left, top, width, height, state, type); + window = new GHOST_WindowCocoa (this, title, left, top, width, height, state, type); if (window) { if (window->getValid()) { @@ -657,6 +817,7 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow( else { GHOST_PRINT("GHOST_SystemCocoa::createWindow(): could not create window\n"); } + [pool drain]; return window; } @@ -713,7 +874,7 @@ GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 GHOST_TSuccess GHOST_SystemCocoa::getModifierKeys(GHOST_ModifierKeys& keys) const { - NSUInteger modifiers = [[NSApp currentEvent] modifierFlags]; + NSUInteger modifiers = [[NSApp currentEvent] modifierFlags]; //Direct query to modifierFlags can be used in 10.6 keys.set(GHOST_kModifierKeyCommand, (modifiers & NSCommandKeyMask) ? true : false); @@ -744,16 +905,9 @@ GHOST_TSuccess GHOST_SystemCocoa::getButtons(GHOST_Buttons& buttons) const */ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) { - NSAutoreleasePool* pool = (NSAutoreleasePool*)m_autoReleasePool; - //bool anyProcessed = false; + bool anyProcessed = false; NSEvent *event; - //Reinit the AutoReleasePool - //This is not done the typical Cocoa way (init at beginning of loop, and drain at the end) - //to allow pool to work with other function calls outside this loop (but in same thread) - [pool drain]; - m_autoReleasePool = [[NSAutoreleasePool alloc] init]; - // SetMouseCoalescingEnabled(false, NULL); //TODO : implement timer ?? @@ -790,14 +944,17 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) }*/ do { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES]; - if (event==nil) + if (event==nil) { + [pool drain]; break; + } - //anyProcessed = true; + anyProcessed = true; switch ([event type]) { case NSKeyDown: @@ -853,47 +1010,42 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) } //Resend event to NSApp to ensure Mac wide events are handled [NSApp sendEvent:event]; + [pool drain]; } while (event!= nil); //} while (waitForEvent && !anyProcessed); Needed only for timer implementation - return true; //anyProcessed; + + return anyProcessed; } -//TODO: To be called from NSWindow delegate -GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(void *eventPtr) +//Note: called from NSWindow delegate +GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window) { - /*WindowRef windowRef; - GHOST_WindowCocoa *window; - - // Check if the event was send to a GHOST window - ::GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &windowRef); - window = (GHOST_WindowCarbon*) ::GetWRefCon(windowRef); if (!validWindow(window)) { - return err; + return GHOST_kFailure; } //if (!getFullScreen()) { - err = noErr; - switch([event ]) + switch(eventType) { - case kEventWindowClose: + case GHOST_kEventWindowClose: pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) ); break; - case kEventWindowActivated: + case GHOST_kEventWindowActivate: m_windowManager->setActiveWindow(window); window->loadCursor(window->getCursorVisibility(), window->getCursorShape()); pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) ); break; - case kEventWindowDeactivated: + case GHOST_kEventWindowDeactivate: m_windowManager->setWindowInactive(window); pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) ); break; - case kEventWindowUpdate: + case GHOST_kEventWindowUpdate: //if (getFullScreen()) GHOST_PRINT("GHOST_SystemCarbon::handleWindowEvent(): full-screen update event\n"); pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) ); break; - case kEventWindowBoundsChanged: + case GHOST_kEventWindowSize: if (!m_ignoreWindowSizedMessages) { window->updateDrawingContext(); @@ -901,7 +1053,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(void *eventPtr) } break; default: - err = eventNotHandledErr; + return GHOST_kFailure; break; } // } @@ -910,7 +1062,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(void *eventPtr) //GHOST_PRINT("GHOST_SystemCarbon::handleWindowEvent(): full-screen window event, " << window << "\n"); //::RemoveEventFromQueue(::GetMainEventQueue(), event); //} - */ return GHOST_kSuccess; } @@ -943,10 +1094,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) GHOST_TabletData& ct=((GHOST_WindowCocoa*)window)->GetCocoaTabletData(); NSUInteger tabletEvent; - ct.Pressure = 0; - ct.Xtilt = 0; - ct.Ytilt = 0; - //Handle tablet events combined with mouse events switch ([event subtype]) { case NX_SUBTYPE_TABLET_POINT: @@ -969,6 +1116,9 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) break; case NSTabletProximity: + ct.Pressure = 0; + ct.Xtilt = 0; + ct.Ytilt = 0; if ([event isEnteringProximity]) { //pointer is entering tablet area proximity @@ -1005,23 +1155,24 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) NSEvent *event = (NSEvent *)eventPtr; GHOST_IWindow* window = m_windowManager->getActiveWindow(); + if (!window) { + printf("\nM invalid window"); + return GHOST_kFailure; + } + switch ([event type]) { case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown: - if (m_windowManager->getActiveWindow()) { - pushEvent(new GHOST_EventButton([event timestamp], GHOST_kEventButtonDown, window, convertButton([event buttonNumber]))); - } + pushEvent(new GHOST_EventButton([event timestamp], GHOST_kEventButtonDown, window, convertButton([event buttonNumber]))); handleTabletEvent(eventPtr); break; case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: - if (m_windowManager->getActiveWindow()) { - pushEvent(new GHOST_EventButton([event timestamp], GHOST_kEventButtonUp, window, convertButton([event buttonNumber]))); - } + pushEvent(new GHOST_EventButton([event timestamp], GHOST_kEventButtonUp, window, convertButton([event buttonNumber]))); handleTabletEvent(eventPtr); break; @@ -1098,16 +1249,16 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) case NSFlagsChanged: modifiers = [event modifierFlags]; if ((modifiers & NSShiftKeyMask) != (m_modifierMask & NSShiftKeyMask)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) ); + pushEvent( new GHOST_EventKey([event timestamp], (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) ); } if ((modifiers & NSControlKeyMask) != (m_modifierMask & NSControlKeyMask)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSControlKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) ); + pushEvent( new GHOST_EventKey([event timestamp], (modifiers & NSControlKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) ); } if ((modifiers & NSAlternateKeyMask) != (m_modifierMask & NSAlternateKeyMask)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSAlternateKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) ); + pushEvent( new GHOST_EventKey([event timestamp], (modifiers & NSAlternateKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) ); } if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) ); + pushEvent( new GHOST_EventKey([event timestamp], (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) ); } m_modifierMask = modifiers; diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h index f383e3a7a81..5ff205d964f 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.h +++ b/intern/ghost/intern/GHOST_WindowCocoa.h @@ -40,8 +40,7 @@ #include "GHOST_Window.h" #include "STR_String.h" -#include - +class GHOST_SystemCocoa; /** * Window on Mac OSX/Cocoa. @@ -60,6 +59,7 @@ public: * Constructor. * Creates a new window and opens it. * To check if the window was created properly, use the getValid() method. + * @param systemCocoa The associated system class to forward events to * @param title The text shown in the title bar of the window. * @param left The coordinate of the left edge of the window. * @param top The coordinate of the top edge of the window. @@ -70,6 +70,7 @@ public: * @param stereoVisual Stereo visual for quad buffered stereo. */ GHOST_WindowCocoa( + const GHOST_SystemCocoa *systemCocoa, const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, @@ -210,8 +211,8 @@ public: virtual bool getFullScreenDirty(); /* accessor for fullscreen window */ - virtual void setMac_windowState(short value); - virtual short getMac_windowState(); + /*virtual void setMac_windowState(short value); + virtual short getMac_windowState();*/ const GHOST_TabletData* GetTabletData() @@ -260,48 +261,28 @@ protected: virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY); - /** - * Converts a string object to a Mac Pascal string. - * @param in The string object to be converted. - * @param out The converted string. - */ - virtual void gen2mac(const STR_String& in, Str255 out) const; - - /** - * Converts a Mac Pascal string to a string object. - * @param in The string to be converted. - * @param out The converted string object. - */ - virtual void mac2gen(const Str255 in, STR_String& out) const; + /** The window containing the OpenGL view */ + NSWindow *m_window; - WindowRef m_windowRef; - CGrafPtr m_grafPtr; - AGLContext m_aglCtx; + /** The openGL view */ + NSOpenGLView *m_openGLView; + + /** The opgnGL drawing context */ + NSOpenGLContext *m_openGLContext; + + //CGrafPtr m_grafPtr; + //AGLContext m_aglCtx; /** The first created OpenGL context (for sharing display lists) */ - static AGLContext s_firstaglCtx; + //static AGLContext s_firstaglCtx; - Cursor* m_customCursor; + NSCursor* m_customCursor; GHOST_TabletData m_tablet; /** When running in full-screen this tells whether to refresh the window. */ bool m_fullScreenDirty; - - /** specific MacOs X full screen window setting as we use partially system mechanism - values : 0 not maximizable default - 1 normal state - 2 maximized state - - this will be reworked when rebuilding GHOST carbon to use new OS X apis - in order to be unified with GHOST fullscreen/maximised settings - - (lukep) - **/ - - short mac_windowState; - - + /** * The width/height of the size rectangle in the lower right corner of a * Mac/Carbon window. This is also the height of the gutter area. diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 092443814b0..4d117d25df3 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -21,26 +21,18 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Maarten Gribnau 05/2001 + Damien Plisson 10/2009 * * ***** END GPL LICENSE BLOCK ***** */ -/** - * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date May 10, 2001 - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include +#include #include "GHOST_WindowCocoa.h" +#include "GHOST_SystemCocoa.h" #include "GHOST_Debug.h" - +/* AGLContext GHOST_WindowCocoa::s_firstaglCtx = NULL; #ifdef GHOST_DRAW_CARBON_GUTTER const GHOST_TInt32 GHOST_WindowCocoa::s_sizeRectSize = 16; @@ -68,7 +60,7 @@ AGL_NONE, WindowRef ugly_hack=NULL; const EventTypeSpec kWEvents[] = { - { kEventClassWindow, kEventWindowZoom }, /* for new zoom behaviour */ + { kEventClassWindow, kEventWindowZoom }, // for new zoom behaviour }; static OSStatus myWEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData) { @@ -88,9 +80,86 @@ static OSStatus myWEventHandlerProc(EventHandlerCallRef handler, EventRef event, } return eventNotHandledErr; +}*/ + +#pragma mark Cocoa delegate object +@interface CocoaWindowDelegate : NSObject +{ + GHOST_SystemCocoa *systemCocoa; + GHOST_WindowCocoa *associatedWindow; } +- (void)setSystemAndWindowCocoa:(const GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa; +- (void)windowWillClose:(NSNotification *)notification; +- (void)windowDidBecomeKey:(NSNotification *)notification; +- (void)windowDidResignKey:(NSNotification *)notification; +- (void)windowDidUpdate:(NSNotification *)notification; +- (void)windowDidResize:(NSNotification *)notification; +@end + +@implementation CocoaWindowDelegate : NSObject +- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa +{ + systemCocoa = sysCocoa; + associatedWindow = winCocoa; +} + +- (void)windowWillClose:(NSNotification *)notification +{ + systemCocoa->handleWindowEvent(GHOST_kEventWindowClose, associatedWindow); +} + +- (void)windowDidBecomeKey:(NSNotification *)notification +{ + systemCocoa->handleWindowEvent(GHOST_kEventWindowActivate, associatedWindow); +} + +- (void)windowDidResignKey:(NSNotification *)notification +{ + systemCocoa->handleWindowEvent(GHOST_kEventWindowDeactivate, associatedWindow); +} + +- (void)windowDidUpdate:(NSNotification *)notification +{ + systemCocoa->handleWindowEvent(GHOST_kEventWindowUpdate, associatedWindow); +} + +- (void)windowDidResize:(NSNotification *)notification +{ + systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, associatedWindow); +} +@end + +#pragma mark NSOpenGLView subclass +//We need to subclass it in order to give Cocoa the feeling key events are trapped +@interface CocoaOpenGLView : NSOpenGLView +{ + +} +@end +@implementation CocoaOpenGLView + +- (BOOL)acceptsFirstResponder +{ + return YES; +} + +//The trick to prevent Cocoa from complaining (beeping) +- (void)keyDown:(NSEvent *)theEvent +{} + +- (BOOL)isOpaque +{ + return YES; +} + +@end + + +#pragma mark initialization / finalization + GHOST_WindowCocoa::GHOST_WindowCocoa( + const GHOST_SystemCocoa *systemCocoa, const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, @@ -101,17 +170,13 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( const bool stereoVisual ) : GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone), - m_windowRef(0), - m_grafPtr(0), - m_aglCtx(0), m_customCursor(0), m_fullScreenDirty(false) { - Str255 title255; - OSStatus err; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; //fprintf(stderr," main screen top %i left %i height %i width %i\n", top, left, height, width); - + /* if (state >= GHOST_kWindowState8Normal ) { if(state == GHOST_kWindowState8Normal) state= GHOST_kWindowStateNormal; else if(state == GHOST_kWindowState8Maximized) state= GHOST_kWindowStateMaximized; @@ -123,26 +188,77 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( setMac_windowState(1); } else setMac_windowState(0); - +*/ if (state != GHOST_kWindowStateFullScreen) { - Rect bnds = { top, left, top+height, left+width }; - // Boolean visible = (state == GHOST_kWindowStateNormal) || (state == GHOST_kWindowStateMaximized); /*unused*/ - gen2mac(title, title255); + + //Creates the window + NSRect rect; + + rect.origin.x = left; + rect.origin.y = top; + rect.size.width = width; + rect.size.height = height; + + m_window = [[NSWindow alloc] initWithContentRect:rect + styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask + backing:NSBackingStoreBuffered defer:NO]; + if (m_window == nil) { + [pool drain]; + return; + } + + [m_window setTitle:[NSString stringWithUTF8String:title]]; + + + //Creates the OpenGL View inside the window + NSOpenGLPixelFormatAttribute attributes[] = + { + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAAccelerated, + NSOpenGLPFAAllowOfflineRenderers, // NOTE: Needed to connect to secondary GPUs + NSOpenGLPFADepthSize, 32, + 0 + }; + + NSOpenGLPixelFormat *pixelFormat = + [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; + + m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect + pixelFormat:pixelFormat]; + + [pixelFormat release]; + + m_openGLContext = [m_openGLView openGLContext]; + + [m_window setContentView:m_openGLView]; + [m_window setInitialFirstResponder:m_openGLView]; + + [m_window setReleasedWhenClosed:NO]; //To avoid bad pointer exception in case of user closing the window + + [m_window makeKeyAndOrderFront:nil]; + + setDrawingContextType(type); + updateDrawingContext(); + activateDrawingContext(); + + // Boolean visible = (state == GHOST_kWindowStateNormal) || (state == GHOST_kWindowStateMaximized); /*unused*/ + /*gen2mac(title, title255); + err = ::CreateNewWindow( kDocumentWindowClass, kWindowStandardDocumentAttributes+kWindowLiveResizeAttribute, &bnds, &m_windowRef); if ( err != noErr) { - fprintf(stderr," error creating window %i \n",err); + fprintf(stderr," error creating window %i \n",(int)err); } else { ::SetWRefCon(m_windowRef,(SInt32)this); setTitle(title); err = InstallWindowEventHandler (m_windowRef, myWEventHandlerProc, GetEventTypeCount(kWEvents), kWEvents,NULL,NULL); if ( err != noErr) { - fprintf(stderr," error creating handler %i \n",err); + fprintf(stderr," error creating handler %i \n",(int)err); } else { // ::TransitionWindow (m_windowRef,kWindowZoomTransitionEffect,kWindowShowTransitionAction,NULL); ::ShowWindow(m_windowRef); @@ -162,7 +278,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( ProcessSerialNumber psn; GetCurrentProcess(&psn); SetFrontProcess(&psn); - } + }*/ } else { /* @@ -179,12 +295,20 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( (SInt32)this); // Store a pointer to the class in the refCon */ //GHOST_PRINT("GHOST_WindowCocoa::GHOST_WindowCocoa(): creating full-screen OpenGL context\n"); - setDrawingContextType(GHOST_kDrawingContextTypeOpenGL);;installDrawingContext(GHOST_kDrawingContextTypeOpenGL); + setDrawingContextType(GHOST_kDrawingContextTypeOpenGL); + installDrawingContext(GHOST_kDrawingContextTypeOpenGL); updateDrawingContext(); - activateDrawingContext(); - - m_tablet.Active = GHOST_kTabletModeNone; + activateDrawingContext(); } + m_tablet.Active = GHOST_kTabletModeNone; + + CocoaWindowDelegate *windowDelegate = [[CocoaWindowDelegate alloc] init]; + [windowDelegate setSystemAndWindowCocoa:systemCocoa windowCocoa:this]; + [m_window setDelegate:windowDelegate]; + + [m_window setAcceptsMouseMovedEvents:YES]; + + [pool drain]; } @@ -192,21 +316,26 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa() { if (m_customCursor) delete m_customCursor; - if(ugly_hack==m_windowRef) ugly_hack= NULL; + /*if(ugly_hack==m_windowRef) ugly_hack= NULL; - // printf("GHOST_WindowCocoa::~GHOST_WindowCocoa(): removing drawing context\n"); - if(ugly_hack==NULL) setDrawingContextType(GHOST_kDrawingContextTypeNone); - if (m_windowRef) { - ::DisposeWindow(m_windowRef); - m_windowRef = 0; + if(ugly_hack==NULL) setDrawingContextType(GHOST_kDrawingContextTypeNone);*/ + + [m_openGLView release]; + + if (m_window) { + [m_window close]; + [m_window release]; + m_window = nil; } } +#pragma mark accessors + bool GHOST_WindowCocoa::getValid() const { bool valid; if (!m_fullScreen) { - valid = (m_windowRef != 0) && (m_grafPtr != 0) && ::IsValidWindowPtr(m_windowRef); + valid = (m_window != 0); //&& ::IsValidWindowPtr(m_windowRef); } else { valid = true; @@ -218,57 +347,73 @@ bool GHOST_WindowCocoa::getValid() const void GHOST_WindowCocoa::setTitle(const STR_String& title) { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid") - Str255 title255; - gen2mac(title, title255); - ::SetWTitle(m_windowRef, title255); + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSString *windowTitle = [[NSString alloc] initWithUTF8String:title]; + + [m_window setTitle:windowTitle]; + + [windowTitle release]; + [pool drain]; } void GHOST_WindowCocoa::getTitle(STR_String& title) const { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid") - Str255 title255; - ::GetWTitle(m_windowRef, title255); - mac2gen(title255, title); + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSString *windowTitle = [m_window title]; + + if (windowTitle != nil) { + title = [windowTitle UTF8String]; + } + + [pool drain]; } void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect& bounds) const { - OSStatus success; - Rect rect; + NSRect rect; GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid") - success = ::GetWindowBounds(m_windowRef, kWindowStructureRgn, &rect); - bounds.m_b = rect.bottom; - bounds.m_l = rect.left; - bounds.m_r = rect.right; - bounds.m_t = rect.top; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSRect screenSize = [[m_window screen] visibleFrame]; + + rect = [m_window frame]; + + bounds.m_b = screenSize.size.height - (rect.origin.y -screenSize.origin.y); + bounds.m_l = rect.origin.x -screenSize.origin.x; + bounds.m_r = rect.origin.x-screenSize.origin.x + rect.size.width; + bounds.m_t = screenSize.size.height - (rect.origin.y + rect.size.height -screenSize.origin.y); + + [pool drain]; } void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const { - Rect rect; + NSRect rect; GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getClientBounds(): window invalid") - //::GetPortBounds(m_grafPtr, &rect); - ::GetWindowBounds(m_windowRef, kWindowContentRgn, &rect); + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSRect screenSize = [[m_window screen] visibleFrame]; - bounds.m_b = rect.bottom; - bounds.m_l = rect.left; - bounds.m_r = rect.right; - bounds.m_t = rect.top; + //Max window contents as screen size (excluding title bar...) + NSRect contentRect = [NSWindow contentRectForFrameRect:screenSize + styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)]; - // Subtract gutter height from bottom -#ifdef GHOST_DRAW_CARBON_GUTTER - if ((bounds.m_b - bounds.m_t) > s_sizeRectSize) - { - bounds.m_b -= s_sizeRectSize; - } - else - { - bounds.m_t = bounds.m_b; - } -#endif //GHOST_DRAW_CARBON_GUTTER + rect = [m_window contentRectForFrameRect:[m_window frame]]; + + bounds.m_b = contentRect.size.height - (rect.origin.y -contentRect.origin.y); + bounds.m_l = rect.origin.x -contentRect.origin.x; + bounds.m_r = rect.origin.x-contentRect.origin.x + rect.size.width; + bounds.m_t = contentRect.size.height - (rect.origin.y + rect.size.height -contentRect.origin.y); + + [pool drain]; } @@ -278,7 +423,10 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width) GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); if (((GHOST_TUns32)cBnds.getWidth()) != width) { - ::SizeWindow(m_windowRef, width, cBnds.getHeight(), true); + NSSize size; + size.width=width; + size.height=cBnds.getHeight(); + [m_window setContentSize:size]; } return GHOST_kSuccess; } @@ -289,15 +437,12 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height) GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid") GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); -#ifdef GHOST_DRAW_CARBON_GUTTER - if (((GHOST_TUns32)cBnds.getHeight()) != height+s_sizeRectSize) { - ::SizeWindow(m_windowRef, cBnds.getWidth(), height+s_sizeRectSize, true); - } -#else //GHOST_DRAW_CARBON_GUTTER if (((GHOST_TUns32)cBnds.getHeight()) != height) { - ::SizeWindow(m_windowRef, cBnds.getWidth(), height, true); + NSSize size; + size.width=cBnds.getWidth(); + size.height=height; + [m_window setContentSize:size]; } -#endif //GHOST_DRAW_CARBON_GUTTER return GHOST_kSuccess; } @@ -307,17 +452,13 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid") GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); -#ifdef GHOST_DRAW_CARBON_GUTTER - if ((((GHOST_TUns32)cBnds.getWidth()) != width) || - (((GHOST_TUns32)cBnds.getHeight()) != height+s_sizeRectSize)) { - ::SizeWindow(m_windowRef, width, height+s_sizeRectSize, true); - } -#else //GHOST_DRAW_CARBON_GUTTER if ((((GHOST_TUns32)cBnds.getWidth()) != width) || (((GHOST_TUns32)cBnds.getHeight()) != height)) { - ::SizeWindow(m_windowRef, width, height, true); + NSSize size; + size.width=width; + size.height=height; + [m_window setContentSize:size]; } -#endif //GHOST_DRAW_CARBON_GUTTER return GHOST_kSuccess; } @@ -325,16 +466,18 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 GHOST_TWindowState GHOST_WindowCocoa::getState() const { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getState(): window invalid") + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_TWindowState state; - if (::IsWindowVisible(m_windowRef) == false) { + if ([m_window isMiniaturized]) { state = GHOST_kWindowStateMinimized; } - else if (::IsWindowInStandardState(m_windowRef, nil, nil)) { + else if ([m_window isZoomed]) { state = GHOST_kWindowStateMaximized; } else { state = GHOST_kWindowStateNormal; } + [pool drain]; return state; } @@ -342,32 +485,34 @@ GHOST_TWindowState GHOST_WindowCocoa::getState() const void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::screenToClient(): window invalid") - Point point; - point.h = inX; - point.v = inY; - GrafPtr oldPort; - ::GetPort(&oldPort); - ::SetPort(m_grafPtr); - ::GlobalToLocal(&point); - ::SetPort(oldPort); - outX = point.h; - outY = point.v; + + NSPoint screenCoord; + NSPoint baseCoord; + + screenCoord.x = inX; + screenCoord.y = inY; + + baseCoord = [m_window convertScreenToBase:screenCoord]; + + outX = baseCoord.x; + outY = baseCoord.y; } void GHOST_WindowCocoa::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::clientToScreen(): window invalid") - Point point; - point.h = inX; - point.v = inY; - GrafPtr oldPort; - ::GetPort(&oldPort); - ::SetPort(m_grafPtr); - ::LocalToGlobal(&point); - ::SetPort(oldPort); - outX = point.h; - outY = point.v; + + NSPoint screenCoord; + NSPoint baseCoord; + + baseCoord.x = inX; + baseCoord.y = inY; + + screenCoord = [m_window convertBaseToScreen:baseCoord]; + + outX = screenCoord.x; + outY = screenCoord.y; } @@ -376,12 +521,17 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setState(): window invalid") switch (state) { case GHOST_kWindowStateMinimized: - ::HideWindow(m_windowRef); + [m_window miniaturize:nil]; break; case GHOST_kWindowStateMaximized: + [m_window zoom:nil]; + break; case GHOST_kWindowStateNormal: default: - ::ShowWindow(m_windowRef); + if ([m_window isMiniaturized]) + [m_window deminiaturize:nil]; + else if ([m_window isZoomed]) + [m_window zoom:nil]; break; } return GHOST_kSuccess; @@ -389,11 +539,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) GHOST_TSuccess GHOST_WindowCocoa::setModifiedState(bool isUnsavedChanges) { - if (isUnsavedChanges) { - SetWindowModified(m_windowRef, 1); - } else { - SetWindowModified(m_windowRef, 0); - } + [m_window setDocumentEdited:isUnsavedChanges]; return GHOST_Window::setModifiedState(isUnsavedChanges); } @@ -404,61 +550,45 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order) { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setOrder(): window invalid") if (order == GHOST_kWindowOrderTop) { - //::BringToFront(m_windowRef); is wrong, front window should be active for input too - ::SelectWindow(m_windowRef); + [m_window orderFront:nil]; } else { - /* doesnt work if you do this with a mouseclick */ - ::SendBehind(m_windowRef, nil); + [m_window orderBack:nil]; } return GHOST_kSuccess; } +#pragma mark Drawing context + /*#define WAIT_FOR_VSYNC 1*/ -#ifdef WAIT_FOR_VSYNC -#include -#endif GHOST_TSuccess GHOST_WindowCocoa::swapBuffers() { -#ifdef WAIT_FOR_VSYNC -/* wait for vsync, to avoid tearing artifacts */ -long VBL = 1; -CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &VBL); -#endif - - GHOST_TSuccess succeeded = GHOST_kSuccess; if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { - if (m_aglCtx) { - ::aglSwapBuffers(m_aglCtx); - } - else { - succeeded = GHOST_kFailure; + if (m_openGLContext != nil) { + [m_openGLContext flushBuffer]; + return GHOST_kSuccess; } } - return succeeded; + return GHOST_kFailure; } GHOST_TSuccess GHOST_WindowCocoa::updateDrawingContext() { - GHOST_TSuccess succeeded = GHOST_kSuccess; if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { - if (m_aglCtx) { - ::aglUpdateContext(m_aglCtx); - } - else { - succeeded = GHOST_kFailure; + if (m_openGLContext != nil) { + [m_openGLContext update]; + return GHOST_kSuccess; } } - return succeeded; + return GHOST_kFailure; } GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext() { - GHOST_TSuccess succeeded = GHOST_kSuccess; if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { - if (m_aglCtx) { - ::aglSetCurrentContext(m_aglCtx); + if (m_openGLContext != nil) { + [m_openGLContext makeCurrentContext]; #ifdef GHOST_DRAW_CARBON_GUTTER // Restrict drawing to non-gutter area ::aglEnable(m_aglCtx, AGL_BUFFER_RECT); @@ -473,23 +603,44 @@ GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext() }; GLboolean result = ::aglSetInteger(m_aglCtx, AGL_BUFFER_RECT, b); #endif //GHOST_DRAW_CARBON_GUTTER - } - else { - succeeded = GHOST_kFailure; + return GHOST_kSuccess; } } - return succeeded; + return GHOST_kFailure; } GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextType type) { GHOST_TSuccess success = GHOST_kFailure; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSOpenGLPixelFormat *pixelFormat; + NSOpenGLContext *tmpOpenGLContext; + switch (type) { case GHOST_kDrawingContextTypeOpenGL: - { if (!getValid()) break; - + + if(!m_fullScreen) + { + pixelFormat = [m_openGLView pixelFormat]; + tmpOpenGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat + shareContext:m_openGLContext]; + if (tmpOpenGLContext == nil) + break; +#ifdef WAIT_FOR_VSYNC + /* wait for vsync, to avoid tearing artifacts */ + [tmpOpenGLContext setValues:1 forParameter:NSOpenGLCPSwapInterval]; +#endif + [m_openGLView setOpenGLContext:tmpOpenGLContext]; + [tmpOpenGLContext setView:m_openGLView]; + + //[m_openGLContext release]; + m_openGLContext = tmpOpenGLContext; + } + /* AGLPixelFormat pixelFormat; if (!m_fullScreen) { pixelFormat = ::aglChoosePixelFormat(0, 0, sPreferredFormatWindow); @@ -507,17 +658,16 @@ GDHandle device=::GetMainDevice();pixelFormat=::aglChoosePixelFormat(&device,1,s //GHOST_PRINT("GHOST_WindowCocoa::installDrawingContext(): created OpenGL context\n"); //::CGGetActiveDisplayList(0, NULL, &m_numDisplays) success = ::aglSetFullScreen(m_aglCtx, m_fullScreenWidth, m_fullScreenHeight, 75, 0) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure; - /* + if (success == GHOST_kSuccess) { GHOST_PRINT("GHOST_WindowCocoa::installDrawingContext(): init full-screen OpenGL succeeded\n"); } else { GHOST_PRINT("GHOST_WindowCocoa::installDrawingContext(): init full-screen OpenGL failed\n"); } - */ + } - ::aglDestroyPixelFormat(pixelFormat); - } + ::aglDestroyPixelFormat(pixelFormat);*/ break; case GHOST_kDrawingContextTypeNone: @@ -527,41 +677,34 @@ GDHandle device=::GetMainDevice();pixelFormat=::aglChoosePixelFormat(&device,1,s default: break; } + [pool drain]; return success; } GHOST_TSuccess GHOST_WindowCocoa::removeDrawingContext() { - GHOST_TSuccess success = GHOST_kFailure; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; switch (m_drawingContextType) { case GHOST_kDrawingContextTypeOpenGL: - if (m_aglCtx) { - aglSetCurrentContext(NULL); - aglSetDrawable(m_aglCtx, NULL); - //aglDestroyContext(m_aglCtx); - if (s_firstaglCtx == m_aglCtx) s_firstaglCtx = NULL; - success = ::aglDestroyContext(m_aglCtx) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure; - m_aglCtx = 0; - } - break; + [m_openGLView clearGLContext]; + return GHOST_kSuccess; case GHOST_kDrawingContextTypeNone: - success = GHOST_kSuccess; + return GHOST_kSuccess; break; default: - break; + return GHOST_kFailure; } - return success; + [pool drain]; } GHOST_TSuccess GHOST_WindowCocoa::invalidate() { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::invalidate(): window invalid") + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; if (!m_fullScreen) { - Rect rect; - ::GetPortBounds(m_grafPtr, &rect); - ::InvalWindowRect(m_windowRef, &rect); + [m_openGLView setNeedsDisplay:YES]; } else { //EventRef event; @@ -574,77 +717,81 @@ GHOST_TSuccess GHOST_WindowCocoa::invalidate() //GHOST_PRINT("GHOST_WindowCocoa::invalidate(): added event to queue " << status << " \n"); m_fullScreenDirty = true; } + [pool drain]; return GHOST_kSuccess; } - -void GHOST_WindowCocoa::gen2mac(const STR_String& in, Str255 out) const -{ - STR_String tempStr = in; - int num = tempStr.Length(); - if (num > 255) num = 255; - ::memcpy(out+1, tempStr.Ptr(), num); - out[0] = num; -} - - -void GHOST_WindowCocoa::mac2gen(const Str255 in, STR_String& out) const -{ - char tmp[256]; - ::memcpy(tmp, in+1, in[0]); - tmp[in[0]] = '\0'; - out = tmp; -} +#pragma mark Cursor handling void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) const { static bool systemCursorVisible = true; + NSAutoreleasePool *pool =[[NSAutoreleasePool alloc] init]; + + NSCursor *tmpCursor =nil; + if (visible != systemCursorVisible) { if (visible) { - ::ShowCursor(); + [NSCursor unhide]; systemCursorVisible = true; } else { - ::HideCursor(); + [NSCursor hide]; systemCursorVisible = false; } } if (cursor == GHOST_kStandardCursorCustom && m_customCursor) { - ::SetCursor( m_customCursor ); + tmpCursor = m_customCursor; } else { - int carbon_cursor; - -#define GCMAP(ghostCursor, carbonCursor) case ghostCursor: carbon_cursor = carbonCursor; break switch (cursor) { - default: - GCMAP( GHOST_kStandardCursorDefault, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorRightArrow, kThemeAliasArrowCursor); - GCMAP( GHOST_kStandardCursorLeftArrow, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorInfo, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorDestroy, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorHelp, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorCycle, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorSpray, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorWait, kThemeWatchCursor); - GCMAP( GHOST_kStandardCursorText, kThemeIBeamCursor); - GCMAP( GHOST_kStandardCursorCrosshair, kThemeCrossCursor); - GCMAP( GHOST_kStandardCursorUpDown, kThemeClosedHandCursor); - GCMAP( GHOST_kStandardCursorLeftRight, kThemeClosedHandCursor); - GCMAP( GHOST_kStandardCursorTopSide, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorBottomSide, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorLeftSide, kThemeResizeLeftCursor); - GCMAP( GHOST_kStandardCursorRightSide, kThemeResizeRightCursor); - GCMAP( GHOST_kStandardCursorTopLeftCorner, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorTopRightCorner, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorBottomRightCorner, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorBottomLeftCorner, kThemeArrowCursor); + case GHOST_kStandardCursorDestroy: + tmpCursor = [NSCursor disappearingItemCursor]; + break; + case GHOST_kStandardCursorText: + tmpCursor = [NSCursor IBeamCursor]; + break; + case GHOST_kStandardCursorCrosshair: + tmpCursor = [NSCursor crosshairCursor]; + break; + case GHOST_kStandardCursorUpDown: + tmpCursor = [NSCursor resizeUpDownCursor]; + break; + case GHOST_kStandardCursorLeftRight: + tmpCursor = [NSCursor resizeLeftRightCursor]; + break; + case GHOST_kStandardCursorTopSide: + tmpCursor = [NSCursor resizeUpCursor]; + break; + case GHOST_kStandardCursorBottomSide: + tmpCursor = [NSCursor resizeDownCursor]; + break; + case GHOST_kStandardCursorLeftSide: + tmpCursor = [NSCursor resizeLeftCursor]; + break; + case GHOST_kStandardCursorRightSide: + tmpCursor = [NSCursor resizeRightCursor]; + break; + case GHOST_kStandardCursorRightArrow: + case GHOST_kStandardCursorInfo: + case GHOST_kStandardCursorLeftArrow: + case GHOST_kStandardCursorHelp: + case GHOST_kStandardCursorCycle: + case GHOST_kStandardCursorSpray: + case GHOST_kStandardCursorWait: + case GHOST_kStandardCursorTopLeftCorner: + case GHOST_kStandardCursorTopRightCorner: + case GHOST_kStandardCursorBottomRightCorner: + case GHOST_kStandardCursorBottomLeftCorner: + case GHOST_kStandardCursorDefault: + default: + tmpCursor = [NSCursor arrowCursor]; + break; }; -#undef GCMAP - - ::SetThemeCursor(carbon_cursor); } + [tmpCursor set]; + [pool drain]; } @@ -656,7 +803,7 @@ bool GHOST_WindowCocoa::getFullScreenDirty() GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible) { - if (::FrontWindow() == m_windowRef) { + if ([m_window isVisible]) { loadCursor(visible, getCursorShape()); } @@ -666,11 +813,11 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible) GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorShape(GHOST_TStandardCursor shape) { if (m_customCursor) { - delete m_customCursor; - m_customCursor = 0; + [m_customCursor release]; + m_customCursor = nil; } - if (::FrontWindow() == m_windowRef) { + if ([m_window isVisible]) { loadCursor(getCursorVisibility(), shape); } @@ -703,14 +850,15 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color) { int y; + NSPoint hotSpotPoint; + NSImage *cursorImage; if (m_customCursor) { - delete m_customCursor; - m_customCursor = 0; + [m_customCursor release]; + m_customCursor = nil; } - - m_customCursor = new Cursor; - if (!m_customCursor) return GHOST_kFailure; + /*TODO: implement this (but unused inproject at present) + cursorImage = [[NSImage alloc] initWithData:bitmap]; for (y=0; y<16; y++) { #if !defined(__LITTLE_ENDIAN__) @@ -723,13 +871,21 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap } - m_customCursor->hotSpot.h = hotX; - m_customCursor->hotSpot.v = hotY; - if (::FrontWindow() == m_windowRef) { + hotSpotPoint.x = hotX; + hotSpotPoint.y = hotY; + + m_customCursor = [[NSCursor alloc] initWithImage:cursorImage + foregroundColorHint:<#(NSColor *)fg#> + backgroundColorHint:<#(NSColor *)bg#> + hotSpot:hotSpotPoint]; + + [cursorImage release]; + + if ([m_window isVisible]) { loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom); } - + */ return GHOST_kSuccess; } @@ -739,7 +895,9 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 bitmap[ return setWindowCustomCursorShape((GHOST_TUns8*)bitmap, (GHOST_TUns8*) mask, 16, 16, hotX, hotY, 0, 1); } +#pragma mark Old carbon stuff to remove +#if 0 void GHOST_WindowCocoa::setMac_windowState(short value) { mac_windowState = value; @@ -749,3 +907,23 @@ short GHOST_WindowCocoa::getMac_windowState() { return mac_windowState; } + +void GHOST_WindowCocoa::gen2mac(const STR_String& in, Str255 out) const +{ + STR_String tempStr = in; + int num = tempStr.Length(); + if (num > 255) num = 255; + ::memcpy(out+1, tempStr.Ptr(), num); + out[0] = num; +} + + +void GHOST_WindowCocoa::mac2gen(const Str255 in, STR_String& out) const +{ + char tmp[256]; + ::memcpy(tmp, in+1, in[0]); + tmp[in[0]] = '\0'; + out = tmp; +} + +#endif \ No newline at end of file diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 80878cf6884..c15106e21c9 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1569,14 +1569,18 @@ void wm_event_add_ghostevent(wmWindow *win, int type, void *customdata) case GHOST_kEventCursorMove: { if(win->active) { GHOST_TEventCursorData *cd= customdata; +#if defined(__APPLE__) && defined(GHOST_COCOA) + //Cocoa already uses coordinates with y=0 at bottom, and returns inwindow coordinates on mouse moved event + event.type= MOUSEMOVE; + event.x= evt->x = cd->x; + event.y = evt->y = cd->y; +#else int cx, cy; - GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy); - event.type= MOUSEMOVE; event.x= evt->x= cx; event.y= evt->y= (win->sizey-1) - cy; - +#endif update_tablet_data(win, &event); wm_event_add(win, &event); } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 466e5868723..e3cfb9ad60d 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -608,7 +608,13 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) GHOST_ScreenToClient(win->ghostwin, wx, wy, &cx, &cy); win->eventstate->x= cx; + +#if defined(__APPLE__) && defined(GHOST_COCOA) + //Cocoa already uses coordinates with y=0 at bottom + win->eventstate->y= cy; +#else win->eventstate->y= (win->sizey-1) - cy; +#endif wm_window_make_drawable(C, win); break; From 9e38ec2506f54a5d5c9c1e8d393309be48032df3 Mon Sep 17 00:00:00 2001 From: "Guillermo S. Romero" Date: Tue, 6 Oct 2009 17:01:00 +0000 Subject: [PATCH 132/138] Add raytrace subdir to Makefiles. The makefile is a copy of the source one, not tuned, just to unbreak build. This raises some questions: why separate dirs? why each build system takes a different approach (different libs vs all source files into one)? --- source/Makefile | 1 + .../blender/render/intern/raytrace/Makefile | 65 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 source/blender/render/intern/raytrace/Makefile diff --git a/source/Makefile b/source/Makefile index 45a15e822dc..4347c79bc79 100644 --- a/source/Makefile +++ b/source/Makefile @@ -83,6 +83,7 @@ GRPLIB += $(NAN_BOOLOP)/lib/$(DEBUG_DIR)libboolop.a GRPLIB += $(NAN_GHOST)/lib/$(DEBUG_DIR)libghost.a GRPLIB += $(NAN_STRING)/lib/$(DEBUG_DIR)libstring.a GRPLIB += $(OCGDIR)/blender/render/$(DEBUG_DIR)librender.a +GRPLIB += $(OCGDIR)/blender/render/$(DEBUG_DIR)librender_raytrace.a # nlin: the reason that some libraries appear more than once below is # to handle circular dependencies in linking among libraries... some diff --git a/source/blender/render/intern/raytrace/Makefile b/source/blender/render/intern/raytrace/Makefile new file mode 100644 index 00000000000..6e40c544c6f --- /dev/null +++ b/source/blender/render/intern/raytrace/Makefile @@ -0,0 +1,65 @@ +# +# $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. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL LICENSE BLOCK ***** +# +# + +LIBNAME = render_raytrace +DIR = $(OCGDIR)/blender/render + +include nan_compile.mk + +CFLAGS += $(LEVEL_1_C_WARNINGS) + +# first /include is my own includes, second is the external interface. +# The external modules follow after. There should be a nicer way to say this. +CPPFLAGS += -I../include +CPPFLAGS += -I../../extern/include +CPPFLAGS += -I../../../blenlib +CPPFLAGS += -I../../../imbuf +CPPFLAGS += -I../../../makesdna +CPPFLAGS += -I../../../makesrna +CPPFLAGS += -I../../../blenkernel +CPPFLAGS += -I../../../quicktime +CPPFLAGS += -I../../../../kernel/gen_messaging +CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include +# not very neat: the rest of blender.. +CPPFLAGS += -I../../../editors/include +CPPFLAGS += $(NAN_SDLCFLAGS) +CPPFLAGS += -I../../../../../intern/smoke/extern + +ifeq ($(WITH_QUICKTIME), true) + CPPFLAGS += -DWITH_QUICKTIME +endif + +ifeq ($(WITH_FFMPEG),true) + CPPFLAGS += -DWITH_FFMPEG +endif + +ifeq ($(WITH_OPENEXR),true) + CPPFLAGS += -DWITH_OPENEXR +endif From 88ab193a21757cdcae51bc96bbd4aec06d2f67f8 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 6 Oct 2009 17:15:10 +0000 Subject: [PATCH 133/138] Bugfix: IK constraint pole angle range was not correct. --- source/blender/makesrna/intern/rna_constraint.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index b630e61a680..e6d8a2f27d7 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -87,7 +87,7 @@ EnumPropertyItem constraint_ik_type_items[] ={ {0, NULL, 0, NULL, NULL}, }; -static EnumPropertyItem constraint_distance_items[] = { +EnumPropertyItem constraint_distance_items[] = { {LIMITDIST_INSIDE, "LIMITDIST_INSIDE", 0, "Inside", ""}, {LIMITDIST_OUTSIDE, "LIMITDIST_OUTSIDE", 0, "Outside", ""}, {LIMITDIST_ONSURFACE, "LIMITDIST_ONSURFACE", 0, "On Surface", ""}, @@ -453,7 +453,7 @@ static void rna_def_constraint_kinematic(BlenderRNA *brna) prop= RNA_def_property(srna, "pole_angle", PROP_FLOAT, PROP_ANGLE); // XXX - todo, convert to rad RNA_def_property_float_sdna(prop, NULL, "poleangle"); - RNA_def_property_range(prop, 0.0, 180.f); + RNA_def_property_range(prop, -180.0f, 180.f); RNA_def_property_ui_text(prop, "Pole Angle", "Pole rotation offset."); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update"); From 041ce137e28bba78d24d2f321f1004d64b9aae34 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 6 Oct 2009 20:00:23 +0000 Subject: [PATCH 134/138] mistake in last commit --- release/scripts/ui/buttons_material.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/release/scripts/ui/buttons_material.py b/release/scripts/ui/buttons_material.py index dee927415e6..e91e324f49d 100644 --- a/release/scripts/ui/buttons_material.py +++ b/release/scripts/ui/buttons_material.py @@ -8,6 +8,8 @@ def active_node_mat(mat): mat_node = mat.active_node_material if mat_node: return mat_node + else: + return mat return None From 46402ccddc84895a1be167be2421d260f24d4972 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 6 Oct 2009 21:28:45 +0000 Subject: [PATCH 135/138] netrender: use TEMP env var if available to set default temporary path --- release/scripts/io/netrender/ui.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/release/scripts/io/netrender/ui.py b/release/scripts/io/netrender/ui.py index 7681d4865e9..cc1cbf3ed4a 100644 --- a/release/scripts/io/netrender/ui.py +++ b/release/scripts/io/netrender/ui.py @@ -234,18 +234,21 @@ NetRenderSettings.BoolProperty( attr="server_broadcast", description="broadcast server address on local network", default = True) -if os.name == 'nt': - NetRenderSettings.StringProperty( attr="path", - name="Path", - description="Path for temporary files", - maxlen = 128, - default = "C:/tmp/") -else: - NetRenderSettings.StringProperty( attr="path", - name="Path", - description="Path for temporary files", - maxlen = 128, - default = "/tmp/") +default_path = os.environ.get("TEMP", None) + +if not default_path: + if os.name == 'nt': + default_path = "c:/tmp/" + else: + default_path = "/tmp/" +elif not default_path.endswith(os.sep): + default_path += os.sep + +NetRenderSettings.StringProperty( attr="path", + name="Path", + description="Path for temporary files", + maxlen = 128, + default = default_path) NetRenderSettings.StringProperty( attr="job_name", name="Job name", From 91400d9da862caf74ccdaf8389d5bc5ce9de506a Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Tue, 6 Oct 2009 23:05:53 +0000 Subject: [PATCH 136/138] * Fix for crash with new raytree --- source/blender/render/intern/source/volumetric.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c index 91c13207da8..90ac45edb60 100644 --- a/source/blender/render/intern/source/volumetric.c +++ b/source/blender/render/intern/source/volumetric.c @@ -139,12 +139,16 @@ static int vol_get_bounds(ShadeInput *shi, float *co, float *vec, float *hitco, */ isect->mode= RE_RAY_MIRROR; - isect->orig.ob = (void*)shi->obi; isect->last_hit = NULL; isect->lay= -1; - if (intersect_type == VOL_BOUNDS_DEPTH) isect->orig.face = (void*)shi->vlr; - else if (intersect_type == VOL_BOUNDS_SS) isect->orig.face= NULL; + if (intersect_type == VOL_BOUNDS_DEPTH) { + isect->orig.face = (void*)shi->vlr; + isect->orig.ob = (void*)shi->obi; + } else if (intersect_type == VOL_BOUNDS_SS) { + isect->orig.face= NULL; + isect->orig.ob = NULL; + } if(RE_rayobject_raycast(R.raytree, isect)) { From f413091dfa3be71ffe03ddd1178ce0b22d0e8cc6 Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Tue, 6 Oct 2009 23:13:07 +0000 Subject: [PATCH 137/138] * Fix for previous 'set object as camera' operator - now properly sets the scene active camera too, plus better notifier. --- source/blender/editors/space_view3d/view3d_view.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index fc332cf6293..505f3abf401 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -443,10 +443,12 @@ static int view3d_setobjectascamera_exec(bContext *C, wmOperator *op) if(BASACT) { rv3d->persp= V3D_CAMOB; v3d->camera= OBACT; + if(v3d->scenelock) + scene->camera= OBACT; smooth_view(C, NULL, v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, &v3d->lens); } - WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, CTX_data_scene(C)); + WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS|NC_OBJECT|ND_DRAW, CTX_data_scene(C)); return OPERATOR_FINISHED; } From a8b82a49ad41491640d390405cf8e8c8c4c05829 Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Tue, 6 Oct 2009 23:37:11 +0000 Subject: [PATCH 138/138] * notifier fix to redraw upon changing lamp shadow type --- source/blender/makesrna/intern/rna_lamp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c index 06fecec6fb6..3d3333a7eed 100644 --- a/source/blender/makesrna/intern/rna_lamp.c +++ b/source/blender/makesrna/intern/rna_lamp.c @@ -456,7 +456,7 @@ static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area) RNA_def_property_enum_bitflag_sdna(prop, NULL, "mode"); RNA_def_property_enum_items(prop, (spot)? prop_spot_shadow_items: prop_shadow_items); RNA_def_property_ui_text(prop, "Shadow Method", "Method to compute lamp shadow with."); - RNA_def_property_update(prop, 0, "rna_Lamp_update"); + RNA_def_property_update(prop, 0, "rna_Lamp_draw_update"); prop= RNA_def_property(srna, "shadow_color", PROP_FLOAT, PROP_COLOR); RNA_def_property_float_sdna(prop, NULL, "shdwr");